158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0
2554c0a3aSHans de Goede /******************************************************************************
3554c0a3aSHans de Goede  *
4554c0a3aSHans de Goede  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5554c0a3aSHans de Goede  *
6554c0a3aSHans de Goede  ******************************************************************************/
7554c0a3aSHans de Goede 
8554c0a3aSHans de Goede #include "odm_precomp.h"
9554c0a3aSHans de Goede 
10554c0a3aSHans de Goede void odm_NHMCounterStatisticsInit(void *pDM_VOID)
11554c0a3aSHans de Goede {
12f8010da6SMarco Cesati 	struct dm_odm_t	*pDM_Odm = (struct dm_odm_t *)pDM_VOID;
13554c0a3aSHans de Goede 
14554c0a3aSHans de Goede 	/* PHY parameters initialize for n series */
15554c0a3aSHans de Goede 	rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x2710);	/* 0x894[31:16]= 0x2710	Time duration for NHM unit: 4us, 0x2710 =40ms */
16554c0a3aSHans de Goede 	/* rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TIMER_11N+2, 0x4e20);	0x894[31:16]= 0x4e20	Time duration for NHM unit: 4us, 0x4e20 =80ms */
17554c0a3aSHans de Goede 	rtw_write16(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N+2, 0xffff);	/* 0x890[31:16]= 0xffff	th_9, th_10 */
18554c0a3aSHans de Goede 	/* rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff5c);	0x898 = 0xffffff5c		th_3, th_2, th_1, th_0 */
19554c0a3aSHans de Goede 	rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH3_TO_TH0_11N, 0xffffff52);	/* 0x898 = 0xffffff52		th_3, th_2, th_1, th_0 */
20554c0a3aSHans de Goede 	rtw_write32(pDM_Odm->Adapter, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffffff);	/* 0x89c = 0xffffffff		th_7, th_6, th_5, th_4 */
21554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_FPGA0_IQK_11N, bMaskByte0, 0xff);		/* 0xe28[7:0]= 0xff		th_8 */
22554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT10|BIT9|BIT8, 0x7);	/* 0x890[9:8]=3			enable CCX */
23554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTC_11N, BIT7, 0x1);		/* 0xc0c[7]= 1			max power among all RX ants */
24554c0a3aSHans de Goede }
25554c0a3aSHans de Goede 
26554c0a3aSHans de Goede void odm_NHMCounterStatistics(void *pDM_VOID)
27554c0a3aSHans de Goede {
28f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
29554c0a3aSHans de Goede 
30554c0a3aSHans de Goede 	/*  Get NHM report */
31554c0a3aSHans de Goede 	odm_GetNHMCounterStatistics(pDM_Odm);
32554c0a3aSHans de Goede 
33554c0a3aSHans de Goede 	/*  Reset NHM counter */
34554c0a3aSHans de Goede 	odm_NHMCounterStatisticsReset(pDM_Odm);
35554c0a3aSHans de Goede }
36554c0a3aSHans de Goede 
37554c0a3aSHans de Goede void odm_GetNHMCounterStatistics(void *pDM_VOID)
38554c0a3aSHans de Goede {
39f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
40554c0a3aSHans de Goede 	u32 value32 = 0;
41554c0a3aSHans de Goede 
42554c0a3aSHans de Goede 	value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_NHM_CNT_11N, bMaskDWord);
43554c0a3aSHans de Goede 
44554c0a3aSHans de Goede 	pDM_Odm->NHM_cnt_0 = (u8)(value32 & bMaskByte0);
45554c0a3aSHans de Goede }
46554c0a3aSHans de Goede 
47554c0a3aSHans de Goede void odm_NHMCounterStatisticsReset(void *pDM_VOID)
48554c0a3aSHans de Goede {
49f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
50554c0a3aSHans de Goede 
51554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 0);
52554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_NHM_TH9_TH10_11N, BIT1, 1);
53554c0a3aSHans de Goede }
54554c0a3aSHans de Goede 
55554c0a3aSHans de Goede void odm_NHMBBInit(void *pDM_VOID)
56554c0a3aSHans de Goede {
57f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
58554c0a3aSHans de Goede 
59554c0a3aSHans de Goede 	pDM_Odm->adaptivity_flag = 0;
60554c0a3aSHans de Goede 	pDM_Odm->tolerance_cnt = 3;
61554c0a3aSHans de Goede 	pDM_Odm->NHMLastTxOkcnt = 0;
62554c0a3aSHans de Goede 	pDM_Odm->NHMLastRxOkcnt = 0;
63554c0a3aSHans de Goede 	pDM_Odm->NHMCurTxOkcnt = 0;
64554c0a3aSHans de Goede 	pDM_Odm->NHMCurRxOkcnt = 0;
65554c0a3aSHans de Goede }
66554c0a3aSHans de Goede 
67554c0a3aSHans de Goede /*  */
68554c0a3aSHans de Goede void odm_NHMBB(void *pDM_VOID)
69554c0a3aSHans de Goede {
70f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
71554c0a3aSHans de Goede 	/* u8 test_status; */
72db07a1caSMarco Cesati 	/* struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt; */
73554c0a3aSHans de Goede 
74554c0a3aSHans de Goede 	pDM_Odm->NHMCurTxOkcnt =
75554c0a3aSHans de Goede 		*(pDM_Odm->pNumTxBytesUnicast)-pDM_Odm->NHMLastTxOkcnt;
76554c0a3aSHans de Goede 	pDM_Odm->NHMCurRxOkcnt =
77554c0a3aSHans de Goede 		*(pDM_Odm->pNumRxBytesUnicast)-pDM_Odm->NHMLastRxOkcnt;
78554c0a3aSHans de Goede 	pDM_Odm->NHMLastTxOkcnt =
79554c0a3aSHans de Goede 		*(pDM_Odm->pNumTxBytesUnicast);
80554c0a3aSHans de Goede 	pDM_Odm->NHMLastRxOkcnt =
81554c0a3aSHans de Goede 		*(pDM_Odm->pNumRxBytesUnicast);
82554c0a3aSHans de Goede 
83554c0a3aSHans de Goede 
84554c0a3aSHans de Goede 	if ((pDM_Odm->NHMCurTxOkcnt) + 1 > (u64)(pDM_Odm->NHMCurRxOkcnt<<2) + 1) { /* Tx > 4*Rx possible for adaptivity test */
85554c0a3aSHans de Goede 		if (pDM_Odm->NHM_cnt_0 >= 190 || pDM_Odm->adaptivity_flag == true) {
86554c0a3aSHans de Goede 			/* Enable EDCCA since it is possible running Adaptivity testing */
87554c0a3aSHans de Goede 			/* test_status = 1; */
88554c0a3aSHans de Goede 			pDM_Odm->adaptivity_flag = true;
89554c0a3aSHans de Goede 			pDM_Odm->tolerance_cnt = 0;
90554c0a3aSHans de Goede 		} else {
91554c0a3aSHans de Goede 			if (pDM_Odm->tolerance_cnt < 3)
92554c0a3aSHans de Goede 				pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
93554c0a3aSHans de Goede 			else
94554c0a3aSHans de Goede 				pDM_Odm->tolerance_cnt = 4;
95554c0a3aSHans de Goede 			/* test_status = 5; */
96554c0a3aSHans de Goede 			if (pDM_Odm->tolerance_cnt > 3) {
97554c0a3aSHans de Goede 				/* test_status = 3; */
98554c0a3aSHans de Goede 				pDM_Odm->adaptivity_flag = false;
99554c0a3aSHans de Goede 			}
100554c0a3aSHans de Goede 		}
101554c0a3aSHans de Goede 	} else { /*  TX<RX */
102554c0a3aSHans de Goede 		if (pDM_Odm->adaptivity_flag == true && pDM_Odm->NHM_cnt_0 <= 200) {
103554c0a3aSHans de Goede 			/* test_status = 2; */
104554c0a3aSHans de Goede 			pDM_Odm->tolerance_cnt = 0;
105554c0a3aSHans de Goede 		} else {
106554c0a3aSHans de Goede 			if (pDM_Odm->tolerance_cnt < 3)
107554c0a3aSHans de Goede 				pDM_Odm->tolerance_cnt = pDM_Odm->tolerance_cnt + 1;
108554c0a3aSHans de Goede 			else
109554c0a3aSHans de Goede 				pDM_Odm->tolerance_cnt = 4;
110554c0a3aSHans de Goede 			/* test_status = 5; */
111554c0a3aSHans de Goede 			if (pDM_Odm->tolerance_cnt > 3) {
112554c0a3aSHans de Goede 				/* test_status = 4; */
113554c0a3aSHans de Goede 				pDM_Odm->adaptivity_flag = false;
114554c0a3aSHans de Goede 			}
115554c0a3aSHans de Goede 		}
116554c0a3aSHans de Goede 	}
117554c0a3aSHans de Goede }
118554c0a3aSHans de Goede 
119554c0a3aSHans de Goede void odm_SearchPwdBLowerBound(void *pDM_VOID, u8 IGI_target)
120554c0a3aSHans de Goede {
121f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
122554c0a3aSHans de Goede 	u32 value32 = 0;
123554c0a3aSHans de Goede 	u8 cnt, IGI;
124554c0a3aSHans de Goede 	bool bAdjust = true;
125554c0a3aSHans de Goede 	s8 TH_L2H_dmc, TH_H2L_dmc;
126554c0a3aSHans de Goede 	s8 Diff;
127554c0a3aSHans de Goede 
128554c0a3aSHans de Goede 	IGI = 0x50; /*  find H2L, L2H lower bound */
129554c0a3aSHans de Goede 	ODM_Write_DIG(pDM_Odm, IGI);
130554c0a3aSHans de Goede 
131554c0a3aSHans de Goede 
132554c0a3aSHans de Goede 	Diff = IGI_target-(s8)IGI;
133554c0a3aSHans de Goede 	TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
134554c0a3aSHans de Goede 	if (TH_L2H_dmc > 10)
135554c0a3aSHans de Goede 		TH_L2H_dmc = 10;
136554c0a3aSHans de Goede 	TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
137554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
138554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
139554c0a3aSHans de Goede 
140554c0a3aSHans de Goede 	mdelay(5);
141554c0a3aSHans de Goede 
142554c0a3aSHans de Goede 	while (bAdjust) {
143554c0a3aSHans de Goede 		for (cnt = 0; cnt < 20; cnt++) {
144554c0a3aSHans de Goede 			value32 = PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG_RPT_11N, bMaskDWord);
145554c0a3aSHans de Goede 
146554c0a3aSHans de Goede 			if (value32 & BIT30)
147554c0a3aSHans de Goede 				pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
148554c0a3aSHans de Goede 			else if (value32 & BIT29)
149554c0a3aSHans de Goede 				pDM_Odm->txEdcca1 = pDM_Odm->txEdcca1 + 1;
150554c0a3aSHans de Goede 			else
151554c0a3aSHans de Goede 				pDM_Odm->txEdcca0 = pDM_Odm->txEdcca0 + 1;
152554c0a3aSHans de Goede 		}
153554c0a3aSHans de Goede 
154554c0a3aSHans de Goede 		if (pDM_Odm->txEdcca1 > 5) {
155554c0a3aSHans de Goede 			IGI = IGI-1;
156554c0a3aSHans de Goede 			TH_L2H_dmc = TH_L2H_dmc + 1;
157554c0a3aSHans de Goede 			if (TH_L2H_dmc > 10)
158554c0a3aSHans de Goede 				TH_L2H_dmc = 10;
159554c0a3aSHans de Goede 			TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
160554c0a3aSHans de Goede 			PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
161554c0a3aSHans de Goede 			PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
162554c0a3aSHans de Goede 
163554c0a3aSHans de Goede 			pDM_Odm->TxHangFlg = true;
164554c0a3aSHans de Goede 			pDM_Odm->txEdcca1 = 0;
165554c0a3aSHans de Goede 			pDM_Odm->txEdcca0 = 0;
166554c0a3aSHans de Goede 
167554c0a3aSHans de Goede 			if (TH_L2H_dmc == 10) {
168554c0a3aSHans de Goede 				bAdjust = false;
169554c0a3aSHans de Goede 				pDM_Odm->TxHangFlg = false;
170554c0a3aSHans de Goede 				pDM_Odm->txEdcca1 = 0;
171554c0a3aSHans de Goede 				pDM_Odm->txEdcca0 = 0;
172554c0a3aSHans de Goede 				pDM_Odm->H2L_lb = TH_H2L_dmc;
173554c0a3aSHans de Goede 				pDM_Odm->L2H_lb = TH_L2H_dmc;
174554c0a3aSHans de Goede 				pDM_Odm->Adaptivity_IGI_upper = IGI;
175554c0a3aSHans de Goede 			}
176554c0a3aSHans de Goede 		} else {
177554c0a3aSHans de Goede 			bAdjust = false;
178554c0a3aSHans de Goede 			pDM_Odm->TxHangFlg = false;
179554c0a3aSHans de Goede 			pDM_Odm->txEdcca1 = 0;
180554c0a3aSHans de Goede 			pDM_Odm->txEdcca0 = 0;
181554c0a3aSHans de Goede 			pDM_Odm->H2L_lb = TH_H2L_dmc;
182554c0a3aSHans de Goede 			pDM_Odm->L2H_lb = TH_L2H_dmc;
183554c0a3aSHans de Goede 			pDM_Odm->Adaptivity_IGI_upper = IGI;
184554c0a3aSHans de Goede 		}
185554c0a3aSHans de Goede 	}
186554c0a3aSHans de Goede }
187554c0a3aSHans de Goede 
188554c0a3aSHans de Goede void odm_AdaptivityInit(void *pDM_VOID)
189554c0a3aSHans de Goede {
190f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
191554c0a3aSHans de Goede 
192554c0a3aSHans de Goede 	if (pDM_Odm->Carrier_Sense_enable == false)
193554c0a3aSHans de Goede 		pDM_Odm->TH_L2H_ini = 0xf7; /*  -7 */
194554c0a3aSHans de Goede 	else
195554c0a3aSHans de Goede 		pDM_Odm->TH_L2H_ini = 0xa;
196554c0a3aSHans de Goede 
197554c0a3aSHans de Goede 	pDM_Odm->AdapEn_RSSI = 20;
198554c0a3aSHans de Goede 	pDM_Odm->TH_EDCCA_HL_diff = 7;
199554c0a3aSHans de Goede 
200554c0a3aSHans de Goede 	pDM_Odm->IGI_Base = 0x32;
201554c0a3aSHans de Goede 	pDM_Odm->IGI_target = 0x1c;
202554c0a3aSHans de Goede 	pDM_Odm->ForceEDCCA = 0;
203554c0a3aSHans de Goede 	pDM_Odm->NHM_disable = false;
204554c0a3aSHans de Goede 	pDM_Odm->TxHangFlg = true;
205554c0a3aSHans de Goede 	pDM_Odm->txEdcca0 = 0;
206554c0a3aSHans de Goede 	pDM_Odm->txEdcca1 = 0;
207554c0a3aSHans de Goede 	pDM_Odm->H2L_lb = 0;
208554c0a3aSHans de Goede 	pDM_Odm->L2H_lb = 0;
209554c0a3aSHans de Goede 	pDM_Odm->Adaptivity_IGI_upper = 0;
210554c0a3aSHans de Goede 	odm_NHMBBInit(pDM_Odm);
211554c0a3aSHans de Goede 
212554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, REG_RD_CTRL, BIT11, 1); /*  stop counting if EDCCA is asserted */
213554c0a3aSHans de Goede }
214554c0a3aSHans de Goede 
215554c0a3aSHans de Goede 
216554c0a3aSHans de Goede void odm_Adaptivity(void *pDM_VOID, u8 IGI)
217554c0a3aSHans de Goede {
218f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
219554c0a3aSHans de Goede 	s8 TH_L2H_dmc, TH_H2L_dmc;
220554c0a3aSHans de Goede 	s8 Diff, IGI_target;
221554c0a3aSHans de Goede 	bool EDCCA_State = false;
222554c0a3aSHans de Goede 
223554c0a3aSHans de Goede 	if (!(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY)) {
224554c0a3aSHans de Goede 		return;
225554c0a3aSHans de Goede 	}
226554c0a3aSHans de Goede 
227554c0a3aSHans de Goede 	if (*pDM_Odm->pBandWidth == ODM_BW20M) /* CHANNEL_WIDTH_20 */
228554c0a3aSHans de Goede 		IGI_target = pDM_Odm->IGI_Base;
229554c0a3aSHans de Goede 	else if (*pDM_Odm->pBandWidth == ODM_BW40M)
230554c0a3aSHans de Goede 		IGI_target = pDM_Odm->IGI_Base + 2;
231554c0a3aSHans de Goede 	else
232554c0a3aSHans de Goede 		IGI_target = pDM_Odm->IGI_Base;
233554c0a3aSHans de Goede 	pDM_Odm->IGI_target = (u8) IGI_target;
234554c0a3aSHans de Goede 
235554c0a3aSHans de Goede 	/* Search pwdB lower bound */
236554c0a3aSHans de Goede 	if (pDM_Odm->TxHangFlg == true) {
237554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_DBG_RPT_11N, bMaskDWord, 0x208);
238554c0a3aSHans de Goede 		odm_SearchPwdBLowerBound(pDM_Odm, pDM_Odm->IGI_target);
239554c0a3aSHans de Goede 	}
240554c0a3aSHans de Goede 
241554c0a3aSHans de Goede 	if ((!pDM_Odm->bLinked) || (*pDM_Odm->pChannel > 149)) { /*  Band4 doesn't need adaptivity */
242554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, 0x7f);
243554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, 0x7f);
244554c0a3aSHans de Goede 		return;
245554c0a3aSHans de Goede 	}
246554c0a3aSHans de Goede 
247554c0a3aSHans de Goede 	if (!pDM_Odm->ForceEDCCA) {
248554c0a3aSHans de Goede 		if (pDM_Odm->RSSI_Min > pDM_Odm->AdapEn_RSSI)
2497bb0dffdSsimran singhal 			EDCCA_State = true;
250554c0a3aSHans de Goede 		else if (pDM_Odm->RSSI_Min < (pDM_Odm->AdapEn_RSSI - 5))
2517bb0dffdSsimran singhal 			EDCCA_State = false;
252554c0a3aSHans de Goede 	} else
2537bb0dffdSsimran singhal 		EDCCA_State = true;
254554c0a3aSHans de Goede 
255554c0a3aSHans de Goede 	if (
256554c0a3aSHans de Goede 		pDM_Odm->bLinked &&
257554c0a3aSHans de Goede 		pDM_Odm->Carrier_Sense_enable == false &&
258554c0a3aSHans de Goede 		pDM_Odm->NHM_disable == false &&
259554c0a3aSHans de Goede 		pDM_Odm->TxHangFlg == false
260554c0a3aSHans de Goede 	)
261554c0a3aSHans de Goede 		odm_NHMBB(pDM_Odm);
262554c0a3aSHans de Goede 
2637bb0dffdSsimran singhal 	if (EDCCA_State) {
264554c0a3aSHans de Goede 		Diff = IGI_target-(s8)IGI;
265554c0a3aSHans de Goede 		TH_L2H_dmc = pDM_Odm->TH_L2H_ini + Diff;
266554c0a3aSHans de Goede 		if (TH_L2H_dmc > 10)
267554c0a3aSHans de Goede 			TH_L2H_dmc = 10;
268554c0a3aSHans de Goede 
269554c0a3aSHans de Goede 		TH_H2L_dmc = TH_L2H_dmc - pDM_Odm->TH_EDCCA_HL_diff;
270554c0a3aSHans de Goede 
271554c0a3aSHans de Goede 		/* replace lower bound to prevent EDCCA always equal  */
272554c0a3aSHans de Goede 		if (TH_H2L_dmc < pDM_Odm->H2L_lb)
273554c0a3aSHans de Goede 			TH_H2L_dmc = pDM_Odm->H2L_lb;
274554c0a3aSHans de Goede 		if (TH_L2H_dmc < pDM_Odm->L2H_lb)
275554c0a3aSHans de Goede 			TH_L2H_dmc = pDM_Odm->L2H_lb;
276554c0a3aSHans de Goede 	} else {
277554c0a3aSHans de Goede 		TH_L2H_dmc = 0x7f;
278554c0a3aSHans de Goede 		TH_H2L_dmc = 0x7f;
279554c0a3aSHans de Goede 	}
280554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte0, (u8)TH_L2H_dmc);
281554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, rOFDM0_ECCAThreshold, bMaskByte2, (u8)TH_H2L_dmc);
282554c0a3aSHans de Goede }
283554c0a3aSHans de Goede 
284554c0a3aSHans de Goede void ODM_Write_DIG(void *pDM_VOID, u8 CurrentIGI)
285554c0a3aSHans de Goede {
286f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
28786d6c0aeSMarco Cesati 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
288554c0a3aSHans de Goede 
289554c0a3aSHans de Goede 	if (pDM_DigTable->bStopDIG) {
290554c0a3aSHans de Goede 		return;
291554c0a3aSHans de Goede 	}
292554c0a3aSHans de Goede 
293554c0a3aSHans de Goede 	if (pDM_DigTable->CurIGValue != CurrentIGI) {
294554c0a3aSHans de Goede 		/* 1 Check initial gain by upper bound */
295554c0a3aSHans de Goede 		if (!pDM_DigTable->bPSDInProgress) {
296554c0a3aSHans de Goede 			if (CurrentIGI > pDM_DigTable->rx_gain_range_max) {
297554c0a3aSHans de Goede 				CurrentIGI = pDM_DigTable->rx_gain_range_max;
298554c0a3aSHans de Goede 			}
299554c0a3aSHans de Goede 
300554c0a3aSHans de Goede 		}
301554c0a3aSHans de Goede 
302554c0a3aSHans de Goede 		/* 1 Set IGI value */
303554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
304554c0a3aSHans de Goede 
305554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG(IGI_B, pDM_Odm), ODM_BIT(IGI, pDM_Odm), CurrentIGI);
306554c0a3aSHans de Goede 
307554c0a3aSHans de Goede 		pDM_DigTable->CurIGValue = CurrentIGI;
308554c0a3aSHans de Goede 	}
309554c0a3aSHans de Goede 
310554c0a3aSHans de Goede }
311554c0a3aSHans de Goede 
312554c0a3aSHans de Goede void odm_PauseDIG(
313554c0a3aSHans de Goede 	void *pDM_VOID,
314d7c2b41fSMarco Cesati 	enum ODM_Pause_DIG_TYPE PauseType,
315554c0a3aSHans de Goede 	u8 IGIValue
316554c0a3aSHans de Goede )
317554c0a3aSHans de Goede {
318f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
31986d6c0aeSMarco Cesati 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
320318dda31SJustin Vreeland 	static bool bPaused;
321554c0a3aSHans de Goede 
322554c0a3aSHans de Goede 	if (
323554c0a3aSHans de Goede 		(pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY) &&
324554c0a3aSHans de Goede 		pDM_Odm->TxHangFlg == true
325554c0a3aSHans de Goede 	) {
326554c0a3aSHans de Goede 		return;
327554c0a3aSHans de Goede 	}
328554c0a3aSHans de Goede 
329554c0a3aSHans de Goede 	if (
330554c0a3aSHans de Goede 		!bPaused && (!(pDM_Odm->SupportAbility & ODM_BB_DIG) ||
331554c0a3aSHans de Goede 		!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
332554c0a3aSHans de Goede 	){
333554c0a3aSHans de Goede 		return;
334554c0a3aSHans de Goede 	}
335554c0a3aSHans de Goede 
336554c0a3aSHans de Goede 	switch (PauseType) {
337554c0a3aSHans de Goede 	/* 1 Pause DIG */
338554c0a3aSHans de Goede 	case ODM_PAUSE_DIG:
339554c0a3aSHans de Goede 		/* 2 Disable DIG */
340554c0a3aSHans de Goede 		ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility & (~ODM_BB_DIG));
341554c0a3aSHans de Goede 
342554c0a3aSHans de Goede 		/* 2 Backup IGI value */
343554c0a3aSHans de Goede 		if (!bPaused) {
344554c0a3aSHans de Goede 			pDM_DigTable->IGIBackup = pDM_DigTable->CurIGValue;
345554c0a3aSHans de Goede 			bPaused = true;
346554c0a3aSHans de Goede 		}
347554c0a3aSHans de Goede 
348554c0a3aSHans de Goede 		/* 2 Write new IGI value */
349554c0a3aSHans de Goede 		ODM_Write_DIG(pDM_Odm, IGIValue);
350554c0a3aSHans de Goede 		break;
351554c0a3aSHans de Goede 
352554c0a3aSHans de Goede 	/* 1 Resume DIG */
353554c0a3aSHans de Goede 	case ODM_RESUME_DIG:
354554c0a3aSHans de Goede 		if (bPaused) {
355554c0a3aSHans de Goede 			/* 2 Write backup IGI value */
356554c0a3aSHans de Goede 			ODM_Write_DIG(pDM_Odm, pDM_DigTable->IGIBackup);
357554c0a3aSHans de Goede 			bPaused = false;
358554c0a3aSHans de Goede 
359554c0a3aSHans de Goede 			/* 2 Enable DIG */
360554c0a3aSHans de Goede 			ODM_CmnInfoUpdate(pDM_Odm, ODM_CMNINFO_ABILITY, pDM_Odm->SupportAbility | ODM_BB_DIG);
361554c0a3aSHans de Goede 		}
362554c0a3aSHans de Goede 		break;
363554c0a3aSHans de Goede 
364554c0a3aSHans de Goede 	default:
365554c0a3aSHans de Goede 		break;
366554c0a3aSHans de Goede 	}
367554c0a3aSHans de Goede }
368554c0a3aSHans de Goede 
369554c0a3aSHans de Goede bool odm_DigAbort(void *pDM_VOID)
370554c0a3aSHans de Goede {
371f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
372554c0a3aSHans de Goede 
373554c0a3aSHans de Goede 	/* SupportAbility */
374554c0a3aSHans de Goede 	if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)) {
375554c0a3aSHans de Goede 		return	true;
376554c0a3aSHans de Goede 	}
377554c0a3aSHans de Goede 
378554c0a3aSHans de Goede 	/* SupportAbility */
379554c0a3aSHans de Goede 	if (!(pDM_Odm->SupportAbility & ODM_BB_DIG)) {
380554c0a3aSHans de Goede 		return	true;
381554c0a3aSHans de Goede 	}
382554c0a3aSHans de Goede 
383554c0a3aSHans de Goede 	/* ScanInProcess */
384554c0a3aSHans de Goede 	if (*(pDM_Odm->pbScanInProcess)) {
385554c0a3aSHans de Goede 		return	true;
386554c0a3aSHans de Goede 	}
387554c0a3aSHans de Goede 
388554c0a3aSHans de Goede 	/* add by Neil Chen to avoid PSD is processing */
389554c0a3aSHans de Goede 	if (pDM_Odm->bDMInitialGainEnable == false) {
390554c0a3aSHans de Goede 		return	true;
391554c0a3aSHans de Goede 	}
392554c0a3aSHans de Goede 
393554c0a3aSHans de Goede 	return	false;
394554c0a3aSHans de Goede }
395554c0a3aSHans de Goede 
396554c0a3aSHans de Goede void odm_DIGInit(void *pDM_VOID)
397554c0a3aSHans de Goede {
398f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
39986d6c0aeSMarco Cesati 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
400554c0a3aSHans de Goede 
401554c0a3aSHans de Goede 	pDM_DigTable->bStopDIG = false;
402554c0a3aSHans de Goede 	pDM_DigTable->bPSDInProgress = false;
403554c0a3aSHans de Goede 	pDM_DigTable->CurIGValue = (u8) PHY_QueryBBReg(pDM_Odm->Adapter, ODM_REG(IGI_A, pDM_Odm), ODM_BIT(IGI, pDM_Odm));
404554c0a3aSHans de Goede 	pDM_DigTable->RssiLowThresh	= DM_DIG_THRESH_LOW;
405554c0a3aSHans de Goede 	pDM_DigTable->RssiHighThresh	= DM_DIG_THRESH_HIGH;
406554c0a3aSHans de Goede 	pDM_DigTable->FALowThresh	= DMfalseALARM_THRESH_LOW;
407554c0a3aSHans de Goede 	pDM_DigTable->FAHighThresh	= DMfalseALARM_THRESH_HIGH;
408554c0a3aSHans de Goede 	pDM_DigTable->BackoffVal = DM_DIG_BACKOFF_DEFAULT;
409554c0a3aSHans de Goede 	pDM_DigTable->BackoffVal_range_max = DM_DIG_BACKOFF_MAX;
410554c0a3aSHans de Goede 	pDM_DigTable->BackoffVal_range_min = DM_DIG_BACKOFF_MIN;
411554c0a3aSHans de Goede 	pDM_DigTable->PreCCK_CCAThres = 0xFF;
412554c0a3aSHans de Goede 	pDM_DigTable->CurCCK_CCAThres = 0x83;
413554c0a3aSHans de Goede 	pDM_DigTable->ForbiddenIGI = DM_DIG_MIN_NIC;
414554c0a3aSHans de Goede 	pDM_DigTable->LargeFAHit = 0;
415554c0a3aSHans de Goede 	pDM_DigTable->Recover_cnt = 0;
416554c0a3aSHans de Goede 	pDM_DigTable->bMediaConnect_0 = false;
417554c0a3aSHans de Goede 	pDM_DigTable->bMediaConnect_1 = false;
418554c0a3aSHans de Goede 
419554c0a3aSHans de Goede 	/* To Initialize pDM_Odm->bDMInitialGainEnable == false to avoid DIG error */
420554c0a3aSHans de Goede 	pDM_Odm->bDMInitialGainEnable = true;
421554c0a3aSHans de Goede 
422554c0a3aSHans de Goede 	pDM_DigTable->DIG_Dynamic_MIN_0 = DM_DIG_MIN_NIC;
423554c0a3aSHans de Goede 	pDM_DigTable->DIG_Dynamic_MIN_1 = DM_DIG_MIN_NIC;
424554c0a3aSHans de Goede 
425554c0a3aSHans de Goede 	/* To Initi BT30 IGI */
426554c0a3aSHans de Goede 	pDM_DigTable->BT30_CurIGI = 0x32;
427554c0a3aSHans de Goede 
428554c0a3aSHans de Goede 	pDM_DigTable->rx_gain_range_max = DM_DIG_MAX_NIC;
429554c0a3aSHans de Goede 	pDM_DigTable->rx_gain_range_min = DM_DIG_MIN_NIC;
430554c0a3aSHans de Goede 
431554c0a3aSHans de Goede }
432554c0a3aSHans de Goede 
433554c0a3aSHans de Goede 
434554c0a3aSHans de Goede void odm_DIG(void *pDM_VOID)
435554c0a3aSHans de Goede {
436f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
437554c0a3aSHans de Goede 
438554c0a3aSHans de Goede 	/*  Common parameters */
43986d6c0aeSMarco Cesati 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
440d7c2b41fSMarco Cesati 	struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
441554c0a3aSHans de Goede 	bool FirstConnect, FirstDisConnect;
442554c0a3aSHans de Goede 	u8 DIG_MaxOfMin, DIG_Dynamic_MIN;
443554c0a3aSHans de Goede 	u8 dm_dig_max, dm_dig_min;
444554c0a3aSHans de Goede 	u8 CurrentIGI = pDM_DigTable->CurIGValue;
445554c0a3aSHans de Goede 	u8 offset;
446554c0a3aSHans de Goede 	u32 dm_FA_thres[3];
447554c0a3aSHans de Goede 	u8 Adap_IGI_Upper = 0;
448554c0a3aSHans de Goede 	u32 TxTp = 0, RxTp = 0;
449554c0a3aSHans de Goede 	bool bDFSBand = false;
450554c0a3aSHans de Goede 	bool bPerformance = true, bFirstTpTarget = false, bFirstCoverage = false;
451554c0a3aSHans de Goede 
452941add8eSPuranjay Mohan 	if (odm_DigAbort(pDM_Odm))
453554c0a3aSHans de Goede 		return;
454554c0a3aSHans de Goede 
455554c0a3aSHans de Goede 	if (pDM_Odm->adaptivity_flag == true)
456554c0a3aSHans de Goede 		Adap_IGI_Upper = pDM_Odm->Adaptivity_IGI_upper;
457554c0a3aSHans de Goede 
458554c0a3aSHans de Goede 
459554c0a3aSHans de Goede 	/* 1 Update status */
460554c0a3aSHans de Goede 	DIG_Dynamic_MIN = pDM_DigTable->DIG_Dynamic_MIN_0;
461554c0a3aSHans de Goede 	FirstConnect = (pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == false);
462554c0a3aSHans de Goede 	FirstDisConnect = (!pDM_Odm->bLinked) && (pDM_DigTable->bMediaConnect_0 == true);
463554c0a3aSHans de Goede 
464554c0a3aSHans de Goede 	/* 1 Boundary Decision */
465554c0a3aSHans de Goede 	/* 2 For WIN\CE */
466554c0a3aSHans de Goede 	dm_dig_max = 0x5A;
467554c0a3aSHans de Goede 	dm_dig_min = DM_DIG_MIN_NIC;
468554c0a3aSHans de Goede 	DIG_MaxOfMin = DM_DIG_MAX_AP;
469554c0a3aSHans de Goede 
470554c0a3aSHans de Goede 	/* 1 Adjust boundary by RSSI */
471554c0a3aSHans de Goede 	if (pDM_Odm->bLinked && bPerformance) {
472554c0a3aSHans de Goede 		/* 2 Modify DIG upper bound */
473554c0a3aSHans de Goede 		/* 4 Modify DIG upper bound for 92E, 8723A\B, 8821 & 8812 BT */
474554c0a3aSHans de Goede 		if (pDM_Odm->bBtLimitedDig == 1) {
475554c0a3aSHans de Goede 			offset = 10;
476554c0a3aSHans de Goede 		} else
477554c0a3aSHans de Goede 			offset = 15;
478554c0a3aSHans de Goede 
479554c0a3aSHans de Goede 		if ((pDM_Odm->RSSI_Min + offset) > dm_dig_max)
480554c0a3aSHans de Goede 			pDM_DigTable->rx_gain_range_max = dm_dig_max;
481554c0a3aSHans de Goede 		else if ((pDM_Odm->RSSI_Min + offset) < dm_dig_min)
482554c0a3aSHans de Goede 			pDM_DigTable->rx_gain_range_max = dm_dig_min;
483554c0a3aSHans de Goede 		else
484554c0a3aSHans de Goede 			pDM_DigTable->rx_gain_range_max = pDM_Odm->RSSI_Min + offset;
485554c0a3aSHans de Goede 
486554c0a3aSHans de Goede 		/* 2 Modify DIG lower bound */
487554c0a3aSHans de Goede 		/* if (pDM_Odm->bOneEntryOnly) */
488554c0a3aSHans de Goede 		{
489554c0a3aSHans de Goede 			if (pDM_Odm->RSSI_Min < dm_dig_min)
490554c0a3aSHans de Goede 				DIG_Dynamic_MIN = dm_dig_min;
491554c0a3aSHans de Goede 			else if (pDM_Odm->RSSI_Min > DIG_MaxOfMin)
492554c0a3aSHans de Goede 				DIG_Dynamic_MIN = DIG_MaxOfMin;
493554c0a3aSHans de Goede 			else
494554c0a3aSHans de Goede 				DIG_Dynamic_MIN = pDM_Odm->RSSI_Min;
495554c0a3aSHans de Goede 		}
496554c0a3aSHans de Goede 	} else {
497554c0a3aSHans de Goede 		pDM_DigTable->rx_gain_range_max = dm_dig_max;
498554c0a3aSHans de Goede 		DIG_Dynamic_MIN = dm_dig_min;
499554c0a3aSHans de Goede 	}
500554c0a3aSHans de Goede 
501554c0a3aSHans de Goede 	/* 1 Force Lower Bound for AntDiv */
502554c0a3aSHans de Goede 	if (pDM_Odm->bLinked && !pDM_Odm->bOneEntryOnly) {
503554c0a3aSHans de Goede 		if (pDM_Odm->SupportAbility & ODM_BB_ANT_DIV) {
504554c0a3aSHans de Goede 			if (
505554c0a3aSHans de Goede 				pDM_Odm->AntDivType == CG_TRX_HW_ANTDIV ||
506554c0a3aSHans de Goede 				pDM_Odm->AntDivType == CG_TRX_SMART_ANTDIV ||
507554c0a3aSHans de Goede 				pDM_Odm->AntDivType == S0S1_SW_ANTDIV
508554c0a3aSHans de Goede 			) {
509554c0a3aSHans de Goede 				if (pDM_DigTable->AntDiv_RSSI_max > DIG_MaxOfMin)
510554c0a3aSHans de Goede 					DIG_Dynamic_MIN = DIG_MaxOfMin;
511554c0a3aSHans de Goede 				else
512554c0a3aSHans de Goede 					DIG_Dynamic_MIN = (u8) pDM_DigTable->AntDiv_RSSI_max;
513554c0a3aSHans de Goede 			}
514554c0a3aSHans de Goede 		}
515554c0a3aSHans de Goede 	}
516554c0a3aSHans de Goede 
517554c0a3aSHans de Goede 	/* 1 Modify DIG lower bound, deal with abnormal case */
518554c0a3aSHans de Goede 	/* 2 Abnormal false alarm case */
519554c0a3aSHans de Goede 	if (FirstDisConnect) {
520554c0a3aSHans de Goede 		pDM_DigTable->rx_gain_range_min = DIG_Dynamic_MIN;
521554c0a3aSHans de Goede 		pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN;
522554c0a3aSHans de Goede 	} else
523554c0a3aSHans de Goede 		pDM_DigTable->rx_gain_range_min =
524554c0a3aSHans de Goede 			odm_ForbiddenIGICheck(pDM_Odm, DIG_Dynamic_MIN, CurrentIGI);
525554c0a3aSHans de Goede 
526554c0a3aSHans de Goede 	if (pDM_Odm->bLinked && !FirstConnect) {
527554c0a3aSHans de Goede 		if (
528554c0a3aSHans de Goede 			(pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
529554c0a3aSHans de Goede 			pDM_Odm->bsta_state
530554c0a3aSHans de Goede 		) {
531554c0a3aSHans de Goede 			pDM_DigTable->rx_gain_range_min = dm_dig_min;
532554c0a3aSHans de Goede 		}
533554c0a3aSHans de Goede 	}
534554c0a3aSHans de Goede 
535554c0a3aSHans de Goede 	/* 2 Abnormal lower bound case */
536554c0a3aSHans de Goede 	if (pDM_DigTable->rx_gain_range_min > pDM_DigTable->rx_gain_range_max) {
537554c0a3aSHans de Goede 		pDM_DigTable->rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
538554c0a3aSHans de Goede 	}
539554c0a3aSHans de Goede 
540554c0a3aSHans de Goede 
541554c0a3aSHans de Goede 	/* 1 False alarm threshold decision */
542554c0a3aSHans de Goede 	odm_FAThresholdCheck(pDM_Odm, bDFSBand, bPerformance, RxTp, TxTp, dm_FA_thres);
543554c0a3aSHans de Goede 
544554c0a3aSHans de Goede 	/* 1 Adjust initial gain by false alarm */
545554c0a3aSHans de Goede 	if (pDM_Odm->bLinked && bPerformance) {
546554c0a3aSHans de Goede 
547*98f668b3SSaurav Girepunje 		if (bFirstTpTarget || FirstConnect) {
548554c0a3aSHans de Goede 			pDM_DigTable->LargeFAHit = 0;
549554c0a3aSHans de Goede 
550554c0a3aSHans de Goede 			if (pDM_Odm->RSSI_Min < DIG_MaxOfMin) {
551554c0a3aSHans de Goede 				if (CurrentIGI < pDM_Odm->RSSI_Min)
552554c0a3aSHans de Goede 					CurrentIGI = pDM_Odm->RSSI_Min;
553554c0a3aSHans de Goede 			} else {
554554c0a3aSHans de Goede 				if (CurrentIGI < DIG_MaxOfMin)
555554c0a3aSHans de Goede 					CurrentIGI = DIG_MaxOfMin;
556554c0a3aSHans de Goede 			}
557554c0a3aSHans de Goede 
558554c0a3aSHans de Goede 		} else {
559554c0a3aSHans de Goede 			if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
560554c0a3aSHans de Goede 				CurrentIGI = CurrentIGI + 4;
561554c0a3aSHans de Goede 			else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
562554c0a3aSHans de Goede 				CurrentIGI = CurrentIGI + 2;
563554c0a3aSHans de Goede 			else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
564554c0a3aSHans de Goede 				CurrentIGI = CurrentIGI - 2;
565554c0a3aSHans de Goede 
566554c0a3aSHans de Goede 			if (
567554c0a3aSHans de Goede 				(pDM_Odm->PhyDbgInfo.NumQryBeaconPkt < 5) &&
568554c0a3aSHans de Goede 				(pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH1) &&
569554c0a3aSHans de Goede 				(pDM_Odm->bsta_state)
570554c0a3aSHans de Goede 			) {
571554c0a3aSHans de Goede 				CurrentIGI = pDM_DigTable->rx_gain_range_min;
572554c0a3aSHans de Goede 			}
573554c0a3aSHans de Goede 		}
574554c0a3aSHans de Goede 	} else {
575554c0a3aSHans de Goede 
576554c0a3aSHans de Goede 		if (FirstDisConnect || bFirstCoverage) {
577554c0a3aSHans de Goede 			CurrentIGI = dm_dig_min;
578554c0a3aSHans de Goede 		} else {
579554c0a3aSHans de Goede 			if (pFalseAlmCnt->Cnt_all > dm_FA_thres[2])
580554c0a3aSHans de Goede 				CurrentIGI = CurrentIGI + 4;
581554c0a3aSHans de Goede 			else if (pFalseAlmCnt->Cnt_all > dm_FA_thres[1])
582554c0a3aSHans de Goede 				CurrentIGI = CurrentIGI + 2;
583554c0a3aSHans de Goede 			else if (pFalseAlmCnt->Cnt_all < dm_FA_thres[0])
584554c0a3aSHans de Goede 				CurrentIGI = CurrentIGI - 2;
585554c0a3aSHans de Goede 		}
586554c0a3aSHans de Goede 	}
587554c0a3aSHans de Goede 
588554c0a3aSHans de Goede 	/* 1 Check initial gain by upper/lower bound */
589554c0a3aSHans de Goede 	if (CurrentIGI < pDM_DigTable->rx_gain_range_min)
590554c0a3aSHans de Goede 		CurrentIGI = pDM_DigTable->rx_gain_range_min;
591554c0a3aSHans de Goede 
592554c0a3aSHans de Goede 	if (CurrentIGI > pDM_DigTable->rx_gain_range_max)
593554c0a3aSHans de Goede 		CurrentIGI = pDM_DigTable->rx_gain_range_max;
594554c0a3aSHans de Goede 
595554c0a3aSHans de Goede 	/* 1 Force upper bound and lower bound for adaptivity */
596554c0a3aSHans de Goede 	if (
597554c0a3aSHans de Goede 		pDM_Odm->SupportAbility & ODM_BB_ADAPTIVITY &&
598554c0a3aSHans de Goede 		pDM_Odm->adaptivity_flag == true
599554c0a3aSHans de Goede 	) {
600554c0a3aSHans de Goede 		if (CurrentIGI > Adap_IGI_Upper)
601554c0a3aSHans de Goede 			CurrentIGI = Adap_IGI_Upper;
602554c0a3aSHans de Goede 
603554c0a3aSHans de Goede 		if (pDM_Odm->IGI_LowerBound != 0) {
604554c0a3aSHans de Goede 			if (CurrentIGI < pDM_Odm->IGI_LowerBound)
605554c0a3aSHans de Goede 				CurrentIGI = pDM_Odm->IGI_LowerBound;
606554c0a3aSHans de Goede 		}
607554c0a3aSHans de Goede 	}
608554c0a3aSHans de Goede 
609554c0a3aSHans de Goede 
610554c0a3aSHans de Goede 	/* 1 Update status */
611554c0a3aSHans de Goede 	if (pDM_Odm->bBtHsOperation) {
612554c0a3aSHans de Goede 		if (pDM_Odm->bLinked) {
613554c0a3aSHans de Goede 			if (pDM_DigTable->BT30_CurIGI > (CurrentIGI))
614554c0a3aSHans de Goede 				ODM_Write_DIG(pDM_Odm, CurrentIGI);
615554c0a3aSHans de Goede 			else
616554c0a3aSHans de Goede 				ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);
617554c0a3aSHans de Goede 
618554c0a3aSHans de Goede 			pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
619554c0a3aSHans de Goede 			pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
620554c0a3aSHans de Goede 		} else {
621554c0a3aSHans de Goede 			if (pDM_Odm->bLinkInProcess)
622554c0a3aSHans de Goede 				ODM_Write_DIG(pDM_Odm, 0x1c);
623554c0a3aSHans de Goede 			else if (pDM_Odm->bBtConnectProcess)
624554c0a3aSHans de Goede 				ODM_Write_DIG(pDM_Odm, 0x28);
625554c0a3aSHans de Goede 			else
626554c0a3aSHans de Goede 				ODM_Write_DIG(pDM_Odm, pDM_DigTable->BT30_CurIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
627554c0a3aSHans de Goede 		}
628554c0a3aSHans de Goede 	} else { /*  BT is not using */
629554c0a3aSHans de Goede 		ODM_Write_DIG(pDM_Odm, CurrentIGI);/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
630554c0a3aSHans de Goede 		pDM_DigTable->bMediaConnect_0 = pDM_Odm->bLinked;
631554c0a3aSHans de Goede 		pDM_DigTable->DIG_Dynamic_MIN_0 = DIG_Dynamic_MIN;
632554c0a3aSHans de Goede 	}
633554c0a3aSHans de Goede }
634554c0a3aSHans de Goede 
635554c0a3aSHans de Goede void odm_DIGbyRSSI_LPS(void *pDM_VOID)
636554c0a3aSHans de Goede {
637f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
638d7c2b41fSMarco Cesati 	struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
639554c0a3aSHans de Goede 
640554c0a3aSHans de Goede 	u8 RSSI_Lower = DM_DIG_MIN_NIC;   /* 0x1E or 0x1C */
641554c0a3aSHans de Goede 	u8 CurrentIGI = pDM_Odm->RSSI_Min;
642554c0a3aSHans de Goede 
643554c0a3aSHans de Goede 	CurrentIGI = CurrentIGI+RSSI_OFFSET_DIG;
644554c0a3aSHans de Goede 
645554c0a3aSHans de Goede 	/*  Using FW PS mode to make IGI */
646554c0a3aSHans de Goede 	/* Adjust by  FA in LPS MODE */
647554c0a3aSHans de Goede 	if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH2_LPS)
648554c0a3aSHans de Goede 		CurrentIGI = CurrentIGI+4;
649554c0a3aSHans de Goede 	else if (pFalseAlmCnt->Cnt_all > DM_DIG_FA_TH1_LPS)
650554c0a3aSHans de Goede 		CurrentIGI = CurrentIGI+2;
651554c0a3aSHans de Goede 	else if (pFalseAlmCnt->Cnt_all < DM_DIG_FA_TH0_LPS)
652554c0a3aSHans de Goede 		CurrentIGI = CurrentIGI-2;
653554c0a3aSHans de Goede 
654554c0a3aSHans de Goede 
655554c0a3aSHans de Goede 	/* Lower bound checking */
656554c0a3aSHans de Goede 
657554c0a3aSHans de Goede 	/* RSSI Lower bound check */
658554c0a3aSHans de Goede 	if ((pDM_Odm->RSSI_Min-10) > DM_DIG_MIN_NIC)
659554c0a3aSHans de Goede 		RSSI_Lower = pDM_Odm->RSSI_Min-10;
660554c0a3aSHans de Goede 	else
661554c0a3aSHans de Goede 		RSSI_Lower = DM_DIG_MIN_NIC;
662554c0a3aSHans de Goede 
663554c0a3aSHans de Goede 	/* Upper and Lower Bound checking */
664554c0a3aSHans de Goede 	if (CurrentIGI > DM_DIG_MAX_NIC)
665554c0a3aSHans de Goede 		CurrentIGI = DM_DIG_MAX_NIC;
666554c0a3aSHans de Goede 	else if (CurrentIGI < RSSI_Lower)
667554c0a3aSHans de Goede 		CurrentIGI = RSSI_Lower;
668554c0a3aSHans de Goede 
669554c0a3aSHans de Goede 	ODM_Write_DIG(pDM_Odm, CurrentIGI);
670554c0a3aSHans de Goede 	/* ODM_Write_DIG(pDM_Odm, pDM_DigTable->CurIGValue); */
671554c0a3aSHans de Goede }
672554c0a3aSHans de Goede 
673554c0a3aSHans de Goede /* 3 ============================================================ */
674554c0a3aSHans de Goede /* 3 FASLE ALARM CHECK */
675554c0a3aSHans de Goede /* 3 ============================================================ */
676554c0a3aSHans de Goede 
677554c0a3aSHans de Goede void odm_FalseAlarmCounterStatistics(void *pDM_VOID)
678554c0a3aSHans de Goede {
679f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
680db07a1caSMarco Cesati 	struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
681554c0a3aSHans de Goede 	u32 ret_value;
682554c0a3aSHans de Goede 
683554c0a3aSHans de Goede 	if (!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT))
684554c0a3aSHans de Goede 		return;
685554c0a3aSHans de Goede 
686554c0a3aSHans de Goede 	/* hold ofdm counter */
687554c0a3aSHans de Goede 	/* hold page C counter */
688554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_HOLDC_11N, BIT31, 1);
689554c0a3aSHans de Goede 	/* hold page D counter */
690554c0a3aSHans de Goede 	PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_OFDM_FA_RSTD_11N, BIT31, 1);
691554c0a3aSHans de Goede 
692554c0a3aSHans de Goede 	ret_value = PHY_QueryBBReg(
693554c0a3aSHans de Goede 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE1_11N, bMaskDWord
694554c0a3aSHans de Goede 	);
695554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_Fast_Fsync = (ret_value&0xffff);
696554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_SB_Search_fail = ((ret_value&0xffff0000)>>16);
697554c0a3aSHans de Goede 
698554c0a3aSHans de Goede 	ret_value = PHY_QueryBBReg(
699554c0a3aSHans de Goede 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE2_11N, bMaskDWord
700554c0a3aSHans de Goede 	);
701554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_OFDM_CCA = (ret_value&0xffff);
702554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_Parity_Fail = ((ret_value&0xffff0000)>>16);
703554c0a3aSHans de Goede 
704554c0a3aSHans de Goede 	ret_value = PHY_QueryBBReg(
705554c0a3aSHans de Goede 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE3_11N, bMaskDWord
706554c0a3aSHans de Goede 	);
707554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_Rate_Illegal = (ret_value&0xffff);
708554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_Crc8_fail = ((ret_value&0xffff0000)>>16);
709554c0a3aSHans de Goede 
710554c0a3aSHans de Goede 	ret_value = PHY_QueryBBReg(
711554c0a3aSHans de Goede 		pDM_Odm->Adapter, ODM_REG_OFDM_FA_TYPE4_11N, bMaskDWord
712554c0a3aSHans de Goede 	);
713554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_Mcs_fail = (ret_value&0xffff);
714554c0a3aSHans de Goede 
715554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_Ofdm_fail =
716554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Parity_Fail +
717554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Rate_Illegal +
718554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Crc8_fail +
719554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Mcs_fail +
720554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Fast_Fsync +
721554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_SB_Search_fail;
722554c0a3aSHans de Goede 
723554c0a3aSHans de Goede 	{
724554c0a3aSHans de Goede 		/* hold cck counter */
725554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT12, 1);
726554c0a3aSHans de Goede 		PHY_SetBBReg(pDM_Odm->Adapter, ODM_REG_CCK_FA_RST_11N, BIT14, 1);
727554c0a3aSHans de Goede 
728554c0a3aSHans de Goede 		ret_value = PHY_QueryBBReg(
729554c0a3aSHans de Goede 			pDM_Odm->Adapter, ODM_REG_CCK_FA_LSB_11N, bMaskByte0
730554c0a3aSHans de Goede 		);
731554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Cck_fail = ret_value;
732554c0a3aSHans de Goede 
733554c0a3aSHans de Goede 		ret_value = PHY_QueryBBReg(
734554c0a3aSHans de Goede 			pDM_Odm->Adapter, ODM_REG_CCK_FA_MSB_11N, bMaskByte3
735554c0a3aSHans de Goede 		);
736554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Cck_fail += (ret_value&0xff)<<8;
737554c0a3aSHans de Goede 
738554c0a3aSHans de Goede 		ret_value = PHY_QueryBBReg(
739554c0a3aSHans de Goede 			pDM_Odm->Adapter, ODM_REG_CCK_CCA_CNT_11N, bMaskDWord
740554c0a3aSHans de Goede 		);
741554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_CCK_CCA =
742554c0a3aSHans de Goede 			((ret_value&0xFF)<<8) | ((ret_value&0xFF00)>>8);
743554c0a3aSHans de Goede 	}
744554c0a3aSHans de Goede 
745554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_all = (
746554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Fast_Fsync +
747554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_SB_Search_fail +
748554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Parity_Fail +
749554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Rate_Illegal +
750554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Crc8_fail +
751554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Mcs_fail +
752554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_Cck_fail
753554c0a3aSHans de Goede 	);
754554c0a3aSHans de Goede 
755554c0a3aSHans de Goede 	FalseAlmCnt->Cnt_CCA_all =
756554c0a3aSHans de Goede 		FalseAlmCnt->Cnt_OFDM_CCA + FalseAlmCnt->Cnt_CCK_CCA;
757554c0a3aSHans de Goede }
758554c0a3aSHans de Goede 
759554c0a3aSHans de Goede 
760554c0a3aSHans de Goede void odm_FAThresholdCheck(
761554c0a3aSHans de Goede 	void *pDM_VOID,
762554c0a3aSHans de Goede 	bool bDFSBand,
763554c0a3aSHans de Goede 	bool bPerformance,
764554c0a3aSHans de Goede 	u32 RxTp,
765554c0a3aSHans de Goede 	u32 TxTp,
766554c0a3aSHans de Goede 	u32 *dm_FA_thres
767554c0a3aSHans de Goede )
768554c0a3aSHans de Goede {
769f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
770554c0a3aSHans de Goede 
771554c0a3aSHans de Goede 	if (pDM_Odm->bLinked && (bPerformance || bDFSBand)) {
772554c0a3aSHans de Goede 		/*  For NIC */
773554c0a3aSHans de Goede 		dm_FA_thres[0] = DM_DIG_FA_TH0;
774554c0a3aSHans de Goede 		dm_FA_thres[1] = DM_DIG_FA_TH1;
775554c0a3aSHans de Goede 		dm_FA_thres[2] = DM_DIG_FA_TH2;
776554c0a3aSHans de Goede 	} else {
777554c0a3aSHans de Goede 		dm_FA_thres[0] = 2000;
778554c0a3aSHans de Goede 		dm_FA_thres[1] = 4000;
779554c0a3aSHans de Goede 		dm_FA_thres[2] = 5000;
780554c0a3aSHans de Goede 	}
781554c0a3aSHans de Goede }
782554c0a3aSHans de Goede 
783554c0a3aSHans de Goede u8 odm_ForbiddenIGICheck(void *pDM_VOID, u8 DIG_Dynamic_MIN, u8 CurrentIGI)
784554c0a3aSHans de Goede {
785f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
78686d6c0aeSMarco Cesati 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
787db07a1caSMarco Cesati 	struct false_ALARM_STATISTICS *pFalseAlmCnt = &pDM_Odm->FalseAlmCnt;
788554c0a3aSHans de Goede 	u8 rx_gain_range_min = pDM_DigTable->rx_gain_range_min;
789554c0a3aSHans de Goede 
790554c0a3aSHans de Goede 	if (pFalseAlmCnt->Cnt_all > 10000) {
791554c0a3aSHans de Goede 		if (pDM_DigTable->LargeFAHit != 3)
792554c0a3aSHans de Goede 			pDM_DigTable->LargeFAHit++;
793554c0a3aSHans de Goede 
794554c0a3aSHans de Goede 		/* if (pDM_DigTable->ForbiddenIGI < pDM_DigTable->CurIGValue) */
795554c0a3aSHans de Goede 		if (pDM_DigTable->ForbiddenIGI < CurrentIGI) {
796554c0a3aSHans de Goede 			pDM_DigTable->ForbiddenIGI = CurrentIGI;
797554c0a3aSHans de Goede 			/* pDM_DigTable->ForbiddenIGI = pDM_DigTable->CurIGValue; */
798554c0a3aSHans de Goede 			pDM_DigTable->LargeFAHit = 1;
799554c0a3aSHans de Goede 		}
800554c0a3aSHans de Goede 
801554c0a3aSHans de Goede 		if (pDM_DigTable->LargeFAHit >= 3) {
802554c0a3aSHans de Goede 			if ((pDM_DigTable->ForbiddenIGI + 2) > pDM_DigTable->rx_gain_range_max)
803554c0a3aSHans de Goede 				rx_gain_range_min = pDM_DigTable->rx_gain_range_max;
804554c0a3aSHans de Goede 			else
805554c0a3aSHans de Goede 				rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
806554c0a3aSHans de Goede 			pDM_DigTable->Recover_cnt = 1800;
807554c0a3aSHans de Goede 		}
808554c0a3aSHans de Goede 	} else {
809554c0a3aSHans de Goede 		if (pDM_DigTable->Recover_cnt != 0) {
810554c0a3aSHans de Goede 			pDM_DigTable->Recover_cnt--;
811554c0a3aSHans de Goede 		} else {
812554c0a3aSHans de Goede 			if (pDM_DigTable->LargeFAHit < 3) {
813554c0a3aSHans de Goede 				if ((pDM_DigTable->ForbiddenIGI - 2) < DIG_Dynamic_MIN) { /* DM_DIG_MIN) */
814554c0a3aSHans de Goede 					pDM_DigTable->ForbiddenIGI = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
815554c0a3aSHans de Goede 					rx_gain_range_min = DIG_Dynamic_MIN; /* DM_DIG_MIN; */
816554c0a3aSHans de Goede 				} else {
817554c0a3aSHans de Goede 					pDM_DigTable->ForbiddenIGI -= 2;
818554c0a3aSHans de Goede 					rx_gain_range_min = (pDM_DigTable->ForbiddenIGI + 2);
819554c0a3aSHans de Goede 				}
820554c0a3aSHans de Goede 			} else
821554c0a3aSHans de Goede 				pDM_DigTable->LargeFAHit = 0;
822554c0a3aSHans de Goede 		}
823554c0a3aSHans de Goede 	}
824554c0a3aSHans de Goede 
825554c0a3aSHans de Goede 	return rx_gain_range_min;
826554c0a3aSHans de Goede 
827554c0a3aSHans de Goede }
828554c0a3aSHans de Goede 
829554c0a3aSHans de Goede /* 3 ============================================================ */
830554c0a3aSHans de Goede /* 3 CCK Packet Detect Threshold */
831554c0a3aSHans de Goede /* 3 ============================================================ */
832554c0a3aSHans de Goede 
833554c0a3aSHans de Goede void odm_CCKPacketDetectionThresh(void *pDM_VOID)
834554c0a3aSHans de Goede {
835f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
836db07a1caSMarco Cesati 	struct false_ALARM_STATISTICS *FalseAlmCnt = &pDM_Odm->FalseAlmCnt;
837554c0a3aSHans de Goede 	u8 CurCCK_CCAThres;
838554c0a3aSHans de Goede 
839554c0a3aSHans de Goede 
840554c0a3aSHans de Goede 	if (
841554c0a3aSHans de Goede 		!(pDM_Odm->SupportAbility & ODM_BB_CCK_PD) ||
842554c0a3aSHans de Goede 		!(pDM_Odm->SupportAbility & ODM_BB_FA_CNT)
843554c0a3aSHans de Goede 	) {
844554c0a3aSHans de Goede 		return;
845554c0a3aSHans de Goede 	}
846554c0a3aSHans de Goede 
847554c0a3aSHans de Goede 	if (pDM_Odm->ExtLNA)
848554c0a3aSHans de Goede 		return;
849554c0a3aSHans de Goede 
850554c0a3aSHans de Goede 	if (pDM_Odm->bLinked) {
851554c0a3aSHans de Goede 		if (pDM_Odm->RSSI_Min > 25)
852554c0a3aSHans de Goede 			CurCCK_CCAThres = 0xcd;
853554c0a3aSHans de Goede 		else if ((pDM_Odm->RSSI_Min <= 25) && (pDM_Odm->RSSI_Min > 10))
854554c0a3aSHans de Goede 			CurCCK_CCAThres = 0x83;
855554c0a3aSHans de Goede 		else {
856554c0a3aSHans de Goede 			if (FalseAlmCnt->Cnt_Cck_fail > 1000)
857554c0a3aSHans de Goede 				CurCCK_CCAThres = 0x83;
858554c0a3aSHans de Goede 			else
859554c0a3aSHans de Goede 				CurCCK_CCAThres = 0x40;
860554c0a3aSHans de Goede 		}
861554c0a3aSHans de Goede 	} else {
862554c0a3aSHans de Goede 		if (FalseAlmCnt->Cnt_Cck_fail > 1000)
863554c0a3aSHans de Goede 			CurCCK_CCAThres = 0x83;
864554c0a3aSHans de Goede 		else
865554c0a3aSHans de Goede 			CurCCK_CCAThres = 0x40;
866554c0a3aSHans de Goede 	}
867554c0a3aSHans de Goede 
868554c0a3aSHans de Goede 	ODM_Write_CCK_CCA_Thres(pDM_Odm, CurCCK_CCAThres);
869554c0a3aSHans de Goede }
870554c0a3aSHans de Goede 
871554c0a3aSHans de Goede void ODM_Write_CCK_CCA_Thres(void *pDM_VOID, u8 CurCCK_CCAThres)
872554c0a3aSHans de Goede {
873f8010da6SMarco Cesati 	struct dm_odm_t *pDM_Odm = (struct dm_odm_t *)pDM_VOID;
87486d6c0aeSMarco Cesati 	struct dig_t *pDM_DigTable = &pDM_Odm->DM_DigTable;
875554c0a3aSHans de Goede 
876554c0a3aSHans de Goede 	/* modify by Guo.Mingzhi 2012-01-03 */
877554c0a3aSHans de Goede 	if (pDM_DigTable->CurCCK_CCAThres != CurCCK_CCAThres)
878554c0a3aSHans de Goede 		rtw_write8(pDM_Odm->Adapter, ODM_REG(CCK_CCA, pDM_Odm), CurCCK_CCAThres);
879554c0a3aSHans de Goede 
880554c0a3aSHans de Goede 	pDM_DigTable->PreCCK_CCAThres = pDM_DigTable->CurCCK_CCAThres;
881554c0a3aSHans de Goede 	pDM_DigTable->CurCCK_CCAThres = CurCCK_CCAThres;
882554c0a3aSHans de Goede }
883