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