linux/drivers/staging/rtl8188eu/hal/phy.c
<<
>>
Prefs
   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#define _RTL8188E_PHYCFG_C_
  16
  17#include <osdep_service.h>
  18#include <drv_types.h>
  19#include <rtw_iol.h>
  20#include <rtl8188e_hal.h>
  21#include <rf.h>
  22#include <phy.h>
  23
  24#define MAX_PRECMD_CNT 16
  25#define MAX_RFDEPENDCMD_CNT 16
  26#define MAX_POSTCMD_CNT 16
  27
  28#define MAX_DOZE_WAITING_TIMES_9x 64
  29
  30static u32 cal_bit_shift(u32 bitmask)
  31{
  32        u32 i;
  33
  34        for (i = 0; i <= 31; i++) {
  35                if (((bitmask >> i) & 0x1) == 1)
  36                        break;
  37        }
  38        return i;
  39}
  40
  41u32 phy_query_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask)
  42{
  43        u32 original_value, bit_shift;
  44
  45        original_value = usb_read32(adapt, regaddr);
  46        bit_shift = cal_bit_shift(bitmask);
  47        return (original_value & bitmask) >> bit_shift;
  48}
  49
  50void phy_set_bb_reg(struct adapter *adapt, u32 regaddr, u32 bitmask, u32 data)
  51{
  52        u32 original_value, bit_shift;
  53
  54        if (bitmask != bMaskDWord) { /* if not "double word" write */
  55                original_value = usb_read32(adapt, regaddr);
  56                bit_shift = cal_bit_shift(bitmask);
  57                data = (original_value & (~bitmask)) | (data << bit_shift);
  58        }
  59
  60        usb_write32(adapt, regaddr, data);
  61}
  62
  63static u32 rf_serial_read(struct adapter *adapt,
  64                        enum rf_radio_path rfpath, u32 offset)
  65{
  66        u32 ret = 0;
  67        struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
  68        u32 tmplong, tmplong2;
  69        u8 rfpi_enable = 0;
  70
  71        offset &= 0xff;
  72
  73        tmplong = phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord);
  74        if (rfpath == RF_PATH_A)
  75                tmplong2 = tmplong;
  76        else
  77                tmplong2 = phy_query_bb_reg(adapt, phyreg->rfHSSIPara2,
  78                                            bMaskDWord);
  79
  80        tmplong2 = (tmplong2 & (~bLSSIReadAddress)) |
  81                   (offset<<23) | bLSSIReadEdge;
  82
  83        phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter2, bMaskDWord,
  84                       tmplong&(~bLSSIReadEdge));
  85        udelay(10);
  86
  87        phy_set_bb_reg(adapt, phyreg->rfHSSIPara2, bMaskDWord, tmplong2);
  88        udelay(100);
  89
  90        udelay(10);
  91
  92        if (rfpath == RF_PATH_A)
  93                rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, BIT(8));
  94        else if (rfpath == RF_PATH_B)
  95                rfpi_enable = (u8)phy_query_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, BIT(8));
  96
  97        if (rfpi_enable)
  98                ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBackPi,
  99                                       bLSSIReadBackData);
 100        else
 101                ret = phy_query_bb_reg(adapt, phyreg->rfLSSIReadBack,
 102                                       bLSSIReadBackData);
 103        return ret;
 104}
 105
 106static void rf_serial_write(struct adapter *adapt,
 107                            enum rf_radio_path rfpath, u32 offset,
 108                            u32 data)
 109{
 110        u32 data_and_addr = 0;
 111        struct bb_reg_def *phyreg = &adapt->HalData->PHYRegDef[rfpath];
 112
 113        offset &= 0xff;
 114        data_and_addr = ((offset<<20) | (data&0x000fffff)) & 0x0fffffff;
 115        phy_set_bb_reg(adapt, phyreg->rf3wireOffset, bMaskDWord, data_and_addr);
 116}
 117
 118u32 rtw_hal_read_rfreg(struct adapter *adapt, enum rf_radio_path rf_path,
 119                     u32 reg_addr, u32 bit_mask)
 120{
 121        u32 original_value, bit_shift;
 122
 123        original_value = rf_serial_read(adapt, rf_path, reg_addr);
 124        bit_shift =  cal_bit_shift(bit_mask);
 125        return (original_value & bit_mask) >> bit_shift;
 126}
 127
 128void phy_set_rf_reg(struct adapter *adapt, enum rf_radio_path rf_path,
 129                     u32 reg_addr, u32 bit_mask, u32 data)
 130{
 131        u32 original_value, bit_shift;
 132
 133        /*  RF data is 12 bits only */
 134        if (bit_mask != bRFRegOffsetMask) {
 135                original_value = rf_serial_read(adapt, rf_path, reg_addr);
 136                bit_shift =  cal_bit_shift(bit_mask);
 137                data = (original_value & (~bit_mask)) | (data << bit_shift);
 138        }
 139
 140        rf_serial_write(adapt, rf_path, reg_addr, data);
 141}
 142
 143static void get_tx_power_index(struct adapter *adapt, u8 channel, u8 *cck_pwr,
 144                               u8 *ofdm_pwr, u8 *bw20_pwr, u8 *bw40_pwr)
 145{
 146        struct hal_data_8188e *hal_data = adapt->HalData;
 147        u8 index = (channel - 1);
 148        u8 TxCount = 0, path_nums;
 149
 150        path_nums = 1;
 151
 152        for (TxCount = 0; TxCount < path_nums; TxCount++) {
 153                if (TxCount == RF_PATH_A) {
 154                        cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
 155                        ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
 156                                            hal_data->OFDM_24G_Diff[TxCount][RF_PATH_A];
 157
 158                        bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
 159                                            hal_data->BW20_24G_Diff[TxCount][RF_PATH_A];
 160                        bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
 161                } else if (TxCount == RF_PATH_B) {
 162                        cck_pwr[TxCount] = hal_data->Index24G_CCK_Base[TxCount][index];
 163                        ofdm_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
 164                        hal_data->BW20_24G_Diff[RF_PATH_A][index]+
 165                        hal_data->BW20_24G_Diff[TxCount][index];
 166
 167                        bw20_pwr[TxCount] = hal_data->Index24G_BW40_Base[RF_PATH_A][index]+
 168                        hal_data->BW20_24G_Diff[TxCount][RF_PATH_A]+
 169                        hal_data->BW20_24G_Diff[TxCount][index];
 170                        bw40_pwr[TxCount] = hal_data->Index24G_BW40_Base[TxCount][index];
 171                }
 172        }
 173}
 174
 175static void phy_power_index_check(struct adapter *adapt, u8 channel,
 176                                  u8 *cck_pwr, u8 *ofdm_pwr, u8 *bw20_pwr,
 177                                  u8 *bw40_pwr)
 178{
 179        struct hal_data_8188e *hal_data = adapt->HalData;
 180
 181        hal_data->CurrentCckTxPwrIdx = cck_pwr[0];
 182        hal_data->CurrentOfdm24GTxPwrIdx = ofdm_pwr[0];
 183        hal_data->CurrentBW2024GTxPwrIdx = bw20_pwr[0];
 184        hal_data->CurrentBW4024GTxPwrIdx = bw40_pwr[0];
 185}
 186
 187void phy_set_tx_power_level(struct adapter *adapt, u8 channel)
 188{
 189        u8 cck_pwr[MAX_TX_COUNT] = {0};
 190        u8 ofdm_pwr[MAX_TX_COUNT] = {0};/*  [0]:RF-A, [1]:RF-B */
 191        u8 bw20_pwr[MAX_TX_COUNT] = {0};
 192        u8 bw40_pwr[MAX_TX_COUNT] = {0};
 193
 194        get_tx_power_index(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
 195                           &bw20_pwr[0], &bw40_pwr[0]);
 196
 197        phy_power_index_check(adapt, channel, &cck_pwr[0], &ofdm_pwr[0],
 198                              &bw20_pwr[0], &bw40_pwr[0]);
 199
 200        rtl88eu_phy_rf6052_set_cck_txpower(adapt, &cck_pwr[0]);
 201        rtl88eu_phy_rf6052_set_ofdm_txpower(adapt, &ofdm_pwr[0], &bw20_pwr[0],
 202                                          &bw40_pwr[0], channel);
 203}
 204
 205static void phy_set_bw_mode_callback(struct adapter *adapt)
 206{
 207        struct hal_data_8188e *hal_data = adapt->HalData;
 208        u8 reg_bw_opmode;
 209        u8 reg_prsr_rsc;
 210
 211        if (adapt->bDriverStopped)
 212                return;
 213
 214        /* Set MAC register */
 215
 216        reg_bw_opmode = usb_read8(adapt, REG_BWOPMODE);
 217        reg_prsr_rsc = usb_read8(adapt, REG_RRSR+2);
 218
 219        switch (hal_data->CurrentChannelBW) {
 220        case HT_CHANNEL_WIDTH_20:
 221                reg_bw_opmode |= BW_OPMODE_20MHZ;
 222                usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
 223                break;
 224        case HT_CHANNEL_WIDTH_40:
 225                reg_bw_opmode &= ~BW_OPMODE_20MHZ;
 226                usb_write8(adapt, REG_BWOPMODE, reg_bw_opmode);
 227                reg_prsr_rsc = (reg_prsr_rsc&0x90) |
 228                               (hal_data->nCur40MhzPrimeSC<<5);
 229                usb_write8(adapt, REG_RRSR+2, reg_prsr_rsc);
 230                break;
 231        default:
 232                break;
 233        }
 234
 235        /* Set PHY related register */
 236        switch (hal_data->CurrentChannelBW) {
 237        case HT_CHANNEL_WIDTH_20:
 238                phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x0);
 239                phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x0);
 240                break;
 241        case HT_CHANNEL_WIDTH_40:
 242                phy_set_bb_reg(adapt, rFPGA0_RFMOD, bRFMOD, 0x1);
 243                phy_set_bb_reg(adapt, rFPGA1_RFMOD, bRFMOD, 0x1);
 244                /* Set Control channel to upper or lower.
 245                 * These settings are required only for 40MHz
 246                 */
 247                phy_set_bb_reg(adapt, rCCK0_System, bCCKSideBand,
 248                    (hal_data->nCur40MhzPrimeSC>>1));
 249                phy_set_bb_reg(adapt, rOFDM1_LSTF, 0xC00,
 250                               hal_data->nCur40MhzPrimeSC);
 251                phy_set_bb_reg(adapt, 0x818, (BIT(26) | BIT(27)),
 252                   (hal_data->nCur40MhzPrimeSC == HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
 253                break;
 254        default:
 255                break;
 256        }
 257
 258        /* Set RF related register */
 259        rtl88eu_phy_rf6052_set_bandwidth(adapt, hal_data->CurrentChannelBW);
 260}
 261
 262void rtw_hal_set_bwmode(struct adapter *adapt, enum ht_channel_width bandwidth,
 263                     unsigned char offset)
 264{
 265        struct hal_data_8188e *hal_data = adapt->HalData;
 266        enum ht_channel_width tmp_bw = hal_data->CurrentChannelBW;
 267
 268        hal_data->CurrentChannelBW = bandwidth;
 269        hal_data->nCur40MhzPrimeSC = offset;
 270
 271        if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
 272                phy_set_bw_mode_callback(adapt);
 273        else
 274                hal_data->CurrentChannelBW = tmp_bw;
 275}
 276
 277static void phy_sw_chnl_callback(struct adapter *adapt, u8 channel)
 278{
 279        u32 param1, param2;
 280        struct hal_data_8188e *hal_data = adapt->HalData;
 281
 282        phy_set_tx_power_level(adapt, channel);
 283
 284        param1 = RF_CHNLBW;
 285        param2 = channel;
 286        hal_data->RfRegChnlVal[0] = (hal_data->RfRegChnlVal[0] &
 287                                          0xfffffc00) | param2;
 288        phy_set_rf_reg(adapt, 0, param1,
 289                       bRFRegOffsetMask, hal_data->RfRegChnlVal[0]);
 290}
 291
 292void rtw_hal_set_chan(struct adapter *adapt, u8 channel)
 293{
 294        struct hal_data_8188e *hal_data = adapt->HalData;
 295        u8 tmpchannel = hal_data->CurrentChannel;
 296
 297        if (channel == 0)
 298                channel = 1;
 299
 300        hal_data->CurrentChannel = channel;
 301
 302        if ((!adapt->bDriverStopped) && (!adapt->bSurpriseRemoved))
 303                phy_sw_chnl_callback(adapt, channel);
 304        else
 305                hal_data->CurrentChannel = tmpchannel;
 306}
 307
 308#define ODM_TXPWRTRACK_MAX_IDX_88E  6
 309
 310static u8 get_right_chnl_for_iqk(u8 chnl)
 311{
 312        u8 place;
 313        u8 channel_all[ODM_TARGET_CHNL_NUM_2G_5G] = {
 314                36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
 315                100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122,
 316                124, 126, 128, 130, 132, 134, 136, 138, 140, 149, 151, 153,
 317                155, 157, 159, 161, 163, 165
 318        };
 319
 320        if (chnl > 14) {
 321                for (place = 0; place < sizeof(channel_all); place++) {
 322                        if (channel_all[place] == chnl)
 323                                return ++place;
 324                }
 325        }
 326        return 0;
 327}
 328
 329void rtl88eu_dm_txpower_track_adjust(struct odm_dm_struct *dm_odm, u8 type,
 330                                     u8 *direction, u32 *out_write_val)
 331{
 332        u8 pwr_value = 0;
 333        /*  Tx power tracking BB swing table. */
 334        if (type == 0) { /* For OFDM adjust */
 335                ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
 336                             ("BbSwingIdxOfdm = %d BbSwingFlagOfdm=%d\n",
 337                             dm_odm->BbSwingIdxOfdm, dm_odm->BbSwingFlagOfdm));
 338
 339                if (dm_odm->BbSwingIdxOfdm <= dm_odm->BbSwingIdxOfdmBase) {
 340                        *direction = 1;
 341                        pwr_value = dm_odm->BbSwingIdxOfdmBase -
 342                                     dm_odm->BbSwingIdxOfdm;
 343                } else {
 344                        *direction = 2;
 345                        pwr_value = dm_odm->BbSwingIdxOfdm -
 346                                     dm_odm->BbSwingIdxOfdmBase;
 347                }
 348
 349        } else if (type == 1) { /* For CCK adjust. */
 350                ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
 351                             ("dm_odm->BbSwingIdxCck = %d dm_odm->BbSwingIdxCckBase = %d\n",
 352                             dm_odm->BbSwingIdxCck, dm_odm->BbSwingIdxCckBase));
 353
 354                if (dm_odm->BbSwingIdxCck <= dm_odm->BbSwingIdxCckBase) {
 355                        *direction = 1;
 356                        pwr_value = dm_odm->BbSwingIdxCckBase -
 357                                     dm_odm->BbSwingIdxCck;
 358                } else {
 359                        *direction = 2;
 360                        pwr_value = dm_odm->BbSwingIdxCck -
 361                                     dm_odm->BbSwingIdxCckBase;
 362                }
 363
 364        }
 365
 366        if (pwr_value >= ODM_TXPWRTRACK_MAX_IDX_88E && *direction == 1)
 367                pwr_value = ODM_TXPWRTRACK_MAX_IDX_88E;
 368
 369        *out_write_val = pwr_value | (pwr_value<<8) | (pwr_value<<16) |
 370                         (pwr_value<<24);
 371}
 372
 373static void dm_txpwr_track_setpwr(struct odm_dm_struct *dm_odm)
 374{
 375        if (dm_odm->BbSwingFlagOfdm || dm_odm->BbSwingFlagCck) {
 376                ODM_RT_TRACE(dm_odm, ODM_COMP_TX_PWR_TRACK, ODM_DBG_LOUD,
 377                             ("dm_txpwr_track_setpwr CH=%d\n", *(dm_odm->pChannel)));
 378                phy_set_tx_power_level(dm_odm->Adapter, *(dm_odm->pChannel));
 379                dm_odm->BbSwingFlagOfdm = false;
 380                dm_odm->BbSwingFlagCck = false;
 381        }
 382}
 383
 384void rtl88eu_dm_txpower_tracking_callback_thermalmeter(struct adapter *adapt)
 385{
 386        struct hal_data_8188e *hal_data = adapt->HalData;
 387        u8 thermal_val = 0, delta, delta_lck, delta_iqk, offset;
 388        u8 thermal_avg_count = 0;
 389        u32 thermal_avg = 0;
 390        s32 ele_d, temp_cck;
 391        s8 ofdm_index[2], cck_index = 0;
 392        s8 ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
 393        u32 i = 0, j = 0;
 394
 395        u8 ofdm_min_index = 6; /* OFDM BB Swing should be less than +3.0dB */
 396        s8 ofdm_index_mapping[2][index_mapping_NUM_88E] = {
 397                /* 2.4G, decrease power */
 398                {0, 0, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11},
 399                /* 2.4G, increase power */
 400                {0, 0, -1, -2, -3, -4, -4, -4, -4, -5, -7, -8, -9, -9, -10},
 401        };
 402        u8 thermal_mapping[2][index_mapping_NUM_88E] = {
 403                /* 2.4G, decrease power */
 404                {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 27},
 405                /* 2.4G, increase power */
 406                {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 25, 25, 25},
 407        };
 408        struct odm_dm_struct *dm_odm = &hal_data->odmpriv;
 409
 410        dm_txpwr_track_setpwr(dm_odm);
 411
 412        dm_odm->RFCalibrateInfo.TXPowerTrackingCallbackCnt++;
 413
 414        dm_odm->RFCalibrateInfo.RegA24 = 0x090e1317;
 415
 416        thermal_val = (u8)rtw_hal_read_rfreg(adapt, RF_PATH_A,
 417                                           RF_T_METER_88E, 0xfc00);
 418
 419        if (thermal_val) {
 420                /* Query OFDM path A default setting */
 421                ele_d = phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord)&bMaskOFDM_D;
 422                for (i = 0; i < OFDM_TABLE_SIZE_92D; i++) {
 423                        if (ele_d == (OFDMSwingTable[i]&bMaskOFDM_D)) {
 424                                ofdm_index_old[0] = (u8)i;
 425                                dm_odm->BbSwingIdxOfdmBase = (u8)i;
 426                                break;
 427                        }
 428                }
 429
 430                /* Query CCK default setting From 0xa24 */
 431                temp_cck = dm_odm->RFCalibrateInfo.RegA24;
 432
 433                for (i = 0; i < CCK_TABLE_SIZE; i++) {
 434                        if ((dm_odm->RFCalibrateInfo.bCCKinCH14 &&
 435                                memcmp(&temp_cck, &CCKSwingTable_Ch14[i][2], 4)) ||
 436                                memcmp(&temp_cck, &CCKSwingTable_Ch1_Ch13[i][2], 4)) {
 437                                        cck_index_old = (u8)i;
 438                                        dm_odm->BbSwingIdxCckBase = (u8)i;
 439                                        break;
 440                        }
 441                }
 442
 443                if (!dm_odm->RFCalibrateInfo.ThermalValue) {
 444                        dm_odm->RFCalibrateInfo.ThermalValue = hal_data->EEPROMThermalMeter;
 445                        dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
 446                        dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
 447
 448                        dm_odm->RFCalibrateInfo.OFDM_index[0] = ofdm_index_old[0];
 449                        dm_odm->RFCalibrateInfo.CCK_index = cck_index_old;
 450                }
 451
 452                /* calculate average thermal meter */
 453                dm_odm->RFCalibrateInfo.ThermalValue_AVG[dm_odm->RFCalibrateInfo.ThermalValue_AVG_index] = thermal_val;
 454                dm_odm->RFCalibrateInfo.ThermalValue_AVG_index++;
 455                if (dm_odm->RFCalibrateInfo.ThermalValue_AVG_index == AVG_THERMAL_NUM_88E)
 456                        dm_odm->RFCalibrateInfo.ThermalValue_AVG_index = 0;
 457
 458                for (i = 0; i < AVG_THERMAL_NUM_88E; i++) {
 459                        if (dm_odm->RFCalibrateInfo.ThermalValue_AVG[i]) {
 460                                thermal_avg += dm_odm->RFCalibrateInfo.ThermalValue_AVG[i];
 461                                thermal_avg_count++;
 462                        }
 463                }
 464
 465                if (thermal_avg_count)
 466                        thermal_val = (u8)(thermal_avg / thermal_avg_count);
 467
 468                if (dm_odm->RFCalibrateInfo.bDoneTxpower &&
 469                        !dm_odm->RFCalibrateInfo.bReloadtxpowerindex)
 470                        delta = abs(thermal_val - dm_odm->RFCalibrateInfo.ThermalValue);
 471                else {
 472                        delta = abs(thermal_val - hal_data->EEPROMThermalMeter);
 473                        if (dm_odm->RFCalibrateInfo.bReloadtxpowerindex) {
 474                                dm_odm->RFCalibrateInfo.bReloadtxpowerindex = false;
 475                                dm_odm->RFCalibrateInfo.bDoneTxpower = false;
 476                        }
 477                }
 478
 479                delta_lck = abs(dm_odm->RFCalibrateInfo.ThermalValue_LCK - thermal_val);
 480                delta_iqk = abs(dm_odm->RFCalibrateInfo.ThermalValue_IQK - thermal_val);
 481
 482                /* Delta temperature is equal to or larger than 20 centigrade.*/
 483                if ((delta_lck >= 8)) {
 484                        dm_odm->RFCalibrateInfo.ThermalValue_LCK = thermal_val;
 485                        rtl88eu_phy_lc_calibrate(adapt);
 486                }
 487
 488                if (delta > 0 && dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
 489                        delta = abs(hal_data->EEPROMThermalMeter - thermal_val);
 490
 491                        /* calculate new OFDM / CCK offset */
 492                        if (thermal_val > hal_data->EEPROMThermalMeter)
 493                                j = 1;
 494                        else
 495                                j = 0;
 496                        for (offset = 0; offset < index_mapping_NUM_88E; offset++) {
 497                                if (delta < thermal_mapping[j][offset]) {
 498                                        if (offset != 0)
 499                                                offset--;
 500                                        break;
 501                                }
 502                        }
 503                        if (offset >= index_mapping_NUM_88E)
 504                                offset = index_mapping_NUM_88E-1;
 505
 506                        /* Updating ofdm_index values with new OFDM / CCK offset */
 507                        ofdm_index[0] = dm_odm->RFCalibrateInfo.OFDM_index[0] + ofdm_index_mapping[j][offset];
 508                        if (ofdm_index[0] > OFDM_TABLE_SIZE_92D-1)
 509                                ofdm_index[0] = OFDM_TABLE_SIZE_92D-1;
 510                        else if (ofdm_index[0] < ofdm_min_index)
 511                                ofdm_index[0] = ofdm_min_index;
 512
 513                        cck_index = dm_odm->RFCalibrateInfo.CCK_index + ofdm_index_mapping[j][offset];
 514                        if (cck_index > CCK_TABLE_SIZE-1)
 515                                cck_index = CCK_TABLE_SIZE-1;
 516                        else if (cck_index < 0)
 517                                cck_index = 0;
 518
 519                        /* 2 temporarily remove bNOPG */
 520                        /* Config by SwingTable */
 521                        if (dm_odm->RFCalibrateInfo.TxPowerTrackControl) {
 522                                dm_odm->RFCalibrateInfo.bDoneTxpower = true;
 523
 524                                /*  Revse TX power table. */
 525                                dm_odm->BbSwingIdxOfdm = (u8)ofdm_index[0];
 526                                dm_odm->BbSwingIdxCck = (u8)cck_index;
 527
 528                                if (dm_odm->BbSwingIdxOfdmCurrent != dm_odm->BbSwingIdxOfdm) {
 529                                        dm_odm->BbSwingIdxOfdmCurrent = dm_odm->BbSwingIdxOfdm;
 530                                        dm_odm->BbSwingFlagOfdm = true;
 531                                }
 532
 533                                if (dm_odm->BbSwingIdxCckCurrent != dm_odm->BbSwingIdxCck) {
 534                                        dm_odm->BbSwingIdxCckCurrent = dm_odm->BbSwingIdxCck;
 535                                        dm_odm->BbSwingFlagCck = true;
 536                                }
 537                        }
 538                }
 539
 540                /* Delta temperature is equal to or larger than 20 centigrade.*/
 541                if (delta_iqk >= 8) {
 542                        dm_odm->RFCalibrateInfo.ThermalValue_IQK = thermal_val;
 543                        rtl88eu_phy_iq_calibrate(adapt, false);
 544                }
 545                /* update thermal meter value */
 546                if (dm_odm->RFCalibrateInfo.TxPowerTrackControl)
 547                        dm_odm->RFCalibrateInfo.ThermalValue = thermal_val;
 548        }
 549        dm_odm->RFCalibrateInfo.TXPowercount = 0;
 550}
 551
 552#define MAX_TOLERANCE 5
 553
 554static u8 phy_path_a_iqk(struct adapter *adapt, bool config_pathb)
 555{
 556        u32 reg_eac, reg_e94, reg_e9c;
 557        u8 result = 0x00;
 558
 559        /* 1 Tx IQK */
 560        /* path-A IQK setting */
 561        phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
 562        phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
 563        phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x8214032a);
 564        phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
 565
 566        /* LO calibration setting */
 567        phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x00462911);
 568
 569        /* One shot, path A LOK & IQK */
 570        phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
 571        phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
 572
 573        mdelay(IQK_DELAY_TIME_88E);
 574
 575        reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
 576        reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
 577        reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
 578
 579        if (!(reg_eac & BIT(28)) &&
 580            (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
 581            (((reg_e9c & 0x03FF0000)>>16) != 0x42))
 582                result |= 0x01;
 583        return result;
 584}
 585
 586static u8 phy_path_a_rx_iqk(struct adapter *adapt, bool configPathB)
 587{
 588        u32 reg_eac, reg_e94, reg_e9c, reg_ea4, u4tmp;
 589        u8 result = 0x00;
 590        struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
 591
 592        /* 1 Get TXIMR setting */
 593        /* modify RXIQK mode table */
 594        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
 595        phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
 596        phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
 597        phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
 598        phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf117B);
 599
 600        /* PA,PAD off */
 601        phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x980);
 602        phy_set_rf_reg(adapt, RF_PATH_A, 0x56, bRFRegOffsetMask, 0x51000);
 603
 604        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
 605
 606        /* IQK setting */
 607        phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
 608        phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
 609
 610        /* path-A IQK setting */
 611        phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x10008c1c);
 612        phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x30008c1c);
 613        phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c1f);
 614        phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160000);
 615
 616        /* LO calibration setting */
 617        phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
 618
 619        /* One shot, path A LOK & IQK */
 620        phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
 621        phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
 622
 623        /* delay x ms */
 624        mdelay(IQK_DELAY_TIME_88E);
 625
 626        /* Check failed */
 627        reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
 628        reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
 629        reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
 630
 631        if (!(reg_eac & BIT(28)) &&
 632            (((reg_e94 & 0x03FF0000)>>16) != 0x142) &&
 633            (((reg_e9c & 0x03FF0000)>>16) != 0x42))
 634                result |= 0x01;
 635        else                                    /* if Tx not OK, ignore Rx */
 636                return result;
 637
 638        u4tmp = 0x80007C00 | (reg_e94&0x3FF0000)  | ((reg_e9c&0x3FF0000) >> 16);
 639        phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, u4tmp);
 640
 641        /* 1 RX IQK */
 642        /* modify RXIQK mode table */
 643        ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
 644                     ("Path-A Rx IQK modify RXIQK mode table 2!\n"));
 645        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
 646        phy_set_rf_reg(adapt, RF_PATH_A, RF_WE_LUT, bRFRegOffsetMask, 0x800a0);
 647        phy_set_rf_reg(adapt, RF_PATH_A, RF_RCK_OS, bRFRegOffsetMask, 0x30000);
 648        phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G1, bRFRegOffsetMask, 0x0000f);
 649        phy_set_rf_reg(adapt, RF_PATH_A, RF_TXPA_G2, bRFRegOffsetMask, 0xf7ffa);
 650        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
 651
 652        /* IQK setting */
 653        phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x01004800);
 654
 655        /* path-A IQK setting */
 656        phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x38008c1c);
 657        phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x18008c1c);
 658        phy_set_bb_reg(adapt, rTx_IQK_PI_A, bMaskDWord, 0x82160c05);
 659        phy_set_bb_reg(adapt, rRx_IQK_PI_A, bMaskDWord, 0x28160c1f);
 660
 661        /* LO calibration setting */
 662        phy_set_bb_reg(adapt, rIQK_AGC_Rsp, bMaskDWord, 0x0046a911);
 663
 664        phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf9000000);
 665        phy_set_bb_reg(adapt, rIQK_AGC_Pts, bMaskDWord, 0xf8000000);
 666
 667        mdelay(IQK_DELAY_TIME_88E);
 668
 669        /*  Check failed */
 670        reg_eac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
 671        reg_e94 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A, bMaskDWord);
 672        reg_e9c = phy_query_bb_reg(adapt, rTx_Power_After_IQK_A, bMaskDWord);
 673        reg_ea4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2, bMaskDWord);
 674
 675        /* reload RF 0xdf */
 676        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x00000000);
 677        phy_set_rf_reg(adapt, RF_PATH_A, 0xdf, bRFRegOffsetMask, 0x180);
 678
 679        if (!(reg_eac & BIT(27)) && /* if Tx is OK, check whether Rx is OK */
 680            (((reg_ea4 & 0x03FF0000)>>16) != 0x132) &&
 681            (((reg_eac & 0x03FF0000)>>16) != 0x36))
 682                result |= 0x02;
 683        else
 684                ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
 685                             ("Path A Rx IQK fail!!\n"));
 686
 687        return result;
 688}
 689
 690static u8 phy_path_b_iqk(struct adapter *adapt)
 691{
 692        u32 regeac, regeb4, regebc, regec4, regecc;
 693        u8 result = 0x00;
 694        struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
 695
 696        /* One shot, path B LOK & IQK */
 697        phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000002);
 698        phy_set_bb_reg(adapt, rIQK_AGC_Cont, bMaskDWord, 0x00000000);
 699
 700        mdelay(IQK_DELAY_TIME_88E);
 701
 702        regeac = phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2, bMaskDWord);
 703        regeb4 = phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B, bMaskDWord);
 704        regebc = phy_query_bb_reg(adapt, rTx_Power_After_IQK_B, bMaskDWord);
 705        regec4 = phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2, bMaskDWord);
 706        regecc = phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2, bMaskDWord);
 707
 708        if (!(regeac & BIT(31)) &&
 709            (((regeb4 & 0x03FF0000)>>16) != 0x142) &&
 710            (((regebc & 0x03FF0000)>>16) != 0x42))
 711                result |= 0x01;
 712        else
 713                return result;
 714
 715        if (!(regeac & BIT(30)) &&
 716            (((regec4 & 0x03FF0000)>>16) != 0x132) &&
 717            (((regecc & 0x03FF0000)>>16) != 0x36))
 718                result |= 0x02;
 719        else
 720                ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION,
 721                             ODM_DBG_LOUD,  ("Path B Rx IQK fail!!\n"));
 722        return result;
 723}
 724
 725static void patha_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
 726                           u8 final_candidate, bool txonly)
 727{
 728        u32 oldval_0, x, tx0_a, reg;
 729        s32 y, tx0_c;
 730
 731        if (final_candidate == 0xFF) {
 732                return;
 733        } else if (iqkok) {
 734                oldval_0 = (phy_query_bb_reg(adapt, rOFDM0_XATxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
 735
 736                x = result[final_candidate][0];
 737                if ((x & 0x00000200) != 0)
 738                        x = x | 0xFFFFFC00;
 739
 740                tx0_a = (x * oldval_0) >> 8;
 741                phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x3FF, tx0_a);
 742                phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(31),
 743                               ((x * oldval_0>>7) & 0x1));
 744
 745                y = result[final_candidate][1];
 746                if ((y & 0x00000200) != 0)
 747                        y = y | 0xFFFFFC00;
 748
 749                tx0_c = (y * oldval_0) >> 8;
 750                phy_set_bb_reg(adapt, rOFDM0_XCTxAFE, 0xF0000000,
 751                               ((tx0_c&0x3C0)>>6));
 752                phy_set_bb_reg(adapt, rOFDM0_XATxIQImbalance, 0x003F0000,
 753                               (tx0_c&0x3F));
 754                phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(29),
 755                               ((y * oldval_0>>7) & 0x1));
 756
 757                if (txonly)
 758                        return;
 759
 760                reg = result[final_candidate][2];
 761                phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0x3FF, reg);
 762
 763                reg = result[final_candidate][3] & 0x3F;
 764                phy_set_bb_reg(adapt, rOFDM0_XARxIQImbalance, 0xFC00, reg);
 765
 766                reg = (result[final_candidate][3] >> 6) & 0xF;
 767                phy_set_bb_reg(adapt, rOFDM0_RxIQExtAnta, 0xF0000000, reg);
 768        }
 769}
 770
 771static void pathb_fill_iqk(struct adapter *adapt, bool iqkok, s32 result[][8],
 772                           u8 final_candidate, bool txonly)
 773{
 774        u32 oldval_1, x, tx1_a, reg;
 775        s32 y, tx1_c;
 776
 777        if (final_candidate == 0xFF) {
 778                return;
 779        } else if (iqkok) {
 780                oldval_1 = (phy_query_bb_reg(adapt, rOFDM0_XBTxIQImbalance, bMaskDWord) >> 22) & 0x3FF;
 781
 782                x = result[final_candidate][4];
 783                if ((x & 0x00000200) != 0)
 784                        x = x | 0xFFFFFC00;
 785                tx1_a = (x * oldval_1) >> 8;
 786                phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x3FF, tx1_a);
 787
 788                phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(27),
 789                               ((x * oldval_1>>7) & 0x1));
 790
 791                y = result[final_candidate][5];
 792                if ((y & 0x00000200) != 0)
 793                        y = y | 0xFFFFFC00;
 794
 795                tx1_c = (y * oldval_1) >> 8;
 796
 797                phy_set_bb_reg(adapt, rOFDM0_XDTxAFE, 0xF0000000,
 798                               ((tx1_c&0x3C0)>>6));
 799                phy_set_bb_reg(adapt, rOFDM0_XBTxIQImbalance, 0x003F0000,
 800                               (tx1_c&0x3F));
 801                phy_set_bb_reg(adapt, rOFDM0_ECCAThreshold, BIT(25),
 802                               ((y * oldval_1>>7) & 0x1));
 803
 804                if (txonly)
 805                        return;
 806
 807                reg = result[final_candidate][6];
 808                phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0x3FF, reg);
 809
 810                reg = result[final_candidate][7] & 0x3F;
 811                phy_set_bb_reg(adapt, rOFDM0_XBRxIQImbalance, 0xFC00, reg);
 812
 813                reg = (result[final_candidate][7] >> 6) & 0xF;
 814                phy_set_bb_reg(adapt, rOFDM0_AGCRSSITable, 0x0000F000, reg);
 815        }
 816}
 817
 818static void save_adda_registers(struct adapter *adapt, u32 *addareg,
 819                                u32 *backup, u32 register_num)
 820{
 821        u32 i;
 822
 823        for (i = 0; i < register_num; i++) {
 824                backup[i] = phy_query_bb_reg(adapt, addareg[i], bMaskDWord);
 825        }
 826}
 827
 828static void save_mac_registers(struct adapter *adapt, u32 *mac_reg,
 829                               u32 *backup)
 830{
 831        u32 i;
 832
 833        for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
 834                backup[i] = usb_read8(adapt, mac_reg[i]);
 835        }
 836        backup[i] = usb_read32(adapt, mac_reg[i]);
 837}
 838
 839static void reload_adda_reg(struct adapter *adapt, u32 *adda_reg,
 840                            u32 *backup, u32 regiester_num)
 841{
 842        u32 i;
 843
 844        for (i = 0; i < regiester_num; i++)
 845                phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, backup[i]);
 846}
 847
 848static void reload_mac_registers(struct adapter *adapt,
 849                                 u32 *mac_reg, u32 *backup)
 850{
 851        u32 i;
 852
 853        for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++) {
 854                usb_write8(adapt, mac_reg[i], (u8)backup[i]);
 855        }
 856        usb_write32(adapt, mac_reg[i], backup[i]);
 857}
 858
 859static void path_adda_on(struct adapter *adapt, u32 *adda_reg,
 860                         bool is_path_a_on, bool is2t)
 861{
 862        u32 path_on;
 863        u32 i;
 864
 865        if (!is2t) {
 866                path_on = 0x0bdb25a0;
 867                phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, 0x0b1b25a0);
 868        } else {
 869                path_on = is_path_a_on ? 0x04db25a4 : 0x0b1b25a4;
 870                phy_set_bb_reg(adapt, adda_reg[0], bMaskDWord, path_on);
 871        }
 872
 873        for (i = 1; i < IQK_ADDA_REG_NUM; i++)
 874                phy_set_bb_reg(adapt, adda_reg[i], bMaskDWord, path_on);
 875}
 876
 877static void mac_setting_calibration(struct adapter *adapt, u32 *mac_reg, u32 *backup)
 878{
 879        u32 i = 0;
 880
 881        usb_write8(adapt, mac_reg[i], 0x3F);
 882
 883        for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++) {
 884                usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(3))));
 885        }
 886        usb_write8(adapt, mac_reg[i], (u8)(backup[i]&(~BIT(5))));
 887}
 888
 889static void path_a_standby(struct adapter *adapt)
 890{
 891
 892        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x0);
 893        phy_set_bb_reg(adapt, 0x840, bMaskDWord, 0x00010000);
 894        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
 895}
 896
 897static void pi_mode_switch(struct adapter *adapt, bool pi_mode)
 898{
 899        u32 mode;
 900
 901        mode = pi_mode ? 0x01000100 : 0x01000000;
 902        phy_set_bb_reg(adapt, rFPGA0_XA_HSSIParameter1, bMaskDWord, mode);
 903        phy_set_bb_reg(adapt, rFPGA0_XB_HSSIParameter1, bMaskDWord, mode);
 904}
 905
 906static bool simularity_compare(struct adapter *adapt, s32 resulta[][8],
 907                               u8 c1, u8 c2)
 908{
 909        u32 i, j, diff, sim_bitmap = 0, bound;
 910        u8 final_candidate[2] = {0xFF, 0xFF};   /* for path A and path B */
 911        bool result = true;
 912        s32 tmp1 = 0, tmp2 = 0;
 913
 914        bound = 4;
 915
 916        for (i = 0; i < bound; i++) {
 917                if ((i == 1) || (i == 3) || (i == 5) || (i == 7)) {
 918                        if ((resulta[c1][i] & 0x00000200) != 0)
 919                                tmp1 = resulta[c1][i] | 0xFFFFFC00;
 920                        else
 921                                tmp1 = resulta[c1][i];
 922
 923                        if ((resulta[c2][i] & 0x00000200) != 0)
 924                                tmp2 = resulta[c2][i] | 0xFFFFFC00;
 925                        else
 926                                tmp2 = resulta[c2][i];
 927                } else {
 928                        tmp1 = resulta[c1][i];
 929                        tmp2 = resulta[c2][i];
 930                }
 931
 932                diff = abs(tmp1 - tmp2);
 933
 934                if (diff > MAX_TOLERANCE) {
 935                        if ((i == 2 || i == 6) && !sim_bitmap) {
 936                                if (resulta[c1][i] + resulta[c1][i+1] == 0)
 937                                        final_candidate[(i/4)] = c2;
 938                                else if (resulta[c2][i] + resulta[c2][i+1] == 0)
 939                                        final_candidate[(i/4)] = c1;
 940                                else
 941                                        sim_bitmap = sim_bitmap | (1<<i);
 942                        } else {
 943                                sim_bitmap = sim_bitmap | (1<<i);
 944                        }
 945                }
 946        }
 947
 948        if (sim_bitmap == 0) {
 949                for (i = 0; i < (bound/4); i++) {
 950                        if (final_candidate[i] != 0xFF) {
 951                                for (j = i*4; j < (i+1)*4-2; j++)
 952                                        resulta[3][j] = resulta[final_candidate[i]][j];
 953                                result = false;
 954                        }
 955                }
 956                return result;
 957        } else {
 958                if (!(sim_bitmap & 0x03)) {                /* path A TX OK */
 959                        for (i = 0; i < 2; i++)
 960                                resulta[3][i] = resulta[c1][i];
 961                }
 962                if (!(sim_bitmap & 0x0c)) {                /* path A RX OK */
 963                        for (i = 2; i < 4; i++)
 964                                resulta[3][i] = resulta[c1][i];
 965                }
 966
 967                if (!(sim_bitmap & 0x30)) { /* path B TX OK */
 968                        for (i = 4; i < 6; i++)
 969                                resulta[3][i] = resulta[c1][i];
 970                }
 971
 972                if (!(sim_bitmap & 0xc0)) { /* path B RX OK */
 973                        for (i = 6; i < 8; i++)
 974                                resulta[3][i] = resulta[c1][i];
 975                }
 976                return false;
 977        }
 978}
 979
 980static void phy_iq_calibrate(struct adapter *adapt, s32 result[][8],
 981                             u8 t, bool is2t)
 982{
 983        struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
 984        u32 i;
 985        u8 path_a_ok, path_b_ok;
 986        u32 adda_reg[IQK_ADDA_REG_NUM] = {
 987                                          rFPGA0_XCD_SwitchControl, rBlue_Tooth,
 988                                          rRx_Wait_CCA, rTx_CCK_RFON,
 989                                          rTx_CCK_BBON, rTx_OFDM_RFON,
 990                                          rTx_OFDM_BBON, rTx_To_Rx,
 991                                          rTx_To_Tx, rRx_CCK,
 992                                          rRx_OFDM, rRx_Wait_RIFS,
 993                                          rRx_TO_Rx, rStandby,
 994                                          rSleep, rPMPD_ANAEN};
 995
 996        u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
 997                                            REG_TXPAUSE, REG_BCN_CTRL,
 998                                            REG_BCN_CTRL_1, REG_GPIO_MUXCFG};
 999
