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