1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  ******************************************************************************/
15 /*  Description: */
16 /*  This file is for 92CE/92CU dynamic mechanism only */
17 
18 /*  include files */
19 
20 #include "odm_precomp.h"
21 #include <usb_ops_linux.h>
22 
23 #define		DPK_DELTA_MAPPING_NUM	13
24 #define		index_mapping_HP_NUM	15
25 /* 091212 chiyokolin */
26 static void
odm_TXPowerTrackingCallback_ThermalMeter_92C(struct rtw_adapter * Adapter)27 odm_TXPowerTrackingCallback_ThermalMeter_92C(struct rtw_adapter *Adapter)
28 {
29 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
30 	struct dm_priv *pdmpriv = &pHalData->dmpriv;
31 	u8 ThermalValue = 0, delta, delta_LCK, delta_IQK, delta_HP;
32 	int ele_A, ele_D, TempCCk, X, value32;
33 	int Y, ele_C;
34 	s8 OFDM_index[2], CCK_index = 0, OFDM_index_old[2] = {0};
35 	s8 CCK_index_old = 0;
36 	int i = 0;
37 	u8 OFDM_min_index = 6, rf; /* OFDM BB Swing should be less than +3.0dB*/
38 	u8 ThermalValue_HP_count = 0;
39 	u32 ThermalValue_HP = 0;
40 	s32 index_mapping_HP[index_mapping_HP_NUM] = {
41 		0, 1, 3, 4, 6,
42 		7, 9, 10, 12, 13,
43 		15, 16, 18, 19, 21
44 	};
45 	s8 index_HP;
46 
47 	pdmpriv->TXPowerTrackingCallbackCnt++;	/* cosa add for debug */
48 	pdmpriv->bTXPowerTrackingInit = true;
49 
50 	if (pHalData->CurrentChannel == 14 && !pdmpriv->bCCKinCH14)
51 		pdmpriv->bCCKinCH14 = true;
52 	else if (pHalData->CurrentChannel != 14 && pdmpriv->bCCKinCH14)
53 		pdmpriv->bCCKinCH14 = false;
54 
55 	ThermalValue = (u8)PHY_QueryRFReg(Adapter, RF_PATH_A, RF_T_METER,
56 					  0x1f);/*  0x24: RF Reg[4:0]	 */
57 
58 	rtl8723a_phy_ap_calibrate(Adapter, (ThermalValue -
59 				  pHalData->EEPROMThermalMeter));
60 
61 	if (pHalData->rf_type == RF_2T2R)
62 		rf = 2;
63 	else
64 		rf = 1;
65 
66 	if (ThermalValue) {
67 		/* Query OFDM path A default setting	 */
68 		ele_D = rtl8723au_read32(Adapter, rOFDM0_XATxIQImbalance) &
69 			bMaskOFDM_D;
70 		for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) {
71 			/* find the index */
72 			if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
73 				OFDM_index_old[0] = (u8)i;
74 				break;
75 			}
76 		}
77 
78 		/* Query OFDM path B default setting  */
79 		if (pHalData->rf_type == RF_2T2R) {
80 			ele_D = rtl8723au_read32(Adapter,
81 						 rOFDM0_XBTxIQImbalance);
82 			ele_D &= bMaskOFDM_D;
83 			for (i = 0; i < OFDM_TABLE_SIZE_92C; i++) {	/* find the index  */
84 				if (ele_D == (OFDMSwingTable23A[i]&bMaskOFDM_D)) {
85 					OFDM_index_old[1] = (u8)i;
86 					break;
87 				}
88 			}
89 		}
90 
91 		/* Query CCK default setting From 0xa24 */
92 		TempCCk = rtl8723au_read32(Adapter, rCCK0_TxFilter2) & bMaskCCK;
93 		for (i = 0 ; i < CCK_TABLE_SIZE ; i++) {
94 			if (pdmpriv->bCCKinCH14) {
95 				if (!memcmp(&TempCCk,
96 					    &CCKSwingTable_Ch1423A[i][2], 4)) {
97 					CCK_index_old = (u8)i;
98 					break;
99 				}
100 			} else {
101 				if (!memcmp(&TempCCk,
102 					    &CCKSwingTable_Ch1_Ch1323A[i][2], 4)) {
103 					CCK_index_old = (u8)i;
104 					break;
105 				}
106 			}
107 		}
108 
109 		if (!pdmpriv->ThermalValue) {
110 			pdmpriv->ThermalValue = pHalData->EEPROMThermalMeter;
111 			pdmpriv->ThermalValue_LCK = ThermalValue;
112 			pdmpriv->ThermalValue_IQK = ThermalValue;
113 			pdmpriv->ThermalValue_DPK = pHalData->EEPROMThermalMeter;
114 
115 			for (i = 0; i < rf; i++) {
116 				pdmpriv->OFDM_index_HP[i] = OFDM_index_old[i];
117 				pdmpriv->OFDM_index[i] = OFDM_index_old[i];
118 			}
119 			pdmpriv->CCK_index_HP = CCK_index_old;
120 			pdmpriv->CCK_index = CCK_index_old;
121 		}
122 
123 		if (pHalData->BoardType == BOARD_USB_High_PA) {
124 			pdmpriv->ThermalValue_HP[pdmpriv->ThermalValue_HP_index] = ThermalValue;
125 			pdmpriv->ThermalValue_HP_index++;
126 			if (pdmpriv->ThermalValue_HP_index == HP_THERMAL_NUM)
127 				pdmpriv->ThermalValue_HP_index = 0;
128 
129 			for (i = 0; i < HP_THERMAL_NUM; i++) {
130 				if (pdmpriv->ThermalValue_HP[i]) {
131 					ThermalValue_HP += pdmpriv->ThermalValue_HP[i];
132 					ThermalValue_HP_count++;
133 				}
134 			}
135 
136 			if (ThermalValue_HP_count)
137 				ThermalValue = (u8)(ThermalValue_HP / ThermalValue_HP_count);
138 		}
139 
140 		delta = (ThermalValue > pdmpriv->ThermalValue) ?
141 			(ThermalValue - pdmpriv->ThermalValue) :
142 			(pdmpriv->ThermalValue - ThermalValue);
143 		if (pHalData->BoardType == BOARD_USB_High_PA) {
144 			if (pdmpriv->bDoneTxpower)
145 				delta_HP = (ThermalValue > pdmpriv->ThermalValue) ?
146 					   (ThermalValue - pdmpriv->ThermalValue) :
147 					   (pdmpriv->ThermalValue - ThermalValue);
148 			else
149 				delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ?
150 					   (ThermalValue - pHalData->EEPROMThermalMeter) :
151 					   (pHalData->EEPROMThermalMeter - ThermalValue);
152 		} else {
153 			delta_HP = 0;
154 		}
155 		delta_LCK = (ThermalValue > pdmpriv->ThermalValue_LCK) ?
156 			    (ThermalValue - pdmpriv->ThermalValue_LCK) :
157 			    (pdmpriv->ThermalValue_LCK - ThermalValue);
158 		delta_IQK = (ThermalValue > pdmpriv->ThermalValue_IQK) ?
159 			    (ThermalValue - pdmpriv->ThermalValue_IQK) :
160 			    (pdmpriv->ThermalValue_IQK - ThermalValue);
161 
162 		if (delta_LCK > 1) {
163 			pdmpriv->ThermalValue_LCK = ThermalValue;
164 			rtl8723a_phy_lc_calibrate(Adapter);
165 		}
166 
167 		if ((delta > 0 || delta_HP > 0) && pdmpriv->TxPowerTrackControl) {
168 			if (pHalData->BoardType == BOARD_USB_High_PA) {
169 				pdmpriv->bDoneTxpower = true;
170 				delta_HP = ThermalValue > pHalData->EEPROMThermalMeter ?
171 					   (ThermalValue - pHalData->EEPROMThermalMeter) :
172 					   (pHalData->EEPROMThermalMeter - ThermalValue);
173 
174 				if (delta_HP > index_mapping_HP_NUM-1)
175 					index_HP = index_mapping_HP[index_mapping_HP_NUM-1];
176 				else
177 					index_HP = index_mapping_HP[delta_HP];
178 
179 				if (ThermalValue > pHalData->EEPROMThermalMeter) {
180 					/* set larger Tx power */
181 					for (i = 0; i < rf; i++)
182 						OFDM_index[i] = pdmpriv->OFDM_index_HP[i] - index_HP;
183 					CCK_index = pdmpriv->CCK_index_HP - index_HP;
184 				} else {
185 					for (i = 0; i < rf; i++)
186 						OFDM_index[i] = pdmpriv->OFDM_index_HP[i] + index_HP;
187 					CCK_index = pdmpriv->CCK_index_HP + index_HP;
188 				}
189 
190 				delta_HP = (ThermalValue > pdmpriv->ThermalValue) ?
191 					   (ThermalValue - pdmpriv->ThermalValue) :
192 					   (pdmpriv->ThermalValue - ThermalValue);
193 			} else {
194 				if (ThermalValue > pdmpriv->ThermalValue) {
195 					for (i = 0; i < rf; i++)
196 						pdmpriv->OFDM_index[i] -= delta;
197 					pdmpriv->CCK_index -= delta;
198 				} else {
199 					for (i = 0; i < rf; i++)
200 						pdmpriv->OFDM_index[i] += delta;
201 					pdmpriv->CCK_index += delta;
202 				}
203 			}
204 
205 			/* no adjust */
206 			if (pHalData->BoardType != BOARD_USB_High_PA) {
207 				if (ThermalValue > pHalData->EEPROMThermalMeter) {
208 					for (i = 0; i < rf; i++)
209 						OFDM_index[i] = pdmpriv->OFDM_index[i]+1;
210 					CCK_index = pdmpriv->CCK_index+1;
211 				} else {
212 					for (i = 0; i < rf; i++)
213 						OFDM_index[i] = pdmpriv->OFDM_index[i];
214 					CCK_index = pdmpriv->CCK_index;
215 				}
216 			}
217 			for (i = 0; i < rf; i++) {
218 				if (OFDM_index[i] > (OFDM_TABLE_SIZE_92C-1))
219 					OFDM_index[i] = (OFDM_TABLE_SIZE_92C-1);
220 				else if (OFDM_index[i] < OFDM_min_index)
221 					OFDM_index[i] = OFDM_min_index;
222 			}
223 
224 			if (CCK_index > (CCK_TABLE_SIZE-1))
225 				CCK_index = CCK_TABLE_SIZE-1;
226 			else if (CCK_index < 0)
227 				CCK_index = 0;
228 		}
229 
230 		if (pdmpriv->TxPowerTrackControl &&
231 		    (delta != 0 || delta_HP != 0)) {
232 			/* Adujst OFDM Ant_A according to IQK result */
233 			ele_D = (OFDMSwingTable23A[OFDM_index[0]] & 0xFFC00000)>>22;
234 			X = pdmpriv->RegE94;
235 			Y = pdmpriv->RegE9C;
236 
237 			if (X != 0) {
238 				if ((X & 0x00000200) != 0)
239 					X = X | 0xFFFFFC00;
240 				ele_A = ((X * ele_D)>>8)&0x000003FF;
241 
242 				/* new element C = element D x Y */
243 				if ((Y & 0x00000200) != 0)
244 					Y = Y | 0xFFFFFC00;
245 				ele_C = ((Y * ele_D)>>8)&0x000003FF;
246 
247 				/* write new elements A, C, D to regC80 and regC94, element B is always 0 */
248 				value32 = (ele_D<<22)|((ele_C&0x3F)<<16)|ele_A;
249 				rtl8723au_write32(Adapter,
250 						  rOFDM0_XATxIQImbalance,
251 						  value32);
252 
253 				value32 = (ele_C&0x000003C0)>>6;
254 				PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE, bMaskH4Bits, value32);
255 
256 				value32 = ((X * ele_D)>>7)&0x01;
257 				PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold,
258 					     BIT(31), value32);
259 
260 				value32 = ((Y * ele_D)>>7)&0x01;
261 				PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold,
262 					     BIT(29), value32);
263 			} else {
264 				rtl8723au_write32(Adapter,
265 						  rOFDM0_XATxIQImbalance,
266 						  OFDMSwingTable23A[OFDM_index[0]]);
267 				PHY_SetBBReg(Adapter, rOFDM0_XCTxAFE,
268 					     bMaskH4Bits, 0x00);
269 				PHY_SetBBReg(Adapter, rOFDM0_ECCAThreshold,
270 					     BIT(31) | BIT(29), 0x00);
271 			}
272 
273 			/* Adjust CCK according to IQK result */
274 			if (!pdmpriv->bCCKinCH14) {
275 				rtl8723au_write8(Adapter, 0xa22, CCKSwingTable_Ch1_Ch1323A[CCK_index][0]);
276 				rtl8723au_write8(Adapter, 0xa23, CCKSwingTable_Ch1_Ch1323A[CCK_index][1]);
277 				rtl8723au_write8(Adapter, 0xa24, CCKSwingTable_Ch1_Ch1323A[CCK_index][2]);
278 				rtl8723au_write8(Adapter, 0xa25, CCKSwingTable_Ch1_Ch1323A[CCK_index][3]);
279 				rtl8723au_write8(Adapter, 0xa26, CCKSwingTable_Ch1_Ch1323A[CCK_index][4]);
280 				rtl8723au_write8(Adapter, 0xa27, CCKSwingTable_Ch1_Ch1323A[CCK_index][5]);
281 				rtl8723au_write8(Adapter, 0xa28, CCKSwingTable_Ch1_Ch1323A[CCK_index][6]);
282 				rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1_Ch1323A[CCK_index][7]);
283 			} else {
284 				rtl8723au_write8(Adapter, 0xa22, CCKSwingTable_Ch1423A[CCK_index][0]);
285 				rtl8723au_write8(Adapter, 0xa23, CCKSwingTable_Ch1423A[CCK_index][1]);
286 				rtl8723au_write8(Adapter, 0xa24, CCKSwingTable_Ch1423A[CCK_index][2]);
287 				rtl8723au_write8(Adapter, 0xa25, CCKSwingTable_Ch1423A[CCK_index][3]);
288 				rtl8723au_write8(Adapter, 0xa26, CCKSwingTable_Ch1423A[CCK_index][4]);
289 				rtl8723au_write8(Adapter, 0xa27, CCKSwingTable_Ch1423A[CCK_index][5]);
290 				rtl8723au_write8(Adapter, 0xa28, CCKSwingTable_Ch1423A[CCK_index][6]);
291 				rtl8723au_write8(Adapter, 0xa29, CCKSwingTable_Ch1423A[CCK_index][7]);
292 			}
293 
294 			if (pHalData->rf_type == RF_2T2R) {
295 				ele_D = (OFDMSwingTable23A[(u8)OFDM_index[1]] & 0xFFC00000)>>22;
296 
297 				/* new element A = element D x X */
298 				X = pdmpriv->RegEB4;
299 				Y = pdmpriv->RegEBC;
300 
301 				if (X != 0) {
302 					if ((X & 0x00000200) != 0)	/* consider minus */
303 						X = X | 0xFFFFFC00;
304 					ele_A = ((X * ele_D)>>8)&0x000003FF;
305 
306 					/* new element C = element D x Y */
307 					if ((Y & 0x00000200) != 0)
308 						Y = Y | 0xFFFFFC00;
309 					ele_C = ((Y * ele_D)>>8)&0x00003FF;
310 
311 					/* write new elements A, C, D to regC88 and regC9C, element B is always 0 */
312 					value32 = (ele_D<<22)|((ele_C&0x3F)<<16) | ele_A;
313 					rtl8723au_write32(Adapter, rOFDM0_XBTxIQImbalance, value32);
314 
315 					value32 = (ele_C&0x000003C0)>>6;
316 					PHY_SetBBReg(Adapter, rOFDM0_XDTxAFE, bMaskH4Bits, value32);
317 
318 					value32 = ((X * ele_D)>>7)&0x01;
319 					PHY_SetBBReg(Adapter,
320 						     rOFDM0_ECCAThreshold,
321 						     BIT(27), value32);
322 
323 					value32 = ((Y * ele_D)>>7)&0x01;
324 					PHY_SetBBReg(Adapter,
325 						     rOFDM0_ECCAThreshold,
326 						     BIT(25), value32);
327 				} else {
328 					rtl8723au_write32(Adapter,
329 							  rOFDM0_XBTxIQImbalance,
330 							  OFDMSwingTable23A[OFDM_index[1]]);
331 					PHY_SetBBReg(Adapter,
332 						     rOFDM0_XDTxAFE,
333 						     bMaskH4Bits, 0x00);
334 					PHY_SetBBReg(Adapter,
335 						     rOFDM0_ECCAThreshold,
336 						     BIT(27) | BIT(25), 0x00);
337 				}
338 			}
339 
340 		}
341 		if (delta_IQK > 3) {
342 			pdmpriv->ThermalValue_IQK = ThermalValue;
343 			rtl8723a_phy_iq_calibrate(Adapter, false);
344 		}
345 
346 		/* update thermal meter value */
347 		if (pdmpriv->TxPowerTrackControl)
348 			pdmpriv->ThermalValue = ThermalValue;
349 	}
350 	pdmpriv->TXPowercount = 0;
351 }
352 
353 /*	Description: */
354 /*		- Dispatch TxPower Tracking direct call ONLY for 92s. */
355 /*		- We shall NOT schedule Workitem within PASSIVE LEVEL, which will cause system resource */
356 /*		   leakage under some platform. */
357 /*	Assumption: */
358 /*		PASSIVE_LEVEL when this routine is called. */
ODM_TXPowerTracking92CDirectCall(struct rtw_adapter * Adapter)359 static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter)
360 {
361 	odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter);
362 }
363 
rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter * Adapter)364 void rtl8723a_odm_check_tx_power_tracking(struct rtw_adapter *Adapter)
365 {
366 	struct hal_data_8723a *pHalData = GET_HAL_DATA(Adapter);
367 	struct dm_priv *pdmpriv = &pHalData->dmpriv;
368 
369 	if (!pdmpriv->TM_Trigger) {		/* at least delay 1 sec */
370 		PHY_SetRFReg(Adapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
371 
372 		pdmpriv->TM_Trigger = 1;
373 		return;
374 	} else {
375 		ODM_TXPowerTracking92CDirectCall(Adapter);
376 		pdmpriv->TM_Trigger = 0;
377 	}
378 }
379 
380 /*	IQK */
381 #define MAX_TOLERANCE		5
382 #define IQK_DELAY_TIME		1	/* ms */
383 
_PHY_PathA_IQK(struct rtw_adapter * pAdapter,bool configPathB)384 static u8 _PHY_PathA_IQK(struct rtw_adapter *pAdapter, bool configPathB)
385 {
386 	u32 regEAC, regE94, regE9C, regEA4;
387 	u8 result = 0x00;
388 	struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
389 
390 	/* path-A IQK setting */
391 	rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x10008c1f);
392 	rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x10008c1f);
393 	rtl8723au_write32(pAdapter, rTx_IQK_PI_A, 0x82140102);
394 
395 	rtl8723au_write32(pAdapter, rRx_IQK_PI_A, configPathB ? 0x28160202 :
396 		IS_81xxC_VENDOR_UMC_B_CUT(pHalData->VersionID)?0x28160202:0x28160502);
397 
398 	/* path-B IQK setting */
399 	if (configPathB) {
400 		rtl8723au_write32(pAdapter, rTx_IQK_Tone_B, 0x10008c22);
401 		rtl8723au_write32(pAdapter, rRx_IQK_Tone_B, 0x10008c22);
402 		rtl8723au_write32(pAdapter, rTx_IQK_PI_B, 0x82140102);
403 		rtl8723au_write32(pAdapter, rRx_IQK_PI_B, 0x28160202);
404 	}
405 
406 	/* LO calibration setting */
407 	rtl8723au_write32(pAdapter, rIQK_AGC_Rsp, 0x001028d1);
408 
409 	/* One shot, path A LOK & IQK */
410 	rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf9000000);
411 	rtl8723au_write32(pAdapter, rIQK_AGC_Pts, 0xf8000000);
412 
413 	/*  delay x ms */
414 	/* PlatformStallExecution(IQK_DELAY_TIME*1000); */
415 	udelay(IQK_DELAY_TIME*1000);
416 
417 	/*  Check failed */
418 	regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2);
419 	regE94 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A);
420 	regE9C = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A);
421 	regEA4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2);
422 
423 	if (!(regEAC & BIT(28)) &&
424 	    (((regE94 & 0x03FF0000)>>16) != 0x142) &&
425 	    (((regE9C & 0x03FF0000)>>16) != 0x42))
426 		result |= 0x01;
427 	else			/* if Tx not OK, ignore Rx */
428 		return result;
429 
430 	if (!(regEAC & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
431 	    (((regEA4 & 0x03FF0000)>>16) != 0x132) &&
432 	    (((regEAC & 0x03FF0000)>>16) != 0x36))
433 		result |= 0x02;
434 	else
435 		DBG_8723A("Path A Rx IQK fail!!\n");
436 	return result;
437 }
438 
_PHY_PathB_IQK(struct rtw_adapter * pAdapter)439 static u8 _PHY_PathB_IQK(struct rtw_adapter *pAdapter)
440 {
441 	u32 regEAC, regEB4, regEBC, regEC4, regECC;
442 	u8 result = 0x00;
443 
444 	/* One shot, path B LOK & IQK */
445 	rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000002);
446 	rtl8723au_write32(pAdapter, rIQK_AGC_Cont, 0x00000000);
447 
448 	/*  delay x ms */
449 	udelay(IQK_DELAY_TIME*1000);
450 
451 	/*  Check failed */
452 	regEAC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2);
453 	regEB4 = rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B);
454 	regEBC = rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B);
455 	regEC4 = rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2);
456 	regECC = rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2);
457 
458 	if (!(regEAC & BIT(31)) &&
459 	    (((regEB4 & 0x03FF0000)>>16) != 0x142) &&
460 	    (((regEBC & 0x03FF0000)>>16) != 0x42))
461 		result |= 0x01;
462 	else
463 		return result;
464 
465 	if (!(regEAC & BIT(30)) &&
466 	    (((regEC4 & 0x03FF0000)>>16) != 0x132) &&
467 	    (((regECC & 0x03FF0000)>>16) != 0x36))
468 		result |= 0x02;
469 	else
470 		DBG_8723A("Path B Rx IQK fail!!\n");
471 	return result;
472 }
473 
_PHY_PathAFillIQKMatrix(struct rtw_adapter * pAdapter,bool bIQKOK,int result[][8],u8 final_candidate,bool bTxOnly)474 static void _PHY_PathAFillIQKMatrix(struct rtw_adapter *pAdapter,
475 	bool bIQKOK,
476 	int result[][8],
477 	u8 final_candidate,
478 	bool bTxOnly
479 	)
480 {
481 	u32 Oldval_0, X, TX0_A, reg;
482 	s32 Y, TX0_C;
483 
484 	DBG_8723A("Path A IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed");
485 
486 	if (final_candidate == 0xFF) {
487 		return;
488 	} else if (bIQKOK) {
489 		Oldval_0 = rtl8723au_read32(pAdapter, rOFDM0_XATxIQImbalance);
490 		Oldval_0 = (Oldval_0 >> 22) & 0x3FF;
491 
492 		X = result[final_candidate][0];
493 		if ((X & 0x00000200) != 0)
494 			X = X | 0xFFFFFC00;
495 		TX0_A = (X * Oldval_0) >> 8;
496 		PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x3FF, TX0_A);
497 		PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(31),
498 			     ((X * Oldval_0>>7) & 0x1));
499 
500 		Y = result[final_candidate][1];
501 		if ((Y & 0x00000200) != 0)
502 			Y = Y | 0xFFFFFC00;
503 		TX0_C = (Y * Oldval_0) >> 8;
504 		PHY_SetBBReg(pAdapter, rOFDM0_XCTxAFE, 0xF0000000,
505 			     ((TX0_C&0x3C0)>>6));
506 		PHY_SetBBReg(pAdapter, rOFDM0_XATxIQImbalance, 0x003F0000,
507 			     (TX0_C&0x3F));
508 		PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(29),
509 			     ((Y * Oldval_0>>7) & 0x1));
510 
511 		if (bTxOnly) {
512 			DBG_8723A("_PHY_PathAFillIQKMatrix only Tx OK\n");
513 			return;
514 		}
515 
516 		reg = result[final_candidate][2];
517 		PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0x3FF, reg);
518 
519 		reg = result[final_candidate][3] & 0x3F;
520 		PHY_SetBBReg(pAdapter, rOFDM0_XARxIQImbalance, 0xFC00, reg);
521 
522 		reg = (result[final_candidate][3] >> 6) & 0xF;
523 		PHY_SetBBReg(pAdapter, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
524 	}
525 }
526 
_PHY_PathBFillIQKMatrix(struct rtw_adapter * pAdapter,bool bIQKOK,int result[][8],u8 final_candidate,bool bTxOnly)527 static void _PHY_PathBFillIQKMatrix(struct rtw_adapter *pAdapter, bool bIQKOK, int result[][8], u8 final_candidate, bool bTxOnly)
528 {
529 	u32 Oldval_1, X, TX1_A, reg;
530 	s32 Y, TX1_C;
531 
532 	DBG_8723A("Path B IQ Calibration %s !\n", (bIQKOK)?"Success":"Failed");
533 
534 	if (final_candidate == 0xFF) {
535 		return;
536 	} else if (bIQKOK) {
537 		Oldval_1 = rtl8723au_read32(pAdapter, rOFDM0_XBTxIQImbalance);
538 		Oldval_1 = (Oldval_1 >> 22) & 0x3FF;
539 
540 		X = result[final_candidate][4];
541 		if ((X & 0x00000200) != 0)
542 			X = X | 0xFFFFFC00;
543 		TX1_A = (X * Oldval_1) >> 8;
544 		PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x3FF, TX1_A);
545 		PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(27),
546 			     ((X * Oldval_1 >> 7) & 0x1));
547 
548 		Y = result[final_candidate][5];
549 		if ((Y & 0x00000200) != 0)
550 			Y = Y | 0xFFFFFC00;
551 		TX1_C = (Y * Oldval_1) >> 8;
552 		PHY_SetBBReg(pAdapter, rOFDM0_XDTxAFE, 0xF0000000,
553 			     ((TX1_C & 0x3C0) >> 6));
554 		PHY_SetBBReg(pAdapter, rOFDM0_XBTxIQImbalance, 0x003F0000,
555 			     (TX1_C & 0x3F));
556 		PHY_SetBBReg(pAdapter, rOFDM0_ECCAThreshold, BIT(25),
557 			     ((Y * Oldval_1 >> 7) & 0x1));
558 
559 		if (bTxOnly)
560 			return;
561 
562 		reg = result[final_candidate][6];
563 		PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
564 
565 		reg = result[final_candidate][7] & 0x3F;
566 		PHY_SetBBReg(pAdapter, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
567 
568 		reg = (result[final_candidate][7] >> 6) & 0xF;
569 		PHY_SetBBReg(pAdapter, rOFDM0_AGCRSSITable, 0x0000F000, reg);
570 	}
571 }
572 
_PHY_SaveADDARegisters(struct rtw_adapter * pAdapter,u32 * ADDAReg,u32 * ADDABackup,u32 RegisterNum)573 static void _PHY_SaveADDARegisters(struct rtw_adapter *pAdapter, u32 *ADDAReg, u32 *ADDABackup, u32 RegisterNum)
574 {
575 	u32 i;
576 
577 	for (i = 0 ; i < RegisterNum ; i++) {
578 		ADDABackup[i] = rtl8723au_read32(pAdapter, ADDAReg[i]);
579 	}
580 }
581 
_PHY_SaveMACRegisters(struct rtw_adapter * pAdapter,u32 * MACReg,u32 * MACBackup)582 static void _PHY_SaveMACRegisters(struct rtw_adapter *pAdapter, u32 *MACReg,
583 				  u32 *MACBackup)
584 {
585 	u32 i;
586 
587 	for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++) {
588 		MACBackup[i] = rtl8723au_read8(pAdapter, MACReg[i]);
589 	}
590 	MACBackup[i] = rtl8723au_read32(pAdapter, MACReg[i]);
591 }
592 
_PHY_ReloadADDARegisters(struct rtw_adapter * pAdapter,u32 * ADDAReg,u32 * ADDABackup,u32 RegiesterNum)593 static void _PHY_ReloadADDARegisters(struct rtw_adapter *pAdapter,
594 				     u32 *ADDAReg, u32 *ADDABackup,
595 				     u32 RegiesterNum)
596 {
597 	u32 i;
598 
599 	for (i = 0 ; i < RegiesterNum ; i++) {
600 		rtl8723au_write32(pAdapter, ADDAReg[i], ADDABackup[i]);
601 	}
602 }
603 
_PHY_ReloadMACRegisters(struct rtw_adapter * pAdapter,u32 * MACReg,u32 * MACBackup)604 static void _PHY_ReloadMACRegisters(struct rtw_adapter *pAdapter,
605 				    u32 *MACReg, u32 *MACBackup)
606 {
607 	u32 i;
608 
609 	for (i = 0 ; i < (IQK_MAC_REG_NUM - 1); i++)
610 		rtl8723au_write8(pAdapter, MACReg[i], (u8)MACBackup[i]);
611 
612 	rtl8723au_write32(pAdapter, MACReg[i], MACBackup[i]);
613 }
614 
_PHY_PathADDAOn(struct rtw_adapter * pAdapter,u32 * ADDAReg,bool isPathAOn,bool is2T)615 static void _PHY_PathADDAOn(struct rtw_adapter *pAdapter, u32 *ADDAReg,
616 			    bool isPathAOn, bool is2T)
617 {
618 	u32 pathOn;
619 	u32 i;
620 
621 	pathOn = isPathAOn ? 0x04db25a4 : 0x0b1b25a4;
622 	if (!is2T) {
623 		pathOn = 0x0bdb25a0;
624 		rtl8723au_write32(pAdapter, ADDAReg[0], 0x0b1b25a0);
625 	} else {
626 		rtl8723au_write32(pAdapter, ADDAReg[0], pathOn);
627 	}
628 
629 	for (i = 1 ; i < IQK_ADDA_REG_NUM ; i++)
630 		rtl8723au_write32(pAdapter, ADDAReg[i], pathOn);
631 }
632 
_PHY_MACSettingCalibration(struct rtw_adapter * pAdapter,u32 * MACReg,u32 * MACBackup)633 static void _PHY_MACSettingCalibration(struct rtw_adapter *pAdapter,
634 				       u32 *MACReg, u32 *MACBackup)
635 {
636 	u32 i = 0;
637 
638 	rtl8723au_write8(pAdapter, MACReg[i], 0x3F);
639 
640 	for (i = 1 ; i < (IQK_MAC_REG_NUM - 1); i++) {
641 		rtl8723au_write8(pAdapter, MACReg[i],
642 				 (u8)(MACBackup[i] & ~BIT(3)));
643 	}
644 	rtl8723au_write8(pAdapter, MACReg[i], (u8)(MACBackup[i] & ~BIT(5)));
645 }
646 
_PHY_PathAStandBy(struct rtw_adapter * pAdapter)647 static void _PHY_PathAStandBy(struct rtw_adapter *pAdapter)
648 {
649 	rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x0);
650 	rtl8723au_write32(pAdapter, 0x840, 0x00010000);
651 	rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000);
652 }
653 
_PHY_PIModeSwitch(struct rtw_adapter * pAdapter,bool PIMode)654 static void _PHY_PIModeSwitch(struct rtw_adapter *pAdapter, bool PIMode)
655 {
656 	u32 mode;
657 
658 	mode = PIMode ? 0x01000100 : 0x01000000;
659 	rtl8723au_write32(pAdapter, 0x820, mode);
660 	rtl8723au_write32(pAdapter, 0x828, mode);
661 }
662 
663 /*
664 return false => do IQK again
665 */
_PHY_SimularityCompare(struct rtw_adapter * pAdapter,int result[][8],u8 c1,u8 c2)666 static bool _PHY_SimularityCompare(struct rtw_adapter *pAdapter, int result[][8], u8 c1, u8 c2)
667 {
668 	u32 i, j, diff, SimularityBitMap, bound = 0;
669 	struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
670 	u8 final_candidate[2] = {0xFF, 0xFF};	/* for path A and path B */
671 	bool bResult = true;
672 
673 	if (pHalData->rf_type == RF_2T2R)
674 		bound = 8;
675 	else
676 		bound = 4;
677 
678 	SimularityBitMap = 0;
679 
680 	for (i = 0; i < bound; i++) {
681 		diff = (result[c1][i] > result[c2][i]) ? (result[c1][i] - result[c2][i]) : (result[c2][i] - result[c1][i]);
682 		if (diff > MAX_TOLERANCE) {
683 			if ((i == 2 || i == 6) && !SimularityBitMap) {
684 				if (result[c1][i]+result[c1][i+1] == 0)
685 					final_candidate[(i/4)] = c2;
686 				else if (result[c2][i]+result[c2][i+1] == 0)
687 					final_candidate[(i/4)] = c1;
688 				else
689 					SimularityBitMap = SimularityBitMap|(1<<i);
690 			} else {
691 				SimularityBitMap = SimularityBitMap|(1<<i);
692 			}
693 		}
694 	}
695 
696 	if (SimularityBitMap == 0) {
697 		for (i = 0; i < (bound/4); i++) {
698 			if (final_candidate[i] != 0xFF) {
699 				for (j = i*4; j < (i+1)*4-2; j++)
700 					result[3][j] = result[final_candidate[i]][j];
701 				bResult = false;
702 			}
703 		}
704 		return bResult;
705 	} else if (!(SimularityBitMap & 0x0F)) {
706 		/* path A OK */
707 		for (i = 0; i < 4; i++)
708 			result[3][i] = result[c1][i];
709 		return false;
710 	} else if (!(SimularityBitMap & 0xF0) && pHalData->rf_type == RF_2T2R) {
711 		/* path B OK */
712 		for (i = 4; i < 8; i++)
713 			result[3][i] = result[c1][i];
714 		return false;
715 	} else {
716 		return false;
717 	}
718 }
719 
_PHY_IQCalibrate(struct rtw_adapter * pAdapter,int result[][8],u8 t,bool is2T)720 static void _PHY_IQCalibrate(struct rtw_adapter *pAdapter, int result[][8], u8 t, bool is2T)
721 {
722 	struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
723 	struct dm_priv *pdmpriv = &pHalData->dmpriv;
724 	u32 i;
725 	u8 PathAOK, PathBOK;
726 	u32 ADDA_REG[IQK_ADDA_REG_NUM] = {
727 		rFPGA0_XCD_SwitchControl, rBlue_Tooth,
728 		rRx_Wait_CCA, rTx_CCK_RFON,
729 		rTx_CCK_BBON, rTx_OFDM_RFON,
730 		rTx_OFDM_BBON, rTx_To_Rx,
731 		rTx_To_Tx, rRx_CCK,
732 		rRx_OFDM, rRx_Wait_RIFS,
733 		rRx_TO_Rx, rStandby,
734 		rSleep, rPMPD_ANAEN
735 	};
736 
737 	u32 IQK_MAC_REG[IQK_MAC_REG_NUM] = {
738 		REG_TXPAUSE, REG_BCN_CTRL,
739 		REG_BCN_CTRL_1, REG_GPIO_MUXCFG
740 	};
741 
742 	u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
743 		rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
744 		rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
745 		rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
746 		rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD
747 	};
748 
749 	const u32 retryCount = 2;
750 
751 	/*  Note: IQ calibration must be performed after loading  */
752 	/*		PHY_REG.txt , and radio_a, radio_b.txt	 */
753 
754 	u32 bbvalue;
755 
756 	if (t == 0) {
757 		bbvalue = rtl8723au_read32(pAdapter, rFPGA0_RFMOD);
758 
759 		/*  Save ADDA parameters, turn Path A ADDA on */
760 		_PHY_SaveADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
761 		_PHY_SaveMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
762 		_PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
763 	}
764 	_PHY_PathADDAOn(pAdapter, ADDA_REG, true, is2T);
765 
766 	if (t == 0)
767 		pdmpriv->bRfPiEnable = (u8)
768 			PHY_QueryBBReg(pAdapter, rFPGA0_XA_HSSIParameter1,
769 				       BIT(8));
770 
771 	if (!pdmpriv->bRfPiEnable) {
772 		/*  Switch BB to PI mode to do IQ Calibration. */
773 		_PHY_PIModeSwitch(pAdapter, true);
774 	}
775 
776 	PHY_SetBBReg(pAdapter, rFPGA0_RFMOD, BIT(24), 0x00);
777 	rtl8723au_write32(pAdapter, rOFDM0_TRxPathEnable, 0x03a05600);
778 	rtl8723au_write32(pAdapter, rOFDM0_TRMuxPar, 0x000800e4);
779 	rtl8723au_write32(pAdapter, rFPGA0_XCD_RFInterfaceSW, 0x22204000);
780 	PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
781 	PHY_SetBBReg(pAdapter, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
782 	PHY_SetBBReg(pAdapter, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
783 	PHY_SetBBReg(pAdapter, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
784 
785 	if (is2T) {
786 		rtl8723au_write32(pAdapter,
787 				  rFPGA0_XA_LSSIParameter, 0x00010000);
788 		rtl8723au_write32(pAdapter,
789 				  rFPGA0_XB_LSSIParameter, 0x00010000);
790 	}
791 
792 	/* MAC settings */
793 	_PHY_MACSettingCalibration(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
794 
795 	/* Page B init */
796 	rtl8723au_write32(pAdapter, rConfig_AntA, 0x00080000);
797 
798 	if (is2T)
799 		rtl8723au_write32(pAdapter, rConfig_AntB, 0x00080000);
800 
801 	/*  IQ calibration setting */
802 	rtl8723au_write32(pAdapter, rFPGA0_IQK, 0x80800000);
803 	rtl8723au_write32(pAdapter, rTx_IQK, 0x01007c00);
804 	rtl8723au_write32(pAdapter, rRx_IQK, 0x01004800);
805 
806 	for (i = 0 ; i < retryCount ; i++) {
807 		PathAOK = _PHY_PathA_IQK(pAdapter, is2T);
808 		if (PathAOK == 0x03) {
809 				DBG_8723A("Path A IQK Success!!\n");
810 				result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16;
811 				result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16;
812 				result[t][2] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_A_2)&0x3FF0000)>>16;
813 				result[t][3] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_A_2)&0x3FF0000)>>16;
814 			break;
815 		} else if (i == (retryCount-1) && PathAOK == 0x01) {
816 			/* Tx IQK OK */
817 			DBG_8723A("Path A IQK Only  Tx Success!!\n");
818 
819 			result[t][0] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_A)&0x3FF0000)>>16;
820 			result[t][1] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_A)&0x3FF0000)>>16;
821 		}
822 	}
823 
824 	if (0x00 == PathAOK) {
825 		DBG_8723A("Path A IQK failed!!\n");
826 	}
827 
828 	if (is2T) {
829 		_PHY_PathAStandBy(pAdapter);
830 
831 		/*  Turn Path B ADDA on */
832 		_PHY_PathADDAOn(pAdapter, ADDA_REG, false, is2T);
833 
834 		for (i = 0 ; i < retryCount ; i++) {
835 			PathBOK = _PHY_PathB_IQK(pAdapter);
836 			if (PathBOK == 0x03) {
837 				DBG_8723A("Path B IQK Success!!\n");
838 				result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16;
839 				result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16;
840 				result[t][6] = (rtl8723au_read32(pAdapter, rRx_Power_Before_IQK_B_2)&0x3FF0000)>>16;
841 				result[t][7] = (rtl8723au_read32(pAdapter, rRx_Power_After_IQK_B_2)&0x3FF0000)>>16;
842 				break;
843 			} else if (i == (retryCount - 1) && PathBOK == 0x01) {
844 				/* Tx IQK OK */
845 				DBG_8723A("Path B Only Tx IQK Success!!\n");
846 				result[t][4] = (rtl8723au_read32(pAdapter, rTx_Power_Before_IQK_B)&0x3FF0000)>>16;
847 				result[t][5] = (rtl8723au_read32(pAdapter, rTx_Power_After_IQK_B)&0x3FF0000)>>16;
848 			}
849 		}
850 
851 		if (0x00 == PathBOK) {
852 			DBG_8723A("Path B IQK failed!!\n");
853 		}
854 	}
855 
856 	/* Back to BB mode, load original value */
857 	rtl8723au_write32(pAdapter, rFPGA0_IQK, 0);
858 
859 	if (t != 0) {
860 		if (!pdmpriv->bRfPiEnable) {
861 			/*  Switch back BB to SI mode after finish IQ Calibration. */
862 			_PHY_PIModeSwitch(pAdapter, false);
863 		}
864 
865 		/*  Reload ADDA power saving parameters */
866 		_PHY_ReloadADDARegisters(pAdapter, ADDA_REG, pdmpriv->ADDA_backup, IQK_ADDA_REG_NUM);
867 
868 		/*  Reload MAC parameters */
869 		_PHY_ReloadMACRegisters(pAdapter, IQK_MAC_REG, pdmpriv->IQK_MAC_backup);
870 
871 		/*  Reload BB parameters */
872 		_PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup, IQK_BB_REG_NUM);
873 
874 		/*  Restore RX initial gain */
875 		rtl8723au_write32(pAdapter,
876 				  rFPGA0_XA_LSSIParameter, 0x00032ed3);
877 		if (is2T) {
878 			rtl8723au_write32(pAdapter,
879 					  rFPGA0_XB_LSSIParameter, 0x00032ed3);
880 		}
881 
882 		/* load 0xe30 IQC default value */
883 		rtl8723au_write32(pAdapter, rTx_IQK_Tone_A, 0x01008c00);
884 		rtl8723au_write32(pAdapter, rRx_IQK_Tone_A, 0x01008c00);
885 
886 	}
887 }
888 
_PHY_LCCalibrate(struct rtw_adapter * pAdapter,bool is2T)889 static void _PHY_LCCalibrate(struct rtw_adapter *pAdapter, bool is2T)
890 {
891 	u8 tmpReg;
892 	u32 RF_Amode = 0, RF_Bmode = 0, LC_Cal;
893 
894 	/* Check continuous TX and Packet TX */
895 	tmpReg = rtl8723au_read8(pAdapter, 0xd03);
896 
897 	if ((tmpReg&0x70) != 0) {
898 		/* Deal with contisuous TX case */
899 		/* disable all continuous TX */
900 		rtl8723au_write8(pAdapter, 0xd03, tmpReg&0x8F);
901 	} else {
902 		/*  Deal with Packet TX case */
903 		/*  block all queues */
904 		rtl8723au_write8(pAdapter, REG_TXPAUSE, 0xFF);
905 	}
906 
907 	if ((tmpReg&0x70) != 0) {
908 		/* 1. Read original RF mode */
909 		/* Path-A */
910 		RF_Amode = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits);
911 
912 		/* Path-B */
913 		if (is2T)
914 			RF_Bmode = PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits);
915 
916 		/* 2. Set RF mode = standby mode */
917 		/* Path-A */
918 		PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, (RF_Amode&0x8FFFF)|0x10000);
919 
920 		/* Path-B */
921 		if (is2T)
922 			PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, (RF_Bmode&0x8FFFF)|0x10000);
923 	}
924 
925 	/* 3. Read RF reg18 */
926 	LC_Cal = PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits);
927 
928 	/* 4. Set LC calibration begin */
929 	PHY_SetRFReg(pAdapter, RF_PATH_A, RF_CHNLBW, bMask12Bits, LC_Cal|0x08000);
930 
931 	msleep(100);
932 
933 	/* Restore original situation */
934 	if ((tmpReg&0x70) != 0) {	/* Deal with contuous TX case  */
935 		/* Path-A */
936 		rtl8723au_write8(pAdapter, 0xd03, tmpReg);
937 		PHY_SetRFReg(pAdapter, RF_PATH_A, RF_AC, bMask12Bits, RF_Amode);
938 
939 		/* Path-B */
940 		if (is2T)
941 			PHY_SetRFReg(pAdapter, RF_PATH_B, RF_AC, bMask12Bits, RF_Bmode);
942 	} else /*  Deal with Packet TX case */
943 		rtl8723au_write8(pAdapter, REG_TXPAUSE, 0x00);
944 }
945 
946 /* Analog Pre-distortion calibration */
947 #define		APK_BB_REG_NUM	8
948 #define		APK_CURVE_REG_NUM 4
949 #define		PATH_NUM		2
950 
rtl8723a_phy_iq_calibrate(struct rtw_adapter * pAdapter,bool bReCovery)951 void rtl8723a_phy_iq_calibrate(struct rtw_adapter *pAdapter, bool bReCovery)
952 {
953 	struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
954 	struct dm_priv *pdmpriv = &pHalData->dmpriv;
955 	s32 result[4][8];	/* last is final result */
956 	u8 i, final_candidate;
957 	bool bPathAOK, bPathBOK;
958 	s32 RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4;
959 	s32 RegECC, RegTmp = 0;
960 	bool is12simular, is13simular, is23simular;
961 	bool bStartContTx = false, bSingleTone = false;
962 	bool bCarrierSuppression = false;
963 	u32 IQK_BB_REG_92C[IQK_BB_REG_NUM] = {
964 		rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
965 		rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
966 		rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
967 		rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
968 		rOFDM0_RxIQExtAnta
969 	};
970 
971 	/* ignore IQK when continuous Tx */
972 	if (bStartContTx || bSingleTone || bCarrierSuppression)
973 		return;
974 
975 	if (bReCovery) {
976 		_PHY_ReloadADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
977 		return;
978 	}
979 	DBG_8723A("IQK:Start!!!\n");
980 
981 	for (i = 0; i < 8; i++) {
982 		result[0][i] = 0;
983 		result[1][i] = 0;
984 		result[2][i] = 0;
985 		result[3][i] = 0;
986 	}
987 	final_candidate = 0xff;
988 	bPathAOK = false;
989 	bPathBOK = false;
990 	is12simular = false;
991 	is23simular = false;
992 	is13simular = false;
993 
994 	for (i = 0; i < 3; i++) {
995 		if (pHalData->rf_type == RF_2T2R)
996 			_PHY_IQCalibrate(pAdapter, result, i, true);
997 		else /*  For 88C 1T1R */
998 			_PHY_IQCalibrate(pAdapter, result, i, false);
999 
1000 		if (i == 1) {
1001 			is12simular = _PHY_SimularityCompare(pAdapter, result, 0, 1);
1002 			if (is12simular) {
1003 				final_candidate = 0;
1004 				break;
1005 			}
1006 		}
1007 
1008 		if (i == 2) {
1009 			is13simular = _PHY_SimularityCompare(pAdapter, result, 0, 2);
1010 			if (is13simular) {
1011 				final_candidate = 0;
1012 				break;
1013 			}
1014 
1015 			is23simular = _PHY_SimularityCompare(pAdapter, result, 1, 2);
1016 			if (is23simular) {
1017 				final_candidate = 1;
1018 			} else {
1019 				for (i = 0; i < 8; i++)
1020 					RegTmp += result[3][i];
1021 
1022 				if (RegTmp != 0)
1023 					final_candidate = 3;
1024 				else
1025 					final_candidate = 0xFF;
1026 			}
1027 		}
1028 	}
1029 
1030 	for (i = 0; i < 4; i++) {
1031 		RegE94 = result[i][0];
1032 		RegE9C = result[i][1];
1033 		RegEA4 = result[i][2];
1034 		RegEAC = result[i][3];
1035 		RegEB4 = result[i][4];
1036 		RegEBC = result[i][5];
1037 		RegEC4 = result[i][6];
1038 		RegECC = result[i][7];
1039 	}
1040 
1041 	if (final_candidate != 0xff) {
1042 		RegE94 = result[final_candidate][0];
1043 		pdmpriv->RegE94 =  RegE94;
1044 		RegE9C = result[final_candidate][1];
1045 		pdmpriv->RegE9C = RegE9C;
1046 		RegEA4 = result[final_candidate][2];
1047 		RegEAC = result[final_candidate][3];
1048 		RegEB4 = result[final_candidate][4];
1049 		pdmpriv->RegEB4 = RegEB4;
1050 		RegEBC = result[final_candidate][5];
1051 		pdmpriv->RegEBC = RegEBC;
1052 		RegEC4 = result[final_candidate][6];
1053 		RegECC = result[final_candidate][7];
1054 		DBG_8723A("IQK: final_candidate is %x\n", final_candidate);
1055 		DBG_8723A("IQK: RegE94 =%x RegE9C =%x RegEA4 =%x RegEAC =%x RegEB4 =%x RegEBC =%x RegEC4 =%x RegECC =%x\n ",
1056 			  RegE94, RegE9C, RegEA4, RegEAC, RegEB4, RegEBC, RegEC4, RegECC);
1057 		bPathAOK = bPathBOK = true;
1058 	} else {
1059 		RegE94 = RegEB4 = pdmpriv->RegE94 = pdmpriv->RegEB4 = 0x100;	/* X default value */
1060 		RegE9C = RegEBC = pdmpriv->RegE9C = pdmpriv->RegEBC = 0x0;		/* Y default value */
1061 	}
1062 
1063 	if ((RegE94 != 0)/*&&(RegEA4 != 0)*/)
1064 		_PHY_PathAFillIQKMatrix(pAdapter, bPathAOK, result, final_candidate, (RegEA4 == 0));
1065 
1066 	if (pHalData->rf_type == RF_2T2R) {
1067 		if ((RegEB4 != 0)/*&&(RegEC4 != 0)*/)
1068 			_PHY_PathBFillIQKMatrix(pAdapter, bPathBOK, result,
1069 						final_candidate, (RegEC4 == 0));
1070 	}
1071 
1072 	_PHY_SaveADDARegisters(pAdapter, IQK_BB_REG_92C, pdmpriv->IQK_BB_backup_recover, 9);
1073 }
1074 
rtl8723a_phy_lc_calibrate(struct rtw_adapter * pAdapter)1075 void rtl8723a_phy_lc_calibrate(struct rtw_adapter *pAdapter)
1076 {
1077 	struct hal_data_8723a *pHalData = GET_HAL_DATA(pAdapter);
1078 	struct mlme_ext_priv *pmlmeext = &pAdapter->mlmeextpriv;
1079 	bool bStartContTx = false, bSingleTone = false, bCarrierSuppression = false;
1080 
1081 	/* ignore IQK when continuous Tx */
1082 	if (bStartContTx || bSingleTone || bCarrierSuppression)
1083 		return;
1084 
1085 	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS)
1086 		return;
1087 
1088 	if (pHalData->rf_type == RF_2T2R)
1089 		_PHY_LCCalibrate(pAdapter, true);
1090 	else	/*  For 88C 1T1R */
1091 		_PHY_LCCalibrate(pAdapter, false);
1092 }
1093 
1094 void
rtl8723a_phy_ap_calibrate(struct rtw_adapter * pAdapter,char delta)1095 rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta)
1096 {
1097 }
1098