GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / staging / rtl8723bs / hal / odm_DIG.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 void odm_NHMCounterStatisticsInit(void *pDM_VOID)
11 {
12         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
13
14         /* PHY parameters initialize for n series */
15         rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710); /* 0x894[31:16]= 0x2710 Time duration for NHM unit: 4us, 0x2710 =40ms */
16         /* rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20);      0x894[31:16]= 0x4e20    Time duration for NHM unit: 4us, 0x4e20 =80ms */
17         rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff);      /* 0x890[31:16]= 0xffff th_9, th_10 */
18         /* rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c);       0x898 = 0xffffff5c              th_3, th_2, th_1, th_0 */
19         rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52);  /* 0x898 = 0xffffff52           th_3, th_2, th_1, th_0 */
20         rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff);  /* 0x89c = 0xffffffff           th_7, th_6, th_5, th_4 */
21         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff);                /* 0xe28[7:0]= 0xff             th_8 */
22         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7); /* 0x890[9:8]=3                 enable CCX */
23         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1);            /* 0xc0c[7]= 1                  max power among all RX ants */
24 }
25
26 void odm_NHMCounterStatistics(void *pDM_VOID)
27 {
28         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
29
30         /*  Get NHM report */
31         odm_GetNHMCounterStatistics(pDM_Odm);
32
33         /*  Reset NHM counter */
34         odm_NHMCounterStatisticsReset(pDM_Odm);
35 }
36
37 void odm_GetNHMCounterStatistics(void *pDM_VOID)
38 {
39         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
40         u32 value32 = 0;
41
42         value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord);
43
44         pDM_Odm->NHM_cnt_0 = (u8)(value32 & bMaskByte0);
45 }
46
47 void odm_NHMCounterStatisticsReset(void *pDM_VOID)
48 {
49         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
50
51         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0);
52         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1);
53 }
54
55 void odm_NHMBBInit(void *pDM_VOID)
56 {
57         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
58
59         pDM_Odm->adaptivity_flag = 0;
60         pDM_Odm->tolerance_cnt = 3;
61         pDM_Odm->NHMLastTxOkcnt = 0;
62         pDM_Odm->NHMLastRxOkcnt = 0;
63         pDM_Odm->NHMCurTxOkcnt = 0;
64         pDM_Odm->NHMCurRxOkcnt = 0;
65 }
66
67 /*  */
68 void odm_NHMBB(void *pDM_VOID)
69 {
70         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
71         /* u8 test_status; */
72         /* struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; */
73
74         pDM_Odm->NHMCurTxOkcnt =
75                 *(pDM_Odm->pNumTxBytesUnicast)-pDM_Odm->NHMLastTxOkcnt;
76         pDM_Odm->NHMCurRxOkcnt =
77                 *(pDM_Odm->pNumRxBytesUnicast)-pDM_Odm->NHMLastRxOkcnt;
78         pDM_Odm->NHMLastTxOkcnt =
79                 *(pDM_Odm->pNumTxBytesUnicast);
80         pDM_Odm->NHMLastRxOkcnt =
81                 *(pDM_Odm->pNumRxBytesUnicast);
82
83
84         if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */
85                 if (pDM_Odm->NHM_cnt_0 >= 190 || pDM_Odm->adaptivity_flag == true) {
86                         /* Enable EDCCA since it is possible running Adaptivity testing */
87                         /* test_status = 1; */
88                         pDM_Odm->adaptivity_flag = true;
89                         pDM_Odm->tolerance_cnt = 0;
90                 } else {
91                         if (pDM_Odm->tolerance_cnt < 3)
92                                 pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
93                         else
94                                 pDM_Odm->tolerance_cnt = 4;
95                         /* test_status = 5; */
96                         if (pDM_Odm->tolerance_cnt > 3) {
97                                 /* test_status = 3; */
98                                 pDM_Odm->adaptivity_flag = false;
99                         }
100                 }
101         } else { /*  TX<RX */
102                 if (pDM_Odm->adaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200) {
103                         /* test_status = 2; */
104                         pDM_Odm->tolerance_cnt = 0;
105                 } else {
106                         if (pDM_Odm->tolerance_cnt < 3)
107                                 pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
108                         else
109                                 pDM_Odm->tolerance_cnt = 4;
110                         /* test_status = 5; */
111                         if (pDM_Odm->tolerance_cnt > 3) {
112                                 /* test_status = 4; */
113                                 pDM_Odm->adaptivity_flag = false;
114                         }
115                 }
116         }
117 }
118
119 void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target)
120 {
121         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
122         u32 value32 = 0;
123         u8 cnt, IGI;
124         bool bAdjust = true;
125         s8 TH_L2H_dmc, TH_H2L_dmc;
126         s8 Diff;
127
128         IGI = 0x50; /*  find H2L, L2H lower bound */
129         ODM_Write_DIG(pDM_Odm, IGI);
130
131
132         Diff = IGI_target-(s8)IGI;
133         TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
134         if (TH_L2H_dmc > 10)
135                 TH_L2H_dmc = 10;
136         TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
137         PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
138         PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
139
140         mdelay(5);
141
142         while (bAdjust) {
143                 for (cnt = 0; cnt < 20; cnt++) {
144                         value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_RPT_11N, bMaskDWord);
145
146                         if (value32 & BIT30)
147                                 pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
148                         else if (value32 & BIT29)
149                                 pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
150                         else
151                                 pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1;
152                 }
153
154                 if (pDM_Odm->txEdcca1 > 5) {
155                         IGI = IGI-1;
156                         TH_L2H_dmc = TH_L2H_dmc + 1;
157                         if (TH_L2H_dmc > 10)
158                                 TH_L2H_dmc = 10;
159                         TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
160                         PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
161                         PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
162
163                         pDM_Odm->TxHangFlg = true;
164                         pDM_Odm->txEdcca1 = 0;
165                         pDM_Odm->txEdcca0 = 0;
166
167                         if (TH_L2H_dmc == 10) {
168                                 bAdjust = false;
169                                 pDM_Odm->TxHangFlg = false;
170                                 pDM_Odm->txEdcca1 = 0;
171                                 pDM_Odm->txEdcca0 = 0;
172                                 pDM_Odm->H2L_lb = TH_H2L_dmc;
173                                 pDM_Odm->L2H_lb = TH_L2H_dmc;
174                                 pDM_Odm->Adaptivity_IGI_upper = IGI;
175                         }
176                 } else {
177                         bAdjust = false;
178                         pDM_Odm->TxHangFlg = false;
179                         pDM_Odm->txEdcca1 = 0;
180                         pDM_Odm->txEdcca0 = 0;
181                         pDM_Odm->H2L_lb = TH_H2L_dmc;
182                         pDM_Odm->L2H_lb = TH_L2H_dmc;
183                         pDM_Odm->Adaptivity_IGI_upper = IGI;
184                 }
185         }
186 }
187
188 void odm_AdaptivityInit(void *pDM_VOID)
189 {
190         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
191
192         if (pDM_Odm->Carrier_Sense_enable == false)
193                 pDM_Odm->TH_L2H_ini = 0xf7; /*  -7 */
194         else
195                 pDM_Odm->TH_L2H_ini = 0xa;
196
197         pDM_Odm->AdapEn_RSSI = 20;
198         pDM_Odm->TH_EDCCA_HL_diff = 7;
199
200         pDM_Odm->IGI_Base = 0x32;
201         pDM_Odm->IGI_target = 0x1c;
202         pDM_Odm->ForceEDCCA = 0;
203         pDM_Odm->NHM_disable = false;
204         pDM_Odm->TxHangFlg = true;
205         pDM_Odm->txEdcca0 = 0;
206         pDM_Odm->txEdcca1 = 0;
207         pDM_Odm->H2L_lb = 0;
208         pDM_Odm->L2H_lb = 0;
209         pDM_Odm->Adaptivity_IGI_upper = 0;
210         odm_NHMBBInit(pDM_Odm);
211
212         PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); /*  stop counting if EDCCA is asserted */
213 }
214
215
216 void odm_Adaptivity(void *pDM_VOID, u8 IGI)
217 {
218         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
219         s8 TH_L2H_dmc, TH_H2L_dmc;
220         s8 Diff, IGI_target;
221         bool EDCCA_State = false;
222
223         if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) {
224                 return;
225         }
226
227         if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */
228                 IGI_target = pDM_Odm->IGI_Base;
229         else if (*pDM_Odm->pBandWidth == ODM_BW40M)
230                 IGI_target = pDM_Odm->IGI_Base + 2;
231         else
232                 IGI_target = pDM_Odm->IGI_Base;
233         pDM_Odm->IGI_target = (u8) IGI_target;
234
235         /* Search pwdB lower bound */
236         if (pDM_Odm->TxHangFlg == true) {
237                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208);
238                 odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target);
239         }
240
241         if ((!pDM_Odm->bLinked) || (*pDM_Odm->pChannel > 149)) { /*  Band4 doesn't need adaptivity */
242                 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, 0x7f);
243                 PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, 0x7f);
244                 return;
245         }
246
247         if (!pDM_Odm->ForceEDCCA) {
248                 if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI)
249                         EDCCA_State = true;
250                 else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5))
251                         EDCCA_State = false;
252         } else
253                 EDCCA_State = true;
254
255         if (
256                 pDM_Odm->bLinked &&
257                 pDM_Odm->Carrier_Sense_enable == false &&
258                 pDM_Odm->NHM_disable == false &&
259                 pDM_Odm->TxHangFlg == false
260         )
261                 odm_NHMBB(pDM_Odm);
262
263         if (EDCCA_State) {
264                 Diff = IGI_target-(s8)IGI;
265                 TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
266                 if (TH_L2H_dmc > 10)
267                         TH_L2H_dmc = 10;
268
269                 TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
270
271                 /* replace lower bound to prevent EDCCA always equal  */
272                 if (TH_H2L_dmc < pDM_Odm->H2L_lb)
273                         TH_H2L_dmc = pDM_Odm->H2L_lb;
274                 if (TH_L2H_dmc < pDM_Odm->L2H_lb)
275                         TH_L2H_dmc = pDM_Odm->L2H_lb;
276         } else {
277                 TH_L2H_dmc = 0x7f;
278                 TH_H2L_dmc = 0x7f;
279         }
280         PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
281         PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
282 }
283
284 void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI)
285 {
286         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
287         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
288
289         if (pDM_DigTable->bStopDIG) {
290                 return;
291         }
292
293         if (pDM_DigTable->CurIGValue != CurrentIGI) {
294                 /* 1 Check initial gain by upper bound */
295                 if (!pDM_DigTable->bPSDInProgress) {
296                         if (CurrentIGI > pDM_DigTable->rx_gain_range_max) {
297                                 CurrentIGI = pDM_DigTable->rx_gain_range_max;
298                         }
299
300                 }
301
302                 /* 1 Set IGI value */
303                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
304
305                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
306
307                 pDM_DigTable->CurIGValue = CurrentIGI;
308         }
309
310 }
311
312 void odm_PauseDIG(
313         void *pDM_VOID,
314         enum ODM_Pause_DIG_TYPE PauseType,
315         u8 IGIValue
316 )
317 {
318         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
319         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
320         static bool bPaused;
321
322         if (
323                 (pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY) &&
324                 pDM_Odm->TxHangFlg == true
325         ) {
326                 return;
327         }
328
329         if (
330                 !bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_DIG) ||
331                 !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
332         ){
333                 return;
334         }
335
336         switch (PauseType) {
337         /* 1 Pause DIG */
338         case ODM_PAUSE_DIG:
339                 /* 2 Disable DIG */
340                 ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_DIG));
341
342                 /* 2 Backup IGI value */
343                 if (!bPaused) {
344                         pDM_DigTable->IGIBackup = pDM_DigTable->CurIGValue;
345                         bPaused = true;
346                 }
347
348                 /* 2 Write new IGI value */
349                 ODM_Write_DIG(pDM_Odm, IGIValue);
350                 break;
351
352         /* 1 Resume DIG */
353         case ODM_RESUME_DIG:
354                 if (bPaused) {
355                         /* 2 Write backup IGI value */
356                         ODM_Write_DIG(pDM_Odm, pDM_DigTable->IGIBackup);
357                         bPaused = false;
358
359                         /* 2 Enable DIG */
360                         ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_DIG);
361                 }
362                 break;
363
364         default:
365                 break;
366         }
367 }
368
369 bool odm_DigAbort(void *pDM_VOID)
370 {
371         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
372
373         /* SupportAbility */
374         if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) {
375                 return  true;
376         }
377
378         /* SupportAbility */
379         if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) {
380                 return  true;
381         }
382
383         /* ScanInProcess */
384         if (*(pDM_Odm->pbScanInProcess)) {
385                 return  true;
386         }
387
388         /* add by Neil Chen to avoid PSD is processing */
389         if (pDM_Odm->bDMInitialGainEnable == false) {
390                 return  true;
391         }
392
393         return  false;
394 }
395
396 void odm_DIGInit(void *pDM_VOID)
397 {
398         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
399         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
400
401         pDM_DigTable->bStopDIG = false;
402         pDM_DigTable->bPSDInProgress = false;
403         pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
404         pDM_DigTable->RssiLowThresh     = DM_DIG_THRESH_LOW;
405         pDM_DigTable->RssiHighThresh    = DM_DIG_THRESH_HIGH;
406         pDM_DigTable->FALowThresh       = DMfalseALARM_THRESH_LOW;
407         pDM_DigTable->FAHighThresh      = DMfalseALARM_THRESH_HIGH;
408         pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
409         pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
410         pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
411         pDM_DigTable->PreCCK_CCAThres = 0xFF;
412         pDM_DigTable->CurCCK_CCAThres = 0x83;
413         pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
414         pDM_DigTable->LargeFAHit = 0;
415         pDM_DigTable->Recover_cnt = 0;
416         pDM_DigTable->bMediaConnect_0 = false;
417         pDM_DigTable->bMediaConnect_1 = false;
418
419         /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
420         pDM_Odm->bDMInitialGainEnable = true;
421
422         pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
423         pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
424
425         /* To Initi BT30 IGI */
426         pDM_DigTable->BT30_CurIGI = 0x32;
427
428         pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
429         pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
430
431 }
432
433
434 void odm_DIG(void *pDM_VOID)
435 {
436         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
437
438         /*  Common parameters */
439         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
440         struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
441         bool FirstConnect, FirstDisConnect;
442         u8 DIG_MaxOfMin, DIG_Dynamic_MIN;
443         u8 dm_dig_max, dm_dig_min;
444         u8 CurrentIGI = pDM_DigTable->CurIGValue;
445         u8 offset;
446         u32 dm_FA_thres[3];
447         u8 Adap_IGI_Upper = 0;
448         u32 TxTp = 0, RxTp = 0;
449         bool bDFSBand = false;
450         bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false;
451
452         if (odm_DigAbort(pDM_Odm))
453                 return;
454
455         if (pDM_Odm->adaptivity_flag == true)
456                 Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper;
457
458
459         /* 1 Update status */
460         DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
461         FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false);
462         FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true);
463
464         /* 1 Boundary Decision */
465         /* 2 For WIN\CE */
466         dm_dig_max = 0x5A;
467         dm_dig_min = DM_DIG_MIN_NIC;
468         DIG_MaxOfMin = DM_DIG_MAX_AP;
469
470         /* 1 Adjust boundary by RSSI */
471         if (pDM_Odm->bLinked && bPerformance) {
472                 /* 2 Modify DIG upper bound */
473                 /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */
474                 if (pDM_Odm->bBtLimitedDig == 1) {
475                         offset = 10;
476                 } else
477                         offset = 15;
478
479                 if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max)
480                         pDM_DigTable->rx_gain_range_max = dm_dig_max;
481                 else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min)
482                         pDM_DigTable->rx_gain_range_max = dm_dig_min;
483                 else
484                         pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset;
485
486                 /* 2 Modify DIG lower bound */
487                 /* if (pDM_Odm->bOneEntryOnly) */
488                 {
489                         if (pDM_Odm->RSSI_Min < dm_dig_min)
490                                 DIG_Dynamic_MIN = dm_dig_min;
491                         else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
492                                 DIG_Dynamic_MIN = DIG_MaxOfMin;
493                         else
494                                 DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
495                 }
496         } else {
497                 pDM_DigTable->rx_gain_range_max = dm_dig_max;
498                 DIG_Dynamic_MIN = dm_dig_min;
499         }
500
501         /* 1 Force Lower Bound for AntDiv */
502         if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) {
503                 if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
504                         if (
505                                 pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV ||
506                                 pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV ||
507                                 pDM_Odm->AntDivType == S0S1_SW_ANTDIV
508                         ) {
509                                 if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin)
510                                         DIG_Dynamic_MIN = DIG_MaxOfMin;
511                                 else
512                                         DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max;
513                         }
514                 }
515         }
516
517         /* 1 Modify DIG lower bound, deal with abnormal case */
518         /* 2 Abnormal false alarm case */
519         if (FirstDisConnect) {
520                 pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN;
521                 pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN;
522         } else
523                 pDM_DigTable->rx_gain_range_min =
524                         odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI);
525
526         if (pDM_Odm->bLinked && !FirstConnect) {
527                 if (
528                         (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
529                         pDM_Odm->bsta_state
530                 ) {
531                         pDM_DigTable->rx_gain_range_min = dm_dig_min;
532                 }
533         }
534
535         /* 2 Abnormal lower bound case */
536         if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) {
537                 pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
538         }
539
540
541         /* 1 False alarm threshold decision */
542         odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres);
543
544         /* 1 Adjust initial gain by false alarm */
545         if (pDM_Odm->bLinked && bPerformance) {
546
547                 if (bFirstTpTarget || FirstConnect) {
548                         pDM_DigTable->LargeFAHit = 0;
549
550                         if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) {
551                                 if (CurrentIGI < pDM_Odm->RSSI_Min)
552                                         CurrentIGI = pDM_Odm->RSSI_Min;
553                         } else {
554                                 if (CurrentIGI < DIG_MaxOfMin)
555                                         CurrentIGI = DIG_MaxOfMin;
556                         }
557
558                 } else {
559                         if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
560                                 CurrentIGI = CurrentIGI + 4;
561                         else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
562                                 CurrentIGI = CurrentIGI + 2;
563                         else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
564                                 CurrentIGI = CurrentIGI - 2;
565
566                         if (
567                                 (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
568                                 (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) &&
569                                 (pDM_Odm->bsta_state)
570                         ) {
571                                 CurrentIGI = pDM_DigTable->rx_gain_range_min;
572                         }
573                 }
574         } else {
575
576                 if (FirstDisConnect || bFirstCoverage) {
577                         CurrentIGI = dm_dig_min;
578                 } else {
579                         if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
580                                 CurrentIGI = CurrentIGI + 4;
581                         else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
582                                 CurrentIGI = CurrentIGI + 2;
583                         else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
584                                 CurrentIGI = CurrentIGI - 2;
585                 }
586         }
587
588         /* 1 Check initial gain by upper/lower bound */
589         if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
590                 CurrentIGI = pDM_DigTable->rx_gain_range_min;
591
592         if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
593                 CurrentIGI = pDM_DigTable->rx_gain_range_max;
594
595         /* 1 Force upper bound and lower bound for adaptivity */
596         if (
597                 pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY &&
598                 pDM_Odm->adaptivity_flag == true
599         ) {
600                 if (CurrentIGI > Adap_IGI_Upper)
601                         CurrentIGI = Adap_IGI_Upper;
602
603                 if (pDM_Odm->IGI_LowerBound != 0) {
604                         if (CurrentIGI < pDM_Odm->IGI_LowerBound)
605                                 CurrentIGI = pDM_Odm->IGI_LowerBound;
606                 }
607         }
608
609
610         /* 1 Update status */
611         if (pDM_Odm->bBtHsOperation) {
612                 if (pDM_Odm->bLinked) {
613                         if (pDM_DigTable->BT30_CurIGI > (CurrentIGI))
614                                 ODM_Write_DIG(pDM_Odm, CurrentIGI);
615                         else
616                                 ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);
617
618                         pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
619                         pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
620                 } else {
621                         if (pDM_Odm->bLinkInProcess)
622                                 ODM_Write_DIG(pDM_Odm, 0x1c);
623                         else if (pDM_Odm->bBtConnectProcess)
624                                 ODM_Write_DIG(pDM_Odm, 0x28);
625                         else
626                                 ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
627                 }
628         } else { /*  BT is not using */
629                 ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
630                 pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
631                 pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
632         }
633 }
634
635 void odm_DIGbyRSSI_LPS(void *pDM_VOID)
636 {
637         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
638         struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
639
640         u8 RSSI_Lower = DM_DIG_MIN_NIC;   /* 0x1E or 0x1C */
641         u8 CurrentIGI = pDM_Odm->RSSI_Min;
642
643         CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
644
645         /*  Using FW PS mode to make IGI */
646         /* Adjust by  FA in LPS MODE */
647         if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
648                 CurrentIGI = CurrentIGI+4;
649         else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
650                 CurrentIGI = CurrentIGI+2;
651         else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
652                 CurrentIGI = CurrentIGI-2;
653
654
655         /* Lower bound checking */
656
657         /* RSSI Lower bound check */
658         if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC)
659                 RSSI_Lower = pDM_Odm->RSSI_Min-10;
660         else
661                 RSSI_Lower = DM_DIG_MIN_NIC;
662
663         /* Upper and Lower Bound checking */
664         if (CurrentIGI > DM_DIG_MAX_NIC)
665                 CurrentIGI = DM_DIG_MAX_NIC;
666         else if (CurrentIGI < RSSI_Lower)
667                 CurrentIGI = RSSI_Lower;
668
669         ODM_Write_DIG(pDM_Odm, CurrentIGI);
670         /* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
671 }
672
673 /* 3 ============================================================ */
674 /* 3 FASLE ALARM CHECK */
675 /* 3 ============================================================ */
676
677 void odm_FalseAlarmCounterStatistics(void *pDM_VOID)
678 {
679         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
680         struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
681         u32 ret_value;
682
683         if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
684                 return;
685
686         /* hold ofdm counter */
687         /* hold page C counter */
688         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1);
689         /* hold page D counter */
690         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1);
691
692         ret_value = PHY_QueryBBReg(
693                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord
694         );
695         FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
696         FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
697
698         ret_value = PHY_QueryBBReg(
699                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord
700         );
701         FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
702         FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
703
704         ret_value = PHY_QueryBBReg(
705                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord
706         );
707         FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
708         FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
709
710         ret_value = PHY_QueryBBReg(
711                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord
712         );
713         FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
714
715         FalseAlmCnt->Cnt_Ofdm_fail =
716                 FalseAlmCnt->Cnt_Parity_Fail +
717                 FalseAlmCnt->Cnt_Rate_Illegal +
718                 FalseAlmCnt->Cnt_Crc8_fail +
719                 FalseAlmCnt->Cnt_Mcs_fail +
720                 FalseAlmCnt->Cnt_Fast_Fsync +
721                 FalseAlmCnt->Cnt_SB_Search_fail;
722
723         {
724                 /* hold cck counter */
725                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
726                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
727
728                 ret_value = PHY_QueryBBReg(
729                         pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0
730                 );
731                 FalseAlmCnt->Cnt_Cck_fail = ret_value;
732
733                 ret_value = PHY_QueryBBReg(
734                         pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3
735                 );
736                 FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8;
737
738                 ret_value = PHY_QueryBBReg(
739                         pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord
740                 );
741                 FalseAlmCnt->Cnt_CCK_CCA =
742                         ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
743         }
744
745         FalseAlmCnt->Cnt_all = (
746                 FalseAlmCnt->Cnt_Fast_Fsync +
747                 FalseAlmCnt->Cnt_SB_Search_fail +
748                 FalseAlmCnt->Cnt_Parity_Fail +
749                 FalseAlmCnt->Cnt_Rate_Illegal +
750                 FalseAlmCnt->Cnt_Crc8_fail +
751                 FalseAlmCnt->Cnt_Mcs_fail +
752                 FalseAlmCnt->Cnt_Cck_fail
753         );
754
755         FalseAlmCnt->Cnt_CCA_all =
756                 FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
757 }
758
759
760 void odm_FAThresholdCheck(
761         void *pDM_VOID,
762         bool bDFSBand,
763         bool bPerformance,
764         u32 RxTp,
765         u32 TxTp,
766         u32 *dm_FA_thres
767 )
768 {
769         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
770
771         if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) {
772                 /*  For NIC */
773                 dm_FA_thres[0] = DM_DIG_FA_TH0;
774                 dm_FA_thres[1] = DM_DIG_FA_TH1;
775                 dm_FA_thres[2] = DM_DIG_FA_TH2;
776         } else {
777                 dm_FA_thres[0] = 2000;
778                 dm_FA_thres[1] = 4000;
779                 dm_FA_thres[2] = 5000;
780         }
781 }
782
783 u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI)
784 {
785         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
786         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
787         struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
788         u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min;
789
790         if (pFalseAlmCnt->Cnt_all > 10000) {
791                 if (pDM_DigTable->LargeFAHit != 3)
792                         pDM_DigTable->LargeFAHit++;
793
794                 /* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */
795                 if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
796                         pDM_DigTable->ForbiddenIGI = CurrentIGI;
797                         /* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */
798                         pDM_DigTable->LargeFAHit = 1;
799                 }
800
801                 if (pDM_DigTable->LargeFAHit >= 3) {
802                         if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max)
803                                 rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
804                         else
805                                 rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
806                         pDM_DigTable->Recover_cnt = 1800;
807                 }
808         } else {
809                 if (pDM_DigTable->Recover_cnt != 0) {
810                         pDM_DigTable->Recover_cnt--;
811                 } else {
812                         if (pDM_DigTable->LargeFAHit < 3) {
813                                 if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
814                                         pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
815                                         rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
816                                 } else {
817                                         pDM_DigTable->ForbiddenIGI -= 2;
818                                         rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
819                                 }
820                         } else
821                                 pDM_DigTable->LargeFAHit = 0;
822                 }
823         }
824
825         return rx_gain_range_min;
826
827 }
828
829 /* 3 ============================================================ */
830 /* 3 CCK Packet Detect Threshold */
831 /* 3 ============================================================ */
832
833 void odm_CCKPacketDetectionThresh(void *pDM_VOID)
834 {
835         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
836         struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
837         u8 CurCCK_CCAThres;
838
839
840         if (
841                 !(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) ||
842                 !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)
843         ) {
844                 return;
845         }
846
847         if (pDM_Odm->ExtLNA)
848                 return;
849
850         if (pDM_Odm->bLinked) {
851                 if (pDM_Odm->RSSI_Min > 25)
852                         CurCCK_CCAThres = 0xcd;
853                 else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10))
854                         CurCCK_CCAThres = 0x83;
855                 else {
856                         if (FalseAlmCnt->Cnt_Cck_fail > 1000)
857                                 CurCCK_CCAThres = 0x83;
858                         else
859                                 CurCCK_CCAThres = 0x40;
860                 }
861         } else {
862                 if (FalseAlmCnt->Cnt_Cck_fail > 1000)
863                         CurCCK_CCAThres = 0x83;
864                 else
865                         CurCCK_CCAThres = 0x40;
866         }
867
868         ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
869 }
870
871 void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres)
872 {
873         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
874         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
875
876         /* modify by Guo.Mingzhi 2012-01-03 */
877         if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
878                 rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
879
880         pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
881         pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
882 }