1 /****************************************************************************** 2 * 3 * Copyright(c) 2009-2014 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 "../base.h" 28 #include "../pci.h" 29 #include "../core.h" 30 #include "reg.h" 31 #include "def.h" 32 #include "phy.h" 33 #include "dm.h" 34 #include "../rtl8723com/dm_common.h" 35 #include "fw.h" 36 #include "trx.h" 37 #include "../btcoexist/rtl_btc.h" 38 39 static const u32 ofdmswing_table[] = { 40 0x0b40002d, /* 0, -15.0dB */ 41 0x0c000030, /* 1, -14.5dB */ 42 0x0cc00033, /* 2, -14.0dB */ 43 0x0d800036, /* 3, -13.5dB */ 44 0x0e400039, /* 4, -13.0dB */ 45 0x0f00003c, /* 5, -12.5dB */ 46 0x10000040, /* 6, -12.0dB */ 47 0x11000044, /* 7, -11.5dB */ 48 0x12000048, /* 8, -11.0dB */ 49 0x1300004c, /* 9, -10.5dB */ 50 0x14400051, /* 10, -10.0dB */ 51 0x15800056, /* 11, -9.5dB */ 52 0x16c0005b, /* 12, -9.0dB */ 53 0x18000060, /* 13, -8.5dB */ 54 0x19800066, /* 14, -8.0dB */ 55 0x1b00006c, /* 15, -7.5dB */ 56 0x1c800072, /* 16, -7.0dB */ 57 0x1e400079, /* 17, -6.5dB */ 58 0x20000080, /* 18, -6.0dB */ 59 0x22000088, /* 19, -5.5dB */ 60 0x24000090, /* 20, -5.0dB */ 61 0x26000098, /* 21, -4.5dB */ 62 0x288000a2, /* 22, -4.0dB */ 63 0x2ac000ab, /* 23, -3.5dB */ 64 0x2d4000b5, /* 24, -3.0dB */ 65 0x300000c0, /* 25, -2.5dB */ 66 0x32c000cb, /* 26, -2.0dB */ 67 0x35c000d7, /* 27, -1.5dB */ 68 0x390000e4, /* 28, -1.0dB */ 69 0x3c8000f2, /* 29, -0.5dB */ 70 0x40000100, /* 30, +0dB */ 71 0x43c0010f, /* 31, +0.5dB */ 72 0x47c0011f, /* 32, +1.0dB */ 73 0x4c000130, /* 33, +1.5dB */ 74 0x50800142, /* 34, +2.0dB */ 75 0x55400155, /* 35, +2.5dB */ 76 0x5a400169, /* 36, +3.0dB */ 77 0x5fc0017f, /* 37, +3.5dB */ 78 0x65400195, /* 38, +4.0dB */ 79 0x6b8001ae, /* 39, +4.5dB */ 80 0x71c001c7, /* 40, +5.0dB */ 81 0x788001e2, /* 41, +5.5dB */ 82 0x7f8001fe /* 42, +6.0dB */ 83 }; 84 85 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = { 86 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */ 87 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */ 88 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */ 89 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */ 90 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */ 91 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */ 92 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */ 93 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */ 94 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */ 95 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */ 96 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */ 97 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */ 98 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */ 99 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */ 100 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */ 101 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */ 102 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */ 103 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */ 104 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */ 105 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */ 106 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */ 107 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */ 108 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */ 109 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */ 110 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */ 111 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */ 112 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */ 113 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */ 114 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */ 115 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */ 116 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */ 117 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */ 118 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */ 119 }; 120 121 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = { 122 {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */ 123 {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */ 124 {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */ 125 {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */ 126 {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */ 127 {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */ 128 {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */ 129 {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */ 130 {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */ 131 {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */ 132 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */ 133 {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */ 134 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */ 135 {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */ 136 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */ 137 {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */ 138 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */ 139 {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */ 140 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */ 141 {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */ 142 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */ 143 {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */ 144 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */ 145 {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */ 146 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */ 147 {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */ 148 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */ 149 {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */ 150 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */ 151 {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */ 152 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */ 153 {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */ 154 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */ 155 }; 156 157 static const u32 edca_setting_dl[PEER_MAX] = { 158 0xa44f, /* 0 UNKNOWN */ 159 0x5ea44f, /* 1 REALTEK_90 */ 160 0x5e4322, /* 2 REALTEK_92SE */ 161 0x5ea42b, /* 3 BROAD */ 162 0xa44f, /* 4 RAL */ 163 0xa630, /* 5 ATH */ 164 0x5ea630, /* 6 CISCO */ 165 0x5ea42b, /* 7 MARVELL */ 166 }; 167 168 static const u32 edca_setting_ul[PEER_MAX] = { 169 0x5e4322, /* 0 UNKNOWN */ 170 0xa44f, /* 1 REALTEK_90 */ 171 0x5ea44f, /* 2 REALTEK_92SE */ 172 0x5ea32b, /* 3 BROAD */ 173 0x5ea422, /* 4 RAL */ 174 0x5ea322, /* 5 ATH */ 175 0x3ea430, /* 6 CISCO */ 176 0x5ea44f, /* 7 MARV */ 177 }; 178 179 void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type, 180 u8 *pdirection, u32 *poutwrite_val) 181 { 182 struct rtl_priv *rtlpriv = rtl_priv(hw); 183 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 184 u8 pwr_val = 0; 185 u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]; 186 u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A]; 187 u8 cck_base = rtldm->swing_idx_cck_base; 188 u8 cck_val = rtldm->swing_idx_cck; 189 190 if (type == 0) { 191 if (ofdm_val <= ofdm_base) { 192 *pdirection = 1; 193 pwr_val = ofdm_base - ofdm_val; 194 } else { 195 *pdirection = 2; 196 pwr_val = ofdm_val - ofdm_base; 197 } 198 } else if (type == 1) { 199 if (cck_val <= cck_base) { 200 *pdirection = 1; 201 pwr_val = cck_base - cck_val; 202 } else { 203 *pdirection = 2; 204 pwr_val = cck_val - cck_base; 205 } 206 } 207 208 if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1)) 209 pwr_val = TXPWRTRACK_MAX_IDX; 210 211 *poutwrite_val = pwr_val | (pwr_val << 8) | 212 (pwr_val << 16) | (pwr_val << 24); 213 } 214 215 void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) 216 { 217 struct rtl_priv *rtlpriv = rtl_priv(hw); 218 struct rate_adaptive *p_ra = &rtlpriv->ra; 219 220 p_ra->ratr_state = DM_RATR_STA_INIT; 221 p_ra->pre_ratr_state = DM_RATR_STA_INIT; 222 223 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) 224 rtlpriv->dm.useramask = true; 225 else 226 rtlpriv->dm.useramask = false; 227 228 p_ra->high_rssi_thresh_for_ra = 50; 229 p_ra->low_rssi_thresh_for_ra40m = 20; 230 } 231 232 static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw) 233 { 234 struct rtl_priv *rtlpriv = rtl_priv(hw); 235 236 rtlpriv->dm.txpower_tracking = true; 237 rtlpriv->dm.txpower_track_control = true; 238 rtlpriv->dm.thermalvalue = 0; 239 240 rtlpriv->dm.ofdm_index[0] = 30; 241 rtlpriv->dm.cck_index = 20; 242 243 rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index; 244 245 rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0]; 246 rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0; 247 rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0; 248 rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0; 249 250 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 251 " rtlpriv->dm.txpower_tracking = %d\n", 252 rtlpriv->dm.txpower_tracking); 253 } 254 255 static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw) 256 { 257 struct rtl_priv *rtlpriv = rtl_priv(hw); 258 259 rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap; 260 261 rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800); 262 rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL; 263 } 264 265 void rtl8723be_dm_init(struct ieee80211_hw *hw) 266 { 267 struct rtl_priv *rtlpriv = rtl_priv(hw); 268 u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f); 269 270 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; 271 rtl_dm_diginit(hw, cur_igvalue); 272 rtl8723be_dm_init_rate_adaptive_mask(hw); 273 rtl8723_dm_init_edca_turbo(hw); 274 rtl8723_dm_init_dynamic_bb_powersaving(hw); 275 rtl8723_dm_init_dynamic_txpower(hw); 276 rtl8723be_dm_init_txpower_tracking(hw); 277 rtl8723be_dm_init_dynamic_atc_switch(hw); 278 } 279 280 static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw) 281 { 282 struct rtl_priv *rtlpriv = rtl_priv(hw); 283 struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable; 284 struct rtl_mac *mac = rtl_mac(rtlpriv); 285 286 /* Determine the minimum RSSI */ 287 if ((mac->link_state < MAC80211_LINKED) && 288 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { 289 rtl_dm_dig->min_undec_pwdb_for_dm = 0; 290 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, 291 "Not connected to any\n"); 292 } 293 if (mac->link_state >= MAC80211_LINKED) { 294 if (mac->opmode == NL80211_IFTYPE_AP || 295 mac->opmode == NL80211_IFTYPE_ADHOC) { 296 rtl_dm_dig->min_undec_pwdb_for_dm = 297 rtlpriv->dm.entry_min_undec_sm_pwdb; 298 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, 299 "AP Client PWDB = 0x%lx\n", 300 rtlpriv->dm.entry_min_undec_sm_pwdb); 301 } else { 302 rtl_dm_dig->min_undec_pwdb_for_dm = 303 rtlpriv->dm.undec_sm_pwdb; 304 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, 305 "STA Default Port PWDB = 0x%x\n", 306 rtl_dm_dig->min_undec_pwdb_for_dm); 307 } 308 } else { 309 rtl_dm_dig->min_undec_pwdb_for_dm = 310 rtlpriv->dm.entry_min_undec_sm_pwdb; 311 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, 312 "AP Ext Port or disconnect PWDB = 0x%x\n", 313 rtl_dm_dig->min_undec_pwdb_for_dm); 314 } 315 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n", 316 rtl_dm_dig->min_undec_pwdb_for_dm); 317 } 318 319 static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw) 320 { 321 struct rtl_priv *rtlpriv = rtl_priv(hw); 322 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 323 struct rtl_sta_info *drv_priv; 324 u8 h2c_parameter[3] = { 0 }; 325 long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff; 326 327 /* AP & ADHOC & MESH */ 328 spin_lock_bh(&rtlpriv->locks.entry_list_lock); 329 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { 330 if (drv_priv->rssi_stat.undec_sm_pwdb < 331 tmp_entry_min_pwdb) 332 tmp_entry_min_pwdb = 333 drv_priv->rssi_stat.undec_sm_pwdb; 334 if (drv_priv->rssi_stat.undec_sm_pwdb > 335 tmp_entry_max_pwdb) 336 tmp_entry_max_pwdb = 337 drv_priv->rssi_stat.undec_sm_pwdb; 338 } 339 spin_unlock_bh(&rtlpriv->locks.entry_list_lock); 340 341 /* If associated entry is found */ 342 if (tmp_entry_max_pwdb != 0) { 343 rtlpriv->dm.entry_max_undec_sm_pwdb = 344 tmp_entry_max_pwdb; 345 RTPRINT(rtlpriv, FDM, DM_PWDB, 346 "EntryMaxPWDB = 0x%lx(%ld)\n", 347 tmp_entry_max_pwdb, tmp_entry_max_pwdb); 348 } else { 349 rtlpriv->dm.entry_max_undec_sm_pwdb = 0; 350 } 351 /* If associated entry is found */ 352 if (tmp_entry_min_pwdb != 0xff) { 353 rtlpriv->dm.entry_min_undec_sm_pwdb = 354 tmp_entry_min_pwdb; 355 RTPRINT(rtlpriv, FDM, DM_PWDB, 356 "EntryMinPWDB = 0x%lx(%ld)\n", 357 tmp_entry_min_pwdb, tmp_entry_min_pwdb); 358 } else { 359 rtlpriv->dm.entry_min_undec_sm_pwdb = 0; 360 } 361 /* Indicate Rx signal strength to FW. */ 362 if (rtlpriv->dm.useramask) { 363 h2c_parameter[2] = 364 (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF); 365 h2c_parameter[1] = 0x20; 366 h2c_parameter[0] = 0; 367 rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter); 368 } else { 369 rtl_write_byte(rtlpriv, 0x4fe, 370 rtlpriv->dm.undec_sm_pwdb); 371 } 372 rtl8723be_dm_find_minimum_rssi(hw); 373 dm_digtable->rssi_val_min = 374 rtlpriv->dm_digtable.min_undec_pwdb_for_dm; 375 } 376 377 void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi) 378 { 379 struct rtl_priv *rtlpriv = rtl_priv(hw); 380 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 381 382 if (dm_digtable->stop_dig) 383 return; 384 385 if (dm_digtable->cur_igvalue != current_igi) { 386 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi); 387 if (rtlpriv->phy.rf_type != RF_1T1R) 388 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 389 0x7f, current_igi); 390 } 391 dm_digtable->pre_igvalue = dm_digtable->cur_igvalue; 392 dm_digtable->cur_igvalue = current_igi; 393 } 394 395 static void rtl8723be_dm_dig(struct ieee80211_hw *hw) 396 { 397 struct rtl_priv *rtlpriv = rtl_priv(hw); 398 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 399 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 400 u8 dig_min_0, dig_maxofmin; 401 bool bfirstconnect, bfirstdisconnect; 402 u8 dm_dig_max, dm_dig_min; 403 u8 current_igi = dm_digtable->cur_igvalue; 404 u8 offset; 405 406 /* AP,BT */ 407 if (mac->act_scanning) 408 return; 409 410 dig_min_0 = dm_digtable->dig_min_0; 411 bfirstconnect = (mac->link_state >= MAC80211_LINKED) && 412 !dm_digtable->media_connect_0; 413 bfirstdisconnect = (mac->link_state < MAC80211_LINKED) && 414 (dm_digtable->media_connect_0); 415 416 dm_dig_max = 0x5a; 417 dm_dig_min = DM_DIG_MIN; 418 dig_maxofmin = DM_DIG_MAX_AP; 419 420 if (mac->link_state >= MAC80211_LINKED) { 421 if ((dm_digtable->rssi_val_min + 10) > dm_dig_max) 422 dm_digtable->rx_gain_max = dm_dig_max; 423 else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min) 424 dm_digtable->rx_gain_max = dm_dig_min; 425 else 426 dm_digtable->rx_gain_max = 427 dm_digtable->rssi_val_min + 10; 428 429 if (rtlpriv->dm.one_entry_only) { 430 offset = 12; 431 if (dm_digtable->rssi_val_min - offset < dm_dig_min) 432 dig_min_0 = dm_dig_min; 433 else if (dm_digtable->rssi_val_min - offset > 434 dig_maxofmin) 435 dig_min_0 = dig_maxofmin; 436 else 437 dig_min_0 = 438 dm_digtable->rssi_val_min - offset; 439 } else { 440 dig_min_0 = dm_dig_min; 441 } 442 443 } else { 444 dm_digtable->rx_gain_max = dm_dig_max; 445 dig_min_0 = dm_dig_min; 446 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n"); 447 } 448 449 if (rtlpriv->falsealm_cnt.cnt_all > 10000) { 450 if (dm_digtable->large_fa_hit != 3) 451 dm_digtable->large_fa_hit++; 452 if (dm_digtable->forbidden_igi < current_igi) { 453 dm_digtable->forbidden_igi = current_igi; 454 dm_digtable->large_fa_hit = 1; 455 } 456 457 if (dm_digtable->large_fa_hit >= 3) { 458 if ((dm_digtable->forbidden_igi + 1) > 459 dm_digtable->rx_gain_max) 460 dm_digtable->rx_gain_min = 461 dm_digtable->rx_gain_max; 462 else 463 dm_digtable->rx_gain_min = 464 dm_digtable->forbidden_igi + 1; 465 dm_digtable->recover_cnt = 3600; 466 } 467 } else { 468 if (dm_digtable->recover_cnt != 0) { 469 dm_digtable->recover_cnt--; 470 } else { 471 if (dm_digtable->large_fa_hit < 3) { 472 if ((dm_digtable->forbidden_igi - 1) < 473 dig_min_0) { 474 dm_digtable->forbidden_igi = 475 dig_min_0; 476 dm_digtable->rx_gain_min = 477 dig_min_0; 478 } else { 479 dm_digtable->forbidden_igi--; 480 dm_digtable->rx_gain_min = 481 dm_digtable->forbidden_igi + 1; 482 } 483 } else { 484 dm_digtable->large_fa_hit = 0; 485 } 486 } 487 } 488 if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max) 489 dm_digtable->rx_gain_min = dm_digtable->rx_gain_max; 490 491 if (mac->link_state >= MAC80211_LINKED) { 492 if (bfirstconnect) { 493 if (dm_digtable->rssi_val_min <= dig_maxofmin) 494 current_igi = dm_digtable->rssi_val_min; 495 else 496 current_igi = dig_maxofmin; 497 498 dm_digtable->large_fa_hit = 0; 499 } else { 500 if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2) 501 current_igi += 4; 502 else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1) 503 current_igi += 2; 504 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0) 505 current_igi -= 2; 506 } 507 } else { 508 if (bfirstdisconnect) { 509 current_igi = dm_digtable->rx_gain_min; 510 } else { 511 if (rtlpriv->falsealm_cnt.cnt_all > 10000) 512 current_igi += 4; 513 else if (rtlpriv->falsealm_cnt.cnt_all > 8000) 514 current_igi += 2; 515 else if (rtlpriv->falsealm_cnt.cnt_all < 500) 516 current_igi -= 2; 517 } 518 } 519 520 if (current_igi > dm_digtable->rx_gain_max) 521 current_igi = dm_digtable->rx_gain_max; 522 else if (current_igi < dm_digtable->rx_gain_min) 523 current_igi = dm_digtable->rx_gain_min; 524 525 rtl8723be_dm_write_dig(hw, current_igi); 526 dm_digtable->media_connect_0 = 527 ((mac->link_state >= MAC80211_LINKED) ? true : false); 528 dm_digtable->dig_min_0 = dig_min_0; 529 } 530 531 static void rtl8723be_dm_false_alarm_counter_statistics( 532 struct ieee80211_hw *hw) 533 { 534 u32 ret_value; 535 struct rtl_priv *rtlpriv = rtl_priv(hw); 536 struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt; 537 538 rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1); 539 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1); 540 541 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD); 542 falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff; 543 falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16; 544 545 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD); 546 falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff; 547 falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16; 548 549 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD); 550 falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff; 551 falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16; 552 553 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD); 554 falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff; 555 556 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + 557 falsealm_cnt->cnt_rate_illegal + 558 falsealm_cnt->cnt_crc8_fail + 559 falsealm_cnt->cnt_mcs_fail + 560 falsealm_cnt->cnt_fast_fsync_fail + 561 falsealm_cnt->cnt_sb_search_fail; 562 563 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1); 564 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1); 565 566 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0); 567 falsealm_cnt->cnt_cck_fail = ret_value; 568 569 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3); 570 falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8; 571 572 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD); 573 falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) | 574 ((ret_value & 0xff00) >> 8); 575 576 falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail + 577 falsealm_cnt->cnt_sb_search_fail + 578 falsealm_cnt->cnt_parity_fail + 579 falsealm_cnt->cnt_rate_illegal + 580 falsealm_cnt->cnt_crc8_fail + 581 falsealm_cnt->cnt_mcs_fail + 582 falsealm_cnt->cnt_cck_fail; 583 584 falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca + 585 falsealm_cnt->cnt_cck_cca; 586 587 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1); 588 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0); 589 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1); 590 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0); 591 592 rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0); 593 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0); 594 595 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0); 596 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2); 597 598 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0); 599 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2); 600 601 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, 602 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n", 603 falsealm_cnt->cnt_parity_fail, 604 falsealm_cnt->cnt_rate_illegal, 605 falsealm_cnt->cnt_crc8_fail, 606 falsealm_cnt->cnt_mcs_fail); 607 608 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, 609 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n", 610 falsealm_cnt->cnt_ofdm_fail, 611 falsealm_cnt->cnt_cck_fail, 612 falsealm_cnt->cnt_all); 613 } 614 615 static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw) 616 { 617 /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/ 618 return; 619 } 620 621 static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index, 622 u8 rfpath, long iqk_result_x, 623 long iqk_result_y) 624 { 625 long ele_a = 0, ele_d, ele_c = 0, value32; 626 627 if (ofdm_index >= 43) 628 ofdm_index = 43 - 1; 629 630 ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22; 631 632 if (iqk_result_x != 0) { 633 if ((iqk_result_x & 0x00000200) != 0) 634 iqk_result_x = iqk_result_x | 0xFFFFFC00; 635 ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF; 636 637 if ((iqk_result_y & 0x00000200) != 0) 638 iqk_result_y = iqk_result_y | 0xFFFFFC00; 639 ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF; 640 641 switch (rfpath) { 642 case RF90_PATH_A: 643 value32 = (ele_d << 22) | 644 ((ele_c & 0x3F) << 16) | ele_a; 645 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, 646 value32); 647 value32 = (ele_c & 0x000003C0) >> 6; 648 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32); 649 value32 = ((iqk_result_x * ele_d) >> 7) & 0x01; 650 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 651 value32); 652 break; 653 default: 654 break; 655 } 656 } else { 657 switch (rfpath) { 658 case RF90_PATH_A: 659 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD, 660 ofdmswing_table[ofdm_index]); 661 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00); 662 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00); 663 break; 664 default: 665 break; 666 } 667 } 668 } 669 670 static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw, 671 enum pwr_track_control_method method, 672 u8 rfpath, u8 idx) 673 { 674 struct rtl_priv *rtlpriv = rtl_priv(hw); 675 struct rtl_phy *rtlphy = &rtlpriv->phy; 676 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 677 u8 swing_idx_ofdm_limit = 36; 678 679 if (method == TXAGC) { 680 rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel); 681 } else if (method == BBSWING) { 682 if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE) 683 rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1; 684 685 if (!rtldm->cck_inch14) { 686 rtl_write_byte(rtlpriv, 0xa22, 687 cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]); 688 rtl_write_byte(rtlpriv, 0xa23, 689 cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]); 690 rtl_write_byte(rtlpriv, 0xa24, 691 cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]); 692 rtl_write_byte(rtlpriv, 0xa25, 693 cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]); 694 rtl_write_byte(rtlpriv, 0xa26, 695 cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]); 696 rtl_write_byte(rtlpriv, 0xa27, 697 cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]); 698 rtl_write_byte(rtlpriv, 0xa28, 699 cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]); 700 rtl_write_byte(rtlpriv, 0xa29, 701 cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]); 702 } else { 703 rtl_write_byte(rtlpriv, 0xa22, 704 cckswing_table_ch14[rtldm->swing_idx_cck][0]); 705 rtl_write_byte(rtlpriv, 0xa23, 706 cckswing_table_ch14[rtldm->swing_idx_cck][1]); 707 rtl_write_byte(rtlpriv, 0xa24, 708 cckswing_table_ch14[rtldm->swing_idx_cck][2]); 709 rtl_write_byte(rtlpriv, 0xa25, 710 cckswing_table_ch14[rtldm->swing_idx_cck][3]); 711 rtl_write_byte(rtlpriv, 0xa26, 712 cckswing_table_ch14[rtldm->swing_idx_cck][4]); 713 rtl_write_byte(rtlpriv, 0xa27, 714 cckswing_table_ch14[rtldm->swing_idx_cck][5]); 715 rtl_write_byte(rtlpriv, 0xa28, 716 cckswing_table_ch14[rtldm->swing_idx_cck][6]); 717 rtl_write_byte(rtlpriv, 0xa29, 718 cckswing_table_ch14[rtldm->swing_idx_cck][7]); 719 } 720 721 if (rfpath == RF90_PATH_A) { 722 if (rtldm->swing_idx_ofdm[RF90_PATH_A] < 723 swing_idx_ofdm_limit) 724 swing_idx_ofdm_limit = 725 rtldm->swing_idx_ofdm[RF90_PATH_A]; 726 727 rtl8723be_set_iqk_matrix(hw, 728 rtldm->swing_idx_ofdm[rfpath], rfpath, 729 rtlphy->iqk_matrix[idx].value[0][0], 730 rtlphy->iqk_matrix[idx].value[0][1]); 731 } else if (rfpath == RF90_PATH_B) { 732 if (rtldm->swing_idx_ofdm[RF90_PATH_B] < 733 swing_idx_ofdm_limit) 734 swing_idx_ofdm_limit = 735 rtldm->swing_idx_ofdm[RF90_PATH_B]; 736 737 rtl8723be_set_iqk_matrix(hw, 738 rtldm->swing_idx_ofdm[rfpath], rfpath, 739 rtlphy->iqk_matrix[idx].value[0][4], 740 rtlphy->iqk_matrix[idx].value[0][5]); 741 } 742 } else { 743 return; 744 } 745 } 746 747 static void rtl8723be_dm_txpower_tracking_callback_thermalmeter( 748 struct ieee80211_hw *hw) 749 { 750 struct rtl_priv *rtlpriv = rtl_priv(hw); 751 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); 752 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 753 u8 thermalvalue = 0, delta, delta_lck, delta_iqk; 754 u8 thermalvalue_avg_count = 0; 755 u32 thermalvalue_avg = 0; 756 int i = 0; 757 758 u8 ofdm_min_index = 6; 759 u8 index_for_channel = 0; 760 761 s8 delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = { 762 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 763 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10, 764 10, 11, 11, 12, 12, 13, 14, 15}; 765 s8 delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = { 766 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5, 767 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9, 768 9, 10, 10, 11, 12, 13, 14, 15}; 769 770 /*Initilization ( 7 steps in total )*/ 771 rtlpriv->dm.txpower_trackinginit = true; 772 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 773 "rtl8723be_dm_txpower_tracking_callback_thermalmeter\n"); 774 775 thermalvalue = (u8)rtl_get_rfreg(hw, 776 RF90_PATH_A, RF_T_METER, 0xfc00); 777 if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 || 778 rtlefuse->eeprom_thermalmeter == 0xFF) 779 return; 780 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 781 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n", 782 thermalvalue, rtldm->thermalvalue, 783 rtlefuse->eeprom_thermalmeter); 784 /*3 Initialize ThermalValues of RFCalibrateInfo*/ 785 if (!rtldm->thermalvalue) { 786 rtlpriv->dm.thermalvalue_lck = thermalvalue; 787 rtlpriv->dm.thermalvalue_iqk = thermalvalue; 788 } 789 790 /*4 Calculate average thermal meter*/ 791 rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue; 792 rtldm->thermalvalue_avg_index++; 793 if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE) 794 rtldm->thermalvalue_avg_index = 0; 795 796 for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) { 797 if (rtldm->thermalvalue_avg[i]) { 798 thermalvalue_avg += rtldm->thermalvalue_avg[i]; 799 thermalvalue_avg_count++; 800 } 801 } 802 803 if (thermalvalue_avg_count) 804 thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count); 805 806 /* 5 Calculate delta, delta_LCK, delta_IQK.*/ 807 delta = (thermalvalue > rtlpriv->dm.thermalvalue) ? 808 (thermalvalue - rtlpriv->dm.thermalvalue) : 809 (rtlpriv->dm.thermalvalue - thermalvalue); 810 delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ? 811 (thermalvalue - rtlpriv->dm.thermalvalue_lck) : 812 (rtlpriv->dm.thermalvalue_lck - thermalvalue); 813 delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ? 814 (thermalvalue - rtlpriv->dm.thermalvalue_iqk) : 815 (rtlpriv->dm.thermalvalue_iqk - thermalvalue); 816 817 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 818 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x delta 0x%x delta_lck 0x%x delta_iqk 0x%x\n", 819 thermalvalue, rtlpriv->dm.thermalvalue, 820 rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk); 821 /* 6 If necessary, do LCK.*/ 822 if (delta_lck >= IQK_THRESHOLD) { 823 rtlpriv->dm.thermalvalue_lck = thermalvalue; 824 rtl8723be_phy_lc_calibrate(hw); 825 } 826 827 /* 7 If necessary, move the index of 828 * swing table to adjust Tx power. 829 */ 830 if (delta > 0 && rtlpriv->dm.txpower_track_control) { 831 delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ? 832 (thermalvalue - rtlefuse->eeprom_thermalmeter) : 833 (rtlefuse->eeprom_thermalmeter - thermalvalue); 834 835 if (delta >= TXSCALE_TABLE_SIZE) 836 delta = TXSCALE_TABLE_SIZE - 1; 837 /* 7.1 Get the final CCK_index and 838 * OFDM_index for each swing table. 839 */ 840 if (thermalvalue > rtlefuse->eeprom_thermalmeter) { 841 rtldm->delta_power_index_last[RF90_PATH_A] = 842 rtldm->delta_power_index[RF90_PATH_A]; 843 rtldm->delta_power_index[RF90_PATH_A] = 844 delta_swing_table_idx_tup_a[delta]; 845 } else { 846 rtldm->delta_power_index_last[RF90_PATH_A] = 847 rtldm->delta_power_index[RF90_PATH_A]; 848 rtldm->delta_power_index[RF90_PATH_A] = 849 -1 * delta_swing_table_idx_tdown_a[delta]; 850 } 851 852 /* 7.2 Handle boundary conditions of index.*/ 853 if (rtldm->delta_power_index[RF90_PATH_A] == 854 rtldm->delta_power_index_last[RF90_PATH_A]) 855 rtldm->power_index_offset[RF90_PATH_A] = 0; 856 else 857 rtldm->power_index_offset[RF90_PATH_A] = 858 rtldm->delta_power_index[RF90_PATH_A] - 859 rtldm->delta_power_index_last[RF90_PATH_A]; 860 861 rtldm->ofdm_index[0] = 862 rtldm->swing_idx_ofdm_base[RF90_PATH_A] + 863 rtldm->power_index_offset[RF90_PATH_A]; 864 rtldm->cck_index = rtldm->swing_idx_cck_base + 865 rtldm->power_index_offset[RF90_PATH_A]; 866 867 rtldm->swing_idx_cck = rtldm->cck_index; 868 rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0]; 869 870 if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1) 871 rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1; 872 else if (rtldm->ofdm_index[0] < ofdm_min_index) 873 rtldm->ofdm_index[0] = ofdm_min_index; 874 875 if (rtldm->cck_index > CCK_TABLE_SIZE - 1) 876 rtldm->cck_index = CCK_TABLE_SIZE - 1; 877 else if (rtldm->cck_index < 0) 878 rtldm->cck_index = 0; 879 } else { 880 rtldm->power_index_offset[RF90_PATH_A] = 0; 881 } 882 883 if ((rtldm->power_index_offset[RF90_PATH_A] != 0) && 884 (rtldm->txpower_track_control)) { 885 rtldm->done_txpower = true; 886 rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0, 887 index_for_channel); 888 889 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck; 890 rtldm->swing_idx_ofdm_base[RF90_PATH_A] = 891 rtldm->swing_idx_ofdm[0]; 892 rtldm->thermalvalue = thermalvalue; 893 } 894 895 if (delta_iqk >= IQK_THRESHOLD) { 896 rtldm->thermalvalue_iqk = thermalvalue; 897 rtl8723be_phy_iq_calibrate(hw, false); 898 } 899 900 rtldm->txpowercount = 0; 901 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n"); 902 903 } 904 905 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw) 906 { 907 struct rtl_priv *rtlpriv = rtl_priv(hw); 908 909 if (!rtlpriv->dm.txpower_tracking) 910 return; 911 912 if (!rtlpriv->dm.tm_trigger) { 913 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16), 914 0x03); 915 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 916 "Trigger 8723be Thermal Meter!!\n"); 917 rtlpriv->dm.tm_trigger = 1; 918 return; 919 } else { 920 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, 921 "Schedule TxPowerTracking !!\n"); 922 rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw); 923 rtlpriv->dm.tm_trigger = 0; 924 } 925 } 926 927 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) 928 { 929 struct rtl_priv *rtlpriv = rtl_priv(hw); 930 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 931 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 932 struct rate_adaptive *p_ra = &rtlpriv->ra; 933 u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m; 934 u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra; 935 u8 go_up_gap = 5; 936 struct ieee80211_sta *sta = NULL; 937 938 if (is_hal_stop(rtlhal)) { 939 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 940 "driver is going to unload\n"); 941 return; 942 } 943 944 if (!rtlpriv->dm.useramask) { 945 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 946 "driver does not control rate adaptive mask\n"); 947 return; 948 } 949 950 if (mac->link_state == MAC80211_LINKED && 951 mac->opmode == NL80211_IFTYPE_STATION) { 952 switch (p_ra->pre_ratr_state) { 953 case DM_RATR_STA_MIDDLE: 954 high_rssithresh_for_ra += go_up_gap; 955 break; 956 case DM_RATR_STA_LOW: 957 high_rssithresh_for_ra += go_up_gap; 958 low_rssithresh_for_ra += go_up_gap; 959 break; 960 default: 961 break; 962 } 963 964 if (rtlpriv->dm.undec_sm_pwdb > 965 (long)high_rssithresh_for_ra) 966 p_ra->ratr_state = DM_RATR_STA_HIGH; 967 else if (rtlpriv->dm.undec_sm_pwdb > 968 (long)low_rssithresh_for_ra) 969 p_ra->ratr_state = DM_RATR_STA_MIDDLE; 970 else 971 p_ra->ratr_state = DM_RATR_STA_LOW; 972 973 if (p_ra->pre_ratr_state != p_ra->ratr_state) { 974 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 975 "RSSI = %ld\n", 976 rtlpriv->dm.undec_sm_pwdb); 977 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 978 "RSSI_LEVEL = %d\n", p_ra->ratr_state); 979 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, 980 "PreState = %d, CurState = %d\n", 981 p_ra->pre_ratr_state, p_ra->ratr_state); 982 983 rcu_read_lock(); 984 sta = rtl_find_sta(hw, mac->bssid); 985 if (sta) 986 rtlpriv->cfg->ops->update_rate_tbl(hw, sta, 987 p_ra->ratr_state, 988 true); 989 rcu_read_unlock(); 990 991 p_ra->pre_ratr_state = p_ra->ratr_state; 992 } 993 } 994 } 995 996 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw) 997 { 998 struct rtl_priv *rtlpriv = rtl_priv(hw); 999 1000 if (rtlpriv->mac80211.mode == WIRELESS_MODE_B) 1001 return true; 1002 1003 return false; 1004 } 1005 1006 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw) 1007 { 1008 struct rtl_priv *rtlpriv = rtl_priv(hw); 1009 struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); 1010 1011 static u64 last_txok_cnt; 1012 static u64 last_rxok_cnt; 1013 u64 cur_txok_cnt = 0; 1014 u64 cur_rxok_cnt = 0; 1015 u32 edca_be_ul = 0x6ea42b; 1016 u32 edca_be_dl = 0x6ea42b;/*not sure*/ 1017 u32 edca_be = 0x5ea42b; 1018 u32 iot_peer = 0; 1019 bool b_is_cur_rdlstate; 1020 bool b_last_is_cur_rdlstate = false; 1021 bool b_bias_on_rx = false; 1022 bool b_edca_turbo_on = false; 1023 1024 b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate; 1025 1026 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; 1027 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; 1028 1029 iot_peer = rtlpriv->mac80211.vendor; 1030 b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ? 1031 true : false; 1032 b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) && 1033 (!rtlpriv->dm.disable_framebursting)) ? 1034 true : false; 1035 1036 if ((iot_peer == PEER_CISCO) && 1037 (mac->mode == WIRELESS_MODE_N_24G)) { 1038 edca_be_dl = edca_setting_dl[iot_peer]; 1039 edca_be_ul = edca_setting_ul[iot_peer]; 1040 } 1041 if (rtl8723be_dm_is_edca_turbo_disable(hw)) 1042 goto exit; 1043 1044 if (b_edca_turbo_on) { 1045 if (b_bias_on_rx) 1046 b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ? 1047 false : true; 1048 else 1049 b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ? 1050 true : false; 1051 1052 edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul; 1053 rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be); 1054 rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate; 1055 rtlpriv->dm.current_turbo_edca = true; 1056 } else { 1057 if (rtlpriv->dm.current_turbo_edca) { 1058 u8 tmp = AC0_BE; 1059 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, 1060 (u8 *)(&tmp)); 1061 } 1062 rtlpriv->dm.current_turbo_edca = false; 1063 } 1064 1065 exit: 1066 rtlpriv->dm.is_any_nonbepkts = false; 1067 last_txok_cnt = rtlpriv->stats.txbytesunicast; 1068 last_rxok_cnt = rtlpriv->stats.rxbytesunicast; 1069 } 1070 1071 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) 1072 { 1073 struct rtl_priv *rtlpriv = rtl_priv(hw); 1074 struct dig_t *dm_digtable = &rtlpriv->dm_digtable; 1075 u8 cur_cck_cca_thresh; 1076 1077 if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) { 1078 if (dm_digtable->rssi_val_min > 25) { 1079 cur_cck_cca_thresh = 0xcd; 1080 } else if ((dm_digtable->rssi_val_min <= 25) && 1081 (dm_digtable->rssi_val_min > 10)) { 1082 cur_cck_cca_thresh = 0x83; 1083 } else { 1084 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) 1085 cur_cck_cca_thresh = 0x83; 1086 else 1087 cur_cck_cca_thresh = 0x40; 1088 } 1089 } else { 1090 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000) 1091 cur_cck_cca_thresh = 0x83; 1092 else 1093 cur_cck_cca_thresh = 0x40; 1094 } 1095 1096 if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh) 1097 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh); 1098 1099 dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres; 1100 dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh; 1101 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, 1102 "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres); 1103 } 1104 1105 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw) 1106 { 1107 struct rtl_priv *rtlpriv = rtl_priv(hw); 1108 u8 reg_c50, reg_c58; 1109 bool fw_current_in_ps_mode = false; 1110 1111 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, 1112 (u8 *)(&fw_current_in_ps_mode)); 1113 if (fw_current_in_ps_mode) 1114 return; 1115 1116 reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0); 1117 reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0); 1118 1119 if (reg_c50 > 0x28 && reg_c58 > 0x28) { 1120 if (!rtlpriv->rtlhal.pre_edcca_enable) { 1121 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03); 1122 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00); 1123 } 1124 } else if (reg_c50 < 0x25 && reg_c58 < 0x25) { 1125 if (rtlpriv->rtlhal.pre_edcca_enable) { 1126 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f); 1127 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f); 1128 } 1129 } 1130 } 1131 1132 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw) 1133 { 1134 struct rtl_priv *rtlpriv = rtl_priv(hw); 1135 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw)); 1136 u8 crystal_cap; 1137 u32 packet_count; 1138 int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0; 1139 int cfo_ave_diff; 1140 1141 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) { 1142 if (rtldm->atc_status == ATC_STATUS_OFF) { 1143 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), 1144 ATC_STATUS_ON); 1145 rtldm->atc_status = ATC_STATUS_ON; 1146 } 1147 if (rtlpriv->cfg->ops->get_btc_status()) { 1148 if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) { 1149 RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD, 1150 "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n"); 1151 return; 1152 } 1153 } 1154 1155 if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) { 1156 rtldm->crystal_cap = rtlpriv->efuse.crystalcap; 1157 crystal_cap = rtldm->crystal_cap & 0x3f; 1158 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, 1159 (crystal_cap | (crystal_cap << 6))); 1160 } 1161 } else { 1162 cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280; 1163 cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280; 1164 packet_count = rtldm->packet_count; 1165 1166 if (packet_count == rtldm->packet_count_pre) 1167 return; 1168 1169 rtldm->packet_count_pre = packet_count; 1170 1171 if (rtlpriv->phy.rf_type == RF_1T1R) 1172 cfo_ave = cfo_khz_a; 1173 else 1174 cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1; 1175 1176 cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ? 1177 (rtldm->cfo_ave_pre - cfo_ave) : 1178 (cfo_ave - rtldm->cfo_ave_pre); 1179 1180 if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) { 1181 rtldm->large_cfo_hit = 1; 1182 return; 1183 } else 1184 rtldm->large_cfo_hit = 0; 1185 1186 rtldm->cfo_ave_pre = cfo_ave; 1187 1188 if (cfo_ave >= -rtldm->cfo_threshold && 1189 cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) { 1190 if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) { 1191 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10; 1192 rtldm->is_freeze = 1; 1193 } else { 1194 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL; 1195 } 1196 } 1197 1198 if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f) 1199 adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1; 1200 else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) && 1201 rtlpriv->dm.crystal_cap > 0) 1202 adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1; 1203 1204 if (adjust_xtal != 0) { 1205 rtldm->is_freeze = 0; 1206 rtldm->crystal_cap += adjust_xtal; 1207 1208 if (rtldm->crystal_cap > 0x3f) 1209 rtldm->crystal_cap = 0x3f; 1210 else if (rtldm->crystal_cap < 0) 1211 rtldm->crystal_cap = 0; 1212 1213 crystal_cap = rtldm->crystal_cap & 0x3f; 1214 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000, 1215 (crystal_cap | (crystal_cap << 6))); 1216 } 1217 1218 if (cfo_ave < CFO_THRESHOLD_ATC && 1219 cfo_ave > -CFO_THRESHOLD_ATC) { 1220 if (rtldm->atc_status == ATC_STATUS_ON) { 1221 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), 1222 ATC_STATUS_OFF); 1223 rtldm->atc_status = ATC_STATUS_OFF; 1224 } 1225 } else { 1226 if (rtldm->atc_status == ATC_STATUS_OFF) { 1227 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11), 1228 ATC_STATUS_ON); 1229 rtldm->atc_status = ATC_STATUS_ON; 1230 } 1231 } 1232 } 1233 } 1234 1235 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw) 1236 { 1237 struct rtl_priv *rtlpriv = rtl_priv(hw); 1238 u8 cnt = 0; 1239 struct rtl_sta_info *drv_priv; 1240 1241 rtlpriv->dm.one_entry_only = false; 1242 1243 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION && 1244 rtlpriv->mac80211.link_state >= MAC80211_LINKED) { 1245 rtlpriv->dm.one_entry_only = true; 1246 return; 1247 } 1248 1249 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP || 1250 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC || 1251 rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) { 1252 spin_lock_bh(&rtlpriv->locks.entry_list_lock); 1253 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) { 1254 cnt++; 1255 } 1256 spin_unlock_bh(&rtlpriv->locks.entry_list_lock); 1257 1258 if (cnt == 1) 1259 rtlpriv->dm.one_entry_only = true; 1260 } 1261 } 1262 1263 void rtl8723be_dm_watchdog(struct ieee80211_hw *hw) 1264 { 1265 struct rtl_priv *rtlpriv = rtl_priv(hw); 1266 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 1267 bool fw_current_inpsmode = false; 1268 bool fw_ps_awake = true; 1269 1270 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS, 1271 (u8 *)(&fw_current_inpsmode)); 1272 1273 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON, 1274 (u8 *)(&fw_ps_awake)); 1275 1276 if (ppsc->p2p_ps_info.p2p_ps_mode) 1277 fw_ps_awake = false; 1278 1279 spin_lock(&rtlpriv->locks.rf_ps_lock); 1280 if ((ppsc->rfpwr_state == ERFON) && 1281 ((!fw_current_inpsmode) && fw_ps_awake) && 1282 (!ppsc->rfchange_inprogress)) { 1283 rtl8723be_dm_common_info_self_update(hw); 1284 rtl8723be_dm_false_alarm_counter_statistics(hw); 1285 rtl8723be_dm_check_rssi_monitor(hw); 1286 rtl8723be_dm_dig(hw); 1287 rtl8723be_dm_dynamic_edcca(hw); 1288 rtl8723be_dm_cck_packet_detection_thresh(hw); 1289 rtl8723be_dm_refresh_rate_adaptive_mask(hw); 1290 rtl8723be_dm_check_edca_turbo(hw); 1291 rtl8723be_dm_dynamic_atc_switch(hw); 1292 rtl8723be_dm_check_txpower_tracking(hw); 1293 rtl8723be_dm_dynamic_txpower(hw); 1294 } 1295 spin_unlock(&rtlpriv->locks.rf_ps_lock); 1296 rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0; 1297 } 1298