0001
0002
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 }