linux/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2009-2012  Realtek Corporation.
   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 * You should have received a copy of the GNU General Public License along with
  15 * this program; if not, write to the Free Software Foundation, Inc.,
  16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  17 *
  18 * The full GNU General Public License is included in this distribution in the
  19 * file called LICENSE.
  20 *
  21 * Contact Information:
  22 * wlanfae <wlanfae@realtek.com>
  23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  24 * Hsinchu 300, Taiwan.
  25 *
  26 * Larry Finger <Larry.Finger@lwfinger.net>
  27 *
  28 *****************************************************************************/
  29
  30#include "../wifi.h"
  31#include "../pci.h"
  32#include "../ps.h"
  33#include "reg.h"
  34#include "def.h"
  35#include "phy.h"
  36#include "rf.h"
  37#include "dm.h"
  38#include "table.h"
  39
  40u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
  41                             enum radio_path rfpath, u32 regaddr, u32 bitmask)
  42{
  43        struct rtl_priv *rtlpriv = rtl_priv(hw);
  44        u32 original_value, readback_value, bitshift;
  45        struct rtl_phy *rtlphy = &(rtlpriv->phy);
  46
  47        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  48                 "regaddr(%#x), rfpath(%#x), bitmask(%#x)\n",
  49                 regaddr, rfpath, bitmask);
  50        if (rtlphy->rf_mode != RF_OP_BY_FW) {
  51                original_value = _rtl92c_phy_rf_serial_read(hw,
  52                                                            rfpath, regaddr);
  53        } else {
  54                original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  55                                                               rfpath, regaddr);
  56        }
  57        bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  58        readback_value = (original_value & bitmask) >> bitshift;
  59        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  60                 "regaddr(%#x), rfpath(%#x), bitmask(%#x), original_value(%#x)\n",
  61                 regaddr, rfpath, bitmask, original_value);
  62        return readback_value;
  63}
  64
  65void rtl92cu_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, bitshift;
  72
  73        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
  74                 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
  75                 regaddr, bitmask, data, rfpath);
  76        if (rtlphy->rf_mode != RF_OP_BY_FW) {
  77                if (bitmask != RFREG_OFFSET_MASK) {
  78                        original_value = _rtl92c_phy_rf_serial_read(hw,
  79                                                                    rfpath,
  80                                                                    regaddr);
  81                        bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  82                        data =
  83                            ((original_value & (~bitmask)) |
  84                             (data << bitshift));
  85                }
  86                _rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data);
  87        } else {
  88                if (bitmask != RFREG_OFFSET_MASK) {
  89                        original_value = _rtl92c_phy_fw_rf_serial_read(hw,
  90                                                                       rfpath,
  91                                                                       regaddr);
  92                        bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
  93                        data =
  94                            ((original_value & (~bitmask)) |
  95                             (data << bitshift));
  96                }
  97                _rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
  98        }
  99        RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 100                 "regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
 101                 regaddr, bitmask, data, rfpath);
 102}
 103
 104bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
 105{
 106        bool rtstatus;
 107        struct rtl_priv *rtlpriv = rtl_priv(hw);
 108        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 109        bool is92c = IS_92C_SERIAL(rtlhal->version);
 110
 111        rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
 112        if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal))
 113                rtl_write_byte(rtlpriv, 0x14, 0x71);
 114        return rtstatus;
 115}
 116
 117bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
 118{
 119        bool rtstatus = true;
 120        struct rtl_priv *rtlpriv = rtl_priv(hw);
 121        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 122        u16 regval;
 123        u8 b_reg_hwparafile = 1;
 124
 125        _rtl92c_phy_init_bb_rf_register_definition(hw);
 126        regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
 127        rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) |
 128                       BIT(0) | BIT(1));
 129        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
 130        rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
 131        rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
 132        if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
 133                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
 134                               FEN_DIO_PCIE |   FEN_BB_GLB_RSTn | FEN_BBRSTB);
 135        } else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
 136                rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
 137                               FEN_BB_GLB_RSTn | FEN_BBRSTB);
 138                rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
 139        }
 140        rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
 141        if (b_reg_hwparafile == 1)
 142                rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
 143        return rtstatus;
 144}
 145
 146bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
 147{
 148        struct rtl_priv *rtlpriv = rtl_priv(hw);
 149        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 150        u32 i;
 151        u32 arraylength;
 152        u32 *ptrarray;
 153
 154        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Read Rtl819XMACPHY_Array\n");
 155        arraylength =  rtlphy->hwparam_tables[MAC_REG].length ;
 156        ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
 157        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Img:RTL8192CEMAC_2T_ARRAY\n");
 158        for (i = 0; i < arraylength; i = i + 2)
 159                rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
 160        return true;
 161}
 162
 163bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
 164                                            u8 configtype)
 165{
 166        int i;
 167        u32 *phy_regarray_table;
 168        u32 *agctab_array_table;
 169        u16 phy_reg_arraylen, agctab_arraylen;
 170        struct rtl_priv *rtlpriv = rtl_priv(hw);
 171        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 172        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 173
 174        if (IS_92C_SERIAL(rtlhal->version)) {
 175                agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length;
 176                agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_2T].pdata;
 177                phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length;
 178                phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata;
 179        } else {
 180                agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length;
 181                agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_1T].pdata;
 182                phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length;
 183                phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata;
 184        }
 185        if (configtype == BASEBAND_CONFIG_PHY_REG) {
 186                for (i = 0; i < phy_reg_arraylen; i = i + 2) {
 187                        if (phy_regarray_table[i] == 0xfe)
 188                                mdelay(50);
 189                        else if (phy_regarray_table[i] == 0xfd)
 190                                mdelay(5);
 191                        else if (phy_regarray_table[i] == 0xfc)
 192                                mdelay(1);
 193                        else if (phy_regarray_table[i] == 0xfb)
 194                                udelay(50);
 195                        else if (phy_regarray_table[i] == 0xfa)
 196                                udelay(5);
 197                        else if (phy_regarray_table[i] == 0xf9)
 198                                udelay(1);
 199                        rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
 200                                      phy_regarray_table[i + 1]);
 201                        udelay(1);
 202                        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 203                                 "The phy_regarray_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
 204                                 phy_regarray_table[i],
 205                                 phy_regarray_table[i + 1]);
 206                }
 207        } else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
 208                for (i = 0; i < agctab_arraylen; i = i + 2) {
 209                        rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
 210                                      agctab_array_table[i + 1]);
 211                        udelay(1);
 212                        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 213                                 "The agctab_array_table[0] is %x Rtl819XPHY_REGArray[1] is %x\n",
 214                                 agctab_array_table[i],
 215                                 agctab_array_table[i + 1]);
 216                }
 217        }
 218        return true;
 219}
 220
 221bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
 222                                              u8 configtype)
 223{
 224        struct rtl_priv *rtlpriv = rtl_priv(hw);
 225        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 226        int i;
 227        u32 *phy_regarray_table_pg;
 228        u16 phy_regarray_pg_len;
 229
 230        rtlphy->pwrgroup_cnt = 0;
 231        phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length;
 232        phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata;
 233        if (configtype == BASEBAND_CONFIG_PHY_REG) {
 234                for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
 235                        if (phy_regarray_table_pg[i] == 0xfe)
 236                                mdelay(50);
 237                        else if (phy_regarray_table_pg[i] == 0xfd)
 238                                mdelay(5);
 239                        else if (phy_regarray_table_pg[i] == 0xfc)
 240                                mdelay(1);
 241                        else if (phy_regarray_table_pg[i] == 0xfb)
 242                                udelay(50);
 243                        else if (phy_regarray_table_pg[i] == 0xfa)
 244                                udelay(5);
 245                        else if (phy_regarray_table_pg[i] == 0xf9)
 246                                udelay(1);
 247                        _rtl92c_store_pwrIndex_diffrate_offset(hw,
 248                                                  phy_regarray_table_pg[i],
 249                                                  phy_regarray_table_pg[i + 1],
 250                                                  phy_regarray_table_pg[i + 2]);
 251                }
 252        } else {
 253                RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
 254                         "configtype != BaseBand_Config_PHY_REG\n");
 255        }
 256        return true;
 257}
 258
 259bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 260                                          enum radio_path rfpath)
 261{
 262        int i;
 263        u32 *radioa_array_table;
 264        u32 *radiob_array_table;
 265        u16 radioa_arraylen, radiob_arraylen;
 266        struct rtl_priv *rtlpriv = rtl_priv(hw);
 267        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 268        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 269
 270        if (IS_92C_SERIAL(rtlhal->version)) {
 271                radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length;
 272                radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata;
 273                radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
 274                radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
 275                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 276                         "Radio_A:RTL8192CERADIOA_2TARRAY\n");
 277                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 278                         "Radio_B:RTL8192CE_RADIOB_2TARRAY\n");
 279        } else {
 280                radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
 281                radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
 282                radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
 283                radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
 284                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 285                         "Radio_A:RTL8192CE_RADIOA_1TARRAY\n");
 286                RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
 287                         "Radio_B:RTL8192CE_RADIOB_1TARRAY\n");
 288        }
 289        RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "Radio No %x\n", rfpath);
 290        switch (rfpath) {
 291        case RF90_PATH_A:
 292                for (i = 0; i < radioa_arraylen; i = i + 2) {
 293                        if (radioa_array_table[i] == 0xfe)
 294                                mdelay(50);
 295                        else if (radioa_array_table[i] == 0xfd)
 296                                mdelay(5);
 297                        else if (radioa_array_table[i] == 0xfc)
 298                                mdelay(1);
 299                        else if (radioa_array_table[i] == 0xfb)
 300                                udelay(50);
 301                        else if (radioa_array_table[i] == 0xfa)
 302                                udelay(5);
 303                        else if (radioa_array_table[i] == 0xf9)
 304                                udelay(1);
 305                        else {
 306                                rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
 307                                              RFREG_OFFSET_MASK,
 308                                              radioa_array_table[i + 1]);
 309                                udelay(1);
 310                        }
 311                }
 312                break;
 313        case RF90_PATH_B:
 314                for (i = 0; i < radiob_arraylen; i = i + 2) {
 315                        if (radiob_array_table[i] == 0xfe) {
 316                                mdelay(50);
 317                        } else if (radiob_array_table[i] == 0xfd)
 318                                mdelay(5);
 319                        else if (radiob_array_table[i] == 0xfc)
 320                                mdelay(1);
 321                        else if (radiob_array_table[i] == 0xfb)
 322                                udelay(50);
 323                        else if (radiob_array_table[i] == 0xfa)
 324                                udelay(5);
 325                        else if (radiob_array_table[i] == 0xf9)
 326                                udelay(1);
 327                        else {
 328                                rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
 329                                              RFREG_OFFSET_MASK,
 330                                              radiob_array_table[i + 1]);
 331                                udelay(1);
 332                        }
 333                }
 334                break;
 335        case RF90_PATH_C:
 336                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 337                         "switch case not processed\n");
 338                break;
 339        case RF90_PATH_D:
 340                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 341                         "switch case not processed\n");
 342                break;
 343        }
 344        return true;
 345}
 346
 347void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
 348{
 349        struct rtl_priv *rtlpriv = rtl_priv(hw);
 350        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 351        struct rtl_phy *rtlphy = &(rtlpriv->phy);
 352        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 353        u8 reg_bw_opmode;
 354        u8 reg_prsr_rsc;
 355
 356        RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "Switch to %s bandwidth\n",
 357                 rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
 358                 "20MHz" : "40MHz");
 359        if (is_hal_stop(rtlhal)) {
 360                rtlphy->set_bwmode_inprogress = false;
 361                return;
 362        }
 363        reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
 364        reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
 365        switch (rtlphy->current_chan_bw) {
 366        case HT_CHANNEL_WIDTH_20:
 367                reg_bw_opmode |= BW_OPMODE_20MHZ;
 368                rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
 369                break;
 370        case HT_CHANNEL_WIDTH_20_40:
 371                reg_bw_opmode &= ~BW_OPMODE_20MHZ;
 372                rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
 373                reg_prsr_rsc =
 374                    (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
 375                rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
 376                break;
 377        default:
 378                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 379                         "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
 380                break;
 381        }
 382        switch (rtlphy->current_chan_bw) {
 383        case HT_CHANNEL_WIDTH_20:
 384                rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
 385                rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
 386                rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
 387                break;
 388        case HT_CHANNEL_WIDTH_20_40:
 389                rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
 390                rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
 391                rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
 392                              (mac->cur_40_prime_sc >> 1));
 393                rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
 394                rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
 395                rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
 396                              (mac->cur_40_prime_sc ==
 397                               HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
 398                break;
 399        default:
 400                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 401                         "unknown bandwidth: %#X\n", rtlphy->current_chan_bw);
 402                break;
 403        }
 404        rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
 405        rtlphy->set_bwmode_inprogress = false;
 406        RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, "<==\n");
 407}
 408
 409void rtl92cu_bb_block_on(struct ieee80211_hw *hw)
 410{
 411        struct rtl_priv *rtlpriv = rtl_priv(hw);
 412
 413        mutex_lock(&rtlpriv->io.bb_mutex);
 414        rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
 415        rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
 416        mutex_unlock(&rtlpriv->io.bb_mutex);
 417}
 418
 419void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
 420{
 421        u8 tmpreg;
 422        u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
 423        struct rtl_priv *rtlpriv = rtl_priv(hw);
 424
 425        tmpreg = rtl_read_byte(rtlpriv, 0xd03);
 426
 427        if ((tmpreg & 0x70) != 0)
 428                rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
 429        else
 430                rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
 431
 432        if ((tmpreg & 0x70) != 0) {
 433                rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
 434                if (is2t)
 435                        rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
 436                                                  MASK12BITS);
 437                rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
 438                              (rf_a_mode & 0x8FFFF) | 0x10000);
 439                if (is2t)
 440                        rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
 441                                      (rf_b_mode & 0x8FFFF) | 0x10000);
 442        }
 443        lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
 444        rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
 445        mdelay(100);
 446        if ((tmpreg & 0x70) != 0) {
 447                rtl_write_byte(rtlpriv, 0xd03, tmpreg);
 448                rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
 449                if (is2t)
 450                        rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
 451                                      rf_b_mode);
 452        } else {
 453                rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
 454        }
 455}
 456
 457static bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 458                                            enum rf_pwrstate rfpwr_state)
 459{
 460        struct rtl_priv *rtlpriv = rtl_priv(hw);
 461        struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
 462        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 463        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 464        bool bresult = true;
 465        u8 i, queue_id;
 466        struct rtl8192_tx_ring *ring = NULL;
 467
 468        switch (rfpwr_state) {
 469        case ERFON:
 470                if ((ppsc->rfpwr_state == ERFOFF) &&
 471                    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
 472                        bool rtstatus;
 473                        u32 InitializeCount = 0;
 474
 475                        do {
 476                                InitializeCount++;
 477                                RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 478                                         "IPS Set eRf nic enable\n");
 479                                rtstatus = rtl_ps_enable_nic(hw);
 480                        } while (!rtstatus && (InitializeCount < 10));
 481                        RT_CLEAR_PS_LEVEL(ppsc,
 482                                          RT_RF_OFF_LEVL_HALT_NIC);
 483                } else {
 484                        RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 485                                 "Set ERFON sleeped:%d ms\n",
 486                                 jiffies_to_msecs(jiffies -
 487                                                  ppsc->last_sleep_jiffies));
 488                        ppsc->last_awake_jiffies = jiffies;
 489                        rtl92ce_phy_set_rf_on(hw);
 490                }
 491                if (mac->link_state == MAC80211_LINKED) {
 492                        rtlpriv->cfg->ops->led_control(hw,
 493                                                       LED_CTL_LINK);
 494                } else {
 495                        rtlpriv->cfg->ops->led_control(hw,
 496                                                       LED_CTL_NO_LINK);
 497                }
 498                break;
 499        case ERFOFF:
 500                for (queue_id = 0, i = 0;
 501                     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
 502                        ring = &pcipriv->dev.tx_ring[queue_id];
 503                        if (skb_queue_len(&ring->queue) == 0 ||
 504                                queue_id == BEACON_QUEUE) {
 505                                queue_id++;
 506                                continue;
 507                        } else {
 508                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 509                                         "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
 510                                         i + 1,
 511                                         queue_id,
 512                                         skb_queue_len(&ring->queue));
 513                                udelay(10);
 514                                i++;
 515                        }
 516                        if (i >= MAX_DOZE_WAITING_TIMES_9x) {
 517                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 518                                         "ERFOFF: %d times TcbBusyQueue[%d] = %d !\n",
 519                                         MAX_DOZE_WAITING_TIMES_9x,
 520                                         queue_id,
 521                                         skb_queue_len(&ring->queue));
 522                                break;
 523                        }
 524                }
 525                if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
 526                        RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 527                                 "IPS Set eRf nic disable\n");
 528                        rtl_ps_disable_nic(hw);
 529                        RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
 530                } else {
 531                        if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
 532                                rtlpriv->cfg->ops->led_control(hw,
 533                                                         LED_CTL_NO_LINK);
 534                        } else {
 535                                rtlpriv->cfg->ops->led_control(hw,
 536                                                         LED_CTL_POWER_OFF);
 537                        }
 538                }
 539                break;
 540        case ERFSLEEP:
 541                if (ppsc->rfpwr_state == ERFOFF)
 542                        return false;
 543                for (queue_id = 0, i = 0;
 544                     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
 545                        ring = &pcipriv->dev.tx_ring[queue_id];
 546                        if (skb_queue_len(&ring->queue) == 0) {
 547                                queue_id++;
 548                                continue;
 549                        } else {
 550                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 551                                         "eRf Off/Sleep: %d times TcbBusyQueue[%d] =%d before doze!\n",
 552                                         i + 1, queue_id,
 553                                         skb_queue_len(&ring->queue));
 554                                udelay(10);
 555                                i++;
 556                        }
 557                        if (i >= MAX_DOZE_WAITING_TIMES_9x) {
 558                                RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
 559                                         "ERFSLEEP: %d times TcbBusyQueue[%d] = %d !\n",
 560                                         MAX_DOZE_WAITING_TIMES_9x,
 561                                         queue_id,
 562                                         skb_queue_len(&ring->queue));
 563                                break;
 564                        }
 565                }
 566                RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 567                         "Set ERFSLEEP awaked:%d ms\n",
 568                         jiffies_to_msecs(jiffies - ppsc->last_awake_jiffies));
 569                ppsc->last_sleep_jiffies = jiffies;
 570                _rtl92c_phy_set_rf_sleep(hw);
 571                break;
 572        default:
 573                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
 574                         "switch case not processed\n");
 575                bresult = false;
 576                break;
 577        }
 578        if (bresult)
 579                ppsc->rfpwr_state = rfpwr_state;
 580        return bresult;
 581}
 582
 583bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
 584                                    enum rf_pwrstate rfpwr_state)
 585{
 586        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 587        bool bresult = false;
 588
 589        if (rfpwr_state == ppsc->rfpwr_state)
 590                return bresult;
 591        bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state);
 592        return bresult;
 593}
 594