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