Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2014  Realtek Corporation.*/
0003 
0004 #include "../wifi.h"
0005 #include "../base.h"
0006 #include "../pci.h"
0007 #include "../core.h"
0008 #include "reg.h"
0009 #include "def.h"
0010 #include "phy.h"
0011 #include "dm.h"
0012 #include "../rtl8723com/dm_common.h"
0013 #include "fw.h"
0014 #include "trx.h"
0015 #include "../btcoexist/rtl_btc.h"
0016 
0017 static const u32 ofdmswing_table[] = {
0018     0x0b40002d, /* 0,  -15.0dB */
0019     0x0c000030, /* 1,  -14.5dB */
0020     0x0cc00033, /* 2,  -14.0dB */
0021     0x0d800036, /* 3,  -13.5dB */
0022     0x0e400039, /* 4,  -13.0dB */
0023     0x0f00003c, /* 5,  -12.5dB */
0024     0x10000040, /* 6,  -12.0dB */
0025     0x11000044, /* 7,  -11.5dB */
0026     0x12000048, /* 8,  -11.0dB */
0027     0x1300004c, /* 9,  -10.5dB */
0028     0x14400051, /* 10, -10.0dB */
0029     0x15800056, /* 11, -9.5dB */
0030     0x16c0005b, /* 12, -9.0dB */
0031     0x18000060, /* 13, -8.5dB */
0032     0x19800066, /* 14, -8.0dB */
0033     0x1b00006c, /* 15, -7.5dB */
0034     0x1c800072, /* 16, -7.0dB */
0035     0x1e400079, /* 17, -6.5dB */
0036     0x20000080, /* 18, -6.0dB */
0037     0x22000088, /* 19, -5.5dB */
0038     0x24000090, /* 20, -5.0dB */
0039     0x26000098, /* 21, -4.5dB */
0040     0x288000a2, /* 22, -4.0dB */
0041     0x2ac000ab, /* 23, -3.5dB */
0042     0x2d4000b5, /* 24, -3.0dB */
0043     0x300000c0, /* 25, -2.5dB */
0044     0x32c000cb, /* 26, -2.0dB */
0045     0x35c000d7, /* 27, -1.5dB */
0046     0x390000e4, /* 28, -1.0dB */
0047     0x3c8000f2, /* 29, -0.5dB */
0048     0x40000100, /* 30, +0dB */
0049     0x43c0010f, /* 31, +0.5dB */
0050     0x47c0011f, /* 32, +1.0dB */
0051     0x4c000130, /* 33, +1.5dB */
0052     0x50800142, /* 34, +2.0dB */
0053     0x55400155, /* 35, +2.5dB */
0054     0x5a400169, /* 36, +3.0dB */
0055     0x5fc0017f, /* 37, +3.5dB */
0056     0x65400195, /* 38, +4.0dB */
0057     0x6b8001ae, /* 39, +4.5dB */
0058     0x71c001c7, /* 40, +5.0dB */
0059     0x788001e2, /* 41, +5.5dB */
0060     0x7f8001fe  /* 42, +6.0dB */
0061 };
0062 
0063 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
0064     {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /*  0, -16.0dB */
0065     {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /*  1, -15.5dB */
0066     {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  2, -15.0dB */
0067     {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /*  3, -14.5dB */
0068     {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  4, -14.0dB */
0069     {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /*  5, -13.5dB */
0070     {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /*  6, -13.0dB */
0071     {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /*  7, -12.5dB */
0072     {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /*  8, -12.0dB */
0073     {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /*  9, -11.5dB */
0074     {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
0075     {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
0076     {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
0077     {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
0078     {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
0079     {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
0080     {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
0081     {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
0082     {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
0083     {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
0084     {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
0085     {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
0086     {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
0087     {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
0088     {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
0089     {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
0090     {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
0091     {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
0092     {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
0093     {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
0094     {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
0095     {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
0096     {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}  /* 32, +0dB */
0097 };
0098 
0099 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
0100     {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /*  0, -16.0dB */
0101     {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  1, -15.5dB */
0102     {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  2, -15.0dB */
0103     {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  3, -14.5dB */
0104     {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /*  4, -14.0dB */
0105     {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  5, -13.5dB */
0106     {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  6, -13.0dB */
0107     {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /*  7, -12.5dB */
0108     {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  8, -12.0dB */
0109     {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /*  9, -11.5dB */
0110     {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
0111     {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
0112     {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
0113     {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
0114     {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
0115     {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
0116     {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
0117     {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
0118     {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
0119     {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
0120     {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
0121     {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
0122     {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
0123     {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
0124     {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
0125     {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
0126     {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
0127     {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
0128     {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
0129     {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
0130     {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
0131     {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
0132     {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}  /* 32, +0dB */
0133 };
0134 
0135 static const u32 edca_setting_dl[PEER_MAX] = {
0136     0xa44f,     /* 0 UNKNOWN */
0137     0x5ea44f,   /* 1 REALTEK_90 */
0138     0x5e4322,   /* 2 REALTEK_92SE */
0139     0x5ea42b,   /* 3 BROAD */
0140     0xa44f,     /* 4 RAL */
0141     0xa630,     /* 5 ATH */
0142     0x5ea630,   /* 6 CISCO */
0143     0x5ea42b,   /* 7 MARVELL */
0144 };
0145 
0146 static const u32 edca_setting_ul[PEER_MAX] = {
0147     0x5e4322,   /* 0 UNKNOWN */
0148     0xa44f,     /* 1 REALTEK_90 */
0149     0x5ea44f,   /* 2 REALTEK_92SE */
0150     0x5ea32b,   /* 3 BROAD */
0151     0x5ea422,   /* 4 RAL */
0152     0x5ea322,   /* 5 ATH */
0153     0x3ea430,   /* 6 CISCO */
0154     0x5ea44f,   /* 7 MARV */
0155 };
0156 
0157 void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
0158                        u8 *pdirection, u32 *poutwrite_val)
0159 {
0160     struct rtl_priv *rtlpriv = rtl_priv(hw);
0161     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
0162     u8 pwr_val = 0;
0163     u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
0164     u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
0165     u8 cck_base = rtldm->swing_idx_cck_base;
0166     u8 cck_val = rtldm->swing_idx_cck;
0167 
0168     if (type == 0) {
0169         if (ofdm_val <= ofdm_base) {
0170             *pdirection = 1;
0171             pwr_val = ofdm_base - ofdm_val;
0172         } else {
0173             *pdirection = 2;
0174             pwr_val = ofdm_val - ofdm_base;
0175         }
0176     } else if (type == 1) {
0177         if (cck_val <= cck_base) {
0178             *pdirection = 1;
0179             pwr_val = cck_base - cck_val;
0180         } else {
0181             *pdirection = 2;
0182             pwr_val = cck_val - cck_base;
0183         }
0184     }
0185 
0186     if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
0187         pwr_val = TXPWRTRACK_MAX_IDX;
0188 
0189     *poutwrite_val = pwr_val | (pwr_val << 8) |
0190         (pwr_val << 16) | (pwr_val << 24);
0191 }
0192 
0193 void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
0194 {
0195     struct rtl_priv *rtlpriv = rtl_priv(hw);
0196     struct rate_adaptive *p_ra = &rtlpriv->ra;
0197 
0198     p_ra->ratr_state = DM_RATR_STA_INIT;
0199     p_ra->pre_ratr_state = DM_RATR_STA_INIT;
0200 
0201     if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
0202         rtlpriv->dm.useramask = true;
0203     else
0204         rtlpriv->dm.useramask = false;
0205 
0206     p_ra->high_rssi_thresh_for_ra = 50;
0207     p_ra->low_rssi_thresh_for_ra40m = 20;
0208 }
0209 
0210 static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
0211 {
0212     struct rtl_priv *rtlpriv = rtl_priv(hw);
0213 
0214     rtlpriv->dm.txpower_tracking = true;
0215     rtlpriv->dm.txpower_track_control = true;
0216     rtlpriv->dm.thermalvalue = 0;
0217 
0218     rtlpriv->dm.ofdm_index[0] = 30;
0219     rtlpriv->dm.cck_index = 20;
0220 
0221     rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
0222 
0223     rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
0224     rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
0225     rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
0226     rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
0227 
0228     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0229         "rtlpriv->dm.txpower_tracking = %d\n",
0230         rtlpriv->dm.txpower_tracking);
0231 }
0232 
0233 static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
0234 {
0235     struct rtl_priv *rtlpriv = rtl_priv(hw);
0236 
0237     rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
0238 
0239     rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
0240     rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
0241 }
0242 
0243 void rtl8723be_dm_init(struct ieee80211_hw *hw)
0244 {
0245     struct rtl_priv *rtlpriv = rtl_priv(hw);
0246     u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
0247 
0248     rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
0249     rtl_dm_diginit(hw, cur_igvalue);
0250     rtl8723be_dm_init_rate_adaptive_mask(hw);
0251     rtl8723_dm_init_edca_turbo(hw);
0252     rtl8723_dm_init_dynamic_bb_powersaving(hw);
0253     rtl8723_dm_init_dynamic_txpower(hw);
0254     rtl8723be_dm_init_txpower_tracking(hw);
0255     rtl8723be_dm_init_dynamic_atc_switch(hw);
0256 }
0257 
0258 static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
0259 {
0260     struct rtl_priv *rtlpriv = rtl_priv(hw);
0261     struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
0262     struct rtl_mac *mac = rtl_mac(rtlpriv);
0263 
0264     /* Determine the minimum RSSI  */
0265     if ((mac->link_state < MAC80211_LINKED) &&
0266         (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
0267         rtl_dm_dig->min_undec_pwdb_for_dm = 0;
0268         rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0269             "Not connected to any\n");
0270     }
0271     if (mac->link_state >= MAC80211_LINKED) {
0272         if (mac->opmode == NL80211_IFTYPE_AP ||
0273             mac->opmode == NL80211_IFTYPE_ADHOC) {
0274             rtl_dm_dig->min_undec_pwdb_for_dm =
0275                 rtlpriv->dm.entry_min_undec_sm_pwdb;
0276             rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0277                 "AP Client PWDB = 0x%lx\n",
0278                 rtlpriv->dm.entry_min_undec_sm_pwdb);
0279         } else {
0280             rtl_dm_dig->min_undec_pwdb_for_dm =
0281                 rtlpriv->dm.undec_sm_pwdb;
0282             rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0283                 "STA Default Port PWDB = 0x%x\n",
0284                 rtl_dm_dig->min_undec_pwdb_for_dm);
0285         }
0286     } else {
0287         rtl_dm_dig->min_undec_pwdb_for_dm =
0288                 rtlpriv->dm.entry_min_undec_sm_pwdb;
0289         rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0290             "AP Ext Port or disconnect PWDB = 0x%x\n",
0291             rtl_dm_dig->min_undec_pwdb_for_dm);
0292     }
0293     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
0294         rtl_dm_dig->min_undec_pwdb_for_dm);
0295 }
0296 
0297 static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
0298 {
0299     struct rtl_priv *rtlpriv = rtl_priv(hw);
0300     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0301     struct rtl_sta_info *drv_priv;
0302     u8 h2c_parameter[3] = { 0 };
0303     long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
0304 
0305     /* AP & ADHOC & MESH */
0306     spin_lock_bh(&rtlpriv->locks.entry_list_lock);
0307     list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
0308         if (drv_priv->rssi_stat.undec_sm_pwdb <
0309                         tmp_entry_min_pwdb)
0310             tmp_entry_min_pwdb =
0311                 drv_priv->rssi_stat.undec_sm_pwdb;
0312         if (drv_priv->rssi_stat.undec_sm_pwdb >
0313                         tmp_entry_max_pwdb)
0314             tmp_entry_max_pwdb =
0315                 drv_priv->rssi_stat.undec_sm_pwdb;
0316     }
0317     spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
0318 
0319     /* If associated entry is found */
0320     if (tmp_entry_max_pwdb != 0) {
0321         rtlpriv->dm.entry_max_undec_sm_pwdb =
0322                             tmp_entry_max_pwdb;
0323         RTPRINT(rtlpriv, FDM, DM_PWDB,
0324             "EntryMaxPWDB = 0x%lx(%ld)\n",
0325              tmp_entry_max_pwdb, tmp_entry_max_pwdb);
0326     } else {
0327         rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
0328     }
0329     /* If associated entry is found */
0330     if (tmp_entry_min_pwdb != 0xff) {
0331         rtlpriv->dm.entry_min_undec_sm_pwdb =
0332                             tmp_entry_min_pwdb;
0333         RTPRINT(rtlpriv, FDM, DM_PWDB,
0334             "EntryMinPWDB = 0x%lx(%ld)\n",
0335              tmp_entry_min_pwdb, tmp_entry_min_pwdb);
0336     } else {
0337         rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
0338     }
0339     /* Indicate Rx signal strength to FW. */
0340     if (rtlpriv->dm.useramask) {
0341         h2c_parameter[2] =
0342             (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
0343         h2c_parameter[1] = 0x20;
0344         h2c_parameter[0] = 0;
0345         rtl8723be_fill_h2c_cmd(hw, H2C_RSSIBE_REPORT, 3, h2c_parameter);
0346     } else {
0347         rtl_write_byte(rtlpriv, 0x4fe,
0348                    rtlpriv->dm.undec_sm_pwdb);
0349     }
0350     rtl8723be_dm_find_minimum_rssi(hw);
0351     dm_digtable->rssi_val_min =
0352             rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
0353 }
0354 
0355 void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
0356 {
0357     struct rtl_priv *rtlpriv = rtl_priv(hw);
0358     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0359 
0360     if (dm_digtable->stop_dig)
0361         return;
0362 
0363     if (dm_digtable->cur_igvalue != current_igi) {
0364         rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
0365         if (rtlpriv->phy.rf_type != RF_1T1R)
0366             rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1,
0367                       0x7f, current_igi);
0368     }
0369     dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
0370     dm_digtable->cur_igvalue = current_igi;
0371 }
0372 
0373 static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
0374 {
0375     struct rtl_priv *rtlpriv = rtl_priv(hw);
0376     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0377     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0378     u8 dig_min_0, dig_maxofmin;
0379     bool bfirstconnect, bfirstdisconnect;
0380     u8 dm_dig_max, dm_dig_min;
0381     u8 current_igi = dm_digtable->cur_igvalue;
0382     u8 offset;
0383 
0384     /* AP,BT */
0385     if (mac->act_scanning)
0386         return;
0387 
0388     dig_min_0 = dm_digtable->dig_min_0;
0389     bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
0390             !dm_digtable->media_connect_0;
0391     bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
0392             (dm_digtable->media_connect_0);
0393 
0394     dm_dig_max = 0x5a;
0395     dm_dig_min = DM_DIG_MIN;
0396     dig_maxofmin = DM_DIG_MAX_AP;
0397 
0398     if (mac->link_state >= MAC80211_LINKED) {
0399         if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
0400             dm_digtable->rx_gain_max = dm_dig_max;
0401         else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
0402             dm_digtable->rx_gain_max = dm_dig_min;
0403         else
0404             dm_digtable->rx_gain_max =
0405                 dm_digtable->rssi_val_min + 10;
0406 
0407         if (rtlpriv->dm.one_entry_only) {
0408             offset = 12;
0409             if (dm_digtable->rssi_val_min - offset < dm_dig_min)
0410                 dig_min_0 = dm_dig_min;
0411             else if (dm_digtable->rssi_val_min - offset >
0412                             dig_maxofmin)
0413                 dig_min_0 = dig_maxofmin;
0414             else
0415                 dig_min_0 =
0416                     dm_digtable->rssi_val_min - offset;
0417         } else {
0418             dig_min_0 = dm_dig_min;
0419         }
0420 
0421     } else {
0422         dm_digtable->rx_gain_max = dm_dig_max;
0423         dig_min_0 = dm_dig_min;
0424         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
0425     }
0426 
0427     if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
0428         if (dm_digtable->large_fa_hit != 3)
0429             dm_digtable->large_fa_hit++;
0430         if (dm_digtable->forbidden_igi < current_igi) {
0431             dm_digtable->forbidden_igi = current_igi;
0432             dm_digtable->large_fa_hit = 1;
0433         }
0434 
0435         if (dm_digtable->large_fa_hit >= 3) {
0436             if ((dm_digtable->forbidden_igi + 1) >
0437                  dm_digtable->rx_gain_max)
0438                 dm_digtable->rx_gain_min =
0439                         dm_digtable->rx_gain_max;
0440             else
0441                 dm_digtable->rx_gain_min =
0442                         dm_digtable->forbidden_igi + 1;
0443             dm_digtable->recover_cnt = 3600;
0444         }
0445     } else {
0446         if (dm_digtable->recover_cnt != 0) {
0447             dm_digtable->recover_cnt--;
0448         } else {
0449             if (dm_digtable->large_fa_hit < 3) {
0450                 if ((dm_digtable->forbidden_igi - 1) <
0451                      dig_min_0) {
0452                     dm_digtable->forbidden_igi =
0453                             dig_min_0;
0454                     dm_digtable->rx_gain_min =
0455                             dig_min_0;
0456                 } else {
0457                     dm_digtable->forbidden_igi--;
0458                     dm_digtable->rx_gain_min =
0459                         dm_digtable->forbidden_igi + 1;
0460                 }
0461             } else {
0462                 dm_digtable->large_fa_hit = 0;
0463             }
0464         }
0465     }
0466     if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
0467         dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
0468 
0469     if (mac->link_state >= MAC80211_LINKED) {
0470         if (bfirstconnect) {
0471             if (dm_digtable->rssi_val_min <= dig_maxofmin)
0472                 current_igi = dm_digtable->rssi_val_min;
0473             else
0474                 current_igi = dig_maxofmin;
0475 
0476             dm_digtable->large_fa_hit = 0;
0477         } else {
0478             if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
0479                 current_igi += 4;
0480             else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
0481                 current_igi += 2;
0482             else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
0483                 current_igi -= 2;
0484         }
0485     } else {
0486         if (bfirstdisconnect) {
0487             current_igi = dm_digtable->rx_gain_min;
0488         } else {
0489             if (rtlpriv->falsealm_cnt.cnt_all > 10000)
0490                 current_igi += 4;
0491             else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
0492                 current_igi += 2;
0493             else if (rtlpriv->falsealm_cnt.cnt_all < 500)
0494                 current_igi -= 2;
0495         }
0496     }
0497 
0498     if (current_igi > dm_digtable->rx_gain_max)
0499         current_igi = dm_digtable->rx_gain_max;
0500     else if (current_igi < dm_digtable->rx_gain_min)
0501         current_igi = dm_digtable->rx_gain_min;
0502 
0503     rtl8723be_dm_write_dig(hw, current_igi);
0504     dm_digtable->media_connect_0 =
0505         ((mac->link_state >= MAC80211_LINKED) ? true : false);
0506     dm_digtable->dig_min_0 = dig_min_0;
0507 }
0508 
0509 static void rtl8723be_dm_false_alarm_counter_statistics(
0510                     struct ieee80211_hw *hw)
0511 {
0512     u32 ret_value;
0513     struct rtl_priv *rtlpriv = rtl_priv(hw);
0514     struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
0515 
0516     rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
0517     rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
0518 
0519     ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
0520     falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
0521     falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
0522 
0523     ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
0524     falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
0525     falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
0526 
0527     ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
0528     falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
0529     falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
0530 
0531     ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
0532     falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
0533 
0534     falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
0535                       falsealm_cnt->cnt_rate_illegal +
0536                       falsealm_cnt->cnt_crc8_fail +
0537                       falsealm_cnt->cnt_mcs_fail +
0538                       falsealm_cnt->cnt_fast_fsync_fail +
0539                       falsealm_cnt->cnt_sb_search_fail;
0540 
0541     rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
0542     rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
0543 
0544     ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
0545     falsealm_cnt->cnt_cck_fail = ret_value;
0546 
0547     ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
0548     falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
0549 
0550     ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
0551     falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
0552                     ((ret_value & 0xff00) >> 8);
0553 
0554     falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
0555                 falsealm_cnt->cnt_sb_search_fail +
0556                 falsealm_cnt->cnt_parity_fail +
0557                 falsealm_cnt->cnt_rate_illegal +
0558                 falsealm_cnt->cnt_crc8_fail +
0559                 falsealm_cnt->cnt_mcs_fail +
0560                 falsealm_cnt->cnt_cck_fail;
0561 
0562     falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
0563                     falsealm_cnt->cnt_cck_cca;
0564 
0565     rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
0566     rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
0567     rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
0568     rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
0569 
0570     rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
0571     rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
0572 
0573     rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
0574     rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
0575 
0576     rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
0577     rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
0578 
0579     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
0580         "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
0581         falsealm_cnt->cnt_parity_fail,
0582         falsealm_cnt->cnt_rate_illegal,
0583         falsealm_cnt->cnt_crc8_fail,
0584         falsealm_cnt->cnt_mcs_fail);
0585 
0586     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
0587         "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
0588         falsealm_cnt->cnt_ofdm_fail,
0589         falsealm_cnt->cnt_cck_fail,
0590         falsealm_cnt->cnt_all);
0591 }
0592 
0593 static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
0594 {
0595     /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
0596     return;
0597 }
0598 
0599 static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
0600                      u8 rfpath, long iqk_result_x,
0601                      long iqk_result_y)
0602 {
0603     long ele_a = 0, ele_d, ele_c = 0, value32;
0604 
0605     if (ofdm_index >= 43)
0606         ofdm_index = 43 - 1;
0607 
0608     ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
0609 
0610     if (iqk_result_x != 0) {
0611         if ((iqk_result_x & 0x00000200) != 0)
0612             iqk_result_x = iqk_result_x | 0xFFFFFC00;
0613         ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
0614 
0615         if ((iqk_result_y & 0x00000200) != 0)
0616             iqk_result_y = iqk_result_y | 0xFFFFFC00;
0617         ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
0618 
0619         switch (rfpath) {
0620         case RF90_PATH_A:
0621             value32 = (ele_d << 22) |
0622                 ((ele_c & 0x3F) << 16) | ele_a;
0623             rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
0624                       value32);
0625             value32 = (ele_c & 0x000003C0) >> 6;
0626             rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
0627             value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
0628             rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
0629                       value32);
0630             break;
0631         default:
0632             break;
0633         }
0634     } else {
0635         switch (rfpath) {
0636         case RF90_PATH_A:
0637             rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
0638                       ofdmswing_table[ofdm_index]);
0639             rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
0640             rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
0641             break;
0642         default:
0643             break;
0644         }
0645     }
0646 }
0647 
0648 static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
0649                     enum pwr_track_control_method method,
0650                     u8 rfpath, u8 idx)
0651 {
0652     struct rtl_priv *rtlpriv = rtl_priv(hw);
0653     struct rtl_phy *rtlphy = &rtlpriv->phy;
0654     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
0655     u8 swing_idx_ofdm_limit = 36;
0656 
0657     if (method == TXAGC) {
0658         rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
0659     } else if (method == BBSWING) {
0660         if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
0661             rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
0662 
0663         if (!rtldm->cck_inch14) {
0664             rtl_write_byte(rtlpriv, 0xa22,
0665                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
0666             rtl_write_byte(rtlpriv, 0xa23,
0667                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
0668             rtl_write_byte(rtlpriv, 0xa24,
0669                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
0670             rtl_write_byte(rtlpriv, 0xa25,
0671                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
0672             rtl_write_byte(rtlpriv, 0xa26,
0673                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
0674             rtl_write_byte(rtlpriv, 0xa27,
0675                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
0676             rtl_write_byte(rtlpriv, 0xa28,
0677                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
0678             rtl_write_byte(rtlpriv, 0xa29,
0679                 cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
0680         } else {
0681             rtl_write_byte(rtlpriv, 0xa22,
0682                 cckswing_table_ch14[rtldm->swing_idx_cck][0]);
0683             rtl_write_byte(rtlpriv, 0xa23,
0684                 cckswing_table_ch14[rtldm->swing_idx_cck][1]);
0685             rtl_write_byte(rtlpriv, 0xa24,
0686                 cckswing_table_ch14[rtldm->swing_idx_cck][2]);
0687             rtl_write_byte(rtlpriv, 0xa25,
0688                 cckswing_table_ch14[rtldm->swing_idx_cck][3]);
0689             rtl_write_byte(rtlpriv, 0xa26,
0690                 cckswing_table_ch14[rtldm->swing_idx_cck][4]);
0691             rtl_write_byte(rtlpriv, 0xa27,
0692                 cckswing_table_ch14[rtldm->swing_idx_cck][5]);
0693             rtl_write_byte(rtlpriv, 0xa28,
0694                 cckswing_table_ch14[rtldm->swing_idx_cck][6]);
0695             rtl_write_byte(rtlpriv, 0xa29,
0696                 cckswing_table_ch14[rtldm->swing_idx_cck][7]);
0697         }
0698 
0699         if (rfpath == RF90_PATH_A) {
0700             if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
0701                 swing_idx_ofdm_limit)
0702                 swing_idx_ofdm_limit =
0703                     rtldm->swing_idx_ofdm[RF90_PATH_A];
0704 
0705             rtl8723be_set_iqk_matrix(hw,
0706                 rtldm->swing_idx_ofdm[rfpath], rfpath,
0707                 rtlphy->iqk_matrix[idx].value[0][0],
0708                 rtlphy->iqk_matrix[idx].value[0][1]);
0709         } else if (rfpath == RF90_PATH_B) {
0710             if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
0711                 swing_idx_ofdm_limit)
0712                 swing_idx_ofdm_limit =
0713                     rtldm->swing_idx_ofdm[RF90_PATH_B];
0714 
0715             rtl8723be_set_iqk_matrix(hw,
0716                 rtldm->swing_idx_ofdm[rfpath], rfpath,
0717                 rtlphy->iqk_matrix[idx].value[0][4],
0718                 rtlphy->iqk_matrix[idx].value[0][5]);
0719         }
0720     } else {
0721         return;
0722     }
0723 }
0724 
0725 static void rtl8723be_dm_txpower_tracking_callback_thermalmeter(
0726                             struct ieee80211_hw *hw)
0727 {
0728     struct rtl_priv *rtlpriv = rtl_priv(hw);
0729     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
0730     struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
0731     u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
0732     u8 thermalvalue_avg_count = 0;
0733     u32 thermalvalue_avg = 0;
0734     int i = 0;
0735 
0736     u8 ofdm_min_index = 6;
0737     u8 index_for_channel = 0;
0738 
0739     static const s8 delta_swing_table_idx_tup_a[TXSCALE_TABLE_SIZE] = {
0740         0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
0741         5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
0742         10, 11, 11, 12, 12, 13, 14, 15};
0743     static const s8 delta_swing_table_idx_tdown_a[TXSCALE_TABLE_SIZE] = {
0744         0, 0, 1, 2, 2, 2, 3, 3, 3, 4,  5,
0745         5, 6, 6, 6, 6, 7, 7, 7, 8, 8,  9,
0746         9, 10, 10, 11, 12, 13, 14, 15};
0747 
0748     /*Initilization ( 7 steps in total )*/
0749     rtlpriv->dm.txpower_trackinginit = true;
0750     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0751         "%s\n", __func__);
0752 
0753     thermalvalue = (u8)rtl_get_rfreg(hw,
0754         RF90_PATH_A, RF_T_METER, 0xfc00);
0755     if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
0756         rtlefuse->eeprom_thermalmeter == 0xFF)
0757         return;
0758     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0759         "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
0760         thermalvalue, rtldm->thermalvalue,
0761         rtlefuse->eeprom_thermalmeter);
0762     /*3 Initialize ThermalValues of RFCalibrateInfo*/
0763     if (!rtldm->thermalvalue) {
0764         rtlpriv->dm.thermalvalue_lck = thermalvalue;
0765         rtlpriv->dm.thermalvalue_iqk = thermalvalue;
0766     }
0767 
0768     /*4 Calculate average thermal meter*/
0769     rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
0770     rtldm->thermalvalue_avg_index++;
0771     if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
0772         rtldm->thermalvalue_avg_index = 0;
0773 
0774     for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
0775         if (rtldm->thermalvalue_avg[i]) {
0776             thermalvalue_avg += rtldm->thermalvalue_avg[i];
0777             thermalvalue_avg_count++;
0778         }
0779     }
0780 
0781     if (thermalvalue_avg_count)
0782         thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
0783 
0784     /* 5 Calculate delta, delta_LCK, delta_IQK.*/
0785     delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
0786         (thermalvalue - rtlpriv->dm.thermalvalue) :
0787         (rtlpriv->dm.thermalvalue - thermalvalue);
0788     delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
0789             (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
0790             (rtlpriv->dm.thermalvalue_lck - thermalvalue);
0791     delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
0792             (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
0793             (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
0794 
0795     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0796         "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",
0797         thermalvalue, rtlpriv->dm.thermalvalue,
0798         rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
0799     /* 6 If necessary, do LCK.*/
0800     if (delta_lck >= IQK_THRESHOLD) {
0801         rtlpriv->dm.thermalvalue_lck = thermalvalue;
0802         rtl8723be_phy_lc_calibrate(hw);
0803     }
0804 
0805     /* 7 If necessary, move the index of
0806      * swing table to adjust Tx power.
0807      */
0808     if (delta > 0 && rtlpriv->dm.txpower_track_control) {
0809         delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
0810             (thermalvalue - rtlefuse->eeprom_thermalmeter) :
0811             (rtlefuse->eeprom_thermalmeter - thermalvalue);
0812 
0813         if (delta >= TXSCALE_TABLE_SIZE)
0814             delta = TXSCALE_TABLE_SIZE - 1;
0815         /* 7.1 Get the final CCK_index and
0816          * OFDM_index for each swing table.
0817          */
0818         if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
0819             rtldm->delta_power_index_last[RF90_PATH_A] =
0820                     rtldm->delta_power_index[RF90_PATH_A];
0821             rtldm->delta_power_index[RF90_PATH_A] =
0822                     delta_swing_table_idx_tup_a[delta];
0823         } else {
0824             rtldm->delta_power_index_last[RF90_PATH_A] =
0825                     rtldm->delta_power_index[RF90_PATH_A];
0826             rtldm->delta_power_index[RF90_PATH_A] =
0827                 -1 * delta_swing_table_idx_tdown_a[delta];
0828         }
0829 
0830         /* 7.2 Handle boundary conditions of index.*/
0831         if (rtldm->delta_power_index[RF90_PATH_A] ==
0832             rtldm->delta_power_index_last[RF90_PATH_A])
0833             rtldm->power_index_offset[RF90_PATH_A] = 0;
0834         else
0835             rtldm->power_index_offset[RF90_PATH_A] =
0836                 rtldm->delta_power_index[RF90_PATH_A] -
0837                 rtldm->delta_power_index_last[RF90_PATH_A];
0838 
0839         rtldm->ofdm_index[0] =
0840             rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
0841             rtldm->power_index_offset[RF90_PATH_A];
0842         rtldm->cck_index = rtldm->swing_idx_cck_base +
0843                    rtldm->power_index_offset[RF90_PATH_A];
0844 
0845         rtldm->swing_idx_cck = rtldm->cck_index;
0846         rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
0847 
0848         if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
0849             rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
0850         else if (rtldm->ofdm_index[0] < ofdm_min_index)
0851             rtldm->ofdm_index[0] = ofdm_min_index;
0852 
0853         if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
0854             rtldm->cck_index = CCK_TABLE_SIZE - 1;
0855         else if (rtldm->cck_index < 0)
0856             rtldm->cck_index = 0;
0857     } else {
0858         rtldm->power_index_offset[RF90_PATH_A] = 0;
0859     }
0860 
0861     if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
0862         (rtldm->txpower_track_control)) {
0863         rtldm->done_txpower = true;
0864         rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
0865                               index_for_channel);
0866 
0867         rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
0868         rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
0869                         rtldm->swing_idx_ofdm[0];
0870         rtldm->thermalvalue = thermalvalue;
0871     }
0872 
0873     if (delta_iqk >= IQK_THRESHOLD) {
0874         rtldm->thermalvalue_iqk = thermalvalue;
0875         rtl8723be_phy_iq_calibrate(hw, false);
0876     }
0877 
0878     rtldm->txpowercount = 0;
0879     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
0880 
0881 }
0882 
0883 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
0884 {
0885     struct rtl_priv *rtlpriv = rtl_priv(hw);
0886 
0887     if (!rtlpriv->dm.txpower_tracking)
0888         return;
0889 
0890     if (!rtlpriv->dm.tm_trigger) {
0891         rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
0892                   0x03);
0893         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0894             "Trigger 8723be Thermal Meter!!\n");
0895         rtlpriv->dm.tm_trigger = 1;
0896         return;
0897     } else {
0898         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0899             "Schedule TxPowerTracking !!\n");
0900         rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
0901         rtlpriv->dm.tm_trigger = 0;
0902     }
0903 }
0904 
0905 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
0906 {
0907     struct rtl_priv *rtlpriv = rtl_priv(hw);
0908     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0909     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0910     struct rate_adaptive *p_ra = &rtlpriv->ra;
0911     u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
0912     u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
0913     u8 go_up_gap = 5;
0914     struct ieee80211_sta *sta = NULL;
0915 
0916     if (is_hal_stop(rtlhal)) {
0917         rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
0918             "driver is going to unload\n");
0919         return;
0920     }
0921 
0922     if (!rtlpriv->dm.useramask) {
0923         rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
0924             "driver does not control rate adaptive mask\n");
0925         return;
0926     }
0927 
0928     if (mac->link_state == MAC80211_LINKED &&
0929         mac->opmode == NL80211_IFTYPE_STATION) {
0930         switch (p_ra->pre_ratr_state) {
0931         case DM_RATR_STA_MIDDLE:
0932             high_rssithresh_for_ra += go_up_gap;
0933             break;
0934         case DM_RATR_STA_LOW:
0935             high_rssithresh_for_ra += go_up_gap;
0936             low_rssithresh_for_ra += go_up_gap;
0937             break;
0938         default:
0939             break;
0940         }
0941 
0942         if (rtlpriv->dm.undec_sm_pwdb >
0943             (long)high_rssithresh_for_ra)
0944             p_ra->ratr_state = DM_RATR_STA_HIGH;
0945         else if (rtlpriv->dm.undec_sm_pwdb >
0946              (long)low_rssithresh_for_ra)
0947             p_ra->ratr_state = DM_RATR_STA_MIDDLE;
0948         else
0949             p_ra->ratr_state = DM_RATR_STA_LOW;
0950 
0951         if (p_ra->pre_ratr_state != p_ra->ratr_state) {
0952             rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
0953                 "RSSI = %ld\n",
0954                  rtlpriv->dm.undec_sm_pwdb);
0955             rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
0956                 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
0957             rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
0958                 "PreState = %d, CurState = %d\n",
0959                 p_ra->pre_ratr_state, p_ra->ratr_state);
0960 
0961             rcu_read_lock();
0962             sta = rtl_find_sta(hw, mac->bssid);
0963             if (sta)
0964                 rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
0965                                p_ra->ratr_state,
0966                                true);
0967             rcu_read_unlock();
0968 
0969             p_ra->pre_ratr_state = p_ra->ratr_state;
0970         }
0971     }
0972 }
0973 
0974 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
0975 {
0976     struct rtl_priv *rtlpriv = rtl_priv(hw);
0977 
0978     if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
0979         return true;
0980 
0981     return false;
0982 }
0983 
0984 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
0985 {
0986     struct rtl_priv *rtlpriv = rtl_priv(hw);
0987     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0988 
0989     static u64 last_txok_cnt;
0990     static u64 last_rxok_cnt;
0991     u64 cur_txok_cnt = 0;
0992     u64 cur_rxok_cnt = 0;
0993     u32 edca_be_ul = 0x6ea42b;
0994     u32 edca_be_dl = 0x6ea42b;/*not sure*/
0995     u32 edca_be = 0x5ea42b;
0996     u32 iot_peer = 0;
0997     bool b_is_cur_rdlstate;
0998     bool b_bias_on_rx = false;
0999     bool b_edca_turbo_on = false;
1000 
1001     cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1002     cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1003 
1004     iot_peer = rtlpriv->mac80211.vendor;
1005     b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1006                true : false;
1007     b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1008                (!rtlpriv->dm.disable_framebursting)) ?
1009                true : false;
1010 
1011     if ((iot_peer == PEER_CISCO) &&
1012         (mac->mode == WIRELESS_MODE_N_24G)) {
1013         edca_be_dl = edca_setting_dl[iot_peer];
1014         edca_be_ul = edca_setting_ul[iot_peer];
1015     }
1016     if (rtl8723be_dm_is_edca_turbo_disable(hw))
1017         goto exit;
1018 
1019     if (b_edca_turbo_on) {
1020         if (b_bias_on_rx)
1021             b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1022                         false : true;
1023         else
1024             b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1025                         true : false;
1026 
1027         edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1028         rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1029         rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1030         rtlpriv->dm.current_turbo_edca = true;
1031     } else {
1032         if (rtlpriv->dm.current_turbo_edca) {
1033             u8 tmp = AC0_BE;
1034             rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1035                               (u8 *)(&tmp));
1036         }
1037         rtlpriv->dm.current_turbo_edca = false;
1038     }
1039 
1040 exit:
1041     rtlpriv->dm.is_any_nonbepkts = false;
1042     last_txok_cnt = rtlpriv->stats.txbytesunicast;
1043     last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1044 }
1045 
1046 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1047 {
1048     struct rtl_priv *rtlpriv = rtl_priv(hw);
1049     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1050     u8 cur_cck_cca_thresh;
1051 
1052     if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1053         if (dm_digtable->rssi_val_min > 25) {
1054             cur_cck_cca_thresh = 0xcd;
1055         } else if ((dm_digtable->rssi_val_min <= 25) &&
1056                (dm_digtable->rssi_val_min > 10)) {
1057             cur_cck_cca_thresh = 0x83;
1058         } else {
1059             if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1060                 cur_cck_cca_thresh = 0x83;
1061             else
1062                 cur_cck_cca_thresh = 0x40;
1063         }
1064     } else {
1065         if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1066             cur_cck_cca_thresh = 0x83;
1067         else
1068             cur_cck_cca_thresh = 0x40;
1069     }
1070 
1071     if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1072         rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1073 
1074     dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1075     dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1076     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
1077         "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1078 }
1079 
1080 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1081 {
1082     struct rtl_priv *rtlpriv = rtl_priv(hw);
1083     u8 reg_c50, reg_c58;
1084     bool fw_current_in_ps_mode = false;
1085 
1086     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1087                       (u8 *)(&fw_current_in_ps_mode));
1088     if (fw_current_in_ps_mode)
1089         return;
1090 
1091     reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1092     reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1093 
1094     if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1095         if (!rtlpriv->rtlhal.pre_edcca_enable) {
1096             rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1097             rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1098         }
1099     } else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1100         if (rtlpriv->rtlhal.pre_edcca_enable) {
1101             rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1102             rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1103         }
1104     }
1105 }
1106 
1107 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1108 {
1109     struct rtl_priv *rtlpriv = rtl_priv(hw);
1110     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1111     u8 crystal_cap;
1112     u32 packet_count;
1113     int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1114     int cfo_ave_diff;
1115 
1116     if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1117         if (rtldm->atc_status == ATC_STATUS_OFF) {
1118             rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1119                       ATC_STATUS_ON);
1120             rtldm->atc_status = ATC_STATUS_ON;
1121         }
1122         if (rtlpriv->cfg->ops->get_btc_status()) {
1123             if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1124                 rtl_dbg(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1125                     "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1126                 return;
1127             }
1128         }
1129 
1130         if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1131             rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1132             crystal_cap = rtldm->crystal_cap & 0x3f;
1133             rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1134                       (crystal_cap | (crystal_cap << 6)));
1135         }
1136     } else {
1137         cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1138         cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1139         packet_count = rtldm->packet_count;
1140 
1141         if (packet_count == rtldm->packet_count_pre)
1142             return;
1143 
1144         rtldm->packet_count_pre = packet_count;
1145 
1146         if (rtlpriv->phy.rf_type == RF_1T1R)
1147             cfo_ave = cfo_khz_a;
1148         else
1149             cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1150 
1151         cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1152                    (rtldm->cfo_ave_pre - cfo_ave) :
1153                    (cfo_ave - rtldm->cfo_ave_pre);
1154 
1155         if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
1156             rtldm->large_cfo_hit = true;
1157             return;
1158         } else
1159             rtldm->large_cfo_hit = false;
1160 
1161         rtldm->cfo_ave_pre = cfo_ave;
1162 
1163         if (cfo_ave >= -rtldm->cfo_threshold &&
1164             cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1165             if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1166                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1167                 rtldm->is_freeze = 1;
1168             } else {
1169                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1170             }
1171         }
1172 
1173         if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1174             adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1175         else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1176                     rtlpriv->dm.crystal_cap > 0)
1177             adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1178 
1179         if (adjust_xtal != 0) {
1180             rtldm->is_freeze = 0;
1181             rtldm->crystal_cap += adjust_xtal;
1182 
1183             if (rtldm->crystal_cap > 0x3f)
1184                 rtldm->crystal_cap = 0x3f;
1185             else if (rtldm->crystal_cap < 0)
1186                 rtldm->crystal_cap = 0;
1187 
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 
1193         if (cfo_ave < CFO_THRESHOLD_ATC &&
1194             cfo_ave > -CFO_THRESHOLD_ATC) {
1195             if (rtldm->atc_status == ATC_STATUS_ON) {
1196                 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1197                           ATC_STATUS_OFF);
1198                 rtldm->atc_status = ATC_STATUS_OFF;
1199             }
1200         } else {
1201             if (rtldm->atc_status == ATC_STATUS_OFF) {
1202                 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1203                           ATC_STATUS_ON);
1204                 rtldm->atc_status = ATC_STATUS_ON;
1205             }
1206         }
1207     }
1208 }
1209 
1210 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1211 {
1212     struct rtl_priv *rtlpriv = rtl_priv(hw);
1213     u8 cnt = 0;
1214     struct rtl_sta_info *drv_priv;
1215 
1216     rtlpriv->dm.one_entry_only = false;
1217 
1218     if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1219         rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1220         rtlpriv->dm.one_entry_only = true;
1221         return;
1222     }
1223 
1224     if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1225         rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1226         rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1227         spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1228         list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1229             cnt++;
1230         }
1231         spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1232 
1233         if (cnt == 1)
1234             rtlpriv->dm.one_entry_only = true;
1235     }
1236 }
1237 
1238 void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1239 {
1240     struct rtl_priv *rtlpriv = rtl_priv(hw);
1241     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1242     bool fw_current_inpsmode = false;
1243     bool fw_ps_awake = true;
1244 
1245     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1246                       (u8 *)(&fw_current_inpsmode));
1247 
1248     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1249                       (u8 *)(&fw_ps_awake));
1250 
1251     if (ppsc->p2p_ps_info.p2p_ps_mode)
1252         fw_ps_awake = false;
1253 
1254     spin_lock(&rtlpriv->locks.rf_ps_lock);
1255     if ((ppsc->rfpwr_state == ERFON) &&
1256         ((!fw_current_inpsmode) && fw_ps_awake) &&
1257         (!ppsc->rfchange_inprogress)) {
1258         rtl8723be_dm_common_info_self_update(hw);
1259         rtl8723be_dm_false_alarm_counter_statistics(hw);
1260         rtl8723be_dm_check_rssi_monitor(hw);
1261         rtl8723be_dm_dig(hw);
1262         rtl8723be_dm_dynamic_edcca(hw);
1263         rtl8723be_dm_cck_packet_detection_thresh(hw);
1264         rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1265         rtl8723be_dm_check_edca_turbo(hw);
1266         rtl8723be_dm_dynamic_atc_switch(hw);
1267         rtl8723be_dm_check_txpower_tracking(hw);
1268         rtl8723be_dm_dynamic_txpower(hw);
1269     }
1270     spin_unlock(&rtlpriv->locks.rf_ps_lock);
1271     rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1272 }