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