1000        /* since 92C & 92D have the different define in IQK_BB_REG */
1001        u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1002                                              rOFDM0_TRxPathEnable, rOFDM0_TRMuxPar,
1003                                              rFPGA0_XCD_RFInterfaceSW, rConfig_AntA, rConfig_AntB,
1004                                              rFPGA0_XAB_RFInterfaceSW, rFPGA0_XA_RFInterfaceOE,
1005                                              rFPGA0_XB_RFInterfaceOE, rFPGA0_RFMOD};
1006
1007        u32 retry_count = 9;
1008        if (*(dm_odm->mp_mode) == 1)
1009                retry_count = 9;
1010        else
1011                retry_count = 2;
1012
1013        if (t == 0) {
1014
1015                /*  Save ADDA parameters, turn Path A ADDA on */
1016                save_adda_registers(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1017                                    IQK_ADDA_REG_NUM);
1018                save_mac_registers(adapt, iqk_mac_reg,
1019                                   dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1020                save_adda_registers(adapt, iqk_bb_reg_92c,
1021                                    dm_odm->RFCalibrateInfo.IQK_BB_backup, IQK_BB_REG_NUM);
1022        }
1023
1024        path_adda_on(adapt, adda_reg, true, is2t);
1025        if (t == 0)
1026                dm_odm->RFCalibrateInfo.bRfPiEnable = (u8)phy_query_bb_reg(adapt, rFPGA0_XA_HSSIParameter1,
1027                                                                           BIT(8));
1028
1029        if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1030                /*  Switch BB to PI mode to do IQ Calibration. */
1031                pi_mode_switch(adapt, true);
1032        }
1033
1034        /* BB setting */
1035        phy_set_bb_reg(adapt, rFPGA0_RFMOD, BIT(24), 0x00);
1036        phy_set_bb_reg(adapt, rOFDM0_TRxPathEnable, bMaskDWord, 0x03a05600);
1037        phy_set_bb_reg(adapt, rOFDM0_TRMuxPar, bMaskDWord, 0x000800e4);
1038        phy_set_bb_reg(adapt, rFPGA0_XCD_RFInterfaceSW, bMaskDWord, 0x22204000);
1039
1040        phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(10), 0x01);
1041        phy_set_bb_reg(adapt, rFPGA0_XAB_RFInterfaceSW, BIT(26), 0x01);
1042        phy_set_bb_reg(adapt, rFPGA0_XA_RFInterfaceOE, BIT(10), 0x00);
1043        phy_set_bb_reg(adapt, rFPGA0_XB_RFInterfaceOE, BIT(10), 0x00);
1044
1045        if (is2t) {
1046                phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter, bMaskDWord,
1047                               0x00010000);
1048                phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter, bMaskDWord,
1049                               0x00010000);
1050        }
1051
1052        /* MAC settings */
1053        mac_setting_calibration(adapt, iqk_mac_reg,
1054                                dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1055
1056        /* Page B init */
1057        /* AP or IQK */
1058        phy_set_bb_reg(adapt, rConfig_AntA, bMaskDWord, 0x0f600000);
1059
1060        if (is2t)
1061                phy_set_bb_reg(adapt, rConfig_AntB, bMaskDWord, 0x0f600000);
1062
1063        /*  IQ calibration setting */
1064        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0x80800000);
1065        phy_set_bb_reg(adapt, rTx_IQK, bMaskDWord, 0x01007c00);
1066        phy_set_bb_reg(adapt, rRx_IQK, bMaskDWord, 0x81004800);
1067
1068        for (i = 0; i < retry_count; i++) {
1069                path_a_ok = phy_path_a_iqk(adapt, is2t);
1070                if (path_a_ok == 0x01) {
1071                                result[t][0] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_A,
1072                                                                 bMaskDWord)&0x3FF0000)>>16;
1073                                result[t][1] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_A,
1074                                                                 bMaskDWord)&0x3FF0000)>>16;
1075                        break;
1076                }
1077        }
1078
1079        for (i = 0; i < retry_count; i++) {
1080                path_a_ok = phy_path_a_rx_iqk(adapt, is2t);
1081                if (path_a_ok == 0x03) {
1082                                result[t][2] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_A_2,
1083                                                                 bMaskDWord)&0x3FF0000)>>16;
1084                                result[t][3] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_A_2,
1085                                                                 bMaskDWord)&0x3FF0000)>>16;
1086                        break;
1087                } else {
1088                        ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1089                                     ("Path A Rx IQK Fail!!\n"));
1090                }
1091        }
1092
1093        if (0x00 == path_a_ok) {
1094                ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1095                             ("Path A IQK failed!!\n"));
1096        }
1097
1098        if (is2t) {
1099                path_a_standby(adapt);
1100
1101                /*  Turn Path B ADDA on */
1102                path_adda_on(adapt, adda_reg, false, is2t);
1103
1104                for (i = 0; i < retry_count; i++) {
1105                        path_b_ok = phy_path_b_iqk(adapt);
1106                        if (path_b_ok == 0x03) {
1107                                result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1108                                                                 bMaskDWord)&0x3FF0000)>>16;
1109                                result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1110                                                                 bMaskDWord)&0x3FF0000)>>16;
1111                                result[t][6] = (phy_query_bb_reg(adapt, rRx_Power_Before_IQK_B_2,
1112                                                                 bMaskDWord)&0x3FF0000)>>16;
1113                                result[t][7] = (phy_query_bb_reg(adapt, rRx_Power_After_IQK_B_2,
1114                                                                 bMaskDWord)&0x3FF0000)>>16;
1115                                break;
1116                        } else if (i == (retry_count - 1) && path_b_ok == 0x01) {       /* Tx IQK OK */
1117                                result[t][4] = (phy_query_bb_reg(adapt, rTx_Power_Before_IQK_B,
1118                                                                 bMaskDWord)&0x3FF0000)>>16;
1119                                result[t][5] = (phy_query_bb_reg(adapt, rTx_Power_After_IQK_B,
1120                                                                 bMaskDWord)&0x3FF0000)>>16;
1121                        }
1122                }
1123
1124                if (0x00 == path_b_ok) {
1125                        ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1126                                     ("Path B IQK failed!!\n"));
1127                }
1128        }
1129
1130        /* Back to BB mode, load original value */
1131        phy_set_bb_reg(adapt, rFPGA0_IQK, bMaskDWord, 0);
1132
1133        if (t != 0) {
1134                if (!dm_odm->RFCalibrateInfo.bRfPiEnable) {
1135                        /* Switch back BB to SI mode after
1136                         * finish IQ Calibration.
1137                         */
1138                        pi_mode_switch(adapt, false);
1139                }
1140
1141                /*  Reload ADDA power saving parameters */
1142                reload_adda_reg(adapt, adda_reg, dm_odm->RFCalibrateInfo.ADDA_backup,
1143                                IQK_ADDA_REG_NUM);
1144
1145                /*  Reload MAC parameters */
1146                reload_mac_registers(adapt, iqk_mac_reg,
1147                                     dm_odm->RFCalibrateInfo.IQK_MAC_backup);
1148
1149                reload_adda_reg(adapt, iqk_bb_reg_92c, dm_odm->RFCalibrateInfo.IQK_BB_backup,
1150                                IQK_BB_REG_NUM);
1151
1152                /*  Restore RX initial gain */
1153                phy_set_bb_reg(adapt, rFPGA0_XA_LSSIParameter,
1154                               bMaskDWord, 0x00032ed3);
1155                if (is2t)
1156                        phy_set_bb_reg(adapt, rFPGA0_XB_LSSIParameter,
1157                                       bMaskDWord, 0x00032ed3);
1158
1159                /* load 0xe30 IQC default value */
1160                phy_set_bb_reg(adapt, rTx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1161                phy_set_bb_reg(adapt, rRx_IQK_Tone_A, bMaskDWord, 0x01008c00);
1162        }
1163}
1164
1165static void phy_lc_calibrate(struct adapter *adapt, bool is2t)
1166{
1167        u8 tmpreg;
1168        u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1169
1170        /* Check continuous TX and Packet TX */
1171        tmpreg = usb_read8(adapt, 0xd03);
1172
1173        if ((tmpreg&0x70) != 0)
1174                usb_write8(adapt, 0xd03, tmpreg&0x8F);
1175        else
1176                usb_write8(adapt, REG_TXPAUSE, 0xFF);
1177
1178        if ((tmpreg&0x70) != 0) {
1179                /* 1. Read original RF mode */
1180                /* Path-A */
1181                rf_a_mode = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_AC,
1182                                             bMask12Bits);
1183
1184                /* Path-B */
1185                if (is2t)
1186                        rf_b_mode = rtw_hal_read_rfreg(adapt, RF_PATH_B, RF_AC,
1187                                                     bMask12Bits);
1188
1189                /* 2. Set RF mode = standby mode */
1190                /* Path-A */
1191                phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits,
1192                               (rf_a_mode&0x8FFFF)|0x10000);
1193
1194                /* Path-B */
1195                if (is2t)
1196                        phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1197                                       (rf_b_mode&0x8FFFF)|0x10000);
1198        }
1199
1200        /* 3. Read RF reg18 */
1201        lc_cal = rtw_hal_read_rfreg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits);
1202
1203        /* 4. Set LC calibration begin bit15 */
1204        phy_set_rf_reg(adapt, RF_PATH_A, RF_CHNLBW, bMask12Bits,
1205                       lc_cal|0x08000);
1206
1207        msleep(100);
1208
1209        /* Restore original situation */
1210        if ((tmpreg&0x70) != 0) {
1211                /* Deal with continuous TX case */
1212                /* Path-A */
1213                usb_write8(adapt, 0xd03, tmpreg);
1214                phy_set_rf_reg(adapt, RF_PATH_A, RF_AC, bMask12Bits, rf_a_mode);
1215
1216                /* Path-B */
1217                if (is2t)
1218                        phy_set_rf_reg(adapt, RF_PATH_B, RF_AC, bMask12Bits,
1219                                       rf_b_mode);
1220        } else {
1221                /* Deal with Packet TX case */
1222                usb_write8(adapt, REG_TXPAUSE, 0x00);
1223        }
1224}
1225
1226void rtl88eu_phy_iq_calibrate(struct adapter *adapt, bool recovery)
1227{
1228        struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1229        s32 result[4][8];
1230        u8 i, final, chn_index;
1231        bool pathaok, pathbok;
1232        s32 reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_ec4;
1233        bool is12simular, is13simular, is23simular;
1234        bool singletone = false, carrier_sup = false;
1235        u32 iqk_bb_reg_92c[IQK_BB_REG_NUM] = {
1236                rOFDM0_XARxIQImbalance, rOFDM0_XBRxIQImbalance,
1237                rOFDM0_ECCAThreshold, rOFDM0_AGCRSSITable,
1238                rOFDM0_XATxIQImbalance, rOFDM0_XBTxIQImbalance,
1239                rOFDM0_XCTxAFE, rOFDM0_XDTxAFE,
1240                rOFDM0_RxIQExtAnta};
1241        bool is2t;
1242
1243        is2t = false;
1244
1245        if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1246                return;
1247
1248        if (singletone || carrier_sup)
1249                return;
1250
1251        if (recovery) {
1252                ODM_RT_TRACE(dm_odm, ODM_COMP_INIT, ODM_DBG_LOUD,
1253                             ("phy_iq_calibrate: Return due to recovery!\n"));
1254                reload_adda_reg(adapt, iqk_bb_reg_92c,
1255                                dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1256                return;
1257        }
1258
1259        for (i = 0; i < 8; i++) {
1260                result[0][i] = 0;
1261                result[1][i] = 0;
1262                result[2][i] = 0;
1263                if ((i == 0) || (i == 2) || (i == 4)  || (i == 6))
1264                        result[3][i] = 0x100;
1265                else
1266                        result[3][i] = 0;
1267        }
1268        final = 0xff;
1269        pathaok = false;
1270        pathbok = false;
1271        is12simular = false;
1272        is23simular = false;
1273        is13simular = false;
1274
1275        for (i = 0; i < 3; i++) {
1276                phy_iq_calibrate(adapt, result, i, is2t);
1277
1278                if (i == 1) {
1279                        is12simular = simularity_compare(adapt, result, 0, 1);
1280                        if (is12simular) {
1281                                final = 0;
1282                                break;
1283                        }
1284                }
1285
1286                if (i == 2) {
1287                        is13simular = simularity_compare(adapt, result, 0, 2);
1288                        if (is13simular) {
1289                                final = 0;
1290                                break;
1291                        }
1292                        is23simular = simularity_compare(adapt, result, 1, 2);
1293                        if (is23simular)
1294                                final = 1;
1295                        else
1296                                final = 3;
1297                }
1298        }
1299
1300        for (i = 0; i < 4; i++) {
1301                reg_e94 = result[i][0];
1302                reg_e9c = result[i][1];
1303                reg_ea4 = result[i][2];
1304                reg_eb4 = result[i][4];
1305                reg_ebc = result[i][5];
1306                reg_ec4 = result[i][6];
1307        }
1308
1309        if (final != 0xff) {
1310                reg_e94 = result[final][0];
1311                reg_e9c = result[final][1];
1312                reg_ea4 = result[final][2];
1313                reg_eb4 = result[final][4];
1314                reg_ebc = result[final][5];
1315                dm_odm->RFCalibrateInfo.RegE94 = reg_e94;
1316                dm_odm->RFCalibrateInfo.RegE9C = reg_e9c;
1317                dm_odm->RFCalibrateInfo.RegEB4 = reg_eb4;
1318                dm_odm->RFCalibrateInfo.RegEBC = reg_ebc;
1319                reg_ec4 = result[final][6];
1320                pathaok = true;
1321                pathbok = true;
1322        } else {
1323                ODM_RT_TRACE(dm_odm, ODM_COMP_CALIBRATION, ODM_DBG_LOUD,
1324                             ("IQK: FAIL use default value\n"));
1325                dm_odm->RFCalibrateInfo.RegE94 = 0x100;
1326                dm_odm->RFCalibrateInfo.RegEB4 = 0x100;
1327                dm_odm->RFCalibrateInfo.RegE9C = 0x0;
1328                dm_odm->RFCalibrateInfo.RegEBC = 0x0;
1329        }
1330        if (reg_e94 != 0)
1331                patha_fill_iqk(adapt, pathaok, result, final,
1332                               (reg_ea4 == 0));
1333        if (is2t) {
1334                if (reg_eb4 != 0)
1335                        pathb_fill_iqk(adapt, pathbok, result, final,
1336                                       (reg_ec4 == 0));
1337        }
1338
1339        chn_index = get_right_chnl_for_iqk(adapt->HalData->CurrentChannel);
1340
1341        if (final < 4) {
1342                for (i = 0; i < IQK_Matrix_REG_NUM; i++)
1343                        dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].Value[0][i] = result[final][i];
1344                dm_odm->RFCalibrateInfo.IQKMatrixRegSetting[chn_index].bIQKDone = true;
1345        }
1346
1347        save_adda_registers(adapt, iqk_bb_reg_92c,
1348                            dm_odm->RFCalibrateInfo.IQK_BB_backup_recover, 9);
1349}
1350
1351void rtl88eu_phy_lc_calibrate(struct adapter *adapt)
1352{
1353        bool singletone = false, carrier_sup = false;
1354        u32 timeout = 2000, timecount = 0;
1355        struct odm_dm_struct *dm_odm = &adapt->HalData->odmpriv;
1356
1357        if (!(dm_odm->SupportAbility & ODM_RF_CALIBRATION))
1358                return;
1359        if (singletone || carrier_sup)
1360                return;
1361
1362        while (*(dm_odm->pbScanInProcess) && timecount < timeout) {
1363                mdelay(50);
1364                timecount += 50;
1365        }
1366
1367        dm_odm->RFCalibrateInfo.bLCKInProgress = true;
1368
1369        phy_lc_calibrate(adapt, false);
1370
1371        dm_odm->RFCalibrateInfo.bLCKInProgress = false;
1372}
1373