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