Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8723au / hal / HalDMOutSrc8723A_CE.c
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
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. */
359 static void ODM_TXPowerTracking92CDirectCall(struct rtw_adapter *Adapter)
360 {
361         odm_TXPowerTrackingCallback_ThermalMeter_92C(Adapter);
362 }
363
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
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
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
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
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
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
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
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
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
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
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
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
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 */
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
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
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
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
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
1095 rtl8723a_phy_ap_calibrate(struct rtw_adapter *pAdapter, char delta)
1096 {
1097 }