GNU Linux-libre 6.7.9-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 bool odm_DigAbort(void *pDM_VOID)
313 {
314         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
315
316         /* SupportAbility */
317         if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) {
318                 return  true;
319         }
320
321         /* SupportAbility */
322         if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) {
323                 return  true;
324         }
325
326         /* ScanInProcess */
327         if (*(pDM_Odm->pbScanInProcess)) {
328                 return  true;
329         }
330
331         /* add by Neil Chen to avoid PSD is processing */
332         if (pDM_Odm->bDMInitialGainEnable == false) {
333                 return  true;
334         }
335
336         return  false;
337 }
338
339 void odm_DIGInit(void *pDM_VOID)
340 {
341         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
342         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
343
344         pDM_DigTable->bStopDIG = false;
345         pDM_DigTable->bPSDInProgress = false;
346         pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
347         pDM_DigTable->RssiLowThresh     = DM_DIG_THRESH_LOW;
348         pDM_DigTable->RssiHighThresh    = DM_DIG_THRESH_HIGH;
349         pDM_DigTable->FALowThresh       = DMfalseALARM_THRESH_LOW;
350         pDM_DigTable->FAHighThresh      = DMfalseALARM_THRESH_HIGH;
351         pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
352         pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
353         pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
354         pDM_DigTable->PreCCK_CCAThres = 0xFF;
355         pDM_DigTable->CurCCK_CCAThres = 0x83;
356         pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
357         pDM_DigTable->LargeFAHit = 0;
358         pDM_DigTable->Recover_cnt = 0;
359         pDM_DigTable->bMediaConnect_0 = false;
360         pDM_DigTable->bMediaConnect_1 = false;
361
362         /* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
363         pDM_Odm->bDMInitialGainEnable = true;
364
365         pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
366         pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
367
368         /* To Initi BT30 IGI */
369         pDM_DigTable->BT30_CurIGI = 0x32;
370
371         pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
372         pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
373
374 }
375
376
377 void odm_DIG(void *pDM_VOID)
378 {
379         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
380
381         /*  Common parameters */
382         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
383         struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
384         bool FirstConnect, FirstDisConnect;
385         u8 DIG_MaxOfMin, DIG_Dynamic_MIN;
386         u8 dm_dig_max, dm_dig_min;
387         u8 CurrentIGI = pDM_DigTable->CurIGValue;
388         u8 offset;
389         u32 dm_FA_thres[3];
390         u8 Adap_IGI_Upper = 0;
391         u32 TxTp = 0, RxTp = 0;
392         bool bDFSBand = false;
393         bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false;
394
395         if (odm_DigAbort(pDM_Odm))
396                 return;
397
398         if (pDM_Odm->adaptivity_flag == true)
399                 Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper;
400
401
402         /* 1 Update status */
403         DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
404         FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false);
405         FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true);
406
407         /* 1 Boundary Decision */
408         /* 2 For WIN\CE */
409         dm_dig_max = 0x5A;
410         dm_dig_min = DM_DIG_MIN_NIC;
411         DIG_MaxOfMin = DM_DIG_MAX_AP;
412
413         /* 1 Adjust boundary by RSSI */
414         if (pDM_Odm->bLinked && bPerformance) {
415                 /* 2 Modify DIG upper bound */
416                 /* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */
417                 if (pDM_Odm->bBtLimitedDig == 1) {
418                         offset = 10;
419                 } else
420                         offset = 15;
421
422                 if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max)
423                         pDM_DigTable->rx_gain_range_max = dm_dig_max;
424                 else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min)
425                         pDM_DigTable->rx_gain_range_max = dm_dig_min;
426                 else
427                         pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset;
428
429                 /* 2 Modify DIG lower bound */
430                 /* if (pDM_Odm->bOneEntryOnly) */
431                 {
432                         if (pDM_Odm->RSSI_Min < dm_dig_min)
433                                 DIG_Dynamic_MIN = dm_dig_min;
434                         else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
435                                 DIG_Dynamic_MIN = DIG_MaxOfMin;
436                         else
437                                 DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
438                 }
439         } else {
440                 pDM_DigTable->rx_gain_range_max = dm_dig_max;
441                 DIG_Dynamic_MIN = dm_dig_min;
442         }
443
444         /* 1 Force Lower Bound for AntDiv */
445         if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) {
446                 if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
447                         if (
448                                 pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV ||
449                                 pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV ||
450                                 pDM_Odm->AntDivType == S0S1_SW_ANTDIV
451                         ) {
452                                 if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin)
453                                         DIG_Dynamic_MIN = DIG_MaxOfMin;
454                                 else
455                                         DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max;
456                         }
457                 }
458         }
459
460         /* 1 Modify DIG lower bound, deal with abnormal case */
461         /* 2 Abnormal false alarm case */
462         if (FirstDisConnect) {
463                 pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN;
464                 pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN;
465         } else
466                 pDM_DigTable->rx_gain_range_min =
467                         odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI);
468
469         if (pDM_Odm->bLinked && !FirstConnect) {
470                 if (
471                         (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
472                         pDM_Odm->bsta_state
473                 ) {
474                         pDM_DigTable->rx_gain_range_min = dm_dig_min;
475                 }
476         }
477
478         /* 2 Abnormal lower bound case */
479         if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) {
480                 pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
481         }
482
483
484         /* 1 False alarm threshold decision */
485         odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres);
486
487         /* 1 Adjust initial gain by false alarm */
488         if (pDM_Odm->bLinked && bPerformance) {
489
490                 if (bFirstTpTarget || FirstConnect) {
491                         pDM_DigTable->LargeFAHit = 0;
492
493                         if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) {
494                                 if (CurrentIGI < pDM_Odm->RSSI_Min)
495                                         CurrentIGI = pDM_Odm->RSSI_Min;
496                         } else {
497                                 if (CurrentIGI < DIG_MaxOfMin)
498                                         CurrentIGI = DIG_MaxOfMin;
499                         }
500
501                 } else {
502                         if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
503                                 CurrentIGI = CurrentIGI + 4;
504                         else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
505                                 CurrentIGI = CurrentIGI + 2;
506                         else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
507                                 CurrentIGI = CurrentIGI - 2;
508
509                         if (
510                                 (pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
511                                 (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) &&
512                                 (pDM_Odm->bsta_state)
513                         ) {
514                                 CurrentIGI = pDM_DigTable->rx_gain_range_min;
515                         }
516                 }
517         } else {
518
519                 if (FirstDisConnect || bFirstCoverage) {
520                         CurrentIGI = dm_dig_min;
521                 } else {
522                         if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
523                                 CurrentIGI = CurrentIGI + 4;
524                         else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
525                                 CurrentIGI = CurrentIGI + 2;
526                         else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
527                                 CurrentIGI = CurrentIGI - 2;
528                 }
529         }
530
531         /* 1 Check initial gain by upper/lower bound */
532         if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
533                 CurrentIGI = pDM_DigTable->rx_gain_range_min;
534
535         if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
536                 CurrentIGI = pDM_DigTable->rx_gain_range_max;
537
538         /* 1 Force upper bound and lower bound for adaptivity */
539         if (
540                 pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY &&
541                 pDM_Odm->adaptivity_flag == true
542         ) {
543                 if (CurrentIGI > Adap_IGI_Upper)
544                         CurrentIGI = Adap_IGI_Upper;
545
546                 if (pDM_Odm->IGI_LowerBound != 0) {
547                         if (CurrentIGI < pDM_Odm->IGI_LowerBound)
548                                 CurrentIGI = pDM_Odm->IGI_LowerBound;
549                 }
550         }
551
552
553         /* 1 Update status */
554         if (pDM_Odm->bBtHsOperation) {
555                 if (pDM_Odm->bLinked) {
556                         if (pDM_DigTable->BT30_CurIGI > (CurrentIGI))
557                                 ODM_Write_DIG(pDM_Odm, CurrentIGI);
558                         else
559                                 ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);
560
561                         pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
562                         pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
563                 } else {
564                         if (pDM_Odm->bLinkInProcess)
565                                 ODM_Write_DIG(pDM_Odm, 0x1c);
566                         else if (pDM_Odm->bBtConnectProcess)
567                                 ODM_Write_DIG(pDM_Odm, 0x28);
568                         else
569                                 ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
570                 }
571         } else { /*  BT is not using */
572                 ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
573                 pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
574                 pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
575         }
576 }
577
578 void odm_DIGbyRSSI_LPS(void *pDM_VOID)
579 {
580         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
581         struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
582
583         u8 RSSI_Lower = DM_DIG_MIN_NIC;   /* 0x1E or 0x1C */
584         u8 CurrentIGI = pDM_Odm->RSSI_Min;
585
586         CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
587
588         /*  Using FW PS mode to make IGI */
589         /* Adjust by  FA in LPS MODE */
590         if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
591                 CurrentIGI = CurrentIGI+4;
592         else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
593                 CurrentIGI = CurrentIGI+2;
594         else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
595                 CurrentIGI = CurrentIGI-2;
596
597
598         /* Lower bound checking */
599
600         /* RSSI Lower bound check */
601         RSSI_Lower = max(pDM_Odm->RSSI_Min - 10, DM_DIG_MIN_NIC);
602
603         /* Upper and Lower Bound checking */
604         if (CurrentIGI > DM_DIG_MAX_NIC)
605                 CurrentIGI = DM_DIG_MAX_NIC;
606         else if (CurrentIGI < RSSI_Lower)
607                 CurrentIGI = RSSI_Lower;
608
609         ODM_Write_DIG(pDM_Odm, CurrentIGI);
610         /* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
611 }
612
613 /* 3 ============================================================ */
614 /* 3 FASLE ALARM CHECK */
615 /* 3 ============================================================ */
616
617 void odm_FalseAlarmCounterStatistics(void *pDM_VOID)
618 {
619         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
620         struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
621         u32 ret_value;
622
623         if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
624                 return;
625
626         /* hold ofdm counter */
627         /* hold page C counter */
628         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1);
629         /* hold page D counter */
630         PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1);
631
632         ret_value = PHY_QueryBBReg(
633                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord
634         );
635         FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
636         FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
637
638         ret_value = PHY_QueryBBReg(
639                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord
640         );
641         FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
642         FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
643
644         ret_value = PHY_QueryBBReg(
645                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord
646         );
647         FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
648         FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
649
650         ret_value = PHY_QueryBBReg(
651                 pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord
652         );
653         FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
654
655         FalseAlmCnt->Cnt_Ofdm_fail =
656                 FalseAlmCnt->Cnt_Parity_Fail +
657                 FalseAlmCnt->Cnt_Rate_Illegal +
658                 FalseAlmCnt->Cnt_Crc8_fail +
659                 FalseAlmCnt->Cnt_Mcs_fail +
660                 FalseAlmCnt->Cnt_Fast_Fsync +
661                 FalseAlmCnt->Cnt_SB_Search_fail;
662
663         {
664                 /* hold cck counter */
665                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
666                 PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
667
668                 ret_value = PHY_QueryBBReg(
669                         pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0
670                 );
671                 FalseAlmCnt->Cnt_Cck_fail = ret_value;
672
673                 ret_value = PHY_QueryBBReg(
674                         pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3
675                 );
676                 FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8;
677
678                 ret_value = PHY_QueryBBReg(
679                         pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord
680                 );
681                 FalseAlmCnt->Cnt_CCK_CCA =
682                         ((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
683         }
684
685         FalseAlmCnt->Cnt_all = (
686                 FalseAlmCnt->Cnt_Fast_Fsync +
687                 FalseAlmCnt->Cnt_SB_Search_fail +
688                 FalseAlmCnt->Cnt_Parity_Fail +
689                 FalseAlmCnt->Cnt_Rate_Illegal +
690                 FalseAlmCnt->Cnt_Crc8_fail +
691                 FalseAlmCnt->Cnt_Mcs_fail +
692                 FalseAlmCnt->Cnt_Cck_fail
693         );
694
695         FalseAlmCnt->Cnt_CCA_all =
696                 FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
697 }
698
699
700 void odm_FAThresholdCheck(
701         void *pDM_VOID,
702         bool bDFSBand,
703         bool bPerformance,
704         u32 RxTp,
705         u32 TxTp,
706         u32 *dm_FA_thres
707 )
708 {
709         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
710
711         if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) {
712                 /*  For NIC */
713                 dm_FA_thres[0] = DM_DIG_FA_TH0;
714                 dm_FA_thres[1] = DM_DIG_FA_TH1;
715                 dm_FA_thres[2] = DM_DIG_FA_TH2;
716         } else {
717                 dm_FA_thres[0] = 2000;
718                 dm_FA_thres[1] = 4000;
719                 dm_FA_thres[2] = 5000;
720         }
721 }
722
723 u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI)
724 {
725         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
726         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
727         struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
728         u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min;
729
730         if (pFalseAlmCnt->Cnt_all > 10000) {
731                 if (pDM_DigTable->LargeFAHit != 3)
732                         pDM_DigTable->LargeFAHit++;
733
734                 /* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */
735                 if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
736                         pDM_DigTable->ForbiddenIGI = CurrentIGI;
737                         /* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */
738                         pDM_DigTable->LargeFAHit = 1;
739                 }
740
741                 if (pDM_DigTable->LargeFAHit >= 3) {
742                         if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max)
743                                 rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
744                         else
745                                 rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
746                         pDM_DigTable->Recover_cnt = 1800;
747                 }
748         } else {
749                 if (pDM_DigTable->Recover_cnt != 0) {
750                         pDM_DigTable->Recover_cnt--;
751                 } else {
752                         if (pDM_DigTable->LargeFAHit < 3) {
753                                 if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
754                                         pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
755                                         rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
756                                 } else {
757                                         pDM_DigTable->ForbiddenIGI -= 2;
758                                         rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
759                                 }
760                         } else
761                                 pDM_DigTable->LargeFAHit = 0;
762                 }
763         }
764
765         return rx_gain_range_min;
766
767 }
768
769 /* 3 ============================================================ */
770 /* 3 CCK Packet Detect Threshold */
771 /* 3 ============================================================ */
772
773 void odm_CCKPacketDetectionThresh(void *pDM_VOID)
774 {
775         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
776         struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
777         u8 CurCCK_CCAThres;
778
779
780         if (
781                 !(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) ||
782                 !(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)
783         ) {
784                 return;
785         }
786
787         if (pDM_Odm->ExtLNA)
788                 return;
789
790         if (pDM_Odm->bLinked) {
791                 if (pDM_Odm->RSSI_Min > 25)
792                         CurCCK_CCAThres = 0xcd;
793                 else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10))
794                         CurCCK_CCAThres = 0x83;
795                 else {
796                         if (FalseAlmCnt->Cnt_Cck_fail > 1000)
797                                 CurCCK_CCAThres = 0x83;
798                         else
799                                 CurCCK_CCAThres = 0x40;
800                 }
801         } else {
802                 if (FalseAlmCnt->Cnt_Cck_fail > 1000)
803                         CurCCK_CCAThres = 0x83;
804                 else
805                         CurCCK_CCAThres = 0x40;
806         }
807
808         ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
809 }
810
811 void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres)
812 {
813         struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
814         struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
815
816         /* modify by Guo.Mingzhi 2012-01-03 */
817         if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
818                 rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
819
820         pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
821         pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
822 }