linux/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/phy.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2012  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../pci.h"
   6#include "../ps.h"
   7#include "reg.h"
   8#include "def.h"
   9#include "phy.h"
  10#include "rf.h"
  11#include "dm.h"
  12#include "table.h"
  13#include "../rtl8723com/phy_common.h"
  14
  15static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
  16                                             enum radio_path rfpath, u32 offset,
  17                                             u32 data);
  18static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
  19static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
  20static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
  21                                                    u8 configtype);
  22static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
  23                                                      u8 configtype);
  24static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
  25                                               u8 channel, u8 *stage, u8 *step,
  26                                               u32 *delay);
  27static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw,
  28                                         enum wireless_mode wirelessmode,
  29                                         long power_indbm);
  30static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw);
  31static void rtl8723e_phy_set_io(struct ieee80211_hw *hw);
  32
  33u32 rtl8723e_phy_query_rf_reg(struct ieee80211_hw *hw,
  34                              enum radio_path rfpath,
  35                              u32 regaddr, u32 bitmask)
  36{
  37        struct rtl_priv *rtlpriv = rtl_priv(hw);
  38        u32 original_value = 0, readback_value, bitshift;
  39        struct rtl_phy *rtlphy = &rtlpriv->phy;
  40        unsigned long flags;
  41
  42        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  43                 "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
  44                 regaddr, rfpath, bitmask);
  45
  46        spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
  47
  48        if (rtlphy->rf_mode != RF_OP_BY_FW) {
  49                original_value = rtl8723_phy_rf_serial_read(hw,
  50                                                            rfpath, regaddr);
  51        }
  52
  53        bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
  54        readback_value = (original_value & bitmask) >> bitshift;
  55
  56        spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
  57
  58        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  59                 "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
  60                  regaddr, rfpath, bitmask, original_value);
  61
  62        return readback_value;
  63}
  64
  65void rtl8723e_phy_set_rf_reg(struct ieee80211_hw *hw,
  66                             enum radio_path rfpath,
  67                           u32 regaddr, u32 bitmask, u32 data)
  68{
  69        struct rtl_priv *rtlpriv = rtl_priv(hw);
  70        struct rtl_phy *rtlphy = &rtlpriv->phy;
  71        u32 original_value = 0, bitshift;
  72        unsigned long flags;
  73
  74        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  75                 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  76                  regaddr, bitmask, data, rfpath);
  77
  78        spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags);
  79
  80        if (rtlphy->rf_mode != RF_OP_BY_FW) {
  81                if (bitmask != RFREG_OFFSET_MASK) {
  82                        original_value = rtl8723_phy_rf_serial_read(hw,
  83                                                                    rfpath,
  84                                                                    regaddr);
  85                        bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
  86                        data =
  87                            ((original_value & (~bitmask)) |
  88                             (data << bitshift));
  89                }
  90
  91                rtl8723_phy_rf_serial_write(hw, rfpath, regaddr, data);
  92        } else {
  93                if (bitmask != RFREG_OFFSET_MASK) {
  94                        bitshift = rtl8723_phy_calculate_bit_shift(bitmask);
  95                        data =
  96                            ((original_value & (~bitmask)) |
  97                             (data << bitshift));
  98                }
  99                _rtl8723e_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
 100        }
 101
 102        spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags);
 103
 104        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 105                 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
 106                 regaddr, bitmask, data, rfpath);
 107
 108}
 109
 110static void _rtl8723e_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
 111                                             enum radio_path rfpath, u32 offset,
 112                                             u32 data)
 113{
 114        WARN_ONCE(true, "rtl8723ae: _rtl8723e_phy_fw_rf_serial_write deprecated!\n");
 115}
 116
 117static void _rtl8723e_phy_bb_config_1t(struct ieee80211_hw *hw)
 118{
 119        rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
 120        rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
 121        rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
 122        rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
 123        rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
 124        rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
 125        rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
 126        rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
 127        rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
 128        rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
 129}
 130
 131bool rtl8723e_phy_mac_config(struct ieee80211_hw *hw)
 132{
 133        struct rtl_priv *rtlpriv = rtl_priv(hw);
 134        bool rtstatus = _rtl8723e_phy_config_mac_with_headerfile(hw);
 135        rtl_write_byte(rtlpriv, 0x04CA, 0x0A);
 136        return rtstatus;
 137}
 138
 139bool rtl8723e_phy_bb_config(struct ieee80211_hw *hw)
 140{
 141        bool rtstatus = true;
 142        struct rtl_priv *rtlpriv = rtl_priv(hw);
 143        u8 tmpu1b;
 144        u8 b_reg_hwparafile = 1;
 145
 146        rtl8723_phy_init_bb_rf_reg_def(hw);
 147
 148        /* 1. 0x28[1] = 1 */
 149        tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_PLL_CTRL);
 150        udelay(2);
 151        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, (tmpu1b|BIT(1)));
 152        udelay(2);
 153        /* 2. 0x29[7:0] = 0xFF */
 154        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL+1, 0xff);
 155        udelay(2);
 156
 157        /* 3. 0x02[1:0] = 2b'11 */
 158        tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN);
 159        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN,
 160                       (tmpu1b | FEN_BB_GLB_RSTN | FEN_BBRSTB));
 161
 162        /* 4. 0x25[6] = 0 */
 163        tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+1);
 164        rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+1, (tmpu1b & (~BIT(6))));
 165
 166        /* 5. 0x24[20] = 0      //Advised by SD3 Alex Wang. 2011.02.09. */
 167        tmpu1b = rtl_read_byte(rtlpriv, REG_AFE_XTAL_CTRL+2);
 168        rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL+2, (tmpu1b & (~BIT(4))));
 169
 170        /* 6. 0x1f[7:0] = 0x07 */
 171        rtl_write_byte(rtlpriv, REG_RF_CTRL, 0x07);
 172
 173        if (b_reg_hwparafile == 1)
 174                rtstatus = _rtl8723e_phy_bb8192c_config_parafile(hw);
 175        return rtstatus;
 176}
 177
 178bool rtl8723e_phy_rf_config(struct ieee80211_hw *hw)
 179{
 180        return rtl8723e_phy_rf6052_config(hw);
 181}
 182
 183static bool _rtl8723e_phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
 184{
 185        struct rtl_priv *rtlpriv = rtl_priv(hw);
 186        struct rtl_phy *rtlphy = &rtlpriv->phy;
 187        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 188        bool rtstatus;
 189
 190        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
 191        rtstatus = _rtl8723e_phy_config_bb_with_headerfile(hw,
 192                                                BASEBAND_CONFIG_PHY_REG);
 193        if (rtstatus != true) {
 194                pr_err("Write BB Reg Fail!!\n");
 195                return false;
 196        }
 197
 198        if (rtlphy->rf_type == RF_1T2R) {
 199                _rtl8723e_phy_bb_config_1t(hw);
 200                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Config to 1T!!\n");
 201        }
 202        if (rtlefuse->autoload_failflag == false) {
 203                rtlphy->pwrgroup_cnt = 0;
 204                rtstatus = _rtl8723e_phy_config_bb_with_pgheaderfile(hw,
 205                                        BASEBAND_CONFIG_PHY_REG);
 206        }
 207        if (rtstatus != true) {
 208                pr_err("BB_PG Reg Fail!!\n");
 209                return false;
 210        }
 211        rtstatus =
 212          _rtl8723e_phy_config_bb_with_headerfile(hw, BASEBAND_CONFIG_AGC_TAB);
 213        if (rtstatus != true) {
 214                pr_err("AGC Table Fail\n");
 215                return false;
 216        }
 217        rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
 218                                        RFPGA0_XA_HSSIPARAMETER2,
 219                                        0x200));
 220
 221        return true;
 222}
 223
 224static bool _rtl8723e_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
 225{
 226        struct rtl_priv *rtlpriv = rtl_priv(hw);
 227        u32 i;
 228        u32 arraylength;
 229        u32 *ptrarray;
 230
 231        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl723MACPHY_Array\n");
 232        arraylength = RTL8723E_MACARRAYLENGTH;
 233        ptrarray = RTL8723EMAC_ARRAY;
 234
 235        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 236                 "Img:RTL8192CEMAC_2T_ARRAY\n");
 237        for (i = 0; i < arraylength; i = i + 2)
 238                rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
 239        return true;
 240}
 241
 242static bool _rtl8723e_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
 243                                                    u8 configtype)
 244{
 245        int i;
 246        u32 *phy_regarray_table;
 247        u32 *agctab_array_table;
 248        u16 phy_reg_arraylen, agctab_arraylen;
 249        struct rtl_priv *rtlpriv = rtl_priv(hw);
 250
 251        agctab_arraylen = RTL8723E_AGCTAB_1TARRAYLENGTH;
 252        agctab_array_table = RTL8723EAGCTAB_1TARRAY;
 253        phy_reg_arraylen = RTL8723E_PHY_REG_1TARRAY_LENGTH;
 254        phy_regarray_table = RTL8723EPHY_REG_1TARRAY;
 255        if (configtype == BASEBAND_CONFIG_PHY_REG) {
 256                for (i = 0; i < phy_reg_arraylen; i = i + 2) {
 257                        if (phy_regarray_table[i] == 0xfe)
 258                                mdelay(50);
 259                        else if (phy_regarray_table[i] == 0xfd)
 260                                mdelay(5);
 261                        else if (phy_regarray_table[i] == 0xfc)
 262                                mdelay(1);
 263                        else if (phy_regarray_table[i] == 0xfb)
 264                                udelay(50);
 265                        else if (phy_regarray_table[i] == 0xfa)
 266                                udelay(5);
 267                        else if (phy_regarray_table[i] == 0xf9)
 268                                udelay(1);
 269                        rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
 270                                      phy_regarray_table[i + 1]);
 271                        udelay(1);
 272                        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 273                                 "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
 274                                 phy_regarray_table[i],
 275                                 phy_regarray_table[i + 1]);
 276                }
 277        } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
 278                for (i = 0; i < agctab_arraylen; i = i + 2) {
 279                        rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
 280                                      agctab_array_table[i + 1]);
 281                        udelay(1);
 282                        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 283                                 "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
 284                                 agctab_array_table[i],
 285                                 agctab_array_table[i + 1]);
 286                }
 287        }
 288        return true;
 289}
 290
 291static void store_pwrindex_diffrate_offset(struct ieee80211_hw *hw,
 292                                           u32 regaddr, u32 bitmask,
 293                                           u32 data)
 294{
 295        struct rtl_priv *rtlpriv = rtl_priv(hw);
 296        struct rtl_phy *rtlphy = &rtlpriv->phy;
 297
 298        if (regaddr == RTXAGC_A_RATE18_06) {
 299                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] =
 300                    data;
 301                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 302                         "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
 303                          rtlphy->pwrgroup_cnt,
 304                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 305                                                            pwrgroup_cnt][0]);
 306        }
 307        if (regaddr == RTXAGC_A_RATE54_24) {
 308                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] =
 309                    data;
 310                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 311                         "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
 312                          rtlphy->pwrgroup_cnt,
 313                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 314                                                            pwrgroup_cnt][1]);
 315        }
 316        if (regaddr == RTXAGC_A_CCK1_MCS32) {
 317                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] =
 318                    data;
 319                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 320                         "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
 321                          rtlphy->pwrgroup_cnt,
 322                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 323                                                            pwrgroup_cnt][6]);
 324        }
 325        if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
 326                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] =
 327                    data;
 328                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 329                         "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
 330                          rtlphy->pwrgroup_cnt,
 331                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 332                                                            pwrgroup_cnt][7]);
 333        }
 334        if (regaddr == RTXAGC_A_MCS03_MCS00) {
 335                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] =
 336                    data;
 337                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 338                         "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
 339                          rtlphy->pwrgroup_cnt,
 340                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 341                                                            pwrgroup_cnt][2]);
 342        }
 343        if (regaddr == RTXAGC_A_MCS07_MCS04) {
 344                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] =
 345                    data;
 346                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 347                         "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
 348                          rtlphy->pwrgroup_cnt,
 349                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 350                                                            pwrgroup_cnt][3]);
 351        }
 352        if (regaddr == RTXAGC_A_MCS11_MCS08) {
 353                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] =
 354                    data;
 355                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 356                         "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
 357                          rtlphy->pwrgroup_cnt,
 358                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 359                                                            pwrgroup_cnt][4]);
 360        }
 361        if (regaddr == RTXAGC_A_MCS15_MCS12) {
 362                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] =
 363                    data;
 364                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 365                         "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
 366                          rtlphy->pwrgroup_cnt,
 367                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 368                                                            pwrgroup_cnt][5]);
 369        }
 370        if (regaddr == RTXAGC_B_RATE18_06) {
 371                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] =
 372                    data;
 373                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 374                         "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
 375                          rtlphy->pwrgroup_cnt,
 376                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 377                                                            pwrgroup_cnt][8]);
 378        }
 379        if (regaddr == RTXAGC_B_RATE54_24) {
 380                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] =
 381                    data;
 382                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 383                         "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
 384                          rtlphy->pwrgroup_cnt,
 385                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 386                                                            pwrgroup_cnt][9]);
 387        }
 388        if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
 389                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] =
 390                    data;
 391                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 392                         "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
 393                          rtlphy->pwrgroup_cnt,
 394                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 395                                                            pwrgroup_cnt][14]);
 396        }
 397        if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
 398                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] =
 399                    data;
 400                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 401                         "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
 402                          rtlphy->pwrgroup_cnt,
 403                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 404                                                            pwrgroup_cnt][15]);
 405        }
 406        if (regaddr == RTXAGC_B_MCS03_MCS00) {
 407                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] =
 408                    data;
 409                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 410                         "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
 411                          rtlphy->pwrgroup_cnt,
 412                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 413                                                            pwrgroup_cnt][10]);
 414        }
 415        if (regaddr == RTXAGC_B_MCS07_MCS04) {
 416                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] =
 417                    data;
 418                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 419                         "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
 420                          rtlphy->pwrgroup_cnt,
 421                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 422                                                            pwrgroup_cnt][11]);
 423        }
 424        if (regaddr == RTXAGC_B_MCS11_MCS08) {
 425                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] =
 426                    data;
 427                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 428                         "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
 429                          rtlphy->pwrgroup_cnt,
 430                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 431                                                            pwrgroup_cnt][12]);
 432        }
 433        if (regaddr == RTXAGC_B_MCS15_MCS12) {
 434                rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] =
 435                    data;
 436                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 437                         "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
 438                          rtlphy->pwrgroup_cnt,
 439                          rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
 440                                                            pwrgroup_cnt][13]);
 441
 442                rtlphy->pwrgroup_cnt++;
 443        }
 444}
 445
 446static bool _rtl8723e_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
 447                                                      u8 configtype)
 448{
 449        struct rtl_priv *rtlpriv = rtl_priv(hw);
 450        int i;
 451        u32 *phy_regarray_table_pg;
 452        u16 phy_regarray_pg_len;
 453
 454        phy_regarray_pg_len = RTL8723E_PHY_REG_ARRAY_PGLENGTH;
 455        phy_regarray_table_pg = RTL8723EPHY_REG_ARRAY_PG;
 456
 457        if (configtype == BASEBAND_CONFIG_PHY_REG) {
 458                for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
 459                        if (phy_regarray_table_pg[i] == 0xfe)
 460                                mdelay(50);
 461                        else if (phy_regarray_table_pg[i] == 0xfd)
 462                                mdelay(5);
 463                        else if (phy_regarray_table_pg[i] == 0xfc)
 464                                mdelay(1);
 465                        else if (phy_regarray_table_pg[i] == 0xfb)
 466                                udelay(50);
 467                        else if (phy_regarray_table_pg[i] == 0xfa)
 468                                udelay(5);
 469                        else if (phy_regarray_table_pg[i] == 0xf9)
 470                                udelay(1);
 471
 472                        store_pwrindex_diffrate_offset(hw,
 473                                                phy_regarray_table_pg[i],
 474                                                phy_regarray_table_pg[i + 1],
 475                                                phy_regarray_table_pg[i + 2]);
 476                }
 477        } else {
 478                RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
 479                         "configtype != BaseBand_Config_PHY_REG\n");
 480        }
 481        return true;
 482}
 483
 484bool rtl8723e_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 485                                            enum radio_path rfpath)
 486{
 487        int i;
 488        bool rtstatus = true;
 489        u32 *radioa_array_table;
 490        u16 radioa_arraylen;
 491
 492        radioa_arraylen = RTL8723ERADIOA_1TARRAYLENGTH;
 493        radioa_array_table = RTL8723E_RADIOA_1TARRAY;
 494
 495        rtstatus = true;
 496
 497        switch (rfpath) {
 498        case RF90_PATH_A:
 499                for (i = 0; i < radioa_arraylen; i = i + 2) {
 500                        if (radioa_array_table[i] == 0xfe) {
 501                                mdelay(50);
 502                        } else if (radioa_array_table[i] == 0xfd) {
 503                                mdelay(5);
 504                        } else if (radioa_array_table[i] == 0xfc) {
 505                                mdelay(1);
 506                        } else if (radioa_array_table[i] == 0xfb) {
 507                                udelay(50);
 508                        } else if (radioa_array_table[i] == 0xfa) {
 509                                udelay(5);
 510                        } else if (radioa_array_table[i] == 0xf9) {
 511                                udelay(1);
 512                        } else {
 513                                rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
 514                                              RFREG_OFFSET_MASK,
 515                                              radioa_array_table[i + 1]);
 516                                udelay(1);
 517                        }
 518                }
 519                break;
 520        case RF90_PATH_B:
 521        case RF90_PATH_C:
 522        case RF90_PATH_D:
 523                break;
 524        }
 525        return true;
 526}
 527
 528void rtl8723e_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
 529{
 530        struct rtl_priv *rtlpriv = rtl_priv(hw);
 531        struct rtl_phy *rtlphy = &rtlpriv->phy;
 532
 533        rtlphy->default_initialgain[0] =
 534            (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
 535        rtlphy->default_initialgain[1] =
 536            (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
 537        rtlphy->default_initialgain[2] =
 538            (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
 539        rtlphy->default_initialgain[3] =
 540            (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0);
 541
 542        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 543                 "Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x\n",
 544                 rtlphy->default_initialgain[0],
 545                 rtlphy->default_initialgain[1],
 546                 rtlphy->default_initialgain[2],
 547                 rtlphy->default_initialgain[3]);
 548
 549        rtlphy->framesync = (u8) rtl_get_bbreg(hw,
 550                                               ROFDM0_RXDETECTOR3, MASKBYTE0);
 551        rtlphy->framesync_c34 = rtl_get_bbreg(hw,
 552                                              ROFDM0_RXDETECTOR2, MASKDWORD);
 553
 554        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 555                 "Default framesync (0x%x) = 0x%x\n",
 556                  ROFDM0_RXDETECTOR3, rtlphy->framesync);
 557}
 558
 559void rtl8723e_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
 560{
 561        struct rtl_priv *rtlpriv = rtl_priv(hw);
 562        struct rtl_phy *rtlphy = &rtlpriv->phy;
 563        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 564        u8 txpwr_level;
 565        long txpwr_dbm;
 566
 567        txpwr_level = rtlphy->cur_cck_txpwridx;
 568        txpwr_dbm = rtl8723_phy_txpwr_idx_to_dbm(hw,
 569                                                 WIRELESS_MODE_B, txpwr_level);
 570        txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
 571            rtlefuse->legacy_ht_txpowerdiff;
 572        if (rtl8723_phy_txpwr_idx_to_dbm(hw,
 573                                         WIRELESS_MODE_G,
 574                                         txpwr_level) > txpwr_dbm)
 575                txpwr_dbm =
 576                    rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
 577                                                 txpwr_level);
 578        txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
 579        if (rtl8723_phy_txpwr_idx_to_dbm(hw,
 580                                         WIRELESS_MODE_N_24G,
 581                                         txpwr_level) > txpwr_dbm)
 582                txpwr_dbm =
 583                    rtl8723_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
 584                                                 txpwr_level);
 585        *powerlevel = txpwr_dbm;
 586}
 587
 588static void _rtl8723e_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
 589                                        u8 *cckpowerlevel, u8 *ofdmpowerlevel)
 590{
 591        struct rtl_priv *rtlpriv = rtl_priv(hw);
 592        struct rtl_phy *rtlphy = &rtlpriv->phy;
 593        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 594        u8 index = (channel - 1);
 595
 596        cckpowerlevel[RF90_PATH_A] =
 597            rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
 598        cckpowerlevel[RF90_PATH_B] =
 599            rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
 600        if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
 601                ofdmpowerlevel[RF90_PATH_A] =
 602                    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
 603                ofdmpowerlevel[RF90_PATH_B] =
 604                    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
 605        } else if (get_rf_type(rtlphy) == RF_2T2R) {
 606                ofdmpowerlevel[RF90_PATH_A] =
 607                    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
 608                ofdmpowerlevel[RF90_PATH_B] =
 609                    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
 610        }
 611}
 612
 613static void _rtl8723e_ccxpower_index_check(struct ieee80211_hw *hw,
 614                                           u8 channel, u8 *cckpowerlevel,
 615                                           u8 *ofdmpowerlevel)
 616{
 617        struct rtl_priv *rtlpriv = rtl_priv(hw);
 618        struct rtl_phy *rtlphy = &rtlpriv->phy;
 619
 620        rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
 621        rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
 622
 623}
 624
 625void rtl8723e_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
 626{
 627        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 628        u8 cckpowerlevel[2], ofdmpowerlevel[2];
 629
 630        if (rtlefuse->txpwr_fromeprom == false)
 631                return;
 632        _rtl8723e_get_txpower_index(hw, channel,
 633                                    &cckpowerlevel[0], &ofdmpowerlevel[0]);
 634        _rtl8723e_ccxpower_index_check(hw,
 635                                       channel, &cckpowerlevel[0],
 636                                       &ofdmpowerlevel[0]);
 637        rtl8723e_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
 638        rtl8723e_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
 639}
 640
 641bool rtl8723e_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
 642{
 643        struct rtl_priv *rtlpriv = rtl_priv(hw);
 644        struct rtl_phy *rtlphy = &rtlpriv->phy;
 645        struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 646        u8 idx;
 647        u8 rf_path;
 648        u8 ccktxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw,
 649                                                      WIRELESS_MODE_B,
 650                                                      power_indbm);
 651        u8 ofdmtxpwridx = _rtl8723e_phy_dbm_to_txpwr_idx(hw,
 652                                                       WIRELESS_MODE_N_24G,
 653                                                       power_indbm);
 654        if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
 655                ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
 656        else
 657                ofdmtxpwridx = 0;
 658        RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
 659                 "%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
 660                  power_indbm, ccktxpwridx, ofdmtxpwridx);
 661        for (idx = 0; idx < 14; idx++) {
 662                for (rf_path = 0; rf_path < 2; rf_path++) {
 663                        rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
 664                        rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
 665                            ofdmtxpwridx;
 666                        rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
 667                            ofdmtxpwridx;
 668                }
 669        }
 670        rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel);
 671        return true;
 672}
 673
 674static u8 _rtl8723e_phy_dbm_to_txpwr_idx(struct ieee80211_hw *hw,
 675                                         enum wireless_mode wirelessmode,
 676                                         long power_indbm)
 677{
 678        u8 txpwridx;
 679        long offset;
 680
 681        switch (wirelessmode) {
 682        case WIRELESS_MODE_B:
 683                offset = -7;
 684                break;
 685        case WIRELESS_MODE_G:
 686        case WIRELESS_MODE_N_24G:
 687                offset = -8;
 688                break;
 689        default:
 690                offset = -8;
 691                break;
 692        }
 693
 694        if ((power_indbm - offset) > 0)
 695                txpwridx = (u8)((power_indbm - offset) * 2);
 696        else
 697                txpwridx = 0;
 698
 699        if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
 700                txpwridx = MAX_TXPWR_IDX_NMODE_92S;
 701
 702        return txpwridx;
 703}
 704
 705void rtl8723e_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
 706{
 707        struct rtl_priv *rtlpriv = rtl_priv(hw);
 708        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 709        enum io_type iotype;
 710
 711        if (!is_hal_stop(rtlhal)) {
 712                switch (operation) {
 713                case SCAN_OPT_BACKUP_BAND0:
 714                        iotype = IO_CMD_PAUSE_BAND0_DM_BY_SCAN;
 715                        rtlpriv->cfg->ops->set_hw_reg(hw,
 716                                                      HW_VAR_IO_CMD,
 717                                                      (u8 *)&iotype);
 718
 719                        break;
 720                case SCAN_OPT_RESTORE:
 721                        iotype = IO_CMD_RESUME_DM_BY_SCAN;
 722                        rtlpriv->cfg->ops->set_hw_reg(hw,
 723                                                      HW_VAR_IO_CMD,
 724                                                      (u8 *)&iotype);
 725                        break;
 726                default:
 727                        pr_err("Unknown Scan Backup operation.\n");
 728                        break;
 729                }
 730        }
 731}
 732
 733void rtl8723e_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
 734{
 735        struct rtl_priv *rtlpriv = rtl_priv(hw);
 736        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 737        struct rtl_phy *rtlphy = &rtlpriv->phy;
 738        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 739        u8 reg_bw_opmode;
 740        u8 reg_prsr_rsc;
 741
 742        RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
 743                 "Switch to %s bandwidth\n",
 744                  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
 745                  "20MHz" : "40MHz");
 746
 747        if (is_hal_stop(rtlhal)) {
 748                rtlphy->set_bwmode_inprogress = false;
 749                return;
 750        }
 751
 752        reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
 753        reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
 754
 755        switch (rtlphy->current_chan_bw) {
 756        case HT_CHANNEL_WIDTH_20:
 757                reg_bw_opmode |= BW_OPMODE_20MHZ;
 758                rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
 759                break;
 760        case HT_CHANNEL_WIDTH_20_40:
 761                reg_bw_opmode &= ~BW_OPMODE_20MHZ;
 762                rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
 763                reg_prsr_rsc =
 764                    (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
 765                rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
 766                break;
 767        default:
 768                pr_err("unknown bandwidth: %#X\n",
 769                       rtlphy->current_chan_bw);
 770                break;
 771        }
 772
 773        switch (rtlphy->current_chan_bw) {
 774        case HT_CHANNEL_WIDTH_20:
 775                rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
 776                rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
 777                rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
 778                break;
 779        case HT_CHANNEL_WIDTH_20_40:
 780                rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
 781                rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
 782
 783                rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
 784                              (mac->cur_40_prime_sc >> 1));
 785                rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
 786                rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
 787
 788                rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
 789                              (mac->cur_40_prime_sc ==
 790                               HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
 791                break;
 792        default:
 793                pr_err("unknown bandwidth: %#X\n",
 794                       rtlphy->current_chan_bw);
 795                break;
 796        }
 797        rtl8723e_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
 798        rtlphy->set_bwmode_inprogress = false;
 799        RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n");
 800}
 801
 802void rtl8723e_phy_set_bw_mode(struct ieee80211_hw *hw,
 803                              enum nl80211_channel_type ch_type)
 804{
 805        struct rtl_priv *rtlpriv = rtl_priv(hw);
 806        struct rtl_phy *rtlphy = &rtlpriv->phy;
 807        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 808        u8 tmp_bw = rtlphy->current_chan_bw;
 809
 810        if (rtlphy->set_bwmode_inprogress)
 811                return;
 812        rtlphy->set_bwmode_inprogress = true;
 813        if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
 814                rtl8723e_phy_set_bw_mode_callback(hw);
 815        } else {
 816                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 817                         "false driver sleep or unload\n");
 818                rtlphy->set_bwmode_inprogress = false;
 819                rtlphy->current_chan_bw = tmp_bw;
 820        }
 821}
 822
 823void rtl8723e_phy_sw_chnl_callback(struct ieee80211_hw *hw)
 824{
 825        struct rtl_priv *rtlpriv = rtl_priv(hw);
 826        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 827        struct rtl_phy *rtlphy = &rtlpriv->phy;
 828        u32 delay;
 829
 830        RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
 831                 "switch to channel%d\n", rtlphy->current_channel);
 832        if (is_hal_stop(rtlhal))
 833                return;
 834        do {
 835                if (!rtlphy->sw_chnl_inprogress)
 836                        break;
 837                if (!_rtl8723e_phy_sw_chnl_step_by_step
 838                    (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
 839                     &rtlphy->sw_chnl_step, &delay)) {
 840                        if (delay > 0)
 841                                mdelay(delay);
 842                        else
 843                                continue;
 844                } else {
 845                        rtlphy->sw_chnl_inprogress = false;
 846                }
 847                break;
 848        } while (true);
 849        RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "\n");
 850}
 851
 852u8 rtl8723e_phy_sw_chnl(struct ieee80211_hw *hw)
 853{
 854        struct rtl_priv *rtlpriv = rtl_priv(hw);
 855        struct rtl_phy *rtlphy = &rtlpriv->phy;
 856        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 857
 858        if (rtlphy->sw_chnl_inprogress)
 859                return 0;
 860        if (rtlphy->set_bwmode_inprogress)
 861                return 0;
 862        WARN_ONCE((rtlphy->current_channel > 14),
 863                  "rtl8723ae: WIRELESS_MODE_G but channel>14");
 864        rtlphy->sw_chnl_inprogress = true;
 865        rtlphy->sw_chnl_stage = 0;
 866        rtlphy->sw_chnl_step = 0;
 867        if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
 868                rtl8723e_phy_sw_chnl_callback(hw);
 869                RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
 870                         "sw_chnl_inprogress false schedule workitem\n");
 871                rtlphy->sw_chnl_inprogress = false;
 872        } else {
 873                RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
 874                         "sw_chnl_inprogress false driver sleep or unload\n");
 875                rtlphy->sw_chnl_inprogress = false;
 876        }
 877        return 1;
 878}
 879
 880static void _rtl8723e_phy_sw_rf_seting(struct ieee80211_hw *hw, u8 channel)
 881{
 882        struct rtl_priv *rtlpriv = rtl_priv(hw);
 883        struct rtl_phy *rtlphy = &rtlpriv->phy;
 884        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 885
 886        if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version)) {
 887                if (channel == 6 && rtlphy->current_chan_bw ==
 888                                HT_CHANNEL_WIDTH_20)
 889                        rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1,
 890                                      MASKDWORD, 0x00255);
 891                else{
 892                        u32 backuprf0x1a = (u32)rtl_get_rfreg(hw,
 893                                        RF90_PATH_A, RF_RX_G1,
 894                                        RFREG_OFFSET_MASK);
 895                        rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1,
 896                                      MASKDWORD, backuprf0x1a);
 897                }
 898        }
 899}
 900
 901static bool _rtl8723e_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
 902                                               u8 channel, u8 *stage, u8 *step,
 903                                               u32 *delay)
 904{
 905        struct rtl_priv *rtlpriv = rtl_priv(hw);
 906        struct rtl_phy *rtlphy = &rtlpriv->phy;
 907        struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
 908        u32 precommoncmdcnt;
 909        struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
 910        u32 postcommoncmdcnt;
 911        struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
 912        u32 rfdependcmdcnt;
 913        struct swchnlcmd *currentcmd = NULL;
 914        u8 rfpath;
 915        u8 num_total_rfpath = rtlphy->num_total_rfpath;
 916
 917        precommoncmdcnt = 0;
 918        rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
 919                                         MAX_PRECMD_CNT,
 920                                         CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
 921        rtl8723_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
 922                                         MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
 923
 924        postcommoncmdcnt = 0;
 925
 926        rtl8723_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
 927                                         MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
 928
 929        rfdependcmdcnt = 0;
 930
 931        WARN_ONCE((channel < 1 || channel > 14),
 932                  "rtl8723ae: illegal channel for Zebra: %d\n", channel);
 933
 934        rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
 935                                         MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
 936                                         RF_CHNLBW, channel, 10);
 937
 938        rtl8723_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
 939                                         MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0,
 940                                         0);
 941
 942        do {
 943                switch (*stage) {
 944                case 0:
 945                        currentcmd = &precommoncmd[*step];
 946                        break;
 947                case 1:
 948                        currentcmd = &rfdependcmd[*step];
 949                        break;
 950                case 2:
 951                        currentcmd = &postcommoncmd[*step];
 952                        break;
 953                default:
 954                        pr_err("Invalid 'stage' = %d, Check it!\n",
 955                               *stage);
 956                        return true;
 957                }
 958
 959                if (currentcmd->cmdid == CMDID_END) {
 960                        if ((*stage) == 2) {
 961                                return true;
 962                        } else {
 963                                (*stage)++;
 964                                (*step) = 0;
 965                                continue;
 966                        }
 967                }
 968
 969                switch (currentcmd->cmdid) {
 970                case CMDID_SET_TXPOWEROWER_LEVEL:
 971                        rtl8723e_phy_set_txpower_level(hw, channel);
 972                        break;
 973                case CMDID_WRITEPORT_ULONG:
 974                        rtl_write_dword(rtlpriv, currentcmd->para1,
 975                                        currentcmd->para2);
 976                        break;
 977                case CMDID_WRITEPORT_USHORT:
 978                        rtl_write_word(rtlpriv, currentcmd->para1,
 979                                       (u16) currentcmd->para2);
 980                        break;
 981                case CMDID_WRITEPORT_UCHAR:
 982                        rtl_write_byte(rtlpriv, currentcmd->para1,
 983                                       (u8) currentcmd->para2);
 984                        break;
 985                case CMDID_RF_WRITEREG:
 986                        for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
 987                                rtlphy->rfreg_chnlval[rfpath] =
 988                                    ((rtlphy->rfreg_chnlval[rfpath] &
 989                                      0xfffffc00) | currentcmd->para2);
 990
 991                                rtl_set_rfreg(hw, (enum radio_path)rfpath,
 992                                              currentcmd->para1,
 993                                              RFREG_OFFSET_MASK,
 994                                              rtlphy->rfreg_chnlval[rfpath]);
 995                        }
 996                        _rtl8723e_phy_sw_rf_seting(hw, channel);
 997                        break;
 998                default:
 999                        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
1000                                 "switch case %#x not processed\n",
1001                                 currentcmd->cmdid);
1002                        break;
1003                }
1004
1005                break;
1006        } while (true);
1007
1008        (*delay) = currentcmd->msdelay;
1009        (*step)++;
1010        return false;
1011}
1012
1013static u8 _rtl8723e_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
1014{
1015        u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
1016        u8 result = 0x00;
1017
1018        rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
1019        rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
1020        rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
1021        rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
1022                      config_pathb ? 0x28160202 : 0x28160502);
1023
1024        if (config_pathb) {
1025                rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
1026                rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
1027                rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
1028                rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
1029        }
1030
1031        rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
1032        rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
1033        rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
1034
1035        mdelay(IQK_DELAY_TIME);
1036
1037        reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
1038        reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
1039        reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
1040        reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
1041
1042        if (!(reg_eac & BIT(28)) &&
1043            (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
1044            (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
1045                result |= 0x01;
1046        else
1047                return result;
1048
1049        if (!(reg_eac & BIT(27)) &&
1050            (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
1051            (((reg_eac & 0x03FF0000) >> 16) != 0x36))
1052                result |= 0x02;
1053        return result;
1054}
1055
1056static u8 _rtl8723e_phy_path_b_iqk(struct ieee80211_hw *hw)
1057{
1058        u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
1059        u8 result = 0x00;
1060
1061        rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
1062        rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
1063        mdelay(IQK_DELAY_TIME);
1064        reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
1065        reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
1066        reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
1067        reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
1068        reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
1069
1070        if (!(reg_eac & BIT(31)) &&
1071            (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
1072            (((reg_ebc & 0x03FF0000) >> 16) != 0x42))
1073                result |= 0x01;
1074        else
1075                return result;
1076        if (!(reg_eac & BIT(30)) &&
1077            (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
1078            (((reg_ecc & 0x03FF0000) >> 16) != 0x36))
1079                result |= 0x02;
1080        return result;
1081}
1082
1083static bool _rtl8723e_phy_simularity_compare(struct ieee80211_hw *hw,
1084                                             long result[][8], u8 c1, u8 c2)
1085{
1086        u32 i, j, diff, simularity_bitmap, bound;
1087
1088        u8 final_candidate[2] = { 0xFF, 0xFF };
1089        bool bresult = true;
1090
1091        bound = 4;
1092
1093        simularity_bitmap = 0;
1094
1095        for (i = 0; i < bound; i++) {
1096                diff = (result[c1][i] > result[c2][i]) ?
1097                    (result[c1][i] - result[c2][i]) :
1098                    (result[c2][i] - result[c1][i]);
1099
1100                if (diff > MAX_TOLERANCE) {
1101                        if ((i == 2 || i == 6) && !simularity_bitmap) {
1102                                if (result[c1][i] + result[c1][i + 1] == 0)
1103                                        final_candidate[(i / 4)] = c2;
1104                                else if (result[c2][i] + result[c2][i + 1] == 0)
1105                                        final_candidate[(i / 4)] = c1;
1106                                else
1107                                        simularity_bitmap = simularity_bitmap |
1108                                            (1 << i);
1109                        } else
1110                                simularity_bitmap =
1111                                    simularity_bitmap | (1 << i);
1112                }
1113        }
1114
1115        if (simularity_bitmap == 0) {
1116                for (i = 0; i < (bound / 4); i++) {
1117                        if (final_candidate[i] != 0xFF) {
1118                                for (j = i * 4; j < (i + 1) * 4 - 2; j++)
1119                                        result[3][j] =
1120                                            result[final_candidate[i]][j];
1121                                bresult = false;
1122                        }
1123                }
1124                return bresult;
1125        } else if (!(simularity_bitmap & 0x0F)) {
1126                for (i = 0; i < 4; i++)
1127                        result[3][i] = result[c1][i];
1128                return false;
1129        } else {
1130                return false;
1131        }
1132
1133}
1134
1135static void _rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw,
1136                                       long result[][8], u8 t, bool is2t)
1137{
1138        struct rtl_priv *rtlpriv = rtl_priv(hw);
1139        struct rtl_phy *rtlphy = &rtlpriv->phy;
1140        u32 i;
1141        u8 patha_ok, pathb_ok;
1142        u32 adda_reg[IQK_ADDA_REG_NUM] = {
1143                0x85c, 0xe6c, 0xe70, 0xe74,
1144                0xe78, 0xe7c, 0xe80, 0xe84,
1145                0xe88, 0xe8c, 0xed0, 0xed4,
1146                0xed8, 0xedc, 0xee0, 0xeec
1147        };
1148
1149        u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
1150                0x522, 0x550, 0x551, 0x040
1151        };
1152
1153        const u32 retrycount = 2;
1154
1155        u32 bbvalue;
1156
1157        if (t == 0) {
1158                bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
1159
1160                rtl8723_save_adda_registers(hw, adda_reg,
1161                                            rtlphy->adda_backup, 16);
1162                rtl8723_phy_save_mac_registers(hw, iqk_mac_reg,
1163                                               rtlphy->iqk_mac_backup);
1164        }
1165        rtl8723_phy_path_adda_on(hw, adda_reg, true, is2t);
1166        if (t == 0) {
1167                rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
1168                                        RFPGA0_XA_HSSIPARAMETER1,
1169                                        BIT(8));
1170        }
1171
1172        if (!rtlphy->rfpi_enable)
1173                rtl8723_phy_pi_mode_switch(hw, true);
1174        if (t == 0) {
1175                rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
1176                rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
1177                rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
1178        }
1179        rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
1180        rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
1181        rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
1182        if (is2t) {
1183                rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
1184                rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
1185        }
1186        rtl8723_phy_mac_setting_calibration(hw, iqk_mac_reg,
1187                                            rtlphy->iqk_mac_backup);
1188        rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
1189        if (is2t)
1190                rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
1191        rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
1192        rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
1193        rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
1194        for (i = 0; i < retrycount; i++) {
1195                patha_ok = _rtl8723e_phy_path_a_iqk(hw, is2t);
1196                if (patha_ok == 0x03) {
1197                        result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
1198                                        0x3FF0000) >> 16;
1199                        result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
1200                                        0x3FF0000) >> 16;
1201                        result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
1202                                        0x3FF0000) >> 16;
1203                        result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
1204                                        0x3FF0000) >> 16;
1205                        break;
1206                } else if (i == (retrycount - 1) && patha_ok == 0x01)
1207
1208                        result[t][0] = (rtl_get_bbreg(hw, 0xe94,
1209                                                      MASKDWORD) & 0x3FF0000) >>
1210                            16;
1211                result[t][1] =
1212                    (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
1213
1214        }
1215
1216        if (is2t) {
1217                rtl8723_phy_path_a_standby(hw);
1218                rtl8723_phy_path_adda_on(hw, adda_reg, false, is2t);
1219                for (i = 0; i < retrycount; i++) {
1220                        pathb_ok = _rtl8723e_phy_path_b_iqk(hw);
1221                        if (pathb_ok == 0x03) {
1222                                result[t][4] = (rtl_get_bbreg(hw,
1223                                                              0xeb4,
1224                                                              MASKDWORD) &
1225                                                0x3FF0000) >> 16;
1226                                result[t][5] =
1227                                    (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
1228                                     0x3FF0000) >> 16;
1229                                result[t][6] =
1230                                    (rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
1231                                     0x3FF0000) >> 16;
1232                                result[t][7] =
1233                                    (rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
1234                                     0x3FF0000) >> 16;
1235                                break;
1236                        } else if (i == (retrycount - 1) && pathb_ok == 0x01) {
1237                                result[t][4] = (rtl_get_bbreg(hw,
1238                                                              0xeb4,
1239                                                              MASKDWORD) &
1240                                                0x3FF0000) >> 16;
1241                        }
1242                        result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
1243                                        0x3FF0000) >> 16;
1244                }
1245        }
1246        rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04);
1247        rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
1248        rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
1249        rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
1250        rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
1251        if (is2t)
1252                rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
1253        if (t != 0) {
1254                if (!rtlphy->rfpi_enable)
1255                        rtl8723_phy_pi_mode_switch(hw, false);
1256                rtl8723_phy_reload_adda_registers(hw, adda_reg,
1257                                                  rtlphy->adda_backup, 16);
1258                rtl8723_phy_reload_mac_registers(hw, iqk_mac_reg,
1259                                                 rtlphy->iqk_mac_backup);
1260        }
1261}
1262
1263static void _rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
1264{
1265        u8 tmpreg;
1266        u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
1267        struct rtl_priv *rtlpriv = rtl_priv(hw);
1268
1269        tmpreg = rtl_read_byte(rtlpriv, 0xd03);
1270
1271        if ((tmpreg & 0x70) != 0)
1272                rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
1273        else
1274                rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
1275
1276        if ((tmpreg & 0x70) != 0) {
1277                rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
1278
1279                if (is2t)
1280                        rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
1281                                                  MASK12BITS);
1282
1283                rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
1284                              (rf_a_mode & 0x8FFFF) | 0x10000);
1285
1286                if (is2t)
1287                        rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
1288                                      (rf_b_mode & 0x8FFFF) | 0x10000);
1289        }
1290        lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
1291
1292        rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
1293
1294        mdelay(100);
1295
1296        if ((tmpreg & 0x70) != 0) {
1297                rtl_write_byte(rtlpriv, 0xd03, tmpreg);
1298                rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
1299
1300                if (is2t)
1301                        rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
1302                                      rf_b_mode);
1303        } else {
1304                rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
1305        }
1306}
1307
1308static void _rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw,
1309                                            bool bmain, bool is2t)
1310{
1311        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1312
1313        if (is_hal_stop(rtlhal)) {
1314                rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
1315                rtl_set_bbreg(hw, RFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
1316        }
1317        if (is2t) {
1318                if (bmain)
1319                        rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
1320                                      BIT(5) | BIT(6), 0x1);
1321                else
1322                        rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
1323                                      BIT(5) | BIT(6), 0x2);
1324        } else {
1325                if (bmain)
1326                        rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
1327                else
1328                        rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
1329
1330        }
1331
1332}
1333
1334#undef IQK_ADDA_REG_NUM
1335#undef IQK_DELAY_TIME
1336
1337void rtl8723e_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery)
1338{
1339        struct rtl_priv *rtlpriv = rtl_priv(hw);
1340        struct rtl_phy *rtlphy = &rtlpriv->phy;
1341
1342        long result[4][8];
1343        u8 i, final_candidate;
1344        bool b_patha_ok, b_pathb_ok;
1345        long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
1346            reg_ecc, reg_tmp = 0;
1347        bool is12simular, is13simular, is23simular;
1348        u32 iqk_bb_reg[10] = {
1349                ROFDM0_XARXIQIMBALANCE,
1350                ROFDM0_XBRXIQIMBALANCE,
1351                ROFDM0_ECCATHRESHOLD,
1352                ROFDM0_AGCRSSITABLE,
1353                ROFDM0_XATXIQIMBALANCE,
1354                ROFDM0_XBTXIQIMBALANCE,
1355                ROFDM0_XCTXIQIMBALANCE,
1356                ROFDM0_XCTXAFE,
1357                ROFDM0_XDTXAFE,
1358                ROFDM0_RXIQEXTANTA
1359        };
1360
1361        if (b_recovery) {
1362                rtl8723_phy_reload_adda_registers(hw,
1363                                                  iqk_bb_reg,
1364                                                  rtlphy->iqk_bb_backup, 10);
1365                return;
1366        }
1367        for (i = 0; i < 8; i++) {
1368                result[0][i] = 0;
1369                result[1][i] = 0;
1370                result[2][i] = 0;
1371                result[3][i] = 0;
1372        }
1373        final_candidate = 0xff;
1374        b_patha_ok = false;
1375        b_pathb_ok = false;
1376        is12simular = false;
1377        is23simular = false;
1378        is13simular = false;
1379        for (i = 0; i < 3; i++) {
1380                _rtl8723e_phy_iq_calibrate(hw, result, i, false);
1381                if (i == 1) {
1382                        is12simular =
1383                          _rtl8723e_phy_simularity_compare(hw, result, 0, 1);
1384                        if (is12simular) {
1385                                final_candidate = 0;
1386                                break;
1387                        }
1388                }
1389                if (i == 2) {
1390                        is13simular =
1391                          _rtl8723e_phy_simularity_compare(hw, result, 0, 2);
1392                        if (is13simular) {
1393                                final_candidate = 0;
1394                                break;
1395                        }
1396                        is23simular =
1397                          _rtl8723e_phy_simularity_compare(hw, result, 1, 2);
1398                        if (is23simular)
1399                                final_candidate = 1;
1400                        else {
1401                                for (i = 0; i < 8; i++)
1402                                        reg_tmp += result[3][i];
1403
1404                                if (reg_tmp != 0)
1405                                        final_candidate = 3;
1406                                else
1407                                        final_candidate = 0xFF;
1408                        }
1409                }
1410        }
1411        for (i = 0; i < 4; i++) {
1412                reg_e94 = result[i][0];
1413                reg_e9c = result[i][1];
1414                reg_ea4 = result[i][2];
1415                reg_eac = result[i][3];
1416                reg_eb4 = result[i][4];
1417                reg_ebc = result[i][5];
1418                reg_ec4 = result[i][6];
1419                reg_ecc = result[i][7];
1420        }
1421        if (final_candidate != 0xff) {
1422                rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
1423                rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
1424                reg_ea4 = result[final_candidate][2];
1425                reg_eac = result[final_candidate][3];
1426                rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
1427                rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
1428                reg_ec4 = result[final_candidate][6];
1429                reg_ecc = result[final_candidate][7];
1430                b_patha_ok = true;
1431                b_pathb_ok = true;
1432        } else {
1433                rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
1434                rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
1435        }
1436        if (reg_e94 != 0)
1437                rtl8723_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result,
1438                                                   final_candidate,
1439                                                   (reg_ea4 == 0));
1440        rtl8723_save_adda_registers(hw, iqk_bb_reg,
1441                                    rtlphy->iqk_bb_backup, 10);
1442}
1443
1444void rtl8723e_phy_lc_calibrate(struct ieee80211_hw *hw)
1445{
1446        _rtl8723e_phy_lc_calibrate(hw, false);
1447}
1448
1449void rtl8723e_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
1450{
1451        _rtl8723e_phy_set_rfpath_switch(hw, bmain, false);
1452}
1453
1454bool rtl8723e_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
1455{
1456        struct rtl_priv *rtlpriv = rtl_priv(hw);
1457        struct rtl_phy *rtlphy = &rtlpriv->phy;
1458        bool postprocessing = false;
1459
1460        RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
1461                 "-->IO Cmd(%#x), set_io_inprogress(%d)\n",
1462                  iotype, rtlphy->set_io_inprogress);
1463        do {
1464                switch (iotype) {
1465                case IO_CMD_RESUME_DM_BY_SCAN:
1466                        RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
1467                                 "[IO CMD] Resume DM after scan.\n");
1468                        postprocessing = true;
1469                        break;
1470                case IO_CMD_PAUSE_BAND0_DM_BY_SCAN:
1471                        RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
1472                                 "[IO CMD] Pause DM before scan.\n");
1473                        postprocessing = true;
1474                        break;
1475                default:
1476                        RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
1477                                 "switch case %#x not processed\n", iotype);
1478                        break;
1479                }
1480        } while (false);
1481        if (postprocessing && !rtlphy->set_io_inprogress) {
1482                rtlphy->set_io_inprogress = true;
1483                rtlphy->current_io_type = iotype;
1484        } else {
1485                return false;
1486        }
1487        rtl8723e_phy_set_io(hw);
1488        RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, "IO Type(%#x)\n", iotype);
1489        return true;
1490}
1491
1492static void rtl8723e_phy_set_io(struct ieee80211_hw *hw)
1493{
1494        struct rtl_priv *rtlpriv = rtl_priv(hw);
1495        struct rtl_phy *rtlphy = &rtlpriv->phy;
1496        struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1497
1498        RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
1499                 "--->Cmd(%#x), set_io_inprogress(%d)\n",
1500                  rtlphy->current_io_type, rtlphy->set_io_inprogress);
1501        switch (rtlphy->current_io_type) {
1502        case IO_CMD_RESUME_DM_BY_SCAN:
1503                dm_digtable->cur_igvalue = rtlphy->initgain_backup.xaagccore1;
1504                rtl8723e_dm_write_dig(hw);
1505                rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel);
1506                break;
1507        case IO_CMD_PAUSE_BAND0_DM_BY_SCAN:
1508                rtlphy->initgain_backup.xaagccore1 = dm_digtable->cur_igvalue;
1509                dm_digtable->cur_igvalue = 0x17;
1510                rtl8723e_dm_write_dig(hw);
1511                break;
1512        default:
1513                RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
1514                         "switch case %#x not processed\n",
1515                         rtlphy->current_io_type);
1516                break;
1517        }
1518        rtlphy->set_io_inprogress = false;
1519        RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
1520                 "(%#x)\n", rtlphy->current_io_type);
1521}
1522
1523static void rtl8723e_phy_set_rf_on(struct ieee80211_hw *hw)
1524{
1525        struct rtl_priv *rtlpriv = rtl_priv(hw);
1526
1527        rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
1528        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
1529        rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
1530        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
1531        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
1532        rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
1533}
1534
1535static void _rtl8723e_phy_set_rf_sleep(struct ieee80211_hw *hw)
1536{
1537        u32 u4b_tmp;
1538        u8 delay = 5;
1539        struct rtl_priv *rtlpriv = rtl_priv(hw);
1540
1541        rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
1542        rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
1543        rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
1544        u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
1545        while (u4b_tmp != 0 && delay > 0) {
1546                rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
1547                rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
1548                rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
1549                u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
1550                delay--;
1551        }
1552        if (delay == 0) {
1553                rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
1554                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
1555                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
1556                rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
1557                RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
1558                         "Switch RF timeout !!!.\n");
1559                return;
1560        }
1561        rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
1562        rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
1563}
1564
1565static bool _rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw,
1566                                             enum rf_pwrstate rfpwr_state)
1567{
1568        struct rtl_priv *rtlpriv = rtl_priv(hw);
1569        struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
1570        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1571        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1572        bool bresult = true;
1573        u8 i, queue_id;
1574        struct rtl8192_tx_ring *ring = NULL;
1575
1576        switch (rfpwr_state) {
1577        case ERFON:
1578                if ((ppsc->rfpwr_state == ERFOFF) &&
1579                    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
1580                        bool rtstatus;
1581                        u32 initializecount = 0;
1582
1583                        do {
1584                                initializecount++;
1585                                RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1586                                         "IPS Set eRf nic enable\n");
1587                                rtstatus = rtl_ps_enable_nic(hw);
1588                        } while (!rtstatus && (initializecount < 10));
1589                        RT_CLEAR_PS_LEVEL(ppsc,
1590                                          RT_RF_OFF_LEVL_HALT_NIC);
1591                } else {
1592                        RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1593                                 "Set ERFON sleeped:%d ms\n",
1594                                  jiffies_to_msecs(jiffies -
1595                                                   ppsc->
1596                                                   last_sleep_jiffies));
1597                        ppsc->last_awake_jiffies = jiffies;
1598                        rtl8723e_phy_set_rf_on(hw);
1599                }
1600                if (mac->link_state == MAC80211_LINKED) {
1601                        rtlpriv->cfg->ops->led_control(hw,
1602                                                       LED_CTL_LINK);
1603                } else {
1604                        rtlpriv->cfg->ops->led_control(hw,
1605                                                       LED_CTL_NO_LINK);
1606                }
1607                break;
1608        case ERFOFF:
1609                if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
1610                        RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1611                                 "IPS Set eRf nic disable\n");
1612                        rtl_ps_disable_nic(hw);
1613                        RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
1614                } else {
1615                        if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
1616                                rtlpriv->cfg->ops->led_control(hw,
1617                                                LED_CTL_NO_LINK);
1618                        } else {
1619                                rtlpriv->cfg->ops->led_control(hw,
1620                                                LED_CTL_POWER_OFF);
1621                        }
1622                }
1623                break;
1624        case ERFSLEEP:
1625                if (ppsc->rfpwr_state == ERFOFF)
1626                        break;
1627                for (queue_id = 0, i = 0;
1628                     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
1629                        ring = &pcipriv->dev.tx_ring[queue_id];
1630                        if (queue_id == BEACON_QUEUE ||
1631                            skb_queue_len(&ring->queue) == 0) {
1632                                queue_id++;
1633                                continue;
1634                        } else {
1635                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
1636                                         "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
1637                                         (i + 1), queue_id,
1638                                         skb_queue_len(&ring->queue));
1639
1640                                udelay(10);
1641                                i++;
1642                        }
1643                        if (i >= MAX_DOZE_WAITING_TIMES_9x) {
1644                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
1645                                         "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
1646                                          MAX_DOZE_WAITING_TIMES_9x,
1647                                          queue_id,
1648                                          skb_queue_len(&ring->queue));
1649                                break;
1650                        }
1651                }
1652                RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
1653                         "Set ERFSLEEP awaked:%d ms\n",
1654                          jiffies_to_msecs(jiffies -
1655                                           ppsc->last_awake_jiffies));
1656                ppsc->last_sleep_jiffies = jiffies;
1657                _rtl8723e_phy_set_rf_sleep(hw);
1658                break;
1659        default:
1660                RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
1661                         "switch case %#x not processed\n", rfpwr_state);
1662                bresult = false;
1663                break;
1664        }
1665        if (bresult)
1666                ppsc->rfpwr_state = rfpwr_state;
1667        return bresult;
1668}
1669
1670bool rtl8723e_phy_set_rf_power_state(struct ieee80211_hw *hw,
1671                                     enum rf_pwrstate rfpwr_state)
1672{
1673        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1674
1675        bool bresult = false;
1676
1677        if (rfpwr_state == ppsc->rfpwr_state)
1678                return bresult;
1679        bresult = _rtl8723e_phy_set_rf_power_state(hw, rfpwr_state);
1680        return bresult;
1681}
1682