1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright(c) 2009-2012 Realtek Corporation.*/ 3 4 #include "../wifi.h" 5 #include "../base.h" 6 #include "../core.h" 7 #include "../rtl8192d/reg.h" 8 #include "../rtl8192d/def.h" 9 #include "../rtl8192d/dm_common.h" 10 #include "../rtl8192d/phy_common.h" 11 #include "../rtl8192d/fw_common.h" 12 #include "phy.h" 13 #include "dm.h" 14 15 #define UNDEC_SM_PWDB entry_min_undec_sm_pwdb 16 17 static void rtl92d_dm_init_dynamic_txpower(struct ieee80211_hw *hw) 18 { 19 struct rtl_priv *rtlpriv = rtl_priv(hw); 20 21 rtlpriv->dm.dynamic_txpower_enable = true; 22 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; 23 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; 24 } 25 26 static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw) 27 { 28 struct rtl_priv *rtlpriv = rtl_priv(hw); 29 struct rtl_phy *rtlphy = &(rtlpriv->phy); 30 struct rtl_hal *rtlhal = rtl_hal(rtlpriv); 31 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 32 long undec_sm_pwdb; 33 34 if ((!rtlpriv->dm.dynamic_txpower_enable) 35 || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { 36 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; 37 return; 38 } 39 if ((mac->link_state < MAC80211_LINKED) && 40 (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { 41 rtl_dbg(rtlpriv, COMP_POWER, DBG_TRACE, 42 "Not connected to any\n"); 43 rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; 44 rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL; 45 return; 46 } 47 if (mac->link_state >= MAC80211_LINKED) { 48 if (mac->opmode == NL80211_IFTYPE_ADHOC) { 49 undec_sm_pwdb = 50 rtlpriv->dm.UNDEC_SM_PWDB; 51 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 52 "IBSS Client PWDB = 0x%lx\n", 53 undec_sm_pwdb); 54 } else { 55 undec_sm_pwdb = 56 rtlpriv->dm.undec_sm_pwdb; 57 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 58 "STA Default Port PWDB = 0x%lx\n", 59 undec_sm_pwdb); 60 } 61 } else { 62 undec_sm_pwdb = 63 rtlpriv->dm.UNDEC_SM_PWDB; 64 65 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 66 "AP Ext Port PWDB = 0x%lx\n", 67 undec_sm_pwdb); 68 } 69 if (rtlhal->current_bandtype == BAND_ON_5G) { 70 if (undec_sm_pwdb >= 0x33) { 71 rtlpriv->dm.dynamic_txhighpower_lvl = 72 TXHIGHPWRLEVEL_LEVEL2; 73 rtl_dbg(rtlpriv, COMP_HIPWR, DBG_LOUD, 74 "5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"); 75 } else if ((undec_sm_pwdb < 0x33) 76 && (undec_sm_pwdb >= 0x2b)) { 77 rtlpriv->dm.dynamic_txhighpower_lvl = 78 TXHIGHPWRLEVEL_LEVEL1; 79 rtl_dbg(rtlpriv, COMP_HIPWR, DBG_LOUD, 80 "5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"); 81 } else if (undec_sm_pwdb < 0x2b) { 82 rtlpriv->dm.dynamic_txhighpower_lvl = 83 TXHIGHPWRLEVEL_NORMAL; 84 rtl_dbg(rtlpriv, COMP_HIPWR, DBG_LOUD, 85 "5G:TxHighPwrLevel_Normal\n"); 86 } 87 } else { 88 if (undec_sm_pwdb >= 89 TX_POWER_NEAR_FIELD_THRESH_LVL2) { 90 rtlpriv->dm.dynamic_txhighpower_lvl = 91 TXHIGHPWRLEVEL_LEVEL2; 92 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 93 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); 94 } else 95 if ((undec_sm_pwdb < 96 (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) 97 && (undec_sm_pwdb >= 98 TX_POWER_NEAR_FIELD_THRESH_LVL1)) { 99 100 rtlpriv->dm.dynamic_txhighpower_lvl = 101 TXHIGHPWRLEVEL_LEVEL1; 102 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 103 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); 104 } else if (undec_sm_pwdb < 105 (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { 106 rtlpriv->dm.dynamic_txhighpower_lvl = 107 TXHIGHPWRLEVEL_NORMAL; 108 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 109 "TXHIGHPWRLEVEL_NORMAL\n"); 110 } 111 } 112 if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) { 113 rtl_dbg(rtlpriv, COMP_POWER, DBG_LOUD, 114 "PHY_SetTxPowerLevel8192S() Channel = %d\n", 115 rtlphy->current_channel); 116 rtl92d_phy_set_txpower_level(hw, rtlphy->current_channel); 117 } 118 rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; 119 } 120 121 static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw) 122 { 123 struct rtl_priv *rtlpriv = rtl_priv(hw); 124 125 /* AP & ADHOC & MESH will return tmp */ 126 if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) 127 return; 128 /* Indicate Rx signal strength to FW. */ 129 if (rtlpriv->dm.useramask) { 130 u32 temp = rtlpriv->dm.undec_sm_pwdb; 131 132 temp <<= 16; 133 temp |= 0x100; 134 /* fw v12 cmdid 5:use max macid ,for nic , 135 * default macid is 0 ,max macid is 1 */ 136 rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp)); 137 } else { 138 rtl_write_byte(rtlpriv, 0x4fe, 139 (u8) rtlpriv->dm.undec_sm_pwdb); 140 } 141 } 142 143 void rtl92de_dm_init(struct ieee80211_hw *hw) 144 { 145 struct rtl_priv *rtlpriv = rtl_priv(hw); 146 147 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; 148 rtl_dm_diginit(hw, 0x20); 149 rtlpriv->dm_digtable.rx_gain_max = DM_DIG_FA_UPPER; 150 rtlpriv->dm_digtable.rx_gain_min = DM_DIG_FA_LOWER; 151 rtl92d_dm_init_dynamic_txpower(hw); 152 rtl92d_dm_init_edca_turbo(hw); 153 rtl92d_dm_init_rate_adaptive_mask(hw); 154 rtl92d_dm_initialize_txpower_tracking(hw); 155 } 156 157 void rtl92de_dm_watchdog(struct ieee80211_hw *hw) 158 { 159 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 160 bool fw_current_inpsmode = false; 161 bool fwps_awake = true; 162 163 /* 1. RF is OFF. (No need to do DM.) 164 * 2. Fw is under power saving mode for FwLPS. 165 * (Prevent from SW/FW I/O racing.) 166 * 3. IPS workitem is scheduled. (Prevent from IPS sequence 167 * to be swapped with DM. 168 * 4. RFChangeInProgress is TRUE. 169 * (Prevent from broken by IPS/HW/SW Rf off.) */ 170 171 if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) && 172 fwps_awake) && (!ppsc->rfchange_inprogress)) { 173 rtl92d_dm_pwdb_monitor(hw); 174 rtl92d_dm_false_alarm_counter_statistics(hw); 175 rtl92d_dm_find_minimum_rssi(hw); 176 rtl92d_dm_dig(hw); 177 /* rtl92d_dm_dynamic_bb_powersaving(hw); */ 178 rtl92d_dm_dynamic_txpower(hw); 179 /* rtl92d_dm_check_txpower_tracking_thermal_meter(hw); */ 180 /* rtl92d_dm_refresh_rate_adaptive_mask(hw); */ 181 /* rtl92d_dm_interrupt_migration(hw); */ 182 rtl92d_dm_check_edca_turbo(hw); 183 } 184 } 185