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