1 /****************************************************************************** 2 * 3 * Copyright(c) 2009-2014 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 * The full GNU General Public License is included in this distribution in the 15 * file called LICENSE. 16 * 17 * Contact Information: 18 * wlanfae <wlanfae@realtek.com> 19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, 20 * Hsinchu 300, Taiwan. 21 * 22 * Larry Finger <Larry.Finger@lwfinger.net> 23 * 24 *****************************************************************************/ 25 26 #include "../wifi.h" 27 #include "reg.h" 28 #include "def.h" 29 #include "phy.h" 30 #include "rf.h" 31 #include "dm.h" 32 33 static bool _rtl8723be_phy_rf6052_config_parafile(struct ieee80211_hw *hw); 34 35 void rtl8723be_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) 36 { 37 struct rtl_priv *rtlpriv = rtl_priv(hw); 38 struct rtl_phy *rtlphy = &(rtlpriv->phy); 39 40 switch (bandwidth) { 41 case HT_CHANNEL_WIDTH_20: 42 rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & 43 0xfffff3ff) | BIT(10) | BIT(11)); 44 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, 45 rtlphy->rfreg_chnlval[0]); 46 break; 47 case HT_CHANNEL_WIDTH_20_40: 48 rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & 49 0xfffff3ff) | BIT(10)); 50 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, 51 rtlphy->rfreg_chnlval[0]); 52 break; 53 default: 54 pr_err("unknown bandwidth: %#X\n", bandwidth); 55 break; 56 } 57 } 58 59 void rtl8723be_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, 60 u8 *ppowerlevel) 61 { 62 struct rtl_priv *rtlpriv = rtl_priv(hw); 63 struct rtl_phy *rtlphy = &(rtlpriv->phy); 64 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 65 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 66 u32 tx_agc[2] = {0, 0}, tmpval; 67 bool turbo_scanoff = false; 68 u8 idx1, idx2; 69 u8 *ptr; 70 u8 direction; 71 u32 pwrtrac_value; 72 73 if (rtlefuse->eeprom_regulatory != 0) 74 turbo_scanoff = true; 75 76 if (mac->act_scanning) { 77 tx_agc[RF90_PATH_A] = 0x3f3f3f3f; 78 tx_agc[RF90_PATH_B] = 0x3f3f3f3f; 79 80 if (turbo_scanoff) { 81 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 82 tx_agc[idx1] = ppowerlevel[idx1] | 83 (ppowerlevel[idx1] << 8) | 84 (ppowerlevel[idx1] << 16) | 85 (ppowerlevel[idx1] << 24); 86 } 87 } 88 } else { 89 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 90 tx_agc[idx1] = ppowerlevel[idx1] | 91 (ppowerlevel[idx1] << 8) | 92 (ppowerlevel[idx1] << 16) | 93 (ppowerlevel[idx1] << 24); 94 } 95 96 if (rtlefuse->eeprom_regulatory == 0) { 97 tmpval = 98 (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + 99 (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8); 100 tx_agc[RF90_PATH_A] += tmpval; 101 102 tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + 103 (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 104 24); 105 tx_agc[RF90_PATH_B] += tmpval; 106 } 107 } 108 109 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 110 ptr = (u8 *)(&(tx_agc[idx1])); 111 for (idx2 = 0; idx2 < 4; idx2++) { 112 if (*ptr > RF6052_MAX_TX_PWR) 113 *ptr = RF6052_MAX_TX_PWR; 114 ptr++; 115 } 116 } 117 rtl8723be_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); 118 if (direction == 1) { 119 tx_agc[0] += pwrtrac_value; 120 tx_agc[1] += pwrtrac_value; 121 } else if (direction == 2) { 122 tx_agc[0] -= pwrtrac_value; 123 tx_agc[1] -= pwrtrac_value; 124 } 125 tmpval = tx_agc[RF90_PATH_A] & 0xff; 126 rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval); 127 128 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 129 "CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, 130 RTXAGC_A_CCK1_MCS32); 131 132 tmpval = tx_agc[RF90_PATH_A] >> 8; 133 134 /*tmpval = tmpval & 0xff00ffff;*/ 135 136 rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval); 137 138 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 139 "CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, 140 RTXAGC_B_CCK11_A_CCK2_11); 141 142 tmpval = tx_agc[RF90_PATH_B] >> 24; 143 rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval); 144 145 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 146 "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, 147 RTXAGC_B_CCK11_A_CCK2_11); 148 149 tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff; 150 rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval); 151 152 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 153 "CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, 154 RTXAGC_B_CCK1_55_MCS32); 155 } 156 157 static void rtl8723be_phy_get_power_base(struct ieee80211_hw *hw, 158 u8 *ppowerlevel_ofdm, 159 u8 *ppowerlevel_bw20, 160 u8 *ppowerlevel_bw40, 161 u8 channel, u32 *ofdmbase, 162 u32 *mcsbase) 163 { 164 struct rtl_priv *rtlpriv = rtl_priv(hw); 165 struct rtl_phy *rtlphy = &(rtlpriv->phy); 166 u32 powerbase0, powerbase1; 167 u8 i, powerlevel[2]; 168 169 for (i = 0; i < 2; i++) { 170 powerbase0 = ppowerlevel_ofdm[i]; 171 172 powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | 173 (powerbase0 << 8) | powerbase0; 174 *(ofdmbase + i) = powerbase0; 175 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 176 " [OFDM power base index rf(%c) = 0x%x]\n", 177 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); 178 } 179 180 for (i = 0; i < 2; i++) { 181 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) 182 powerlevel[i] = ppowerlevel_bw20[i]; 183 else 184 powerlevel[i] = ppowerlevel_bw40[i]; 185 186 powerbase1 = powerlevel[i]; 187 powerbase1 = (powerbase1 << 24) | (powerbase1 << 16) | 188 (powerbase1 << 8) | powerbase1; 189 190 *(mcsbase + i) = powerbase1; 191 192 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 193 " [MCS power base index rf(%c) = 0x%x]\n", 194 ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); 195 } 196 } 197 198 static void _rtl8723be_get_txpower_writeval_by_regulatory( 199 struct ieee80211_hw *hw, 200 u8 channel, u8 index, 201 u32 *powerbase0, 202 u32 *powerbase1, 203 u32 *p_outwriteval) 204 { 205 struct rtl_priv *rtlpriv = rtl_priv(hw); 206 struct rtl_phy *rtlphy = &(rtlpriv->phy); 207 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 208 u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; 209 u32 writeval, customer_limit, rf; 210 211 for (rf = 0; rf < 2; rf++) { 212 switch (rtlefuse->eeprom_regulatory) { 213 case 0: 214 chnlgroup = 0; 215 216 writeval = 217 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + 218 (rf ? 8 : 0)] 219 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 220 221 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 222 "RTK better performance, writeval(%c) = 0x%x\n", 223 ((rf == 0) ? 'A' : 'B'), writeval); 224 break; 225 case 1: 226 if (rtlphy->pwrgroup_cnt == 1) { 227 chnlgroup = 0; 228 } else { 229 if (channel < 3) 230 chnlgroup = 0; 231 else if (channel < 6) 232 chnlgroup = 1; 233 else if (channel < 9) 234 chnlgroup = 2; 235 else if (channel < 12) 236 chnlgroup = 3; 237 else if (channel < 14) 238 chnlgroup = 4; 239 else if (channel == 14) 240 chnlgroup = 5; 241 } 242 243 writeval = 244 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] 245 [index + (rf ? 8 : 0)] + ((index < 2) ? 246 powerbase0[rf] : 247 powerbase1[rf]); 248 249 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 250 "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", 251 ((rf == 0) ? 'A' : 'B'), writeval); 252 253 break; 254 case 2: 255 writeval = 256 ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 257 258 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 259 "Better regulatory, writeval(%c) = 0x%x\n", 260 ((rf == 0) ? 'A' : 'B'), writeval); 261 break; 262 case 3: 263 chnlgroup = 0; 264 265 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { 266 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 267 "customer's limit, 40MHz rf(%c) = 0x%x\n", 268 ((rf == 0) ? 'A' : 'B'), 269 rtlefuse->pwrgroup_ht40 270 [rf][channel - 1]); 271 } else { 272 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 273 "customer's limit, 20MHz rf(%c) = 0x%x\n", 274 ((rf == 0) ? 'A' : 'B'), 275 rtlefuse->pwrgroup_ht20 276 [rf][channel - 1]); 277 } 278 279 if (index < 2) 280 pwr_diff = 281 rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; 282 else if (rtlphy->current_chan_bw == 283 HT_CHANNEL_WIDTH_20) 284 pwr_diff = 285 rtlefuse->txpwr_ht20diff[rf][channel-1]; 286 287 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) 288 customer_pwr_diff = 289 rtlefuse->pwrgroup_ht40[rf][channel-1]; 290 else 291 customer_pwr_diff = 292 rtlefuse->pwrgroup_ht20[rf][channel-1]; 293 294 if (pwr_diff > customer_pwr_diff) 295 pwr_diff = 0; 296 else 297 pwr_diff = customer_pwr_diff - pwr_diff; 298 299 for (i = 0; i < 4; i++) { 300 pwr_diff_limit[i] = 301 (u8)((rtlphy->mcs_txpwrlevel_origoffset 302 [chnlgroup][index + (rf ? 8 : 0)] & 303 (0x7f << (i * 8))) >> (i * 8)); 304 305 if (pwr_diff_limit[i] > pwr_diff) 306 pwr_diff_limit[i] = pwr_diff; 307 } 308 309 customer_limit = (pwr_diff_limit[3] << 24) | 310 (pwr_diff_limit[2] << 16) | 311 (pwr_diff_limit[1] << 8) | 312 (pwr_diff_limit[0]); 313 314 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 315 "Customer's limit rf(%c) = 0x%x\n", 316 ((rf == 0) ? 'A' : 'B'), customer_limit); 317 318 writeval = customer_limit + ((index < 2) ? 319 powerbase0[rf] : 320 powerbase1[rf]); 321 322 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 323 "Customer, writeval rf(%c)= 0x%x\n", 324 ((rf == 0) ? 'A' : 'B'), writeval); 325 break; 326 default: 327 chnlgroup = 0; 328 writeval = 329 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] 330 [index + (rf ? 8 : 0)] 331 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 332 333 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 334 "RTK better performance, writeval rf(%c) = 0x%x\n", 335 ((rf == 0) ? 'A' : 'B'), writeval); 336 break; 337 } 338 339 if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) 340 writeval = writeval - 0x06060606; 341 else if (rtlpriv->dm.dynamic_txhighpower_lvl == 342 TXHIGHPWRLEVEL_BT2) 343 writeval = writeval - 0x0c0c0c0c; 344 *(p_outwriteval + rf) = writeval; 345 } 346 } 347 348 static void _rtl8723be_write_ofdm_power_reg(struct ieee80211_hw *hw, 349 u8 index, u32 *pvalue) 350 { 351 struct rtl_priv *rtlpriv = rtl_priv(hw); 352 u16 regoffset_a[6] = { 353 RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24, 354 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, 355 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 356 }; 357 u16 regoffset_b[6] = { 358 RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24, 359 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, 360 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 361 }; 362 u8 i, rf, pwr_val[4]; 363 u32 writeval; 364 u16 regoffset; 365 366 for (rf = 0; rf < 2; rf++) { 367 writeval = pvalue[rf]; 368 for (i = 0; i < 4; i++) { 369 pwr_val[i] = (u8)((writeval & (0x7f << 370 (i * 8))) >> (i * 8)); 371 372 if (pwr_val[i] > RF6052_MAX_TX_PWR) 373 pwr_val[i] = RF6052_MAX_TX_PWR; 374 } 375 writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | 376 (pwr_val[1] << 8) | pwr_val[0]; 377 378 if (rf == 0) 379 regoffset = regoffset_a[index]; 380 else 381 regoffset = regoffset_b[index]; 382 rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); 383 384 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 385 "Set 0x%x = %08x\n", regoffset, writeval); 386 } 387 } 388 389 void rtl8723be_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, 390 u8 *ppowerlevel_ofdm, 391 u8 *ppowerlevel_bw20, 392 u8 *ppowerlevel_bw40, u8 channel) 393 { 394 u32 writeval[2], powerbase0[2], powerbase1[2]; 395 u8 index; 396 u8 direction; 397 u32 pwrtrac_value; 398 399 rtl8723be_phy_get_power_base(hw, ppowerlevel_ofdm, ppowerlevel_bw20, 400 ppowerlevel_bw40, channel, 401 &powerbase0[0], &powerbase1[0]); 402 403 rtl8723be_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); 404 405 for (index = 0; index < 6; index++) { 406 _rtl8723be_get_txpower_writeval_by_regulatory(hw, 407 channel, index, 408 &powerbase0[0], 409 &powerbase1[0], 410 &writeval[0]); 411 if (direction == 1) { 412 writeval[0] += pwrtrac_value; 413 writeval[1] += pwrtrac_value; 414 } else if (direction == 2) { 415 writeval[0] -= pwrtrac_value; 416 writeval[1] -= pwrtrac_value; 417 } 418 _rtl8723be_write_ofdm_power_reg(hw, index, &writeval[0]); 419 } 420 } 421 422 bool rtl8723be_phy_rf6052_config(struct ieee80211_hw *hw) 423 { 424 struct rtl_priv *rtlpriv = rtl_priv(hw); 425 struct rtl_phy *rtlphy = &(rtlpriv->phy); 426 427 if (rtlphy->rf_type == RF_1T1R) 428 rtlphy->num_total_rfpath = 1; 429 else 430 rtlphy->num_total_rfpath = 2; 431 432 return _rtl8723be_phy_rf6052_config_parafile(hw); 433 434 } 435 436 static bool _rtl8723be_phy_rf6052_config_parafile(struct ieee80211_hw *hw) 437 { 438 struct rtl_priv *rtlpriv = rtl_priv(hw); 439 struct rtl_phy *rtlphy = &(rtlpriv->phy); 440 u32 u4_regvalue = 0; 441 u8 rfpath; 442 bool rtstatus = true; 443 struct bb_reg_def *pphyreg; 444 445 for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { 446 pphyreg = &rtlphy->phyreg_def[rfpath]; 447 448 switch (rfpath) { 449 case RF90_PATH_A: 450 case RF90_PATH_C: 451 u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, 452 BRFSI_RFENV); 453 break; 454 case RF90_PATH_B: 455 case RF90_PATH_D: 456 u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs, 457 BRFSI_RFENV << 16); 458 break; 459 } 460 461 rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1); 462 udelay(1); 463 464 rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); 465 udelay(1); 466 467 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, 468 B3WIREADDREAALENGTH, 0x0); 469 udelay(1); 470 471 rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0); 472 udelay(1); 473 474 switch (rfpath) { 475 case RF90_PATH_A: 476 rtstatus = rtl8723be_phy_config_rf_with_headerfile(hw, 477 (enum radio_path)rfpath); 478 break; 479 case RF90_PATH_B: 480 rtstatus = rtl8723be_phy_config_rf_with_headerfile(hw, 481 (enum radio_path)rfpath); 482 break; 483 case RF90_PATH_C: 484 break; 485 case RF90_PATH_D: 486 break; 487 } 488 489 switch (rfpath) { 490 case RF90_PATH_A: 491 case RF90_PATH_C: 492 rtl_set_bbreg(hw, pphyreg->rfintfs, 493 BRFSI_RFENV, u4_regvalue); 494 break; 495 case RF90_PATH_B: 496 case RF90_PATH_D: 497 rtl_set_bbreg(hw, pphyreg->rfintfs, 498 BRFSI_RFENV << 16, u4_regvalue); 499 break; 500 } 501 502 if (!rtstatus) { 503 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, 504 "Radio[%d] Fail!!\n", rfpath); 505 return false; 506 } 507 } 508 509 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); 510 return rtstatus; 511 } 512