1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
3 
4 #include "../include/drv_types.h"
5 
6 /*---------------------------Define Local Constant---------------------------*/
7 /*  2010/04/25 MH Define the max tx power tracking tx agc power. */
8 #define		ODM_TXPWRTRACK_MAX_IDX_88E		6
9 
10 /*---------------------------Define Local Constant---------------------------*/
11 
12 /* 3============================================================ */
13 /* 3 Tx Power Tracking */
14 /* 3============================================================ */
15 /*-----------------------------------------------------------------------------
16  * Function:	ODM_TxPwrTrackAdjust88E()
17  *
18  * Overview:	88E we can not write 0xc80/c94/c4c/ 0xa2x. Instead of write TX agc.
19  *				No matter OFDM & CCK use the same method.
20  *
21  * Input:		NONE
22  *
23  * Output:		NONE
24  *
25  * Return:		NONE
26  *
27  * Revised History:
28  *	When		Who		Remark
29  *	04/23/2012	MHC		Create Version 0.
30  *	04/23/2012	MHC		Adjust TX agc directly not throughput BB digital.
31  *
32  *---------------------------------------------------------------------------*/
ODM_TxPwrTrackAdjust88E(struct odm_dm_struct * dm_odm,u8 Type,u8 * pDirection,u32 * pOutWriteVal)33 void ODM_TxPwrTrackAdjust88E(struct odm_dm_struct *dm_odm, u8 Type,/*  0 = OFDM, 1 = CCK */
34 	u8 *pDirection, 		/*  1 = +(increase) 2 = -(decrease) */
35 	u32 *pOutWriteVal		/*  Tx tracking CCK/OFDM BB swing index adjust */
36 	)
37 {
38 	u8 pwr_value = 0;
39 	/*  Tx power tracking BB swing table. */
40 	/*  The base index = 12. +((12-n)/2)dB 13~?? = decrease tx pwr by -((n-12)/2)dB */
41 	if (Type == 0) {		/*  For OFDM afjust */
42 		if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
43 			*pDirection	= 1;
44 			pwr_value		= (dm_odm->BbSwingIdxOfdmBase - dm_odm->BbSwingIdxOfdm);
45 		} else {
46 			*pDirection	= 2;
47 			pwr_value		= (dm_odm->BbSwingIdxOfdm - dm_odm->BbSwingIdxOfdmBase);
48 		}
49 	} else if (Type == 1) {	/*  For CCK adjust. */
50 		if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
51 			*pDirection	= 1;
52 			pwr_value		= (dm_odm->BbSwingIdxCckBase - dm_odm->BbSwingIdxCck);
53 		} else {
54 			*pDirection	= 2;
55 			pwr_value		= (dm_odm->BbSwingIdxCck - dm_odm->BbSwingIdxCckBase);
56 		}
57 	}
58 
59 	/*  */
60 	/*  2012/04/25 MH According to Ed/Luke.Lees estimate for EVM the max tx power tracking */
61 	/*  need to be less than 6 power index for 88E. */
62 	/*  */
63 	if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *pDirection == 1)
64 		pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
65 
66 	*pOutWriteVal = pwr_value | (pwr_value << 8) | (pwr_value << 16) | (pwr_value << 24);
67 }	/*  ODM_TxPwrTrackAdjust88E */
68 
69 /*-----------------------------------------------------------------------------
70  * Function:	odm_TxPwrTrackSetPwr88E()
71  *
72  * Overview:	88E change all channel tx power accordign to flag.
73  *				OFDM & CCK are all different.
74  *
75  * Input:		NONE
76  *
77  * Output:		NONE
78  *
79  * Return:		NONE
80  *
81  * Revised History:
82  *	When		Who		Remark
83  *	04/23/2012	MHC		Create Version 0.
84  *
85  *---------------------------------------------------------------------------*/
odm_TxPwrTrackSetPwr88E(struct odm_dm_struct * dm_odm)86 static void odm_TxPwrTrackSetPwr88E(struct odm_dm_struct *dm_odm)
87 {
88 	if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
89 		PHY_SetTxPowerLevel8188E(dm_odm->Adapter, *dm_odm->pChannel);
90 		dm_odm->BbSwingFlagOfdm = false;
91 		dm_odm->BbSwingFlagCck	= false;
92 	}
93 }	/*  odm_TxPwrTrackSetPwr88E */
94 
95 /* 091212 chiyokolin */
96 void
odm_TXPowerTrackingCallback_ThermalMeter_8188E(struct adapter * Adapter)97 odm_TXPowerTrackingCallback_ThermalMeter_8188E(
98 	struct adapter *Adapter
99 	)
100 {
101 	struct hal_data_8188e *pHalData = &Adapter->haldata;
102 	u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, offset;
103 	u8 ThermalValue_AVG_count = 0;
104 	u32 ThermalValue_AVG = 0;
105 	s32 ele_D, TempCCk;
106 	s8 OFDM_index, CCK_index = 0;
107 	s8 OFDM_index_old = 0, CCK_index_old = 0;
108 	u32 i = 0, j = 0;
109 
110 	u8 OFDM_min_index = 6; /* OFDM BB Swing should be less than +3.0dB, which is required by Arthur */
111 	s8 OFDM_index_mapping[2][index_mapping_NUM_88E] = {
112 		{0, 0, 2, 3, 4, 4, 		/* 2.4G, decrease power */
113 		5, 6, 7, 7, 8, 9,
114 		10, 10, 11}, /*  For lower temperature, 20120220 updated on 20120220. */
115 		{0, 0, -1, -2, -3, -4, 		/* 2.4G, increase power */
116 		-4, -4, -4, -5, -7, -8,
117 		-9, -9, -10},
118 	};
119 	u8 Thermal_mapping[2][index_mapping_NUM_88E] = {
120 		{0, 2, 4, 6, 8, 10, 		/* 2.4G, decrease power */
121 		12, 14, 16, 18, 20, 22,
122 		24, 26, 27},
123 		{0, 2, 4, 6, 8, 10, 		/* 2.4G,, increase power */
124 		12, 14, 16, 18, 20, 22,
125 		25, 25, 25},
126 	};
127 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
128 
129 	/*  2012/04/25 MH Add for tx power tracking to set tx power in tx agc for 88E. */
130 	odm_TxPwrTrackSetPwr88E(dm_odm);
131 
132 	/*  <Kordan> RFCalibrateInfo.RegA24 will be initialized when ODM HW configuring, but MP configures with para files. */
133 	dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
134 
135 	ThermalValue = (u8)rtl8188e_PHY_QueryRFReg(Adapter, RF_T_METER_88E, 0xfc00); /* 0x42: RF Reg[15:10] 88E */
136 
137 	if (ThermalValue) {
138 		/* Query OFDM path A default setting */
139 		ele_D = rtl8188e_PHY_QueryBBReg(Adapter, rOFDM0_XATxIQImbalance, bMaskDWord) & bMaskOFDM_D;
140 		for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {	/* find the index */
141 			if (ele_D == (OFDMSwingTable[i] & bMaskOFDM_D)) {
142 				OFDM_index_old = (u8)i;
143 				dm_odm->BbSwingIdxOfdmBase = (u8)i;
144 				break;
145 			}
146 		}
147 
148 		/* Query CCK default setting From 0xa24 */
149 		TempCCk = dm_odm->RFCalibrateInfo.RegA24;
150 
151 		for (i = 0; i < CCK_TABLE_SIZE; i++) {
152 			if (memcmp((void *)&TempCCk, (void *)&cck_swing_table[i][2], 4)) {
153 				CCK_index_old = (u8)i;
154 				dm_odm->BbSwingIdxCckBase = (u8)i;
155 				break;
156 			}
157 		}
158 
159 		if (!dm_odm->RFCalibrateInfo.ThermalValue) {
160 			dm_odm->RFCalibrateInfo.ThermalValue = pHalData->EEPROMThermalMeter;
161 			dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
162 			dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
163 
164 			dm_odm->RFCalibrateInfo.OFDM_index = OFDM_index_old;
165 			dm_odm->RFCalibrateInfo.CCK_index = CCK_index_old;
166 		}
167 
168 		/* calculate average thermal meter */
169 		dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = ThermalValue;
170 		dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
171 		if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
172 			dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
173 
174 		for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
175 			if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
176 				ThermalValue_AVG += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
177 				ThermalValue_AVG_count++;
178 			}
179 		}
180 
181 		if (ThermalValue_AVG_count)
182 			ThermalValue = (u8)(ThermalValue_AVG / ThermalValue_AVG_count);
183 
184 		if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
185 			delta = ThermalValue > pHalData->EEPROMThermalMeter ?
186 				(ThermalValue - pHalData->EEPROMThermalMeter) :
187 				(pHalData->EEPROMThermalMeter - ThermalValue);
188 			dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
189 			dm_odm->RFCalibrateInfo.bDoneTxpower = false;
190 		} else if (dm_odm->RFCalibrateInfo.bDoneTxpower) {
191 			delta = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue) ?
192 				(ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue) :
193 				(dm_odm->RFCalibrateInfo.ThermalValue - ThermalValue);
194 		} else {
195 			delta = ThermalValue > pHalData->EEPROMThermalMeter ?
196 				(ThermalValue - pHalData->EEPROMThermalMeter) :
197 				(pHalData->EEPROMThermalMeter - ThermalValue);
198 		}
199 		delta_LCK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_LCK) ?
200 			    (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_LCK) :
201 			    (dm_odm->RFCalibrateInfo.ThermalValue_LCK - ThermalValue);
202 		delta_IQK = (ThermalValue > dm_odm->RFCalibrateInfo.ThermalValue_IQK) ?
203 			    (ThermalValue - dm_odm->RFCalibrateInfo.ThermalValue_IQK) :
204 			    (dm_odm->RFCalibrateInfo.ThermalValue_IQK - ThermalValue);
205 
206 		if ((delta_LCK >= 8)) { /*  Delta temperature is equal to or larger than 20 centigrade. */
207 			dm_odm->RFCalibrateInfo.ThermalValue_LCK = ThermalValue;
208 			PHY_LCCalibrate_8188E(Adapter);
209 		}
210 
211 		if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
212 			delta = ThermalValue > pHalData->EEPROMThermalMeter ?
213 				(ThermalValue - pHalData->EEPROMThermalMeter) :
214 				(pHalData->EEPROMThermalMeter - ThermalValue);
215 			/* calculate new OFDM / CCK offset */
216 			if (ThermalValue > pHalData->EEPROMThermalMeter)
217 				j = 1;
218 			else
219 				j = 0;
220 			for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
221 				if (delta < Thermal_mapping[j][offset]) {
222 					if (offset != 0)
223 						offset--;
224 					break;
225 				}
226 			}
227 			if (offset >= index_mapping_NUM_88E)
228 				offset = index_mapping_NUM_88E - 1;
229 			OFDM_index = dm_odm->RFCalibrateInfo.OFDM_index + OFDM_index_mapping[j][offset];
230 			CCK_index = dm_odm->RFCalibrateInfo.CCK_index + OFDM_index_mapping[j][offset];
231 
232 			if (OFDM_index > OFDM_TABLE_SIZE_92D - 1)
233 				OFDM_index = OFDM_TABLE_SIZE_92D - 1;
234 			else if (OFDM_index < OFDM_min_index)
235 				OFDM_index = OFDM_min_index;
236 
237 			if (CCK_index > CCK_TABLE_SIZE - 1)
238 				CCK_index = CCK_TABLE_SIZE - 1;
239 			else if (CCK_index < 0)
240 				CCK_index = 0;
241 
242 			/* 2 temporarily remove bNOPG */
243 			/* Config by SwingTable */
244 			if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
245 				dm_odm->RFCalibrateInfo.bDoneTxpower = true;
246 
247 				/*  Revse TX power table. */
248 				dm_odm->BbSwingIdxOfdm		= (u8)OFDM_index;
249 				dm_odm->BbSwingIdxCck		= (u8)CCK_index;
250 
251 				if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
252 					dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
253 					dm_odm->BbSwingFlagOfdm = true;
254 				}
255 
256 				if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
257 					dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
258 					dm_odm->BbSwingFlagCck = true;
259 				}
260 			}
261 		}
262 
263 		if (delta_IQK >= 8) { /*  Delta temperature is equal to or larger than 20 centigrade. */
264 			dm_odm->RFCalibrateInfo.ThermalValue_IQK = ThermalValue;
265 			PHY_IQCalibrate_8188E(Adapter, false);
266 		}
267 		/* update thermal meter value */
268 		if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
269 			dm_odm->RFCalibrateInfo.ThermalValue = ThermalValue;
270 	}
271 }
272 
273 /* 1 7.	IQK */
274 #define MAX_TOLERANCE		5
275 #define IQK_DELAY_TIME		1		/* ms */
276 
277 static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
phy_PathA_IQK_8188E(struct adapter * adapt)278 phy_PathA_IQK_8188E(struct adapter *adapt)
279 {
280 	u32 regeac, regE94, regE9C;
281 	u8 result = 0x00;
282 
283 	/* 1 Tx IQK */
284 	/* path-A IQK setting */
285 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
286 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
287 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
288 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
289 
290 	/* LO calibration setting */
291 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
292 
293 	/* One shot, path A LOK & IQK */
294 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
295 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
296 
297 	/*  delay x ms */
298 	/* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
299 	mdelay(IQK_DELAY_TIME_88E);
300 
301 	/*  Check failed */
302 	regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
303 	regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
304 	regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
305 
306 	if (!(regeac & BIT(28)) &&
307 	    (((regE94 & 0x03FF0000) >> 16) != 0x142) &&
308 	    (((regE9C & 0x03FF0000) >> 16) != 0x42))
309 		result |= 0x01;
310 	return result;
311 }
312 
313 static u8 /* bit0 = 1 => Tx OK, bit1 = 1 => Rx OK */
phy_PathA_RxIQK(struct adapter * adapt)314 phy_PathA_RxIQK(struct adapter *adapt)
315 {
316 	u32 regeac, regE94, regE9C, regEA4, u4tmp;
317 	u8 result = 0x00;
318 
319 	/* 1 Get TXIMR setting */
320 	/* modify RXIQK mode table */
321 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
322 	rtl8188e_PHY_SetRFReg(adapt, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
323 	rtl8188e_PHY_SetRFReg(adapt, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
324 	rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
325 	rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
326 
327 	/* PA,PAD off */
328 	rtl8188e_PHY_SetRFReg(adapt, 0xdf, bRFRegOffsetMask, 0x980);
329 	rtl8188e_PHY_SetRFReg(adapt, 0x56, bRFRegOffsetMask, 0x51000);
330 
331 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
332 
333 	/* IQK setting */
334 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
335 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
336 
337 	/* path-A IQK setting */
338 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
339 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
340 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
341 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
342 
343 	/* LO calibration setting */
344 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
345 
346 	/* One shot, path A LOK & IQK */
347 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
348 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
349 
350 	/*  delay x ms */
351 	mdelay(IQK_DELAY_TIME_88E);
352 
353 	/*  Check failed */
354 	regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
355 	regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
356 	regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
357 
358 	if (!(regeac & BIT(28)) &&
359 	    (((regE94 & 0x03FF0000) >> 16) != 0x142) &&
360 	    (((regE9C & 0x03FF0000) >> 16) != 0x42))
361 		result |= 0x01;
362 	else							/* if Tx not OK, ignore Rx */
363 		return result;
364 
365 	u4tmp = 0x80007C00 | (regE94 & 0x3FF0000)  | ((regE9C & 0x3FF0000) >> 16);
366 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, u4tmp);
367 
368 	/* 1 RX IQK */
369 	/* modify RXIQK mode table */
370 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
371 	rtl8188e_PHY_SetRFReg(adapt, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
372 	rtl8188e_PHY_SetRFReg(adapt, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
373 	rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
374 	rtl8188e_PHY_SetRFReg(adapt, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
375 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
376 
377 	/* IQK setting */
378 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
379 
380 	/* path-A IQK setting */
381 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
382 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
383 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
384 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
385 
386 	/* LO calibration setting */
387 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
388 
389 	/* One shot, path A LOK & IQK */
390 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
391 	rtl8188e_PHY_SetBBReg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
392 
393 	/*  delay x ms */
394 	/* PlatformStallExecution(IQK_DELAY_TIME_88E*1000); */
395 	mdelay(IQK_DELAY_TIME_88E);
396 
397 	/*  Check failed */
398 	regeac = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
399 	regE94 = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
400 	regE9C = rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
401 	regEA4 = rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
402 
403 	/* reload RF 0xdf */
404 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
405 	rtl8188e_PHY_SetRFReg(adapt, 0xdf, bRFRegOffsetMask, 0x180);
406 
407 	if (!(regeac & BIT(27)) &&		/* if Tx is OK, check whether Rx is OK */
408 	    (((regEA4 & 0x03FF0000) >> 16) != 0x132) &&
409 	    (((regeac & 0x03FF0000) >> 16) != 0x36))
410 		result |= 0x02;
411 
412 	return result;
413 }
414 
patha_fill_iqk(struct adapter * adapt,bool iqkok,s32 result[][8],u8 final_candidate,bool txonly)415 static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8], u8 final_candidate, bool txonly)
416 {
417 	u32 Oldval_0, X, TX0_A, reg;
418 	s32 Y, TX0_C;
419 
420 	if (final_candidate == 0xFF) {
421 		return;
422 	} else if (iqkok) {
423 		Oldval_0 = (rtl8188e_PHY_QueryBBReg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
424 
425 		X = result[final_candidate][0];
426 		if ((X & 0x00000200) != 0)
427 			X = X | 0xFFFFFC00;
428 		TX0_A = (X * Oldval_0) >> 8;
429 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
430 
431 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_ECCAThreshold, BIT(31), ((X * Oldval_0 >> 7) & 0x1));
432 
433 		Y = result[final_candidate][1];
434 		if ((Y & 0x00000200) != 0)
435 			Y = Y | 0xFFFFFC00;
436 
437 		TX0_C = (Y * Oldval_0) >> 8;
438 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XCTxAFE, 0xF0000000, ((TX0_C & 0x3C0) >> 6));
439 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000, (TX0_C & 0x3F));
440 
441 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_ECCAThreshold, BIT(29), ((Y * Oldval_0 >> 7) & 0x1));
442 
443 		if (txonly)
444 			return;
445 
446 		reg = result[final_candidate][2];
447 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
448 
449 		reg = result[final_candidate][3] & 0x3F;
450 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
451 
452 		reg = (result[final_candidate][3] >> 6) & 0xF;
453 		rtl8188e_PHY_SetBBReg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
454 	}
455 }
456 
_PHY_SaveADDARegisters(struct adapter * adapt,u32 * ADDAReg,u32 * ADDABackup,u32 RegisterNum)457 void _PHY_SaveADDARegisters(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum)
458 {
459 	u32 i;
460 
461 	for (i = 0; i < RegisterNum; i++) {
462 		ADDABackup[i] = rtl8188e_PHY_QueryBBReg(adapt, ADDAReg[i], bMaskDWord);
463 	}
464 }
465 
466 /* FIXME: return an error to caller */
_PHY_SaveMACRegisters(struct adapter * adapt,u32 * MACReg,u32 * MACBackup)467 static void _PHY_SaveMACRegisters(
468 		struct adapter *adapt,
469 		u32 *MACReg,
470 		u32 *MACBackup
471 	)
472 {
473 	u32 i;
474 	int res;
475 
476 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
477 		u8 reg;
478 
479 		res = rtw_read8(adapt, MACReg[i], &reg);
480 		if (res)
481 			return;
482 
483 		MACBackup[i] = reg;
484 	}
485 
486 	res = rtw_read32(adapt, MACReg[i], MACBackup + i);
487 	(void)res;
488 }
489 
reload_adda_reg(struct adapter * adapt,u32 * ADDAReg,u32 * ADDABackup,u32 RegiesterNum)490 static void reload_adda_reg(struct adapter *adapt, u32 *ADDAReg, u32 *ADDABackup, u32 RegiesterNum)
491 {
492 	u32 i;
493 
494 	for (i = 0; i < RegiesterNum; i++)
495 		rtl8188e_PHY_SetBBReg(adapt, ADDAReg[i], bMaskDWord, ADDABackup[i]);
496 }
497 
498 static void
_PHY_ReloadMACRegisters(struct adapter * adapt,u32 * MACReg,u32 * MACBackup)499 _PHY_ReloadMACRegisters(
500 		struct adapter *adapt,
501 		u32 *MACReg,
502 		u32 *MACBackup
503 	)
504 {
505 	u32 i;
506 
507 	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
508 		rtw_write8(adapt, MACReg[i], (u8)MACBackup[i]);
509 
510 	rtw_write32(adapt, MACReg[i], MACBackup[i]);
511 }
512 
513 static void
_PHY_PathADDAOn(struct adapter * adapt,u32 * ADDAReg)514 _PHY_PathADDAOn(
515 		struct adapter *adapt,
516 		u32 *ADDAReg)
517 {
518 	u32 i;
519 
520 	rtl8188e_PHY_SetBBReg(adapt, ADDAReg[0], bMaskDWord, 0x0b1b25a0);
521 
522 	for (i = 1; i < IQK_ADDA_REG_NUM; i++)
523 		rtl8188e_PHY_SetBBReg(adapt, ADDAReg[i], bMaskDWord, 0x0bdb25a0);
524 }
525 
526 void
_PHY_MACSettingCalibration(struct adapter * adapt,u32 * MACReg,u32 * MACBackup)527 _PHY_MACSettingCalibration(
528 		struct adapter *adapt,
529 		u32 *MACReg,
530 		u32 *MACBackup
531 	)
532 {
533 	u32 i = 0;
534 
535 	rtw_write8(adapt, MACReg[i], 0x3F);
536 
537 	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
538 		rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i] & (~BIT(3))));
539 
540 	rtw_write8(adapt, MACReg[i], (u8)(MACBackup[i] & (~BIT(5))));
541 }
542 
_PHY_PIModeSwitch(struct adapter * adapt,bool PIMode)543 static void _PHY_PIModeSwitch(
544 		struct adapter *adapt,
545 		bool PIMode
546 	)
547 {
548 	u32 mode;
549 
550 	mode = PIMode ? 0x01000100 : 0x01000000;
551 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
552 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
553 }
554 
phy_SimularityCompare_8188E(struct adapter * adapt,s32 resulta[][8],u8 c1,u8 c2)555 static bool phy_SimularityCompare_8188E(
556 		struct adapter *adapt,
557 		s32 resulta[][8],
558 		u8  c1,
559 		u8  c2
560 	)
561 {
562 	u32 i, j, diff, sim_bitmap, bound = 0;
563 	u8 final_candidate[2] = {0xFF, 0xFF};	/* for path A and path B */
564 	bool result = true;
565 	s32 tmp1 = 0, tmp2 = 0;
566 
567 	bound = 4;
568 	sim_bitmap = 0;
569 
570 	for (i = 0; i < bound; i++) {
571 		if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
572 			if ((resulta[c1][i] & 0x00000200) != 0)
573 				tmp1 = resulta[c1][i] | 0xFFFFFC00;
574 			else
575 				tmp1 = resulta[c1][i];
576 
577 			if ((resulta[c2][i] & 0x00000200) != 0)
578 				tmp2 = resulta[c2][i] | 0xFFFFFC00;
579 			else
580 				tmp2 = resulta[c2][i];
581 		} else {
582 			tmp1 = resulta[c1][i];
583 			tmp2 = resulta[c2][i];
584 		}
585 
586 		diff = (tmp1 > tmp2) ? (tmp1 - tmp2) : (tmp2 - tmp1);
587 
588 		if (diff > MAX_TOLERANCE) {
589 			if ((i == 2 || i == 6) && !sim_bitmap) {
590 				if (resulta[c1][i] + resulta[c1][i + 1] == 0)
591 					final_candidate[(i / 4)] = c2;
592 				else if (resulta[c2][i] + resulta[c2][i + 1] == 0)
593 					final_candidate[(i / 4)] = c1;
594 				else
595 					sim_bitmap = sim_bitmap | (1 << i);
596 			} else {
597 				sim_bitmap = sim_bitmap | (1 << i);
598 			}
599 		}
600 	}
601 
602 	if (sim_bitmap == 0) {
603 		for (i = 0; i < (bound / 4); i++) {
604 			if (final_candidate[i] != 0xFF) {
605 				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
606 					resulta[3][j] = resulta[final_candidate[i]][j];
607 				result = false;
608 			}
609 		}
610 		return result;
611 	} else {
612 		if (!(sim_bitmap & 0x03)) {		   /* path A TX OK */
613 			for (i = 0; i < 2; i++)
614 				resulta[3][i] = resulta[c1][i];
615 		}
616 		if (!(sim_bitmap & 0x0c)) {		   /* path A RX OK */
617 			for (i = 2; i < 4; i++)
618 				resulta[3][i] = resulta[c1][i];
619 		}
620 
621 		if (!(sim_bitmap & 0x30)) { /* path B TX OK */
622 			for (i = 4; i < 6; i++)
623 				resulta[3][i] = resulta[c1][i];
624 		}
625 
626 		if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
627 			for (i = 6; i < 8; i++)
628 				resulta[3][i] = resulta[c1][i];
629 		}
630 		return false;
631 	}
632 }
633 
phy_IQCalibrate_8188E(struct adapter * adapt,s32 result[][8],u8 t)634 static void phy_IQCalibrate_8188E(struct adapter *adapt, s32 result[][8], u8 t)
635 {
636 	struct hal_data_8188e *pHalData = &adapt->haldata;
637 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
638 	u32 i;
639 	u8 PathAOK;
640 	u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
641 						rFPGA0_XCD_SwitchControl, rBlue_Tooth,
642 						rRx_Wait_CCA, 	rTx_CCK_RFON,
643 						rTx_CCK_BBON, rTx_OFDM_RFON,
644 						rTx_OFDM_BBON, rTx_To_Rx,
645 						rTx_To_Tx, 	rRx_CCK,
646 						rRx_OFDM, 	rRx_Wait_RIFS,
647 						rRx_TO_Rx, 	rStandby,
648 						rSleep, 			rPMPD_ANAEN };
649 	u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
650 						REG_TXPAUSE, 	REG_BCN_CTRL,
651 						REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
652 
653 	/* since 92C & 92D have the different define in IQK_BB_REG */
654 	u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
655 							rOFDM0_TRxPathEnable, 	rOFDM0_TRMuxPar,
656 							rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
657 							rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
658 							rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
659 							};
660 	u32 retryCount = 2;
661 	/*  Note: IQ calibration must be performed after loading */
662 	/* 		PHY_REG.txt , and radio_a, radio_b.txt */
663 
664 	if (t == 0) {
665 		/*  Save ADDA parameters, turn Path A ADDA on */
666 		_PHY_SaveADDARegisters(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
667 		_PHY_SaveMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
668 		_PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
669 	}
670 
671 	_PHY_PathADDAOn(adapt, ADDA_REG);
672 	if (t == 0)
673 		dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)rtl8188e_PHY_QueryBBReg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
674 
675 	if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
676 		/*  Switch BB to PI mode to do IQ Calibration. */
677 		_PHY_PIModeSwitch(adapt, true);
678 	}
679 
680 	/* BB setting */
681 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
682 	rtl8188e_PHY_SetBBReg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
683 	rtl8188e_PHY_SetBBReg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
684 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
685 
686 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
687 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
688 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
689 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
690 
691 	/* MAC settings */
692 	_PHY_MACSettingCalibration(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
693 
694 	/* Page B init */
695 	/* AP or IQK */
696 	rtl8188e_PHY_SetBBReg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
697 
698 
699 	/*  IQ calibration setting */
700 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
701 	rtl8188e_PHY_SetBBReg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
702 	rtl8188e_PHY_SetBBReg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
703 
704 	for (i = 0; i < retryCount; i++) {
705 		PathAOK = phy_PathA_IQK_8188E(adapt);
706 		if (PathAOK == 0x01) {
707 			result[t][0] = (rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_Before_IQK_A, bMaskDWord) & 0x3FF0000) >> 16;
708 			result[t][1] = (rtl8188e_PHY_QueryBBReg(adapt, rTx_Power_After_IQK_A, bMaskDWord) & 0x3FF0000) >> 16;
709 			break;
710 		}
711 	}
712 
713 	for (i = 0; i < retryCount; i++) {
714 		PathAOK = phy_PathA_RxIQK(adapt);
715 		if (PathAOK == 0x03) {
716 			result[t][2] = (rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16;
717 			result[t][3] = (rtl8188e_PHY_QueryBBReg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord) & 0x3FF0000) >> 16;
718 			break;
719 		}
720 	}
721 
722 	/* Back to BB mode, load original value */
723 	rtl8188e_PHY_SetBBReg(adapt, rFPGA0_IQK, bMaskDWord, 0);
724 
725 	if (t != 0) {
726 		if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
727 			/*  Switch back BB to SI mode after finish IQ Calibration. */
728 			_PHY_PIModeSwitch(adapt, false);
729 		}
730 
731 		/*  Reload ADDA power saving parameters */
732 		reload_adda_reg(adapt, ADDA_REG, dm_odm->RFCalibrateInfo.ADDA_backup, IQK_ADDA_REG_NUM);
733 
734 		/*  Reload MAC parameters */
735 		_PHY_ReloadMACRegisters(adapt, IQK_MAC_REG, dm_odm->RFCalibrateInfo.IQK_MAC_backup);
736 
737 		reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
738 
739 		/*  Restore RX initial gain */
740 		rtl8188e_PHY_SetBBReg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord, 0x00032ed3);
741 
742 		/* load 0xe30 IQC default value */
743 		rtl8188e_PHY_SetBBReg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
744 		rtl8188e_PHY_SetBBReg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
745 	}
746 }
747 
phy_LCCalibrate_8188E(struct adapter * adapt)748 static void phy_LCCalibrate_8188E(struct adapter *adapt)
749 {
750 	u8 tmpreg;
751 	u32 RF_Amode = 0, LC_Cal;
752 	int res;
753 
754 	/* Check continuous TX and Packet TX */
755 	res = rtw_read8(adapt, 0xd03, &tmpreg);
756 	if (res)
757 		return;
758 
759 	if ((tmpreg & 0x70) != 0)			/* Deal with contisuous TX case */
760 		rtw_write8(adapt, 0xd03, tmpreg & 0x8F);	/* disable all continuous TX */
761 	else							/*  Deal with Packet TX case */
762 		rtw_write8(adapt, REG_TXPAUSE, 0xFF);		/*  block all queues */
763 
764 	if ((tmpreg & 0x70) != 0) {
765 		/* 1. Read original RF mode */
766 		/* Path-A */
767 		RF_Amode = rtl8188e_PHY_QueryRFReg(adapt, RF_AC, bMask12Bits);
768 
769 		/* 2. Set RF mode = standby mode */
770 		/* Path-A */
771 		rtl8188e_PHY_SetRFReg(adapt, RF_AC, bMask12Bits, (RF_Amode & 0x8FFFF) | 0x10000);
772 	}
773 
774 	/* 3. Read RF reg18 */
775 	LC_Cal = rtl8188e_PHY_QueryRFReg(adapt, RF_CHNLBW, bMask12Bits);
776 
777 	/* 4. Set LC calibration begin	bit15 */
778 	rtl8188e_PHY_SetRFReg(adapt, RF_CHNLBW, bMask12Bits, LC_Cal | 0x08000);
779 
780 	msleep(100);
781 
782 	/* Restore original situation */
783 	if ((tmpreg & 0x70) != 0) {
784 		/* Deal with continuous TX case */
785 		/* Path-A */
786 		rtw_write8(adapt, 0xd03, tmpreg);
787 		rtl8188e_PHY_SetRFReg(adapt, RF_AC, bMask12Bits, RF_Amode);
788 	} else {
789 		/*  Deal with Packet TX case */
790 		rtw_write8(adapt, REG_TXPAUSE, 0x00);
791 	}
792 }
793 
PHY_IQCalibrate_8188E(struct adapter * adapt,bool recovery)794 void PHY_IQCalibrate_8188E(struct adapter *adapt, bool recovery)
795 {
796 	struct hal_data_8188e *pHalData = &adapt->haldata;
797 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
798 	s32 result[4][8];	/* last is final result */
799 	u8 i, final_candidate;
800 	bool pathaok;
801 	s32 RegE94, RegE9C, RegEA4, RegEB4, RegEBC;
802 	bool is12simular, is13simular, is23simular;
803 	u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
804 		rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
805 		rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
806 		rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
807 		rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
808 		rOFDM0_RxIQExtAnta};
809 
810 	if (recovery) {
811 		reload_adda_reg(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
812 		return;
813 	}
814 
815 	for (i = 0; i < 8; i++) {
816 		result[0][i] = 0;
817 		result[1][i] = 0;
818 		result[2][i] = 0;
819 		if ((i == 0) || (i == 2) || (i == 4)  || (i == 6))
820 			result[3][i] = 0x100;
821 		else
822 			result[3][i] = 0;
823 	}
824 	final_candidate = 0xff;
825 	pathaok = false;
826 	is12simular = false;
827 	is23simular = false;
828 	is13simular = false;
829 
830 	for (i = 0; i < 3; i++) {
831 		phy_IQCalibrate_8188E(adapt, result, i);
832 
833 		if (i == 1) {
834 			is12simular = phy_SimularityCompare_8188E(adapt, result, 0, 1);
835 			if (is12simular) {
836 				final_candidate = 0;
837 				break;
838 			}
839 		}
840 
841 		if (i == 2) {
842 			is13simular = phy_SimularityCompare_8188E(adapt, result, 0, 2);
843 			if (is13simular) {
844 				final_candidate = 0;
845 
846 				break;
847 			}
848 			is23simular = phy_SimularityCompare_8188E(adapt, result, 1, 2);
849 			if (is23simular) {
850 				final_candidate = 1;
851 			} else {
852 				final_candidate = 3;
853 			}
854 		}
855 	}
856 
857 	for (i = 0; i < 4; i++) {
858 		RegE94 = result[i][0];
859 		RegE9C = result[i][1];
860 		RegEA4 = result[i][2];
861 		RegEB4 = result[i][4];
862 		RegEBC = result[i][5];
863 	}
864 
865 	if (final_candidate != 0xff) {
866 		RegE94 = result[final_candidate][0];
867 		RegE9C = result[final_candidate][1];
868 		RegEA4 = result[final_candidate][2];
869 		RegEB4 = result[final_candidate][4];
870 		RegEBC = result[final_candidate][5];
871 		dm_odm->RFCalibrateInfo.RegE94 = RegE94;
872 		dm_odm->RFCalibrateInfo.RegE9C = RegE9C;
873 		dm_odm->RFCalibrateInfo.RegEB4 = RegEB4;
874 		dm_odm->RFCalibrateInfo.RegEBC = RegEBC;
875 		pathaok = true;
876 	} else {
877 		dm_odm->RFCalibrateInfo.RegE94 = 0x100;
878 		dm_odm->RFCalibrateInfo.RegEB4 = 0x100;	/* X default value */
879 		dm_odm->RFCalibrateInfo.RegE9C = 0x0;
880 		dm_odm->RFCalibrateInfo.RegEBC = 0x0;	/* Y default value */
881 	}
882 	if (RegE94 != 0)
883 		patha_fill_iqk(adapt, pathaok, result, final_candidate, (RegEA4 == 0));
884 
885 /* To Fix BSOD when final_candidate is 0xff */
886 /* by sherry 20120321 */
887 	if (final_candidate < 4) {
888 		for (i = 0; i < IQK_Matrix_REG_NUM; i++)
889 			dm_odm->RFCalibrateInfo.IQKMatrixRegSetting.Value[0][i] = result[final_candidate][i];
890 		dm_odm->RFCalibrateInfo.IQKMatrixRegSetting.bIQKDone = true;
891 	}
892 
893 	_PHY_SaveADDARegisters(adapt, IQK_BB_REG_92C, dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
894 }
895 
PHY_LCCalibrate_8188E(struct adapter * adapt)896 void PHY_LCCalibrate_8188E(struct adapter *adapt)
897 {
898 	u32 timeout = 2000, timecount = 0;
899 	struct hal_data_8188e *pHalData = &adapt->haldata;
900 	struct odm_dm_struct *dm_odm = &pHalData->odmpriv;
901 
902 	while (*dm_odm->pbScanInProcess && timecount < timeout) {
903 		mdelay(50);
904 		timecount += 50;
905 	}
906 
907 	phy_LCCalibrate_8188E(adapt);
908 }
909