1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2010 Realtek Corporation.*/ 3 4 #include "../wifi.h" 5 #include "reg.h" 6 #include "def.h" 7 #include "phy.h" 8 #include "rf.h" 9 #include "dm.h" 10 11 static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw); 12 13 void rtl8821ae_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) 14 { 15 switch (bandwidth) { 16 case HT_CHANNEL_WIDTH_20: 17 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 3); 18 rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 3); 19 break; 20 case HT_CHANNEL_WIDTH_20_40: 21 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 1); 22 rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 1); 23 break; 24 case HT_CHANNEL_WIDTH_80: 25 rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, BIT(11)|BIT(10), 0); 26 rtl_set_rfreg(hw, RF90_PATH_B, RF_CHNLBW, BIT(11)|BIT(10), 0); 27 break; 28 default: 29 pr_err("unknown bandwidth: %#X\n", bandwidth); 30 break; 31 } 32 } 33 34 void rtl8821ae_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, 35 u8 *ppowerlevel) 36 { 37 struct rtl_priv *rtlpriv = rtl_priv(hw); 38 struct rtl_phy *rtlphy = &rtlpriv->phy; 39 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 40 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 41 u32 tx_agc[2] = {0, 0}, tmpval; 42 bool turbo_scanoff = false; 43 u8 idx1, idx2; 44 u8 *ptr; 45 u8 direction; 46 u32 pwrtrac_value; 47 48 if (rtlefuse->eeprom_regulatory != 0) 49 turbo_scanoff = true; 50 51 if (mac->act_scanning) { 52 tx_agc[RF90_PATH_A] = 0x3f3f3f3f; 53 tx_agc[RF90_PATH_B] = 0x3f3f3f3f; 54 55 if (turbo_scanoff) { 56 for (idx1 = RF90_PATH_A; 57 idx1 <= RF90_PATH_B; 58 idx1++) { 59 tx_agc[idx1] = ppowerlevel[idx1] | 60 (ppowerlevel[idx1] << 8) | 61 (ppowerlevel[idx1] << 16) | 62 (ppowerlevel[idx1] << 24); 63 } 64 } 65 } else { 66 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 67 tx_agc[idx1] = ppowerlevel[idx1] | 68 (ppowerlevel[idx1] << 8) | 69 (ppowerlevel[idx1] << 16) | 70 (ppowerlevel[idx1] << 24); 71 } 72 73 if (rtlefuse->eeprom_regulatory == 0) { 74 tmpval = 75 (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + 76 (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 77 8); 78 tx_agc[RF90_PATH_A] += tmpval; 79 80 tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + 81 (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 82 24); 83 tx_agc[RF90_PATH_B] += tmpval; 84 } 85 } 86 87 for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) { 88 ptr = (u8 *)(&tx_agc[idx1]); 89 for (idx2 = 0; idx2 < 4; idx2++) { 90 if (*ptr > RF6052_MAX_TX_PWR) 91 *ptr = RF6052_MAX_TX_PWR; 92 ptr++; 93 } 94 } 95 rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); 96 if (direction == 1) { 97 tx_agc[0] += pwrtrac_value; 98 tx_agc[1] += pwrtrac_value; 99 } else if (direction == 2) { 100 tx_agc[0] -= pwrtrac_value; 101 tx_agc[1] -= pwrtrac_value; 102 } 103 tmpval = tx_agc[RF90_PATH_A]; 104 rtl_set_bbreg(hw, RTXAGC_A_CCK11_CCK1, MASKDWORD, tmpval); 105 106 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 107 "CCK PWR 1~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval, 108 RTXAGC_A_CCK11_CCK1); 109 110 tmpval = tx_agc[RF90_PATH_B]; 111 rtl_set_bbreg(hw, RTXAGC_B_CCK11_CCK1, MASKDWORD, tmpval); 112 113 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 114 "CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval, 115 RTXAGC_B_CCK11_CCK1); 116 } 117 118 static void rtl8821ae_phy_get_power_base(struct ieee80211_hw *hw, 119 u8 *ppowerlevel_ofdm, 120 u8 *ppowerlevel_bw20, 121 u8 *ppowerlevel_bw40, u8 channel, 122 u32 *ofdmbase, u32 *mcsbase) 123 { 124 struct rtl_priv *rtlpriv = rtl_priv(hw); 125 struct rtl_phy *rtlphy = &rtlpriv->phy; 126 u32 powerbase0, powerbase1; 127 u8 i, powerlevel[2]; 128 129 for (i = 0; i < 2; i++) { 130 powerbase0 = ppowerlevel_ofdm[i]; 131 132 powerbase0 = (powerbase0 << 24) | (powerbase0 << 16) | 133 (powerbase0 << 8) | powerbase0; 134 *(ofdmbase + i) = powerbase0; 135 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 136 " [OFDM power base index rf(%c) = 0x%x]\n", 137 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)); 138 } 139 140 for (i = 0; i < 2; i++) { 141 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) 142 powerlevel[i] = ppowerlevel_bw20[i]; 143 else 144 powerlevel[i] = ppowerlevel_bw40[i]; 145 146 powerbase1 = powerlevel[i]; 147 powerbase1 = (powerbase1 << 24) | 148 (powerbase1 << 16) | (powerbase1 << 8) | powerbase1; 149 150 *(mcsbase + i) = powerbase1; 151 152 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 153 " [MCS power base index rf(%c) = 0x%x]\n", 154 ((i == 0) ? 'A' : 'B'), *(mcsbase + i)); 155 } 156 } 157 158 static void get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, 159 u8 channel, u8 index, 160 u32 *powerbase0, 161 u32 *powerbase1, 162 u32 *p_outwriteval) 163 { 164 struct rtl_priv *rtlpriv = rtl_priv(hw); 165 struct rtl_phy *rtlphy = &rtlpriv->phy; 166 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 167 u8 i, chnlgroup = 0, pwr_diff_limit[4], pwr_diff = 0, customer_pwr_diff; 168 u32 writeval, customer_limit, rf; 169 170 for (rf = 0; rf < 2; rf++) { 171 switch (rtlefuse->eeprom_regulatory) { 172 case 0: 173 chnlgroup = 0; 174 175 writeval = 176 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + 177 (rf ? 8 : 0)] 178 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 179 180 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 181 "RTK better performance, writeval(%c) = 0x%x\n", 182 ((rf == 0) ? 'A' : 'B'), writeval); 183 break; 184 case 1: 185 if (rtlphy->pwrgroup_cnt == 1) { 186 chnlgroup = 0; 187 } else { 188 if (channel < 3) 189 chnlgroup = 0; 190 else if (channel < 6) 191 chnlgroup = 1; 192 else if (channel < 9) 193 chnlgroup = 2; 194 else if (channel < 12) 195 chnlgroup = 3; 196 else if (channel < 14) 197 chnlgroup = 4; 198 else if (channel == 14) 199 chnlgroup = 5; 200 } 201 202 writeval = 203 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] 204 [index + (rf ? 8 : 0)] + ((index < 2) ? 205 powerbase0[rf] : 206 powerbase1[rf]); 207 208 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 209 "Realtek regulatory, 20MHz, writeval(%c) = 0x%x\n", 210 ((rf == 0) ? 'A' : 'B'), writeval); 211 212 break; 213 case 2: 214 writeval = 215 ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 216 217 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 218 "Better regulatory, writeval(%c) = 0x%x\n", 219 ((rf == 0) ? 'A' : 'B'), writeval); 220 break; 221 case 3: 222 chnlgroup = 0; 223 224 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { 225 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 226 "customer's limit, 40MHz rf(%c) = 0x%x\n", 227 ((rf == 0) ? 'A' : 'B'), 228 rtlefuse->pwrgroup_ht40[rf][channel - 229 1]); 230 } else { 231 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 232 "customer's limit, 20MHz rf(%c) = 0x%x\n", 233 ((rf == 0) ? 'A' : 'B'), 234 rtlefuse->pwrgroup_ht20[rf][channel - 235 1]); 236 } 237 238 if (index < 2) 239 pwr_diff = rtlefuse->txpwr_legacyhtdiff[rf][channel-1]; 240 else if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) 241 pwr_diff = 242 rtlefuse->txpwr_ht20diff[rf][channel-1]; 243 244 if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) 245 customer_pwr_diff = 246 rtlefuse->pwrgroup_ht40[rf][channel-1]; 247 else 248 customer_pwr_diff = 249 rtlefuse->pwrgroup_ht20[rf][channel-1]; 250 251 if (pwr_diff > customer_pwr_diff) 252 pwr_diff = 0; 253 else 254 pwr_diff = customer_pwr_diff - pwr_diff; 255 256 for (i = 0; i < 4; i++) { 257 pwr_diff_limit[i] = 258 (u8)((rtlphy->mcs_txpwrlevel_origoffset 259 [chnlgroup][index + (rf ? 8 : 0)] & 260 (0x7f << (i * 8))) >> (i * 8)); 261 262 if (pwr_diff_limit[i] > pwr_diff) 263 pwr_diff_limit[i] = pwr_diff; 264 } 265 266 customer_limit = (pwr_diff_limit[3] << 24) | 267 (pwr_diff_limit[2] << 16) | 268 (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]); 269 270 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 271 "Customer's limit rf(%c) = 0x%x\n", 272 ((rf == 0) ? 'A' : 'B'), customer_limit); 273 274 writeval = customer_limit + 275 ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 276 277 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 278 "Customer, writeval rf(%c)= 0x%x\n", 279 ((rf == 0) ? 'A' : 'B'), writeval); 280 break; 281 default: 282 chnlgroup = 0; 283 writeval = 284 rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] 285 [index + (rf ? 8 : 0)] 286 + ((index < 2) ? powerbase0[rf] : powerbase1[rf]); 287 288 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 289 "RTK better performance, writeval rf(%c) = 0x%x\n", 290 ((rf == 0) ? 'A' : 'B'), writeval); 291 break; 292 } 293 294 if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1) 295 writeval = writeval - 0x06060606; 296 else if (rtlpriv->dm.dynamic_txhighpower_lvl == 297 TXHIGHPWRLEVEL_BT2) 298 writeval = writeval - 0x0c0c0c0c; 299 *(p_outwriteval + rf) = writeval; 300 } 301 } 302 303 static void _rtl8821ae_write_ofdm_power_reg(struct ieee80211_hw *hw, 304 u8 index, u32 *pvalue) 305 { 306 struct rtl_priv *rtlpriv = rtl_priv(hw); 307 u16 regoffset_a[6] = { 308 RTXAGC_A_OFDM18_OFDM6, RTXAGC_A_OFDM54_OFDM24, 309 RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04, 310 RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12 311 }; 312 u16 regoffset_b[6] = { 313 RTXAGC_B_OFDM18_OFDM6, RTXAGC_B_OFDM54_OFDM24, 314 RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04, 315 RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12 316 }; 317 u8 i, rf, pwr_val[4]; 318 u32 writeval; 319 u16 regoffset; 320 321 for (rf = 0; rf < 2; rf++) { 322 writeval = pvalue[rf]; 323 for (i = 0; i < 4; i++) { 324 pwr_val[i] = (u8)((writeval & (0x7f << 325 (i * 8))) >> (i * 8)); 326 327 if (pwr_val[i] > RF6052_MAX_TX_PWR) 328 pwr_val[i] = RF6052_MAX_TX_PWR; 329 } 330 writeval = (pwr_val[3] << 24) | (pwr_val[2] << 16) | 331 (pwr_val[1] << 8) | pwr_val[0]; 332 333 if (rf == 0) 334 regoffset = regoffset_a[index]; 335 else 336 regoffset = regoffset_b[index]; 337 rtl_set_bbreg(hw, regoffset, MASKDWORD, writeval); 338 339 RTPRINT(rtlpriv, FPHY, PHY_TXPWR, 340 "Set 0x%x = %08x\n", regoffset, writeval); 341 } 342 } 343 344 void rtl8821ae_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw, 345 u8 *ppowerlevel_ofdm, 346 u8 *ppowerlevel_bw20, 347 u8 *ppowerlevel_bw40, 348 u8 channel) 349 { 350 u32 writeval[2], powerbase0[2], powerbase1[2]; 351 u8 index; 352 u8 direction; 353 u32 pwrtrac_value; 354 355 rtl8821ae_phy_get_power_base(hw, ppowerlevel_ofdm, 356 ppowerlevel_bw20, 357 ppowerlevel_bw40, 358 channel, 359 &powerbase0[0], 360 &powerbase1[0]); 361 362 rtl8821ae_dm_txpower_track_adjust(hw, 1, &direction, &pwrtrac_value); 363 364 for (index = 0; index < 6; index++) { 365 get_txpower_writeval_by_regulatory(hw, channel, index, 366 &powerbase0[0], 367 &powerbase1[0], 368 &writeval[0]); 369 if (direction == 1) { 370 writeval[0] += pwrtrac_value; 371 writeval[1] += pwrtrac_value; 372 } else if (direction == 2) { 373 writeval[0] -= pwrtrac_value; 374 writeval[1] -= pwrtrac_value; 375 } 376 _rtl8821ae_write_ofdm_power_reg(hw, index, &writeval[0]); 377 } 378 } 379 380 bool rtl8821ae_phy_rf6052_config(struct ieee80211_hw *hw) 381 { 382 struct rtl_priv *rtlpriv = rtl_priv(hw); 383 struct rtl_phy *rtlphy = &rtlpriv->phy; 384 385 if (rtlphy->rf_type == RF_1T1R) 386 rtlphy->num_total_rfpath = 1; 387 else 388 rtlphy->num_total_rfpath = 2; 389 390 return _rtl8821ae_phy_rf6052_config_parafile(hw); 391 } 392 393 static bool _rtl8821ae_phy_rf6052_config_parafile(struct ieee80211_hw *hw) 394 { 395 struct rtl_priv *rtlpriv = rtl_priv(hw); 396 struct rtl_phy *rtlphy = &rtlpriv->phy; 397 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 398 u8 rfpath; 399 bool rtstatus = true; 400 401 for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { 402 switch (rfpath) { 403 case RF90_PATH_A: { 404 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 405 rtstatus = 406 rtl8812ae_phy_config_rf_with_headerfile(hw, 407 (enum radio_path)rfpath); 408 else 409 rtstatus = 410 rtl8821ae_phy_config_rf_with_headerfile(hw, 411 (enum radio_path)rfpath); 412 break; 413 } 414 case RF90_PATH_B: 415 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) 416 rtstatus = 417 rtl8812ae_phy_config_rf_with_headerfile(hw, 418 (enum radio_path)rfpath); 419 else 420 rtstatus = 421 rtl8821ae_phy_config_rf_with_headerfile(hw, 422 (enum radio_path)rfpath); 423 break; 424 case RF90_PATH_C: 425 break; 426 case RF90_PATH_D: 427 break; 428 } 429 430 if (!rtstatus) { 431 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, 432 "Radio[%d] Fail!!\n", rfpath); 433 return false; 434 } 435 } 436 437 /*put arrays in dm.c*/ 438 RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, "\n"); 439 return rtstatus; 440 } 441