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 "../base.h" 32#include "../core.h" 33#include "reg.h" 34#include "def.h" 35#include "phy.h" 36#include "dm.h" 37#include "fw.h" 38 39static const u32 edca_setting_dl[PEER_MAX] = { 40 0xa44f, /* 0 UNKNOWN */ 41 0x5ea44f, /* 1 REALTEK_90 */ 42 0x5ea44f, /* 2 REALTEK_92SE */ 43 0xa630, /* 3 BROAD */ 44 0xa44f, /* 4 RAL */ 45 0xa630, /* 5 ATH */ 46 0xa630, /* 6 CISCO */ 47 0xa42b, /* 7 MARV */ 48}; 49 50static const u32 edca_setting_dl_gmode[PEER_MAX] = { 51 0x4322, /* 0 UNKNOWN */ 52 0xa44f, /* 1 REALTEK_90 */ 53 0x5ea44f, /* 2 REALTEK_92SE */ 54 0xa42b, /* 3 BROAD */ 55 0x5e4322, /* 4 RAL */ 56 0x4322, /* 5 ATH */ 57 0xa430, /* 6 CISCO */ 58 0x5ea44f, /* 7 MARV */ 59}; 60 61static const u32 edca_setting_ul[PEER_MAX] = { 62 0x5e4322, /* 0 UNKNOWN */ 63 0xa44f, /* 1 REALTEK_90 */ 64 0x5ea44f, /* 2 REALTEK_92SE */ 65 0x5ea322, /* 3 BROAD */ 66 0x5ea422, /* 4 RAL */ 67 0x5ea322, /* 5 ATH */ 68 0x3ea44f, /* 6 CISCO */ 69 0x5ea44f, /* 7 MARV */ 70}; 71 72static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) 73{ 74 struct rtl_priv *rtlpriv = rtl_priv(hw); 75 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 76 77 static u64 last_txok_cnt; 78 static u64 last_rxok_cnt; 79 u64 cur_txok_cnt = 0; 80 u64 cur_rxok_cnt = 0; 81 82 u32 edca_be_ul = edca_setting_ul[mac->vendor]; 83 u32 edca_be_dl = edca_setting_dl[mac->vendor]; 84 u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; 85 86 if (mac->link_state != MAC80211_LINKED) { 87 rtlpriv->dm.current_turbo_edca = false; 88 goto dm_checkedcaturbo_exit; 89 } 90 91 if ((!rtlpriv->dm.is_any_nonbepkts) && 92 (!rtlpriv->dm.disable_framebursting)) { 93 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; 94 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; 95 96 if (rtlpriv->phy.rf_type == RF_1T2R) { 97 if (cur_txok_cnt > 4 * cur_rxok_cnt) { 98 /* Uplink TP is present. */ 99 if (rtlpriv->dm.is_cur_rdlstate || 100 !rtlpriv->dm.current_turbo_edca) { 101 rtl_write_dword(rtlpriv, EDCAPARA_BE, 102 edca_be_ul); 103 rtlpriv->dm.is_cur_rdlstate = false; 104 } 105 } else {/* Balance TP is present. */ 106 if (!rtlpriv->dm.is_cur_rdlstate || 107 !rtlpriv->dm.current_turbo_edca) { 108 if (mac->mode == WIRELESS_MODE_G || 109 mac->mode == WIRELESS_MODE_B) 110 rtl_write_dword(rtlpriv, 111 EDCAPARA_BE, 112 edca_gmode); 113 else 114 rtl_write_dword(rtlpriv, 115 EDCAPARA_BE, 116 edca_be_dl); 117 rtlpriv->dm.is_cur_rdlstate = true; 118 } 119 } 120 rtlpriv->dm.current_turbo_edca = true; 121 } else { 122 if (cur_rxok_cnt > 4 * cur_txok_cnt) { 123 if (!rtlpriv->dm.is_cur_rdlstate || 124 !rtlpriv->dm.current_turbo_edca) { 125 if (mac->mode == WIRELESS_MODE_G || 126 mac->mode == WIRELESS_MODE_B) 127 rtl_write_dword(rtlpriv, 128 EDCAPARA_BE, 129 edca_gmode); 130 else 131 rtl_write_dword(rtlpriv, 132 EDCAPARA_BE, 133 edca_be_dl); 134 rtlpriv->dm.is_cur_rdlstate = true; 135 } 136 } else { 137 if (rtlpriv->dm.is_cur_rdlstate || 138 !rtlpriv->dm.current_turbo_edca) { 139 rtl_write_dword(rtlpriv, EDCAPARA_BE, 140 edca_be_ul); 141 rtlpriv->dm.is_cur_rdlstate = false; 142 } 143 } 144 rtlpriv->dm.current_turbo_edca = true; 145 } 146 } else { 147 if (rtlpriv->dm.current_turbo_edca) { 148 u8 tmp = AC0_BE; 149 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, 150 &tmp); 151 rtlpriv->dm.current_turbo_edca = false; 152 } 153 } 154 155dm_checkedcaturbo_exit: 156 rtlpriv->dm.is_any_nonbepkts = false; 157 last_txok_cnt = rtlpriv->stats.txbytesunicast; 158 last_rxok_cnt = rtlpriv->stats.rxbytesunicast; 159} 160 161static void _rtl92s_dm_txpowertracking_callback_thermalmeter( 162 struct ieee80211_hw *hw) 163{ 164 struct rtl_priv *rtlpriv = rtl_priv(hw); 165 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 166 u8 thermalvalue = 0; 167 u32 fw_cmd = 0; 168 169 rtlpriv->dm.txpower_trackinginit = true; 170 171 thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); 172 173 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 174 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermal meter 0x%x\n", 175 thermalvalue, 176 rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter); 177 178 if (thermalvalue) { 179 rtlpriv->dm.thermalvalue = thermalvalue; 180 if (hal_get_firmwareversion(rtlpriv) >= 0x35) { 181 rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); 182 } else { 183 fw_cmd = (FW_TXPWR_TRACK_THERMAL | 184 (rtlpriv->efuse.thermalmeter[0] << 8) | 185 (thermalvalue << 16)); 186 187 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 188 "Write to FW Thermal Val = 0x%x\n", fw_cmd); 189 190 rtl_write_dword(rtlpriv, WFM5, fw_cmd); 191 rtl92s_phy_chk_fwcmd_iodone(hw); 192 } 193 } 194 195 rtlpriv->dm.txpowercount = 0; 196} 197 198static void _rtl92s_dm_check_txpowertracking_thermalmeter( 199 struct ieee80211_hw *hw) 200{ 201 struct rtl_priv *rtlpriv = rtl_priv(hw); 202 struct rtl_phy *rtlphy = &(rtlpriv->phy); 203 static u8 tm_trigger; 204 u8 tx_power_checkcnt = 5; 205 206 /* 2T2R TP issue */ 207 if (rtlphy->rf_type == RF_2T2R) 208 return; 209 210 if (!rtlpriv->dm.txpower_tracking) 211 return; 212 213 if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) { 214 rtlpriv->dm.txpowercount++; 215 return; 216 } 217 218 if (!tm_trigger) { 219 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, 220 RFREG_OFFSET_MASK, 0x60); 221 tm_trigger = 1; 222 } else { 223 _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); 224 tm_trigger = 0; 225 } 226} 227 228static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) 229{ 230 struct rtl_priv *rtlpriv = rtl_priv(hw); 231 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 232 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 233 struct rate_adaptive *ra = &(rtlpriv->ra); 234 struct ieee80211_sta *sta = NULL; 235 u32 low_rssi_thresh = 0; 236 u32 middle_rssi_thresh = 0; 237 u32 high_rssi_thresh = 0; 238 239 if (is_hal_stop(rtlhal)) 240 return; 241 242 if (!rtlpriv->dm.useramask) 243 return; 244 245 if (hal_get_firmwareversion(rtlpriv) >= 61 && 246 !rtlpriv->dm.inform_fw_driverctrldm) { 247 rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); 248 rtlpriv->dm.inform_fw_driverctrldm = true; 249 } 250 251 if ((mac->link_state == MAC80211_LINKED) && 252 (mac->opmode == NL80211_IFTYPE_STATION)) { 253 switch (ra->pre_ratr_state) { 254 case DM_RATR_STA_HIGH: 255 high_rssi_thresh = 40; 256 middle_rssi_thresh = 30; 257 low_rssi_thresh = 20; 258 break; 259 case DM_RATR_STA_MIDDLE: 260 high_rssi_thresh = 44; 261 middle_rssi_thresh = 30; 262 low_rssi_thresh = 20; 263 break; 264 case DM_RATR_STA_LOW: 265 high_rssi_thresh = 44; 266 middle_rssi_thresh = 34; 267 low_rssi_thresh = 20; 268 break; 269 case DM_RATR_STA_ULTRALOW: 270 high_rssi_thresh = 44; 271 middle_rssi_thresh = 34; 272 low_rssi_thresh = 24; 273 break; 274 default: 275 high_rssi_thresh = 44; 276 middle_rssi_thresh = 34; 277 low_rssi_thresh = 24; 278 break; 279 } 280 281 if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) { 282 ra->ratr_state = DM_RATR_STA_HIGH; 283 } else if (rtlpriv->dm.undec_sm_pwdb > 284 (long)middle_rssi_thresh) { 285 ra->ratr_state = DM_RATR_STA_LOW; 286 } else if (rtlpriv->dm.undec_sm_pwdb > 287 (long)low_rssi_thresh) { 288 ra->ratr_state = DM_RATR_STA_LOW; 289 } else { 290 ra->ratr_state = DM_RATR_STA_ULTRALOW; 291 } 292 293 if (ra->pre_ratr_state != ra->ratr_state) { 294 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 295 "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n", 296 rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, 297 ra->pre_ratr_state, ra->ratr_state); 298 299 rcu_read_lock(); 300 sta = rtl_find_sta(hw, mac->bssid); 301 if (sta) 302 rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 303 ra->ratr_state); 304 rcu_read_unlock(); 305 306 ra->pre_ratr_state = ra->ratr_state; 307 } 308 } 309} 310 311static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) 312{ 313 struct rtl_priv *rtlpriv = rtl_priv(hw); 314 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 315 struct rtl_phy *rtlphy = &(rtlpriv->phy); 316 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 317 bool current_mrc; 318 bool enable_mrc = true; 319 long tmpentry_maxpwdb = 0; 320 u8 rssi_a = 0; 321 u8 rssi_b = 0; 322 323 if (is_hal_stop(rtlhal)) 324 return; 325 326 if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R)) 327 return; 328 329 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); 330 331 if (mac->link_state >= MAC80211_LINKED) { 332 if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) { 333 rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; 334 rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; 335 } 336 } 337 338 /* MRC settings would NOT affect TP on Wireless B mode. */ 339 if (mac->mode != WIRELESS_MODE_B) { 340 if ((rssi_a == 0) && (rssi_b == 0)) { 341 enable_mrc = true; 342 } else if (rssi_b > 30) { 343 /* Turn on B-Path */ 344 enable_mrc = true; 345 } else if (rssi_b < 5) { 346 /* Turn off B-path */ 347 enable_mrc = false; 348 /* Take care of RSSI differentiation. */ 349 } else if (rssi_a > 15 && (rssi_a >= rssi_b)) { 350 if ((rssi_a - rssi_b) > 15) 351 /* Turn off B-path */ 352 enable_mrc = false; 353 else if ((rssi_a - rssi_b) < 10) 354 /* Turn on B-Path */ 355 enable_mrc = true; 356 else 357 enable_mrc = current_mrc; 358 } else { 359 /* Turn on B-Path */ 360 enable_mrc = true; 361 } 362 } 363 364 /* Update MRC settings if needed. */ 365 if (enable_mrc != current_mrc) 366 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, 367 (u8 *)&enable_mrc); 368 369} 370 371void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw) 372{ 373 struct rtl_priv *rtlpriv = rtl_priv(hw); 374 375 rtlpriv->dm.current_turbo_edca = false; 376 rtlpriv->dm.is_any_nonbepkts = false; 377 rtlpriv->dm.is_cur_rdlstate = false; 378} 379 380static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) 381{ 382 struct rtl_priv *rtlpriv = rtl_priv(hw); 383 struct rate_adaptive *ra = &(rtlpriv->ra); 384 385 ra->ratr_state = DM_RATR_STA_MAX; 386 ra->pre_ratr_state = DM_RATR_STA_MAX; 387 388 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER && 389 hal_get_firmwareversion(rtlpriv) >= 60) 390 rtlpriv->dm.useramask = true; 391 else 392 rtlpriv->dm.useramask = false; 393 394 rtlpriv->dm.useramask = false; 395 rtlpriv->dm.inform_fw_driverctrldm = false; 396} 397 398static void _rtl92s_dm_init_txpowertracking_thermalmeter( 399 struct ieee80211_hw *hw) 400{ 401 struct rtl_priv *rtlpriv = rtl_priv(hw); 402 403 rtlpriv->dm.txpower_tracking = true; 404 rtlpriv->dm.txpowercount = 0; 405 rtlpriv->dm.txpower_trackinginit = false; 406} 407 408static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) 409{ 410 struct rtl_priv *rtlpriv = rtl_priv(hw); 411 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); 412 u32 ret_value; 413 414 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); 415 falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); 416 417 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); 418 falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); 419 falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); 420 ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); 421 falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); 422 423 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + 424 falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail + 425 falsealm_cnt->cnt_mcs_fail; 426 427 /* read CCK false alarm */ 428 ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD); 429 falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff); 430 falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + 431 falsealm_cnt->cnt_cck_fail; 432} 433 434static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) 435{ 436 struct rtl_priv *rtlpriv = rtl_priv(hw); 437 struct dig_t *digtable = &rtlpriv->dm_digtable; 438 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); 439 440 if (falsealm_cnt->cnt_all > digtable->fa_highthresh) { 441 if ((digtable->back_val - 6) < 442 digtable->backoffval_range_min) 443 digtable->back_val = digtable->backoffval_range_min; 444 else 445 digtable->back_val -= 6; 446 } else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) { 447 if ((digtable->back_val + 6) > 448 digtable->backoffval_range_max) 449 digtable->back_val = 450 digtable->backoffval_range_max; 451 else 452 digtable->back_val += 6; 453 } 454} 455 456static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) 457{ 458 struct rtl_priv *rtlpriv = rtl_priv(hw); 459 struct dig_t *digtable = &rtlpriv->dm_digtable; 460 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); 461 static u8 initialized, force_write; 462 u8 initial_gain = 0; 463 464 if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) || 465 (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) { 466 if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) { 467 if (rtlpriv->psc.rfpwr_state != ERFON) 468 return; 469 470 if (digtable->backoff_enable_flag) 471 rtl92s_backoff_enable_flag(hw); 472 else 473 digtable->back_val = DM_DIG_BACKOFF_MAX; 474 475 if ((digtable->rssi_val + 10 - digtable->back_val) > 476 digtable->rx_gain_max) 477 digtable->cur_igvalue = 478 digtable->rx_gain_max; 479 else if ((digtable->rssi_val + 10 - digtable->back_val) 480 < digtable->rx_gain_min) 481 digtable->cur_igvalue = 482 digtable->rx_gain_min; 483 else 484 digtable->cur_igvalue = digtable->rssi_val + 10 485 - digtable->back_val; 486 487 if (falsealm_cnt->cnt_all > 10000) 488 digtable->cur_igvalue = 489 (digtable->cur_igvalue > 0x33) ? 490 digtable->cur_igvalue : 0x33; 491 492 if (falsealm_cnt->cnt_all > 16000) 493 digtable->cur_igvalue = 494 digtable->rx_gain_max; 495 /* connected -> connected or disconnected -> disconnected */ 496 } else { 497 /* Firmware control DIG, do nothing in driver dm */ 498 return; 499 } 500 /* disconnected -> connected or connected -> 501 * disconnected or beforeconnect->(dis)connected */ 502 } else { 503 /* Enable FW DIG */ 504 digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; 505 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); 506 507 digtable->back_val = DM_DIG_BACKOFF_MAX; 508 digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0]; 509 digtable->pre_igvalue = 0; 510 return; 511 } 512 513 /* Forced writing to prevent from fw-dig overwriting. */ 514 if (digtable->pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 515 MASKBYTE0)) 516 force_write = 1; 517 518 if ((digtable->pre_igvalue != digtable->cur_igvalue) || 519 !initialized || force_write) { 520 /* Disable FW DIG */ 521 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE); 522 523 initial_gain = (u8)digtable->cur_igvalue; 524 525 /* Set initial gain. */ 526 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain); 527 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain); 528 digtable->pre_igvalue = digtable->cur_igvalue; 529 initialized = 1; 530 force_write = 0; 531 } 532} 533 534static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) 535{ 536 struct rtl_priv *rtlpriv = rtl_priv(hw); 537 struct dig_t *dig = &rtlpriv->dm_digtable; 538 539 if (rtlpriv->mac80211.act_scanning) 540 return; 541 542 /* Decide the current status and if modify initial gain or not */ 543 if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || 544 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) 545 dig->cur_sta_cstate = DIG_STA_CONNECT; 546 else 547 dig->cur_sta_cstate = DIG_STA_DISCONNECT; 548 549 dig->rssi_val = rtlpriv->dm.undec_sm_pwdb; 550 551 /* Change dig mode to rssi */ 552 if (dig->cur_sta_cstate != DIG_STA_DISCONNECT) { 553 if (dig->dig_twoport_algorithm == 554 DIG_TWO_PORT_ALGO_FALSE_ALARM) { 555 dig->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; 556 rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); 557 } 558 } 559 560 _rtl92s_dm_false_alarm_counter_statistics(hw); 561 _rtl92s_dm_initial_gain_sta_beforeconnect(hw); 562 563 dig->pre_sta_cstate = dig->cur_sta_cstate; 564} 565 566static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) 567{ 568 struct rtl_priv *rtlpriv = rtl_priv(hw); 569 struct rtl_phy *rtlphy = &(rtlpriv->phy); 570 struct dig_t *digtable = &rtlpriv->dm_digtable; 571 572 /* 2T2R TP issue */ 573 if (rtlphy->rf_type == RF_2T2R) 574 return; 575 576 if (!rtlpriv->dm.dm_initialgain_enable) 577 return; 578 579 if (digtable->dig_enable_flag == false) 580 return; 581 582 _rtl92s_dm_ctrl_initgain_bytwoport(hw); 583} 584 585static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) 586{ 587 struct rtl_priv *rtlpriv = rtl_priv(hw); 588 struct rtl_phy *rtlphy = &(rtlpriv->phy); 589 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 590 long undec_sm_pwdb; 591 long txpwr_threshold_lv1, txpwr_threshold_lv2; 592 593 /* 2T2R TP issue */ 594 if (rtlphy->rf_type == RF_2T2R) 595 return; 596 597 if (!rtlpriv->dm.dynamic_txpower_enable || 598 rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { 599 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; 600 return; 601 } 602 603 if ((mac->link_state < MAC80211_LINKED) && 604 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { 605 RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, 606 "Not connected to any\n"); 607 608 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; 609 610 rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; 611 return; 612 } 613 614 if (mac->link_state >= MAC80211_LINKED) { 615 if (mac->opmode == NL80211_IFTYPE_ADHOC) { 616 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; 617 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 618 "AP Client PWDB = 0x%lx\n", 619 undec_sm_pwdb); 620 } else { 621 undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; 622 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 623 "STA Default Port PWDB = 0x%lx\n", 624 undec_sm_pwdb); 625 } 626 } else { 627 undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; 628 629 RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, 630 "AP Ext Port PWDB = 0x%lx\n", 631 undec_sm_pwdb); 632 } 633 634 txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; 635 txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; 636 637 if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) 638 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; 639 else if (undec_sm_pwdb >= txpwr_threshold_lv2) 640 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; 641 else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) && 642 (undec_sm_pwdb >= txpwr_threshold_lv1)) 643 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; 644 else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3)) 645 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; 646 647 if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) 648 rtl92s_phy_set_txpower(hw, rtlphy->current_channel); 649 650 rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; 651} 652 653static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) 654{ 655 struct rtl_priv *rtlpriv = rtl_priv(hw); 656 struct dig_t *digtable = &rtlpriv->dm_digtable; 657 658 /* Disable DIG scheme now.*/ 659 digtable->dig_enable_flag = true; 660 digtable->backoff_enable_flag = true; 661 662 if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) && 663 (hal_get_firmwareversion(rtlpriv) >= 0x3c)) 664 digtable->dig_algorithm = DIG_ALGO_BY_TOW_PORT; 665 else 666 digtable->dig_algorithm = 667 DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; 668 669 digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; 670 digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; 671 /* off=by real rssi value, on=by digtable->rssi_val for new dig */ 672 digtable->dig_dbgmode = DM_DBG_OFF; 673 digtable->dig_slgorithm_switch = 0; 674 675 /* 2007/10/04 MH Define init gain threshol. */ 676 digtable->dig_state = DM_STA_DIG_MAX; 677 digtable->dig_highpwrstate = DM_STA_DIG_MAX; 678 679 digtable->cur_sta_cstate = DIG_STA_DISCONNECT; 680 digtable->pre_sta_cstate = DIG_STA_DISCONNECT; 681 digtable->cur_ap_cstate = DIG_AP_DISCONNECT; 682 digtable->pre_ap_cstate = DIG_AP_DISCONNECT; 683 684 digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; 685 digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; 686 687 digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; 688 digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; 689 690 digtable->rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; 691 digtable->rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; 692 693 /* for dig debug rssi value */ 694 digtable->rssi_val = 50; 695 digtable->back_val = DM_DIG_BACKOFF_MAX; 696 digtable->rx_gain_max = DM_DIG_MAX; 697 698 digtable->rx_gain_min = DM_DIG_MIN; 699 700 digtable->backoffval_range_max = DM_DIG_BACKOFF_MAX; 701 digtable->backoffval_range_min = DM_DIG_BACKOFF_MIN; 702} 703 704static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw) 705{ 706 struct rtl_priv *rtlpriv = rtl_priv(hw); 707 708 if ((hal_get_firmwareversion(rtlpriv) >= 60) && 709 (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)) 710 rtlpriv->dm.dynamic_txpower_enable = true; 711 else 712 rtlpriv->dm.dynamic_txpower_enable = false; 713 714 rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; 715 rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; 716} 717 718void rtl92s_dm_init(struct ieee80211_hw *hw) 719{ 720 struct rtl_priv *rtlpriv = rtl_priv(hw); 721 722 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; 723 rtlpriv->dm.undec_sm_pwdb = -1; 724 725 _rtl92s_dm_init_dynamic_txpower(hw); 726 rtl92s_dm_init_edca_turbo(hw); 727 _rtl92s_dm_init_rate_adaptive_mask(hw); 728 _rtl92s_dm_init_txpowertracking_thermalmeter(hw); 729 _rtl92s_dm_init_dig(hw); 730 731 rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE); 732} 733 734void rtl92s_dm_watchdog(struct ieee80211_hw *hw) 735{ 736 _rtl92s_dm_check_edca_turbo(hw); 737 _rtl92s_dm_check_txpowertracking_thermalmeter(hw); 738 _rtl92s_dm_ctrl_initgain_byrssi(hw); 739 _rtl92s_dm_dynamic_txpower(hw); 740 _rtl92s_dm_refresh_rateadaptive_mask(hw); 741 _rtl92s_dm_switch_baseband_mrc(hw); 742} 743 744