Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include "reg.h"
0006 #include "def.h"
0007 #include "phy.h"
0008 #include "rf.h"
0009 #include "dm.h"
0010 
0011 static bool _rtl8723e_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
0012 
0013 void rtl8723e_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
0014 {
0015     struct rtl_priv *rtlpriv = rtl_priv(hw);
0016     struct rtl_phy *rtlphy = &rtlpriv->phy;
0017 
0018     switch (bandwidth) {
0019     case HT_CHANNEL_WIDTH_20:
0020         rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0021                          0xfffff3ff) | 0x0400);
0022         rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
0023                   rtlphy->rfreg_chnlval[0]);
0024         break;
0025     case HT_CHANNEL_WIDTH_20_40:
0026         rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
0027                          0xfffff3ff));
0028         rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
0029                   rtlphy->rfreg_chnlval[0]);
0030         break;
0031     default:
0032         pr_err("unknown bandwidth: %#X\n", bandwidth);
0033         break;
0034     }
0035 }
0036 
0037 void rtl8723e_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
0038                      u8 *ppowerlevel)
0039 {
0040     struct rtl_priv *rtlpriv = rtl_priv(hw);
0041     struct rtl_phy *rtlphy = &rtlpriv->phy;
0042     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0043     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0044     u32 tx_agc[2] = {0, 0}, tmpval;
0045     bool turbo_scanoff = false;
0046     u8 idx1, idx2;
0047     u8 *ptr;
0048 
0049     if (rtlefuse->eeprom_regulatory != 0)
0050         turbo_scanoff = true;
0051 
0052     if (mac->act_scanning) {
0053         tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
0054         tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
0055 
0056         if (turbo_scanoff) {
0057             for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B;
0058                 idx1++) {
0059                 tx_agc[idx1] = ppowerlevel[idx1] |
0060                     (ppowerlevel[idx1] << 8) |
0061                     (ppowerlevel[idx1] << 16) |
0062                     (ppowerlevel[idx1] << 24);
0063             }
0064         }
0065     } else {
0066         for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
0067             tx_agc[idx1] = ppowerlevel[idx1] |
0068                 (ppowerlevel[idx1] << 8) |
0069                 (ppowerlevel[idx1] << 16) |
0070                 (ppowerlevel[idx1] << 24);
0071         }
0072 
0073         if (rtlefuse->eeprom_regulatory == 0) {
0074             tmpval =
0075                 (rtlphy->mcs_txpwrlevel_origoffset[0][6]) +
0076                 (rtlphy->mcs_txpwrlevel_origoffset[0][7] <<
0077                  8);
0078             tx_agc[RF90_PATH_A] += tmpval;
0079 
0080             tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) +
0081                 (rtlphy->mcs_txpwrlevel_origoffset[0][15] <<
0082                  24);
0083             tx_agc[RF90_PATH_B] += tmpval;
0084         }
0085     }
0086 
0087     for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
0088         ptr = (u8 *)&tx_agc[idx1];
0089         for (idx2 = 0; idx2 < 4; idx2++) {
0090             if (*ptr > RF6052_MAX_TX_PWR)
0091                 *ptr = RF6052_MAX_TX_PWR;
0092             ptr++;
0093         }
0094     }
0095 
0096     tmpval = tx_agc[RF90_PATH_A] & 0xff;
0097     rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
0098 
0099     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0100         "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
0101          RTXAGC_A_CCK1_MCS32);
0102 
0103     tmpval = tx_agc[RF90_PATH_A] >> 8;
0104 
0105     tmpval = tmpval & 0xff00ffff;
0106 
0107     rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
0108 
0109     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0110         "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
0111          RTXAGC_B_CCK11_A_CCK2_11);
0112 
0113     tmpval = tx_agc[RF90_PATH_B] >> 24;
0114     rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
0115 
0116     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0117         "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
0118          RTXAGC_B_CCK11_A_CCK2_11);
0119 
0120     tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
0121     rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
0122 
0123     RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0124         "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
0125          RTXAGC_B_CCK1_55_MCS32);
0126 }
0127 
0128 static void rtl8723e_phy_get_power_base(struct ieee80211_hw *hw,
0129                     u8 *ppowerlevel, u8 channel,
0130                     u32 *ofdmbase, u32 *mcsbase)
0131 {
0132     struct rtl_priv *rtlpriv = rtl_priv(hw);
0133     struct rtl_phy *rtlphy = &rtlpriv->phy;
0134     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0135     u32 powerbase0, powerbase1;
0136     u8 legacy_pwrdiff, ht20_pwrdiff;
0137     u8 i, powerlevel[2];
0138 
0139     for (i = 0; i < 2; i++) {
0140         powerlevel[i] = ppowerlevel[i];
0141         legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
0142         powerbase0 = powerlevel[i] + legacy_pwrdiff;
0143 
0144         powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) |
0145             (powerbase0 << 8) | powerbase0;
0146         *(ofdmbase + i) = powerbase0;
0147         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0148             " [OFDM power base index rf(%c) = 0x%x]\n",
0149              ((i == 0) ? 'A' : 'B'), *(ofdmbase + i));
0150     }
0151 
0152     for (i = 0; i < 2; i++) {
0153         if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
0154             ht20_pwrdiff =
0155                 rtlefuse->txpwr_ht20diff[i][channel - 1];
0156             powerlevel[i] += ht20_pwrdiff;
0157         }
0158         powerbase1 = powerlevel[i];
0159         powerbase1 = (powerbase1 << 24) |
0160             (powerbase1 << 16) | (powerbase1 << 8) | powerbase1;
0161 
0162         *(mcsbase + i) = powerbase1;
0163 
0164         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0165             " [MCS power base index rf(%c) = 0x%x]\n",
0166              ((i == 0) ? 'A' : 'B'), *(mcsbase + i));
0167     }
0168 }
0169 
0170 static void get_txpower_writeval_by_reg(struct ieee80211_hw *hw,
0171                     u8 channel, u8 index,
0172                     u32 *powerbase0,
0173                     u32 *powerbase1,
0174                     u32 *p_outwriteval)
0175 {
0176     struct rtl_priv *rtlpriv = rtl_priv(hw);
0177     struct rtl_phy *rtlphy = &rtlpriv->phy;
0178     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0179     u8 i, chnlgroup = 0, pwr_diff_limit[4];
0180     u32 writeval, customer_limit, rf;
0181 
0182     for (rf = 0; rf < 2; rf++) {
0183         switch (rtlefuse->eeprom_regulatory) {
0184         case 0:
0185             chnlgroup = 0;
0186 
0187             writeval =
0188                 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index +
0189                                 (rf ? 8 : 0)]
0190                 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0191 
0192             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0193                 "RTK better performance, writeval(%c) = 0x%x\n",
0194                 ((rf == 0) ? 'A' : 'B'), writeval);
0195             break;
0196         case 1:
0197             if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
0198                 writeval = ((index < 2) ? powerbase0[rf] :
0199                         powerbase1[rf]);
0200 
0201                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0202                     "Realtek regulatory, 40MHz, writeval(%c) = 0x%x\n",
0203                     ((rf == 0) ? 'A' : 'B'), writeval);
0204             } else {
0205                 if (rtlphy->pwrgroup_cnt == 1)
0206                     chnlgroup = 0;
0207                 if (rtlphy->pwrgroup_cnt >= 3) {
0208                     if (channel <= 3)
0209                         chnlgroup = 0;
0210                     else if (channel >= 4 && channel <= 9)
0211                         chnlgroup = 1;
0212                     else if (channel > 9)
0213                         chnlgroup = 2;
0214                     if (rtlphy->current_chan_bw ==
0215                         HT_CHANNEL_WIDTH_20)
0216                         chnlgroup++;
0217                     else
0218                         chnlgroup += 4;
0219                 }
0220 
0221                 writeval =
0222                     rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
0223                     [index + (rf ? 8 : 0)] + ((index < 2) ?
0224                                   powerbase0[rf] :
0225                                   powerbase1[rf]);
0226 
0227                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0228                     "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n",
0229                     ((rf == 0) ? 'A' : 'B'), writeval);
0230             }
0231             break;
0232         case 2:
0233             writeval =
0234                 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0235 
0236             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0237                 "Better regulatory, writeval(%c) = 0x%x\n",
0238                 ((rf == 0) ? 'A' : 'B'), writeval);
0239             break;
0240         case 3:
0241             chnlgroup = 0;
0242 
0243             if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) {
0244                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0245                     "customer's limit, 40MHz rf(%c) = 0x%x\n",
0246                     ((rf == 0) ? 'A' : 'B'),
0247                     rtlefuse->pwrgroup_ht40[rf][channel -
0248                                      1]);
0249             } else {
0250                 RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0251                     "customer's limit, 20MHz rf(%c) = 0x%x\n",
0252                     ((rf == 0) ? 'A' : 'B'),
0253                     rtlefuse->pwrgroup_ht20[rf][channel -
0254                                      1]);
0255             }
0256             for (i = 0; i < 4; i++) {
0257                 pwr_diff_limit[i] =
0258                     (u8)((rtlphy->mcs_txpwrlevel_origoffset
0259                       [chnlgroup][index +
0260                         (rf ? 8 : 0)] & (0x7f <<
0261                         (i * 8))) >> (i * 8));
0262 
0263                 if (rtlphy->current_chan_bw ==
0264                     HT_CHANNEL_WIDTH_20_40) {
0265                     if (pwr_diff_limit[i] >
0266                         rtlefuse->
0267                         pwrgroup_ht40[rf][channel - 1])
0268                         pwr_diff_limit[i] =
0269                             rtlefuse->pwrgroup_ht40[rf]
0270                             [channel - 1];
0271                 } else {
0272                     if (pwr_diff_limit[i] >
0273                         rtlefuse->
0274                         pwrgroup_ht20[rf][channel - 1])
0275                         pwr_diff_limit[i] =
0276                             rtlefuse->pwrgroup_ht20[rf]
0277                             [channel - 1];
0278                 }
0279             }
0280 
0281             customer_limit = (pwr_diff_limit[3] << 24) |
0282                 (pwr_diff_limit[2] << 16) |
0283                 (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
0284 
0285             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0286                 "Customer's limit rf(%c) = 0x%x\n",
0287                  ((rf == 0) ? 'A' : 'B'), customer_limit);
0288 
0289             writeval = customer_limit +
0290                 ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0291 
0292             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0293                 "Customer, writeval rf(%c)= 0x%x\n",
0294                  ((rf == 0) ? 'A' : 'B'), writeval);
0295             break;
0296         default:
0297             chnlgroup = 0;
0298             writeval =
0299                 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
0300                 [index + (rf ? 8 : 0)]
0301                 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]);
0302 
0303             RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0304                 "RTK better performance, writeval rf(%c) = 0x%x\n",
0305                 ((rf == 0) ? 'A' : 'B'), writeval);
0306             break;
0307         }
0308 
0309         if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
0310             writeval = writeval - 0x06060606;
0311         else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
0312              TXHIGHPWRLEVEL_BT2)
0313             writeval = writeval - 0x0c0c0c0c;
0314         *(p_outwriteval + rf) = writeval;
0315     }
0316 }
0317 
0318 static void _rtl8723e_write_ofdm_power_reg(struct ieee80211_hw *hw,
0319                        u8 index, u32 *pvalue)
0320 {
0321     struct rtl_priv *rtlpriv = rtl_priv(hw);
0322     struct rtl_phy *rtlphy = &rtlpriv->phy;
0323 
0324     u16 regoffset_a[6] = {
0325         RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
0326         RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
0327         RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
0328     };
0329     u16 regoffset_b[6] = {
0330         RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
0331         RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
0332         RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
0333     };
0334     u8 i, rf, pwr_val[4];
0335     u32 writeval;
0336     u16 regoffset;
0337 
0338     for (rf = 0; rf < 2; rf++) {
0339         writeval = pvalue[rf];
0340         for (i = 0; i < 4; i++) {
0341             pwr_val[i] = (u8)((writeval & (0x7f <<
0342                        (i * 8))) >> (i * 8));
0343 
0344             if (pwr_val[i] > RF6052_MAX_TX_PWR)
0345                 pwr_val[i] = RF6052_MAX_TX_PWR;
0346         }
0347         writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
0348             (pwr_val[1] << 8) | pwr_val[0];
0349 
0350         if (rf == 0)
0351             regoffset = regoffset_a[index];
0352         else
0353             regoffset = regoffset_b[index];
0354         rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval);
0355 
0356         RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
0357             "Set 0x%x = %08x\n", regoffset, writeval);
0358 
0359         if (((get_rf_type(rtlphy) == RF_2T2R) &&
0360              (regoffset == RTXAGC_A_MCS15_MCS12 ||
0361               regoffset == RTXAGC_B_MCS15_MCS12)) ||
0362             ((get_rf_type(rtlphy) != RF_2T2R) &&
0363              (regoffset == RTXAGC_A_MCS07_MCS04 ||
0364               regoffset == RTXAGC_B_MCS07_MCS04))) {
0365 
0366             writeval = pwr_val[3];
0367             if (regoffset == RTXAGC_A_MCS15_MCS12 ||
0368                 regoffset == RTXAGC_A_MCS07_MCS04)
0369                 regoffset = 0xc90;
0370             if (regoffset == RTXAGC_B_MCS15_MCS12 ||
0371                 regoffset == RTXAGC_B_MCS07_MCS04)
0372                 regoffset = 0xc98;
0373 
0374             for (i = 0; i < 3; i++) {
0375                 writeval = (writeval > 6) ? (writeval - 6) : 0;
0376                 rtl_write_byte(rtlpriv, (u32) (regoffset + i),
0377                            (u8)writeval);
0378             }
0379         }
0380     }
0381 }
0382 
0383 void rtl8723e_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
0384                       u8 *ppowerlevel, u8 channel)
0385 {
0386     u32 writeval[2], powerbase0[2], powerbase1[2];
0387     u8 index;
0388 
0389     rtl8723e_phy_get_power_base(hw, ppowerlevel,
0390                     channel, &powerbase0[0], &powerbase1[0]);
0391 
0392     for (index = 0; index < 6; index++) {
0393         get_txpower_writeval_by_reg(hw, channel, index, &powerbase0[0],
0394                         &powerbase1[0],
0395                         &writeval[0]);
0396 
0397         _rtl8723e_write_ofdm_power_reg(hw, index, &writeval[0]);
0398     }
0399 }
0400 
0401 bool rtl8723e_phy_rf6052_config(struct ieee80211_hw *hw)
0402 {
0403     struct rtl_priv *rtlpriv = rtl_priv(hw);
0404     struct rtl_phy *rtlphy = &rtlpriv->phy;
0405 
0406     if (rtlphy->rf_type == RF_1T1R)
0407         rtlphy->num_total_rfpath = 1;
0408     else
0409         rtlphy->num_total_rfpath = 2;
0410 
0411     return _rtl8723e_phy_rf6052_config_parafile(hw);
0412 }
0413 
0414 static bool _rtl8723e_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
0415 {
0416     struct rtl_priv *rtlpriv = rtl_priv(hw);
0417     struct rtl_phy *rtlphy = &rtlpriv->phy;
0418     u32 u4_regvalue = 0;
0419     u8 rfpath;
0420     bool rtstatus = true;
0421     struct bb_reg_def *pphyreg;
0422 
0423     for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
0424 
0425         pphyreg = &rtlphy->phyreg_def[rfpath];
0426 
0427         switch (rfpath) {
0428         case RF90_PATH_A:
0429         case RF90_PATH_C:
0430             u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
0431                             BRFSI_RFENV);
0432             break;
0433         case RF90_PATH_B:
0434         case RF90_PATH_D:
0435             u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
0436                             BRFSI_RFENV << 16);
0437             break;
0438         }
0439 
0440         rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
0441         udelay(1);
0442 
0443         rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
0444         udelay(1);
0445 
0446         rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
0447                   B3WIREADDREAALENGTH, 0x0);
0448         udelay(1);
0449 
0450         rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
0451         udelay(1);
0452 
0453         switch (rfpath) {
0454         case RF90_PATH_A:
0455             rtstatus = rtl8723e_phy_config_rf_with_headerfile(hw,
0456                         (enum radio_path)rfpath);
0457             break;
0458         case RF90_PATH_B:
0459             rtstatus =
0460               rtl8723e_phy_config_rf_with_headerfile(hw,
0461                         (enum radio_path)rfpath);
0462             break;
0463         case RF90_PATH_C:
0464             break;
0465         case RF90_PATH_D:
0466             break;
0467         }
0468 
0469         switch (rfpath) {
0470         case RF90_PATH_A:
0471         case RF90_PATH_C:
0472             rtl_set_bbreg(hw, pphyreg->rfintfs,
0473                       BRFSI_RFENV, u4_regvalue);
0474             break;
0475         case RF90_PATH_B:
0476         case RF90_PATH_D:
0477             rtl_set_bbreg(hw, pphyreg->rfintfs,
0478                       BRFSI_RFENV << 16, u4_regvalue);
0479             break;
0480         }
0481 
0482         if (!rtstatus) {
0483             rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE,
0484                 "Radio[%d] Fail!!\n", rfpath);
0485             return false;
0486         }
0487     }
0488 
0489     rtl_dbg(rtlpriv, COMP_INIT, DBG_TRACE, "\n");
0490     return rtstatus;
0491 }