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