xref: /linux/drivers/staging/rtl8723bs/hal/odm_DIG.c (revision dd093fb0)
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 }
823