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