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