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