Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2010  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 "fw.h"
0013 #include "trx.h"
0014 #include "../btcoexist/rtl_btc.h"
0015 
0016 static const u32 txscaling_tbl[TXSCALE_TABLE_SIZE] = {
0017     0x081, /* 0, -12.0dB */
0018     0x088, /* 1, -11.5dB */
0019     0x090, /* 2, -11.0dB */
0020     0x099, /* 3, -10.5dB */
0021     0x0A2, /* 4, -10.0dB */
0022     0x0AC, /* 5, -9.5dB */
0023     0x0B6, /* 6, -9.0dB */
0024     0x0C0, /* 7, -8.5dB */
0025     0x0CC, /* 8, -8.0dB */
0026     0x0D8, /* 9, -7.5dB */
0027     0x0E5, /* 10, -7.0dB */
0028     0x0F2, /* 11, -6.5dB */
0029     0x101, /* 12, -6.0dB */
0030     0x110, /* 13, -5.5dB */
0031     0x120, /* 14, -5.0dB */
0032     0x131, /* 15, -4.5dB */
0033     0x143, /* 16, -4.0dB */
0034     0x156, /* 17, -3.5dB */
0035     0x16A, /* 18, -3.0dB */
0036     0x180, /* 19, -2.5dB */
0037     0x197, /* 20, -2.0dB */
0038     0x1AF, /* 21, -1.5dB */
0039     0x1C8, /* 22, -1.0dB */
0040     0x1E3, /* 23, -0.5dB */
0041     0x200, /* 24, +0  dB */
0042     0x21E, /* 25, +0.5dB */
0043     0x23E, /* 26, +1.0dB */
0044     0x261, /* 27, +1.5dB */
0045     0x285, /* 28, +2.0dB */
0046     0x2AB, /* 29, +2.5dB */
0047     0x2D3, /* 30, +3.0dB */
0048     0x2FE, /* 31, +3.5dB */
0049     0x32B, /* 32, +4.0dB */
0050     0x35C, /* 33, +4.5dB */
0051     0x38E, /* 34, +5.0dB */
0052     0x3C4, /* 35, +5.5dB */
0053     0x3FE  /* 36, +6.0dB */
0054 };
0055 
0056 static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = {
0057     0x081, /* 0, -12.0dB */
0058     0x088, /* 1, -11.5dB */
0059     0x090, /* 2, -11.0dB */
0060     0x099, /* 3, -10.5dB */
0061     0x0A2, /* 4, -10.0dB */
0062     0x0AC, /* 5, -9.5dB */
0063     0x0B6, /* 6, -9.0dB */
0064     0x0C0, /* 7, -8.5dB */
0065     0x0CC, /* 8, -8.0dB */
0066     0x0D8, /* 9, -7.5dB */
0067     0x0E5, /* 10, -7.0dB */
0068     0x0F2, /* 11, -6.5dB */
0069     0x101, /* 12, -6.0dB */
0070     0x110, /* 13, -5.5dB */
0071     0x120, /* 14, -5.0dB */
0072     0x131, /* 15, -4.5dB */
0073     0x143, /* 16, -4.0dB */
0074     0x156, /* 17, -3.5dB */
0075     0x16A, /* 18, -3.0dB */
0076     0x180, /* 19, -2.5dB */
0077     0x197, /* 20, -2.0dB */
0078     0x1AF, /* 21, -1.5dB */
0079     0x1C8, /* 22, -1.0dB */
0080     0x1E3, /* 23, -0.5dB */
0081     0x200, /* 24, +0  dB */
0082     0x21E, /* 25, +0.5dB */
0083     0x23E, /* 26, +1.0dB */
0084     0x261, /* 27, +1.5dB */
0085     0x285, /* 28, +2.0dB */
0086     0x2AB, /* 29, +2.5dB */
0087     0x2D3, /* 30, +3.0dB */
0088     0x2FE, /* 31, +3.5dB */
0089     0x32B, /* 32, +4.0dB */
0090     0x35C, /* 33, +4.5dB */
0091     0x38E, /* 34, +5.0dB */
0092     0x3C4, /* 35, +5.5dB */
0093     0x3FE  /* 36, +6.0dB */
0094 };
0095 
0096 static const u32 edca_setting_dl[PEER_MAX] = {
0097     0xa44f,     /* 0 UNKNOWN */
0098     0x5ea44f,   /* 1 REALTEK_90 */
0099     0x5e4322,   /* 2 REALTEK_92SE */
0100     0x5ea42b,       /* 3 BROAD  */
0101     0xa44f,     /* 4 RAL */
0102     0xa630,     /* 5 ATH */
0103     0x5ea630,       /* 6 CISCO */
0104     0x5ea42b,       /* 7 MARVELL */
0105 };
0106 
0107 static const u32 edca_setting_ul[PEER_MAX] = {
0108     0x5e4322,   /* 0 UNKNOWN */
0109     0xa44f,     /* 1 REALTEK_90 */
0110     0x5ea44f,   /* 2 REALTEK_92SE */
0111     0x5ea32b,   /* 3 BROAD */
0112     0x5ea422,   /* 4 RAL */
0113     0x5ea322,   /* 5 ATH */
0114     0x3ea430,   /* 6 CISCO */
0115     0x5ea44f,   /* 7 MARV */
0116 };
0117 
0118 static const u8 rtl8818e_delta_swing_table_idx_24gb_p[] = {
0119     0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4,
0120     4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9};
0121 
0122 static const u8 rtl8818e_delta_swing_table_idx_24gb_n[] = {
0123     0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,
0124     7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11};
0125 
0126 static const u8 rtl8812ae_delta_swing_table_idx_24gb_n[]  = {
0127     0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
0128     6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
0129 
0130 static const u8 rtl8812ae_delta_swing_table_idx_24gb_p[] = {
0131     0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
0132     6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
0133 
0134 static const u8 rtl8812ae_delta_swing_table_idx_24ga_n[] = {
0135     0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
0136     6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
0137 
0138 static const u8 rtl8812ae_delta_swing_table_idx_24ga_p[] = {
0139     0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
0140     6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
0141 
0142 static const u8 rtl8812ae_delta_swing_table_idx_24gcckb_n[] = {
0143     0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
0144     6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
0145 
0146 static const u8 rtl8812ae_delta_swing_table_idx_24gcckb_p[] = {
0147     0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
0148     6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
0149 
0150 static const u8 rtl8812ae_delta_swing_table_idx_24gccka_n[] = {
0151     0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
0152     6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
0153 
0154 static const u8 rtl8812ae_delta_swing_table_idx_24gccka_p[] = {
0155     0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
0156     6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
0157 
0158 static const u8 rtl8812ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = {
0159     {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7,
0160     7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13},
0161     {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
0162     7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13},
0163     {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11,
0164     12, 12, 13, 14, 14, 14, 15, 16, 17, 17, 17, 18, 18, 18},
0165 };
0166 
0167 static const u8 rtl8812ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = {
0168     {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8,
0169     8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
0170     {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
0171     8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
0172     {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9,
0173     9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
0174 };
0175 
0176 static const u8 rtl8812ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
0177     {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
0178     8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13},
0179     {0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9,
0180     9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13},
0181     {0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11,
0182     12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18},
0183 };
0184 
0185 static const u8 rtl8812ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
0186     {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8,
0187     8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
0188     {0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
0189     9, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
0190     {0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9,
0191     10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
0192 };
0193 
0194 static const u8 rtl8821ae_delta_swing_table_idx_24ga_n[]  = {
0195     0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
0196     6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
0197 
0198 static const u8 rtl8821ae_delta_swing_table_idx_24ga_p[] = {
0199     0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
0200     8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
0201 
0202 static const u8 rtl8821ae_delta_swing_table_idx_24gccka_n[] = {
0203     0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
0204     6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
0205 
0206 static const u8 rtl8821ae_delta_swing_table_idx_24gccka_p[] = {
0207     0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
0208     8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
0209 
0210 static const u8 rtl8821ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
0211     {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
0212     12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
0213     {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
0214     12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
0215     {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
0216     12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
0217 };
0218 
0219 static const u8 rtl8821ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
0220     {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
0221     12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
0222     {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
0223     12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
0224     {0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
0225     12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
0226 };
0227 
0228 void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw,
0229                        u8 type, u8 *pdirection,
0230                        u32 *poutwrite_val)
0231 {
0232     struct rtl_priv *rtlpriv = rtl_priv(hw);
0233     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
0234     u8 pwr_val = 0;
0235 
0236     if (type == 0) {
0237         if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <=
0238             rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) {
0239             *pdirection = 1;
0240             pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] -
0241                     rtldm->swing_idx_ofdm[RF90_PATH_A];
0242         } else {
0243             *pdirection = 2;
0244             pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] -
0245                 rtldm->swing_idx_ofdm_base[RF90_PATH_A];
0246         }
0247     } else if (type == 1) {
0248         if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) {
0249             *pdirection = 1;
0250             pwr_val = rtldm->swing_idx_cck_base -
0251                     rtldm->swing_idx_cck;
0252         } else {
0253             *pdirection = 2;
0254             pwr_val = rtldm->swing_idx_cck -
0255                 rtldm->swing_idx_cck_base;
0256         }
0257     }
0258 
0259     if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
0260         pwr_val = TXPWRTRACK_MAX_IDX;
0261 
0262     *poutwrite_val = pwr_val | (pwr_val << 8)|
0263                 (pwr_val << 16)|
0264                 (pwr_val << 24);
0265 }
0266 
0267 void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw)
0268 {
0269     struct rtl_priv *rtlpriv = rtl_priv(hw);
0270     struct rtl_dm *rtldm = rtl_dm(rtlpriv);
0271     struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
0272     u8 p = 0;
0273 
0274     rtldm->swing_idx_cck_base = rtldm->default_cck_index;
0275     rtldm->swing_idx_cck = rtldm->default_cck_index;
0276     rtldm->cck_index = 0;
0277 
0278     for (p = RF90_PATH_A; p <= RF90_PATH_B; ++p) {
0279         rtldm->swing_idx_ofdm_base[p] = rtldm->default_ofdm_index;
0280         rtldm->swing_idx_ofdm[p] = rtldm->default_ofdm_index;
0281         rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
0282 
0283         rtldm->power_index_offset[p] = 0;
0284         rtldm->delta_power_index[p] = 0;
0285         rtldm->delta_power_index_last[p] = 0;
0286         /*Initial Mix mode power tracking*/
0287         rtldm->absolute_ofdm_swing_idx[p] = 0;
0288         rtldm->remnant_ofdm_swing_idx[p] = 0;
0289     }
0290     /*Initial at Modify Tx Scaling Mode*/
0291     rtldm->modify_txagc_flag_path_a = false;
0292     /*Initial at Modify Tx Scaling Mode*/
0293     rtldm->modify_txagc_flag_path_b = false;
0294     rtldm->remnant_cck_idx = 0;
0295     rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
0296     rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
0297     rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
0298 }
0299 
0300 static u8  rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw)
0301 {
0302     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0303     u8 i = 0;
0304     u32  bb_swing;
0305 
0306     bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype,
0307                       RF90_PATH_A);
0308 
0309     for (i = 0; i < TXSCALE_TABLE_SIZE; ++i)
0310         if (bb_swing == rtl8821ae_txscaling_table[i])
0311             break;
0312 
0313     return i;
0314 }
0315 
0316 void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(
0317                 struct ieee80211_hw *hw)
0318 {
0319     struct rtl_priv *rtlpriv = rtl_priv(hw);
0320     struct rtl_dm *rtldm = rtl_dm(rtlpriv);
0321     struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
0322     u8 default_swing_index  = 0;
0323     u8 p = 0;
0324 
0325     rtlpriv->dm.txpower_track_control = true;
0326     rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
0327     rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
0328     rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
0329     default_swing_index = rtl8821ae_dm_get_swing_index(hw);
0330 
0331     rtldm->default_ofdm_index =
0332         (default_swing_index == TXSCALE_TABLE_SIZE) ?
0333         24 : default_swing_index;
0334     rtldm->default_cck_index = 24;
0335 
0336     rtldm->swing_idx_cck_base = rtldm->default_cck_index;
0337     rtldm->cck_index = rtldm->default_cck_index;
0338 
0339     for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) {
0340         rtldm->swing_idx_ofdm_base[p] =
0341             rtldm->default_ofdm_index;
0342         rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
0343         rtldm->delta_power_index[p] = 0;
0344         rtldm->power_index_offset[p] = 0;
0345         rtldm->delta_power_index_last[p] = 0;
0346     }
0347 }
0348 
0349 void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
0350 {
0351     struct rtl_priv *rtlpriv = rtl_priv(hw);
0352 
0353     rtlpriv->dm.current_turbo_edca = false;
0354     rtlpriv->dm.is_any_nonbepkts = false;
0355     rtlpriv->dm.is_cur_rdlstate = false;
0356 }
0357 
0358 void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
0359 {
0360     struct rtl_priv *rtlpriv = rtl_priv(hw);
0361     struct rate_adaptive *p_ra = &rtlpriv->ra;
0362 
0363     p_ra->ratr_state = DM_RATR_STA_INIT;
0364     p_ra->pre_ratr_state = DM_RATR_STA_INIT;
0365 
0366     rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
0367     if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
0368         rtlpriv->dm.useramask = true;
0369     else
0370         rtlpriv->dm.useramask = false;
0371 
0372     p_ra->high_rssi_thresh_for_ra = 50;
0373     p_ra->low_rssi_thresh_for_ra40m = 20;
0374 }
0375 
0376 static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
0377 {
0378     struct rtl_priv *rtlpriv = rtl_priv(hw);
0379 
0380     rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
0381 
0382     rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
0383     rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
0384 }
0385 
0386 static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw)
0387 {
0388     struct rtl_priv *rtlpriv = rtl_priv(hw);
0389     struct rtl_phy *rtlphy = &rtlpriv->phy;
0390     u8 tmp;
0391 
0392     rtlphy->cck_high_power =
0393         (bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC,
0394                     ODM_BIT_CCK_RPT_FORMAT_11AC);
0395 
0396     tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC,
0397                 ODM_BIT_BB_RX_PATH_11AC);
0398     if (tmp & BIT(0))
0399         rtlpriv->dm.rfpath_rxenable[0] = true;
0400     if (tmp & BIT(1))
0401         rtlpriv->dm.rfpath_rxenable[1] = true;
0402 }
0403 
0404 void rtl8821ae_dm_init(struct ieee80211_hw *hw)
0405 {
0406     struct rtl_priv *rtlpriv = rtl_priv(hw);
0407     struct rtl_phy *rtlphy = &rtlpriv->phy;
0408     u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
0409 
0410     spin_lock(&rtlpriv->locks.iqk_lock);
0411     rtlphy->lck_inprogress = false;
0412     spin_unlock(&rtlpriv->locks.iqk_lock);
0413 
0414     rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
0415     rtl8821ae_dm_common_info_self_init(hw);
0416     rtl_dm_diginit(hw, cur_igvalue);
0417     rtl8821ae_dm_init_rate_adaptive_mask(hw);
0418     rtl8821ae_dm_init_edca_turbo(hw);
0419     rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(hw);
0420     rtl8821ae_dm_init_dynamic_atc_switch(hw);
0421 }
0422 
0423 static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
0424 {
0425     struct rtl_priv *rtlpriv = rtl_priv(hw);
0426     struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
0427     struct rtl_mac *mac = rtl_mac(rtlpriv);
0428 
0429     /* Determine the minimum RSSI  */
0430     if ((mac->link_state < MAC80211_LINKED) &&
0431         (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
0432         rtl_dm_dig->min_undec_pwdb_for_dm = 0;
0433         pr_debug("rtl8821ae: Not connected to any AP\n");
0434     }
0435     if (mac->link_state >= MAC80211_LINKED) {
0436         if (mac->opmode == NL80211_IFTYPE_AP ||
0437             mac->opmode == NL80211_IFTYPE_ADHOC) {
0438             rtl_dm_dig->min_undec_pwdb_for_dm =
0439                 rtlpriv->dm.entry_min_undec_sm_pwdb;
0440             rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0441                 "AP Client PWDB = 0x%lx\n",
0442                 rtlpriv->dm.entry_min_undec_sm_pwdb);
0443         } else {
0444             rtl_dm_dig->min_undec_pwdb_for_dm =
0445                 rtlpriv->dm.undec_sm_pwdb;
0446             rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0447                 "STA Default Port PWDB = 0x%x\n",
0448                 rtl_dm_dig->min_undec_pwdb_for_dm);
0449         }
0450     } else {
0451         rtl_dm_dig->min_undec_pwdb_for_dm =
0452             rtlpriv->dm.entry_min_undec_sm_pwdb;
0453         rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
0454             "AP Ext Port or disconnect PWDB = 0x%x\n",
0455             rtl_dm_dig->min_undec_pwdb_for_dm);
0456     }
0457     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0458         "MinUndecoratedPWDBForDM =%d\n",
0459         rtl_dm_dig->min_undec_pwdb_for_dm);
0460 }
0461 
0462 static void  rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw)
0463 {
0464     struct rtl_priv *rtlpriv = rtl_priv(hw);
0465 
0466     rtl_write_byte(rtlpriv, RA_RSSI_DUMP,
0467                rtlpriv->stats.rx_rssi_percentage[0]);
0468     rtl_write_byte(rtlpriv, RB_RSSI_DUMP,
0469                rtlpriv->stats.rx_rssi_percentage[1]);
0470 
0471     /* Rx EVM*/
0472     rtl_write_byte(rtlpriv, RS1_RX_EVM_DUMP,
0473                rtlpriv->stats.rx_evm_dbm[0]);
0474     rtl_write_byte(rtlpriv, RS2_RX_EVM_DUMP,
0475                rtlpriv->stats.rx_evm_dbm[1]);
0476 
0477     /*Rx SNR*/
0478     rtl_write_byte(rtlpriv, RA_RX_SNR_DUMP,
0479                (u8)(rtlpriv->stats.rx_snr_db[0]));
0480     rtl_write_byte(rtlpriv, RB_RX_SNR_DUMP,
0481                (u8)(rtlpriv->stats.rx_snr_db[1]));
0482 
0483     /*Rx Cfo_Short*/
0484     rtl_write_word(rtlpriv, RA_CFO_SHORT_DUMP,
0485                rtlpriv->stats.rx_cfo_short[0]);
0486     rtl_write_word(rtlpriv, RB_CFO_SHORT_DUMP,
0487                rtlpriv->stats.rx_cfo_short[1]);
0488 
0489     /*Rx Cfo_Tail*/
0490     rtl_write_word(rtlpriv, RA_CFO_LONG_DUMP,
0491                rtlpriv->stats.rx_cfo_tail[0]);
0492     rtl_write_word(rtlpriv, RB_CFO_LONG_DUMP,
0493                rtlpriv->stats.rx_cfo_tail[1]);
0494 }
0495 
0496 static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw)
0497 {
0498     struct rtl_priv *rtlpriv = rtl_priv(hw);
0499     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0500     struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
0501     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0502     struct rtl_sta_info *drv_priv;
0503     u8 h2c_parameter[4] = { 0 };
0504     long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
0505     u8 stbc_tx = 0;
0506     u64 cur_rxokcnt = 0;
0507     static u64 last_txokcnt = 0, last_rxokcnt;
0508 
0509     cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt;
0510     last_txokcnt = rtlpriv->stats.txbytesunicast;
0511     last_rxokcnt = rtlpriv->stats.rxbytesunicast;
0512     if (cur_rxokcnt > (last_txokcnt * 6))
0513         h2c_parameter[3] = 0x01;
0514     else
0515         h2c_parameter[3] = 0x00;
0516 
0517     /* AP & ADHOC & MESH */
0518     if (mac->opmode == NL80211_IFTYPE_AP ||
0519         mac->opmode == NL80211_IFTYPE_ADHOC ||
0520         mac->opmode == NL80211_IFTYPE_MESH_POINT) {
0521         spin_lock_bh(&rtlpriv->locks.entry_list_lock);
0522         list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
0523             if (drv_priv->rssi_stat.undec_sm_pwdb <
0524                     tmp_entry_min_pwdb)
0525                 tmp_entry_min_pwdb =
0526                     drv_priv->rssi_stat.undec_sm_pwdb;
0527             if (drv_priv->rssi_stat.undec_sm_pwdb >
0528                     tmp_entry_max_pwdb)
0529                 tmp_entry_max_pwdb =
0530                     drv_priv->rssi_stat.undec_sm_pwdb;
0531         }
0532         spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
0533 
0534         /* If associated entry is found */
0535         if (tmp_entry_max_pwdb != 0) {
0536             rtlpriv->dm.entry_max_undec_sm_pwdb =
0537                 tmp_entry_max_pwdb;
0538             RTPRINT(rtlpriv, FDM, DM_PWDB,
0539                 "EntryMaxPWDB = 0x%lx(%ld)\n",
0540                 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
0541         } else {
0542             rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
0543         }
0544         /* If associated entry is found */
0545         if (tmp_entry_min_pwdb != 0xff) {
0546             rtlpriv->dm.entry_min_undec_sm_pwdb =
0547                 tmp_entry_min_pwdb;
0548             RTPRINT(rtlpriv, FDM, DM_PWDB,
0549                 "EntryMinPWDB = 0x%lx(%ld)\n",
0550                 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
0551         } else {
0552             rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
0553         }
0554     }
0555     /* Indicate Rx signal strength to FW. */
0556     if (rtlpriv->dm.useramask) {
0557         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
0558             if (mac->mode == WIRELESS_MODE_AC_24G ||
0559                 mac->mode == WIRELESS_MODE_AC_5G ||
0560                 mac->mode == WIRELESS_MODE_AC_ONLY)
0561                 stbc_tx = (mac->vht_cur_stbc &
0562                        STBC_VHT_ENABLE_TX) ? 1 : 0;
0563             else
0564                 stbc_tx = (mac->ht_cur_stbc &
0565                        STBC_HT_ENABLE_TX) ? 1 : 0;
0566             h2c_parameter[3] |= stbc_tx << 1;
0567         }
0568         h2c_parameter[2] =
0569             (u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
0570         h2c_parameter[1] = 0x20;
0571         h2c_parameter[0] = 0;
0572         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
0573             rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4,
0574                            h2c_parameter);
0575         else
0576             rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3,
0577                            h2c_parameter);
0578     } else {
0579         rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
0580     }
0581     if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
0582         rtl8812ae_dm_rssi_dump_to_register(hw);
0583     rtl8821ae_dm_find_minimum_rssi(hw);
0584     dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
0585 }
0586 
0587 void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca)
0588 {
0589     struct rtl_priv *rtlpriv = rtl_priv(hw);
0590     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0591 
0592     if (dm_digtable->cur_cck_cca_thres != current_cca)
0593         rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca);
0594 
0595     dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
0596     dm_digtable->cur_cck_cca_thres = current_cca;
0597 }
0598 
0599 void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
0600 {
0601     struct rtl_priv *rtlpriv = rtl_priv(hw);
0602     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0603 
0604     if (dm_digtable->stop_dig)
0605         return;
0606 
0607     if (dm_digtable->cur_igvalue != current_igi) {
0608         rtl_set_bbreg(hw, DM_REG_IGI_A_11AC,
0609                   DM_BIT_IGI_11AC, current_igi);
0610         if (rtlpriv->phy.rf_type != RF_1T1R)
0611             rtl_set_bbreg(hw, DM_REG_IGI_B_11AC,
0612                       DM_BIT_IGI_11AC, current_igi);
0613     }
0614     dm_digtable->cur_igvalue = current_igi;
0615 }
0616 
0617 static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
0618 {
0619     struct rtl_priv *rtlpriv = rtl_priv(hw);
0620     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
0621     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0622     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0623     u8 dig_min_0;
0624     u8 dig_max_of_min;
0625     bool first_connect, first_disconnect;
0626     u8 dm_dig_max, dm_dig_min, offset;
0627     u8 current_igi = dm_digtable->cur_igvalue;
0628 
0629     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "\n");
0630 
0631     if (mac->act_scanning) {
0632         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0633             "Return: In Scan Progress\n");
0634         return;
0635     }
0636 
0637     /*add by Neil Chen to avoid PSD is processing*/
0638     dig_min_0 = dm_digtable->dig_min_0;
0639     first_connect = (mac->link_state >= MAC80211_LINKED) &&
0640             (!dm_digtable->media_connect_0);
0641     first_disconnect = (mac->link_state < MAC80211_LINKED) &&
0642             (dm_digtable->media_connect_0);
0643 
0644     /*1 Boundary Decision*/
0645 
0646     dm_dig_max = 0x5A;
0647 
0648     if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
0649         dm_dig_min = DM_DIG_MIN;
0650     else
0651         dm_dig_min = 0x1C;
0652 
0653     dig_max_of_min = DM_DIG_MAX_AP;
0654 
0655     if (mac->link_state >= MAC80211_LINKED) {
0656         if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
0657             offset = 20;
0658         else
0659             offset = 10;
0660 
0661         if ((dm_digtable->rssi_val_min + offset) > dm_dig_max)
0662             dm_digtable->rx_gain_max = dm_dig_max;
0663         else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min)
0664             dm_digtable->rx_gain_max = dm_dig_min;
0665         else
0666             dm_digtable->rx_gain_max =
0667                 dm_digtable->rssi_val_min + offset;
0668 
0669         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0670             "dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x\n",
0671             dm_digtable->rssi_val_min,
0672             dm_digtable->rx_gain_max);
0673         if (rtlpriv->dm.one_entry_only) {
0674             offset = 0;
0675 
0676             if (dm_digtable->rssi_val_min - offset < dm_dig_min)
0677                 dig_min_0 = dm_dig_min;
0678             else if (dm_digtable->rssi_val_min -
0679                 offset > dig_max_of_min)
0680                 dig_min_0 = dig_max_of_min;
0681             else
0682                 dig_min_0 =
0683                     dm_digtable->rssi_val_min - offset;
0684 
0685             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0686                 "bOneEntryOnly=TRUE, dig_min_0=0x%x\n",
0687                 dig_min_0);
0688         } else {
0689             dig_min_0 = dm_dig_min;
0690         }
0691     } else {
0692         dm_digtable->rx_gain_max = dm_dig_max;
0693         dig_min_0 = dm_dig_min;
0694         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n");
0695     }
0696 
0697     if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
0698         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0699             "Abnormally false alarm case.\n");
0700 
0701         if (dm_digtable->large_fa_hit != 3)
0702             dm_digtable->large_fa_hit++;
0703         if (dm_digtable->forbidden_igi < current_igi) {
0704             dm_digtable->forbidden_igi = current_igi;
0705             dm_digtable->large_fa_hit = 1;
0706         }
0707 
0708         if (dm_digtable->large_fa_hit >= 3) {
0709             if ((dm_digtable->forbidden_igi + 1) >
0710                 dm_digtable->rx_gain_max)
0711                 dm_digtable->rx_gain_min =
0712                     dm_digtable->rx_gain_max;
0713             else
0714                 dm_digtable->rx_gain_min =
0715                     (dm_digtable->forbidden_igi + 1);
0716             dm_digtable->recover_cnt = 3600;
0717         }
0718     } else {
0719         /*Recovery mechanism for IGI lower bound*/
0720         if (dm_digtable->recover_cnt != 0) {
0721             dm_digtable->recover_cnt--;
0722         } else {
0723             if (dm_digtable->large_fa_hit < 3) {
0724                 if ((dm_digtable->forbidden_igi - 1) <
0725                     dig_min_0) {
0726                     dm_digtable->forbidden_igi =
0727                         dig_min_0;
0728                     dm_digtable->rx_gain_min =
0729                         dig_min_0;
0730                     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0731                         "Normal Case: At Lower Bound\n");
0732                 } else {
0733                     dm_digtable->forbidden_igi--;
0734                     dm_digtable->rx_gain_min =
0735                       (dm_digtable->forbidden_igi + 1);
0736                     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0737                         "Normal Case: Approach Lower Bound\n");
0738                 }
0739             } else {
0740                 dm_digtable->large_fa_hit = 0;
0741             }
0742         }
0743     }
0744     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0745         "pDM_DigTable->LargeFAHit=%d\n",
0746         dm_digtable->large_fa_hit);
0747 
0748     if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10)
0749         dm_digtable->rx_gain_min = dm_dig_min;
0750 
0751     if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
0752         dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
0753 
0754     /*Adjust initial gain by false alarm*/
0755     if (mac->link_state >= MAC80211_LINKED) {
0756         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0757             "DIG AfterLink\n");
0758         if (first_connect) {
0759             if (dm_digtable->rssi_val_min <= dig_max_of_min)
0760                 current_igi = dm_digtable->rssi_val_min;
0761             else
0762                 current_igi = dig_max_of_min;
0763             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0764                 "First Connect\n");
0765         } else {
0766             if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
0767                 current_igi = current_igi + 4;
0768             else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
0769                 current_igi = current_igi + 2;
0770             else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
0771                 current_igi = current_igi - 2;
0772 
0773             if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) &&
0774                 (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) {
0775                 current_igi = dm_digtable->rx_gain_min;
0776                 rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0777                     "Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n");
0778             }
0779         }
0780     } else {
0781         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0782             "DIG BeforeLink\n");
0783         if (first_disconnect) {
0784             current_igi = dm_digtable->rx_gain_min;
0785             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0786                 "First DisConnect\n");
0787         } else {
0788             /* 2012.03.30 LukeLee: enable DIG before
0789              * link but with very high thresholds
0790              */
0791             if (rtlpriv->falsealm_cnt.cnt_all > 2000)
0792                 current_igi = current_igi + 4;
0793             else if (rtlpriv->falsealm_cnt.cnt_all > 600)
0794                 current_igi = current_igi + 2;
0795             else if (rtlpriv->falsealm_cnt.cnt_all < 300)
0796                 current_igi = current_igi - 2;
0797 
0798             if (current_igi >= 0x3e)
0799                 current_igi = 0x3e;
0800 
0801             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n");
0802         }
0803     }
0804     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0805         "DIG End Adjust IGI\n");
0806     /* Check initial gain by upper/lower bound*/
0807 
0808     if (current_igi > dm_digtable->rx_gain_max)
0809         current_igi = dm_digtable->rx_gain_max;
0810     if (current_igi < dm_digtable->rx_gain_min)
0811         current_igi = dm_digtable->rx_gain_min;
0812 
0813     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0814         "rx_gain_max=0x%x, rx_gain_min=0x%x\n",
0815         dm_digtable->rx_gain_max, dm_digtable->rx_gain_min);
0816     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0817         "TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all);
0818     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
0819         "CurIGValue=0x%x\n", current_igi);
0820 
0821     rtl8821ae_dm_write_dig(hw, current_igi);
0822     dm_digtable->media_connect_0 =
0823         ((mac->link_state >= MAC80211_LINKED) ? true : false);
0824     dm_digtable->dig_min_0 = dig_min_0;
0825 }
0826 
0827 static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw)
0828 {
0829     struct rtl_priv *rtlpriv = rtl_priv(hw);
0830     u8 cnt = 0;
0831     struct rtl_sta_info *drv_priv;
0832 
0833     rtlpriv->dm.tx_rate = 0xff;
0834 
0835     rtlpriv->dm.one_entry_only = false;
0836 
0837     if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
0838         rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
0839         rtlpriv->dm.one_entry_only = true;
0840         return;
0841     }
0842 
0843     if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
0844         rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
0845         rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
0846         spin_lock_bh(&rtlpriv->locks.entry_list_lock);
0847         list_for_each_entry(drv_priv, &rtlpriv->entry_list, list)
0848             cnt++;
0849         spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
0850 
0851         if (cnt == 1)
0852             rtlpriv->dm.one_entry_only = true;
0853     }
0854 }
0855 
0856 static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
0857 {
0858     struct rtl_priv *rtlpriv = rtl_priv(hw);
0859     struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
0860     u32 cck_enable = 0;
0861 
0862     /*read OFDM FA counter*/
0863     falsealm_cnt->cnt_ofdm_fail =
0864         rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD);
0865     falsealm_cnt->cnt_cck_fail =
0866         rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD);
0867 
0868     cck_enable =  rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28));
0869     if (cck_enable)  /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/
0870         falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
0871                     falsealm_cnt->cnt_cck_fail;
0872     else
0873         falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
0874 
0875     /*reset OFDM FA counter*/
0876     rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
0877     rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
0878     /* reset CCK FA counter*/
0879     rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
0880     rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
0881 
0882     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n",
0883         falsealm_cnt->cnt_cck_fail);
0884     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n",
0885         falsealm_cnt->cnt_ofdm_fail);
0886     rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n",
0887         falsealm_cnt->cnt_all);
0888 }
0889 
0890 static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
0891         struct ieee80211_hw *hw)
0892 {
0893     struct rtl_priv *rtlpriv = rtl_priv(hw);
0894 
0895     if (!rtlpriv->dm.tm_trigger) {
0896         rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
0897                   BIT(17) | BIT(16), 0x03);
0898         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0899             "Trigger 8812 Thermal Meter!!\n");
0900         rtlpriv->dm.tm_trigger = 1;
0901         return;
0902     }
0903     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0904         "Schedule TxPowerTracking direct call!!\n");
0905     rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
0906 }
0907 
0908 static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
0909 {
0910     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
0911     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
0912     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0913 
0914     if (mac->link_state >= MAC80211_LINKED) {
0915         if (rtldm->linked_interval < 3)
0916             rtldm->linked_interval++;
0917 
0918         if (rtldm->linked_interval == 2) {
0919             if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
0920                 rtl8812ae_phy_iq_calibrate(hw, false);
0921             else
0922                 rtl8821ae_phy_iq_calibrate(hw, false);
0923         }
0924     } else {
0925         rtldm->linked_interval = 0;
0926     }
0927 }
0928 
0929 static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
0930                         const u8 **up_a,
0931                         const u8 **down_a,
0932                         const u8 **up_b,
0933                         const u8 **down_b)
0934 {
0935     struct rtl_priv *rtlpriv = rtl_priv(hw);
0936     struct rtl_phy *rtlphy = &rtlpriv->phy;
0937     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
0938     u8 channel = rtlphy->current_channel;
0939     u8 rate = rtldm->tx_rate;
0940 
0941     if (1 <= channel && channel <= 14) {
0942         if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
0943             *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p;
0944             *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n;
0945             *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p;
0946             *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n;
0947         } else {
0948             *up_a = rtl8812ae_delta_swing_table_idx_24ga_p;
0949             *down_a = rtl8812ae_delta_swing_table_idx_24ga_n;
0950             *up_b = rtl8812ae_delta_swing_table_idx_24gb_p;
0951             *down_b = rtl8812ae_delta_swing_table_idx_24gb_n;
0952         }
0953     } else if (36 <= channel && channel <= 64) {
0954         *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0];
0955         *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0];
0956         *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0];
0957         *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0];
0958     } else if (100 <= channel && channel <= 140) {
0959         *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1];
0960         *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1];
0961         *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1];
0962         *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1];
0963     } else if (149 <= channel && channel <= 173) {
0964         *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2];
0965         *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2];
0966         *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2];
0967         *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2];
0968     } else {
0969         *up_a = rtl8818e_delta_swing_table_idx_24gb_p;
0970         *down_a = rtl8818e_delta_swing_table_idx_24gb_n;
0971         *up_b = rtl8818e_delta_swing_table_idx_24gb_p;
0972         *down_b = rtl8818e_delta_swing_table_idx_24gb_n;
0973     }
0974 }
0975 
0976 void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
0977 {
0978     struct rtl_priv *rtlpriv = rtl_priv(hw);
0979     struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
0980     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
0981     u8 p = 0;
0982 
0983     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
0984         "Get C2H Command! Rate=0x%x\n", rate);
0985 
0986     rtldm->tx_rate = rate;
0987 
0988     if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
0989         rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
0990     } else {
0991         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
0992             rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
0993     }
0994 }
0995 
0996 u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
0997 {
0998     struct rtl_priv *rtlpriv = rtl_priv(hw);
0999     u8 ret_rate = MGN_1M;
1000 
1001     switch (rate) {
1002     case DESC_RATE1M:
1003         ret_rate = MGN_1M;
1004         break;
1005     case DESC_RATE2M:
1006         ret_rate = MGN_2M;
1007         break;
1008     case DESC_RATE5_5M:
1009         ret_rate = MGN_5_5M;
1010         break;
1011     case DESC_RATE11M:
1012         ret_rate = MGN_11M;
1013         break;
1014     case DESC_RATE6M:
1015         ret_rate = MGN_6M;
1016         break;
1017     case DESC_RATE9M:
1018         ret_rate = MGN_9M;
1019         break;
1020     case DESC_RATE12M:
1021         ret_rate = MGN_12M;
1022         break;
1023     case DESC_RATE18M:
1024         ret_rate = MGN_18M;
1025         break;
1026     case DESC_RATE24M:
1027         ret_rate = MGN_24M;
1028         break;
1029     case DESC_RATE36M:
1030         ret_rate = MGN_36M;
1031         break;
1032     case DESC_RATE48M:
1033         ret_rate = MGN_48M;
1034         break;
1035     case DESC_RATE54M:
1036         ret_rate = MGN_54M;
1037         break;
1038     case DESC_RATEMCS0:
1039         ret_rate = MGN_MCS0;
1040         break;
1041     case DESC_RATEMCS1:
1042         ret_rate = MGN_MCS1;
1043         break;
1044     case DESC_RATEMCS2:
1045         ret_rate = MGN_MCS2;
1046         break;
1047     case DESC_RATEMCS3:
1048         ret_rate = MGN_MCS3;
1049         break;
1050     case DESC_RATEMCS4:
1051         ret_rate = MGN_MCS4;
1052         break;
1053     case DESC_RATEMCS5:
1054         ret_rate = MGN_MCS5;
1055         break;
1056     case DESC_RATEMCS6:
1057         ret_rate = MGN_MCS6;
1058         break;
1059     case DESC_RATEMCS7:
1060         ret_rate = MGN_MCS7;
1061         break;
1062     case DESC_RATEMCS8:
1063         ret_rate = MGN_MCS8;
1064         break;
1065     case DESC_RATEMCS9:
1066         ret_rate = MGN_MCS9;
1067         break;
1068     case DESC_RATEMCS10:
1069         ret_rate = MGN_MCS10;
1070         break;
1071     case DESC_RATEMCS11:
1072         ret_rate = MGN_MCS11;
1073         break;
1074     case DESC_RATEMCS12:
1075         ret_rate = MGN_MCS12;
1076         break;
1077     case DESC_RATEMCS13:
1078         ret_rate = MGN_MCS13;
1079         break;
1080     case DESC_RATEMCS14:
1081         ret_rate = MGN_MCS14;
1082         break;
1083     case DESC_RATEMCS15:
1084         ret_rate = MGN_MCS15;
1085         break;
1086     case DESC_RATEVHT1SS_MCS0:
1087         ret_rate = MGN_VHT1SS_MCS0;
1088         break;
1089     case DESC_RATEVHT1SS_MCS1:
1090         ret_rate = MGN_VHT1SS_MCS1;
1091         break;
1092     case DESC_RATEVHT1SS_MCS2:
1093         ret_rate = MGN_VHT1SS_MCS2;
1094         break;
1095     case DESC_RATEVHT1SS_MCS3:
1096         ret_rate = MGN_VHT1SS_MCS3;
1097         break;
1098     case DESC_RATEVHT1SS_MCS4:
1099         ret_rate = MGN_VHT1SS_MCS4;
1100         break;
1101     case DESC_RATEVHT1SS_MCS5:
1102         ret_rate = MGN_VHT1SS_MCS5;
1103         break;
1104     case DESC_RATEVHT1SS_MCS6:
1105         ret_rate = MGN_VHT1SS_MCS6;
1106         break;
1107     case DESC_RATEVHT1SS_MCS7:
1108         ret_rate = MGN_VHT1SS_MCS7;
1109         break;
1110     case DESC_RATEVHT1SS_MCS8:
1111         ret_rate = MGN_VHT1SS_MCS8;
1112         break;
1113     case DESC_RATEVHT1SS_MCS9:
1114         ret_rate = MGN_VHT1SS_MCS9;
1115         break;
1116     case DESC_RATEVHT2SS_MCS0:
1117         ret_rate = MGN_VHT2SS_MCS0;
1118         break;
1119     case DESC_RATEVHT2SS_MCS1:
1120         ret_rate = MGN_VHT2SS_MCS1;
1121         break;
1122     case DESC_RATEVHT2SS_MCS2:
1123         ret_rate = MGN_VHT2SS_MCS2;
1124         break;
1125     case DESC_RATEVHT2SS_MCS3:
1126         ret_rate = MGN_VHT2SS_MCS3;
1127         break;
1128     case DESC_RATEVHT2SS_MCS4:
1129         ret_rate = MGN_VHT2SS_MCS4;
1130         break;
1131     case DESC_RATEVHT2SS_MCS5:
1132         ret_rate = MGN_VHT2SS_MCS5;
1133         break;
1134     case DESC_RATEVHT2SS_MCS6:
1135         ret_rate = MGN_VHT2SS_MCS6;
1136         break;
1137     case DESC_RATEVHT2SS_MCS7:
1138         ret_rate = MGN_VHT2SS_MCS7;
1139         break;
1140     case DESC_RATEVHT2SS_MCS8:
1141         ret_rate = MGN_VHT2SS_MCS8;
1142         break;
1143     case DESC_RATEVHT2SS_MCS9:
1144         ret_rate = MGN_VHT2SS_MCS9;
1145         break;
1146     default:
1147         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1148             "HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1149             rate);
1150         break;
1151     }
1152     return ret_rate;
1153 }
1154 
1155 /*-----------------------------------------------------------------------------
1156  * Function:    odm_TxPwrTrackSetPwr88E()
1157  *
1158  * Overview:    88E change all channel tx power accordign to flag.
1159  *              OFDM & CCK are all different.
1160  *
1161  * Input:       NONE
1162  *
1163  * Output:      NONE
1164  *
1165  * Return:      NONE
1166  *
1167  * Revised History:
1168  *  When        Who     Remark
1169  *  04/23/2012  MHC     Create Version 0.
1170  *
1171  *---------------------------------------------------------------------------
1172  */
1173 void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1174                       enum pwr_track_control_method method,
1175                       u8 rf_path, u8 channel_mapped_index)
1176 {
1177     struct rtl_priv *rtlpriv = rtl_priv(hw);
1178     struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1179     struct rtl_phy *rtlphy = &rtlpriv->phy;
1180     u32 final_swing_idx[2];
1181     u8 pwr_tracking_limit = 26; /*+1.0dB*/
1182     u8 tx_rate = 0xFF;
1183     s8 final_ofdm_swing_index = 0;
1184 
1185     if (rtldm->tx_rate != 0xFF)
1186         tx_rate =
1187             rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1188 
1189     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1190         "===>%s\n", __func__);
1191     /*20130429 Mimic Modify High Rate BBSwing Limit.*/
1192     if (tx_rate != 0xFF) {
1193         /*CCK*/
1194         if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1195             pwr_tracking_limit = 32; /*+4dB*/
1196         /*OFDM*/
1197         else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1198             pwr_tracking_limit = 30; /*+3dB*/
1199         else if (tx_rate == MGN_54M)
1200             pwr_tracking_limit = 28; /*+2dB*/
1201         /*HT*/
1202          /*QPSK/BPSK*/
1203         else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1204             pwr_tracking_limit = 34; /*+5dB*/
1205          /*16QAM*/
1206         else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1207             pwr_tracking_limit = 30; /*+3dB*/
1208          /*64QAM*/
1209         else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1210             pwr_tracking_limit = 28; /*+2dB*/
1211          /*QPSK/BPSK*/
1212         else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1213             pwr_tracking_limit = 34; /*+5dB*/
1214          /*16QAM*/
1215         else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1216             pwr_tracking_limit = 30; /*+3dB*/
1217          /*64QAM*/
1218         else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1219             pwr_tracking_limit = 28; /*+2dB*/
1220 
1221         /*2 VHT*/
1222          /*QPSK/BPSK*/
1223         else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1224              (tx_rate <= MGN_VHT1SS_MCS2))
1225             pwr_tracking_limit = 34; /*+5dB*/
1226          /*16QAM*/
1227         else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1228              (tx_rate <= MGN_VHT1SS_MCS4))
1229             pwr_tracking_limit = 30; /*+3dB*/
1230          /*64QAM*/
1231         else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1232              (tx_rate <= MGN_VHT1SS_MCS6))
1233             pwr_tracking_limit = 28; /*+2dB*/
1234         else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1235             pwr_tracking_limit = 26; /*+1dB*/
1236         else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1237             pwr_tracking_limit = 24; /*+0dB*/
1238         else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1239             pwr_tracking_limit = 22; /*-1dB*/
1240          /*QPSK/BPSK*/
1241         else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1242              (tx_rate <= MGN_VHT2SS_MCS2))
1243             pwr_tracking_limit = 34; /*+5dB*/
1244          /*16QAM*/
1245         else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1246              (tx_rate <= MGN_VHT2SS_MCS4))
1247             pwr_tracking_limit = 30; /*+3dB*/
1248          /*64QAM*/
1249         else if ((tx_rate >= MGN_VHT2SS_MCS5) &&
1250              (tx_rate <= MGN_VHT2SS_MCS6))
1251             pwr_tracking_limit = 28; /*+2dB*/
1252         else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/
1253             pwr_tracking_limit = 26; /*+1dB*/
1254         else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/
1255             pwr_tracking_limit = 24; /*+0dB*/
1256         else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/
1257             pwr_tracking_limit = 22; /*-1dB*/
1258         else
1259             pwr_tracking_limit = 24;
1260     }
1261     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1262         "TxRate=0x%x, PwrTrackingLimit=%d\n",
1263         tx_rate, pwr_tracking_limit);
1264 
1265     if (method == BBSWING) {
1266         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1267             "===>%s\n", __func__);
1268 
1269         if (rf_path == RF90_PATH_A) {
1270             u32 tmp;
1271 
1272             final_swing_idx[RF90_PATH_A] =
1273                 (rtldm->ofdm_index[RF90_PATH_A] >
1274                 pwr_tracking_limit) ?
1275                 pwr_tracking_limit :
1276                 rtldm->ofdm_index[RF90_PATH_A];
1277             tmp = final_swing_idx[RF90_PATH_A];
1278             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1279                 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1280                 rtldm->ofdm_index[RF90_PATH_A],
1281                 final_swing_idx[RF90_PATH_A]);
1282 
1283             rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1284                       txscaling_tbl[tmp]);
1285         } else {
1286             u32 tmp;
1287 
1288             final_swing_idx[RF90_PATH_B] =
1289                 rtldm->ofdm_index[RF90_PATH_B] >
1290                 pwr_tracking_limit ?
1291                 pwr_tracking_limit :
1292                 rtldm->ofdm_index[RF90_PATH_B];
1293             tmp = final_swing_idx[RF90_PATH_B];
1294             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1295                 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n",
1296                 rtldm->ofdm_index[RF90_PATH_B],
1297                 final_swing_idx[RF90_PATH_B]);
1298 
1299             rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1300                       txscaling_tbl[tmp]);
1301         }
1302     } else if (method == MIX_MODE) {
1303         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1304             "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1305             rtldm->default_ofdm_index,
1306             rtldm->absolute_ofdm_swing_idx[rf_path],
1307             rf_path);
1308 
1309         final_ofdm_swing_index = rtldm->default_ofdm_index +
1310                 rtldm->absolute_ofdm_swing_idx[rf_path];
1311 
1312         if (rf_path == RF90_PATH_A) {
1313             /*BBSwing higher then Limit*/
1314             if (final_ofdm_swing_index > pwr_tracking_limit) {
1315                 rtldm->remnant_cck_idx =
1316                     final_ofdm_swing_index -
1317                     pwr_tracking_limit;
1318                 /* CCK Follow the same compensation value
1319                  * as Path A
1320                  */
1321                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1322                     final_ofdm_swing_index -
1323                     pwr_tracking_limit;
1324 
1325                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1326                           txscaling_tbl[pwr_tracking_limit]);
1327 
1328                 rtldm->modify_txagc_flag_path_a = true;
1329 
1330                 /*Set TxAGC Page C{};*/
1331                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1332                     rtlphy->current_channel,
1333                     RF90_PATH_A);
1334 
1335                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1336                     "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
1337                     pwr_tracking_limit,
1338                     rtldm->remnant_ofdm_swing_idx[rf_path]);
1339             } else if (final_ofdm_swing_index < 0) {
1340                 rtldm->remnant_cck_idx = final_ofdm_swing_index;
1341                 /* CCK Follow the same compensate value as Path A*/
1342                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1343                     final_ofdm_swing_index;
1344 
1345                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1346                     txscaling_tbl[0]);
1347 
1348                 rtldm->modify_txagc_flag_path_a = true;
1349 
1350                 /*Set TxAGC Page C{};*/
1351                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1352                     rtlphy->current_channel, RF90_PATH_A);
1353 
1354                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1355                     "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1356                     rtldm->remnant_ofdm_swing_idx[rf_path]);
1357             } else {
1358                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1359                     txscaling_tbl[(u8)final_ofdm_swing_index]);
1360 
1361                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1362                     "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n",
1363                     final_ofdm_swing_index);
1364                 /*If TxAGC has changed, reset TxAGC again*/
1365                 if (rtldm->modify_txagc_flag_path_a) {
1366                     rtldm->remnant_cck_idx = 0;
1367                     rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1368 
1369                     /*Set TxAGC Page C{};*/
1370                     rtl8821ae_phy_set_txpower_level_by_path(hw,
1371                         rtlphy->current_channel, RF90_PATH_A);
1372                     rtldm->modify_txagc_flag_path_a = false;
1373 
1374                     rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
1375                         DBG_LOUD,
1376                         "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1377                 }
1378             }
1379         }
1380         /*BBSwing higher then Limit*/
1381         if (rf_path == RF90_PATH_B) {
1382             if (final_ofdm_swing_index > pwr_tracking_limit) {
1383                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1384                     final_ofdm_swing_index -
1385                     pwr_tracking_limit;
1386 
1387                 rtl_set_bbreg(hw, RB_TXSCALE,
1388                     0xFFE00000,
1389                     txscaling_tbl[pwr_tracking_limit]);
1390 
1391                 rtldm->modify_txagc_flag_path_b = true;
1392 
1393                 /*Set TxAGC Page E{};*/
1394                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1395                     rtlphy->current_channel, RF90_PATH_B);
1396 
1397                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1398                     "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1399                     pwr_tracking_limit,
1400                      rtldm->remnant_ofdm_swing_idx[rf_path]);
1401             } else if (final_ofdm_swing_index < 0) {
1402                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1403                     final_ofdm_swing_index;
1404 
1405                 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1406                           txscaling_tbl[0]);
1407 
1408                 rtldm->modify_txagc_flag_path_b = true;
1409 
1410                 /*Set TxAGC Page E{};*/
1411                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1412                     rtlphy->current_channel, RF90_PATH_B);
1413 
1414                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1415                     "******Path_B Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1416                     rtldm->remnant_ofdm_swing_idx[rf_path]);
1417             } else {
1418                 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1419                     txscaling_tbl[(u8)final_ofdm_swing_index]);
1420 
1421                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1422                     "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1423                     final_ofdm_swing_index);
1424                  /*If TxAGC has changed, reset TxAGC again*/
1425                 if (rtldm->modify_txagc_flag_path_b) {
1426                     rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1427 
1428                     /*Set TxAGC Page E{};*/
1429                     rtl8821ae_phy_set_txpower_level_by_path(hw,
1430                     rtlphy->current_channel, RF90_PATH_B);
1431 
1432                     rtldm->modify_txagc_flag_path_b =
1433                         false;
1434 
1435                     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1436                         "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1437                 }
1438             }
1439         }
1440     } else {
1441         return;
1442     }
1443 }
1444 
1445 void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1446     struct ieee80211_hw *hw)
1447 {
1448     struct rtl_priv *rtlpriv = rtl_priv(hw);
1449     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1450     struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1451     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1452     u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
1453     u8 thermal_value_avg_count = 0;
1454     u32 thermal_value_avg = 0;
1455     /* OFDM BB Swing should be less than +3.0dB, */
1456     u8 ofdm_min_index = 6;
1457      /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
1458     u8 index_for_channel = 0;
1459     /* 1. The following TWO tables decide
1460      * the final index of OFDM/CCK swing table.
1461      */
1462     const u8 *delta_swing_table_idx_tup_a;
1463     const u8 *delta_swing_table_idx_tdown_a;
1464     const u8 *delta_swing_table_idx_tup_b;
1465     const u8 *delta_swing_table_idx_tdown_b;
1466 
1467     /*2. Initialization ( 7 steps in total )*/
1468     rtl8812ae_get_delta_swing_table(hw,
1469         &delta_swing_table_idx_tup_a,
1470         &delta_swing_table_idx_tdown_a,
1471         &delta_swing_table_idx_tup_b,
1472         &delta_swing_table_idx_tdown_b);
1473 
1474     rtldm->txpower_trackinginit = true;
1475 
1476     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1477         "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
1478         rtldm->swing_idx_cck_base,
1479         rtldm->swing_idx_ofdm_base[RF90_PATH_A],
1480         rtldm->default_ofdm_index);
1481 
1482     thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A,
1483         /*0x42: RF Reg[15:10] 88E*/
1484         RF_T_METER_8812A, 0xfc00);
1485     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1486         "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1487         thermal_value, rtlefuse->eeprom_thermalmeter);
1488     if (!rtldm->txpower_track_control ||
1489         rtlefuse->eeprom_thermalmeter == 0 ||
1490         rtlefuse->eeprom_thermalmeter == 0xFF)
1491         return;
1492 
1493     /* 3. Initialize ThermalValues of RFCalibrateInfo*/
1494 
1495     if (rtlhal->reloadtxpowerindex)
1496         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1497             "reload ofdm index for band switch\n");
1498 
1499     /*4. Calculate average thermal meter*/
1500     rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
1501     rtldm->thermalvalue_avg_index++;
1502     if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
1503         /*Average times =  c.AverageThermalNum*/
1504         rtldm->thermalvalue_avg_index = 0;
1505 
1506     for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
1507         if (rtldm->thermalvalue_avg[i]) {
1508             thermal_value_avg += rtldm->thermalvalue_avg[i];
1509             thermal_value_avg_count++;
1510         }
1511     }
1512     /*Calculate Average ThermalValue after average enough times*/
1513     if (thermal_value_avg_count) {
1514         thermal_value = (u8)(thermal_value_avg /
1515                 thermal_value_avg_count);
1516         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1517             "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1518             thermal_value, rtlefuse->eeprom_thermalmeter);
1519     }
1520 
1521     /*5. Calculate delta, delta_LCK, delta_IQK.
1522      *"delta" here is used to determine whether
1523      *thermal value changes or not.
1524      */
1525     delta = (thermal_value > rtldm->thermalvalue) ?
1526         (thermal_value - rtldm->thermalvalue) :
1527         (rtldm->thermalvalue - thermal_value);
1528     delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
1529         (thermal_value - rtldm->thermalvalue_lck) :
1530         (rtldm->thermalvalue_lck - thermal_value);
1531     delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
1532         (thermal_value - rtldm->thermalvalue_iqk) :
1533         (rtldm->thermalvalue_iqk - thermal_value);
1534 
1535     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1536         "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
1537         delta, delta_lck, delta_iqk);
1538 
1539     /* 6. If necessary, do LCK.
1540      * Delta temperature is equal to or larger than 20 centigrade.
1541      */
1542     if (delta_lck >= IQK_THRESHOLD) {
1543         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1544             "delta_LCK(%d) >= Threshold_IQK(%d)\n",
1545             delta_lck, IQK_THRESHOLD);
1546         rtldm->thermalvalue_lck = thermal_value;
1547         rtl8821ae_phy_lc_calibrate(hw);
1548     }
1549 
1550     /*7. If necessary, move the index of swing table to adjust Tx power.*/
1551 
1552     if (delta > 0 && rtldm->txpower_track_control) {
1553         /* "delta" here is used to record the
1554          * absolute value of differrence.
1555          */
1556         delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1557             (thermal_value - rtlefuse->eeprom_thermalmeter) :
1558             (rtlefuse->eeprom_thermalmeter - thermal_value);
1559 
1560         if (delta >= TXPWR_TRACK_TABLE_SIZE)
1561             delta = TXPWR_TRACK_TABLE_SIZE - 1;
1562 
1563         /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
1564 
1565         if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1566             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1567                 "delta_swing_table_idx_tup_a[%d] = %d\n",
1568                 delta, delta_swing_table_idx_tup_a[delta]);
1569             rtldm->delta_power_index_last[RF90_PATH_A] =
1570                 rtldm->delta_power_index[RF90_PATH_A];
1571             rtldm->delta_power_index[RF90_PATH_A] =
1572                 delta_swing_table_idx_tup_a[delta];
1573 
1574             rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1575                 delta_swing_table_idx_tup_a[delta];
1576             /*Record delta swing for mix mode power tracking*/
1577 
1578             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1579                 "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1580             rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1581 
1582             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1583                 "delta_swing_table_idx_tup_b[%d] = %d\n",
1584                 delta, delta_swing_table_idx_tup_b[delta]);
1585             rtldm->delta_power_index_last[RF90_PATH_B] =
1586                 rtldm->delta_power_index[RF90_PATH_B];
1587             rtldm->delta_power_index[RF90_PATH_B] =
1588                 delta_swing_table_idx_tup_b[delta];
1589 
1590             rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1591                 delta_swing_table_idx_tup_b[delta];
1592             /*Record delta swing for mix mode power tracking*/
1593 
1594             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1595                 "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1596                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1597         } else {
1598             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1599                 "delta_swing_table_idx_tdown_a[%d] = %d\n",
1600                 delta, delta_swing_table_idx_tdown_a[delta]);
1601 
1602             rtldm->delta_power_index_last[RF90_PATH_A] =
1603                 rtldm->delta_power_index[RF90_PATH_A];
1604             rtldm->delta_power_index[RF90_PATH_A] =
1605                 -1 * delta_swing_table_idx_tdown_a[delta];
1606 
1607             rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1608                 -1 * delta_swing_table_idx_tdown_a[delta];
1609             /* Record delta swing for mix mode power tracking*/
1610             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1611                 "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1612                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1613 
1614             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1615                 "deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
1616                 delta, delta_swing_table_idx_tdown_b[delta]);
1617 
1618             rtldm->delta_power_index_last[RF90_PATH_B] =
1619                 rtldm->delta_power_index[RF90_PATH_B];
1620             rtldm->delta_power_index[RF90_PATH_B] =
1621                 -1 * delta_swing_table_idx_tdown_b[delta];
1622 
1623             rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1624                 -1 * delta_swing_table_idx_tdown_b[delta];
1625             /*Record delta swing for mix mode power tracking*/
1626 
1627             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1628                 "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1629                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1630         }
1631 
1632         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1633             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1634                 "============================= [Path-%c]Calculating PowerIndexOffset =============================\n",
1635                 (p == RF90_PATH_A ? 'A' : 'B'));
1636 
1637             if (rtldm->delta_power_index[p] ==
1638                 rtldm->delta_power_index_last[p])
1639                 /*If Thermal value changes but lookup
1640                 table value still the same*/
1641                 rtldm->power_index_offset[p] = 0;
1642             else
1643                 rtldm->power_index_offset[p] =
1644                     rtldm->delta_power_index[p] -
1645                     rtldm->delta_power_index_last[p];
1646                 /* Power Index Diff between 2
1647                  * times Power Tracking
1648                  */
1649             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1650                 "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n",
1651                 (p == RF90_PATH_A ? 'A' : 'B'),
1652                 rtldm->power_index_offset[p],
1653                 rtldm->delta_power_index[p],
1654                 rtldm->delta_power_index_last[p]);
1655 
1656             rtldm->ofdm_index[p] =
1657                     rtldm->swing_idx_ofdm_base[p] +
1658                     rtldm->power_index_offset[p];
1659             rtldm->cck_index =
1660                     rtldm->swing_idx_cck_base +
1661                     rtldm->power_index_offset[p];
1662 
1663             rtldm->swing_idx_cck = rtldm->cck_index;
1664             rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1665 
1666             /****Print BB Swing Base and Index Offset */
1667 
1668             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1669                 "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
1670                 rtldm->swing_idx_cck,
1671                 rtldm->swing_idx_cck_base,
1672                 rtldm->power_index_offset[p]);
1673             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1674                 "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
1675                 rtldm->swing_idx_ofdm[p],
1676                 (p == RF90_PATH_A ? 'A' : 'B'),
1677                 rtldm->swing_idx_ofdm_base[p],
1678                 rtldm->power_index_offset[p]);
1679 
1680             /*7.1 Handle boundary conditions of index.*/
1681 
1682             if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
1683                 rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
1684             else if (rtldm->ofdm_index[p] < ofdm_min_index)
1685                 rtldm->ofdm_index[p] = ofdm_min_index;
1686         }
1687         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1688             "\n\n====================================================================================\n");
1689         if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
1690             rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
1691         else if (rtldm->cck_index < 0)
1692             rtldm->cck_index = 0;
1693     } else {
1694         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1695             "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
1696             rtldm->txpower_track_control,
1697             thermal_value,
1698             rtldm->thermalvalue);
1699 
1700         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1701             rtldm->power_index_offset[p] = 0;
1702     }
1703     /*Print Swing base & current*/
1704     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1705         "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n",
1706         rtldm->cck_index, rtldm->swing_idx_cck_base);
1707     for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1708         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1709             "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n",
1710             rtldm->ofdm_index[p],
1711             (p == RF90_PATH_A ? 'A' : 'B'),
1712             rtldm->swing_idx_ofdm_base[p]);
1713     }
1714 
1715     if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
1716         rtldm->power_index_offset[RF90_PATH_B] != 0) &&
1717         rtldm->txpower_track_control) {
1718         /*7.2 Configure the Swing Table to adjust Tx Power.
1719          *Always TRUE after Tx Power is adjusted by power tracking.
1720          *
1721          *2012/04/23 MH According to Luke's suggestion,
1722          *we can not write BB digital
1723          *to increase TX power. Otherwise, EVM will be bad.
1724          *
1725          *2012/04/25 MH Add for tx power tracking to set
1726          *tx power in tx agc for 88E.
1727          */
1728         if (thermal_value > rtldm->thermalvalue) {
1729             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1730                 "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n",
1731                 rtldm->power_index_offset[RF90_PATH_A],
1732                 delta, thermal_value,
1733                 rtlefuse->eeprom_thermalmeter,
1734                 rtldm->thermalvalue);
1735 
1736             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1737                 "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1738                 rtldm->power_index_offset[RF90_PATH_B],
1739                 delta, thermal_value,
1740                 rtlefuse->eeprom_thermalmeter,
1741                 rtldm->thermalvalue);
1742         } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
1743             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1744                 "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1745                 rtldm->power_index_offset[RF90_PATH_A],
1746                 delta, thermal_value,
1747                 rtlefuse->eeprom_thermalmeter,
1748                 rtldm->thermalvalue);
1749 
1750             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1751                 "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1752                 rtldm->power_index_offset[RF90_PATH_B],
1753                 delta, thermal_value,
1754                 rtlefuse->eeprom_thermalmeter,
1755                 rtldm->thermalvalue);
1756         }
1757 
1758         if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1759             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1760                 "Temperature(%d) higher than PG value(%d)\n",
1761                 thermal_value, rtlefuse->eeprom_thermalmeter);
1762 
1763             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1764                 "**********Enter POWER Tracking MIX_MODE**********\n");
1765             for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1766                 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1767                                  p, 0);
1768         } else {
1769             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1770                 "Temperature(%d) lower than PG value(%d)\n",
1771                 thermal_value, rtlefuse->eeprom_thermalmeter);
1772 
1773             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1774                 "**********Enter POWER Tracking MIX_MODE**********\n");
1775             for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1776                 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1777                                  p, index_for_channel);
1778         }
1779         /*Record last time Power Tracking result as base.*/
1780         rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
1781         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1782                 rtldm->swing_idx_ofdm_base[p] =
1783                     rtldm->swing_idx_ofdm[p];
1784 
1785         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1786             "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n",
1787             rtldm->thermalvalue, thermal_value);
1788         /*Record last Power Tracking Thermal Value*/
1789         rtldm->thermalvalue = thermal_value;
1790     }
1791     /*Delta temperature is equal to or larger than
1792     20 centigrade (When threshold is 8).*/
1793     if (delta_iqk >= IQK_THRESHOLD)
1794         rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8);
1795 
1796     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1797         "<===%s\n", __func__);
1798 }
1799 
1800 static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw,
1801                         const u8 **up_a,
1802                         const u8 **down_a)
1803 {
1804     struct rtl_priv *rtlpriv = rtl_priv(hw);
1805     struct rtl_phy *rtlphy = &rtlpriv->phy;
1806     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1807     u8 channel = rtlphy->current_channel;
1808     u8 rate = rtldm->tx_rate;
1809 
1810     if (1 <= channel && channel <= 14) {
1811         if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1812             *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p;
1813             *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n;
1814         } else {
1815             *up_a = rtl8821ae_delta_swing_table_idx_24ga_p;
1816             *down_a = rtl8821ae_delta_swing_table_idx_24ga_n;
1817         }
1818     } else if (36 <= channel && channel <= 64) {
1819         *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0];
1820         *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0];
1821     } else if (100 <= channel && channel <= 140) {
1822         *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1];
1823         *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1];
1824     } else if (149 <= channel && channel <= 173) {
1825         *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2];
1826         *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2];
1827     } else {
1828         *up_a = rtl8818e_delta_swing_table_idx_24gb_p;
1829         *down_a = rtl8818e_delta_swing_table_idx_24gb_n;
1830     }
1831     return;
1832 }
1833 
1834 /*-----------------------------------------------------------------------------
1835  * Function:    odm_TxPwrTrackSetPwr88E()
1836  *
1837  * Overview:    88E change all channel tx power accordign to flag.
1838  *              OFDM & CCK are all different.
1839  *
1840  * Input:       NONE
1841  *
1842  * Output:      NONE
1843  *
1844  * Return:      NONE
1845  *
1846  * Revised History:
1847  *  When        Who     Remark
1848  *  04/23/2012  MHC     Create Version 0.
1849  *
1850  *---------------------------------------------------------------------------
1851  */
1852 void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1853                       enum pwr_track_control_method method,
1854                       u8 rf_path, u8 channel_mapped_index)
1855 {
1856     struct rtl_priv *rtlpriv = rtl_priv(hw);
1857     struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1858     struct rtl_phy *rtlphy = &rtlpriv->phy;
1859     u32 final_swing_idx[1];
1860     u8 pwr_tracking_limit = 26; /*+1.0dB*/
1861     u8 tx_rate = 0xFF;
1862     s8 final_ofdm_swing_index = 0;
1863 
1864     if (rtldm->tx_rate != 0xFF)
1865         tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1866 
1867     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
1868 
1869     if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
1870         /*CCK*/
1871         if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1872             pwr_tracking_limit = 32; /*+4dB*/
1873         /*OFDM*/
1874         else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1875             pwr_tracking_limit = 30; /*+3dB*/
1876         else if (tx_rate == MGN_54M)
1877             pwr_tracking_limit = 28; /*+2dB*/
1878         /*HT*/
1879         /*QPSK/BPSK*/
1880         else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1881             pwr_tracking_limit = 34; /*+5dB*/
1882         /*16QAM*/
1883         else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1884             pwr_tracking_limit = 30; /*+3dB*/
1885         /*64QAM*/
1886         else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1887             pwr_tracking_limit = 28; /*+2dB*/
1888         /*2 VHT*/
1889         /*QPSK/BPSK*/
1890         else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1891             (tx_rate <= MGN_VHT1SS_MCS2))
1892             pwr_tracking_limit = 34; /*+5dB*/
1893         /*16QAM*/
1894         else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1895             (tx_rate <= MGN_VHT1SS_MCS4))
1896             pwr_tracking_limit = 30; /*+3dB*/
1897         /*64QAM*/
1898         else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1899             (tx_rate <= MGN_VHT1SS_MCS6))
1900             pwr_tracking_limit = 28; /*+2dB*/
1901         else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1902             pwr_tracking_limit = 26; /*+1dB*/
1903         else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1904             pwr_tracking_limit = 24; /*+0dB*/
1905         else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1906             pwr_tracking_limit = 22; /*-1dB*/
1907         else
1908             pwr_tracking_limit = 24;
1909     }
1910     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1911         "TxRate=0x%x, PwrTrackingLimit=%d\n",
1912         tx_rate, pwr_tracking_limit);
1913 
1914     if (method == BBSWING) {
1915         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1916             "===>%s\n", __func__);
1917         if (rf_path == RF90_PATH_A) {
1918             final_swing_idx[RF90_PATH_A] =
1919                 (rtldm->ofdm_index[RF90_PATH_A] >
1920                 pwr_tracking_limit) ?
1921                 pwr_tracking_limit :
1922                 rtldm->ofdm_index[RF90_PATH_A];
1923             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1924                 "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1925                 rtldm->ofdm_index[RF90_PATH_A],
1926                 final_swing_idx[RF90_PATH_A]);
1927 
1928             rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1929                 txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
1930         }
1931     } else if (method == MIX_MODE) {
1932         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1933             "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1934             rtldm->default_ofdm_index,
1935             rtldm->absolute_ofdm_swing_idx[rf_path],
1936             rf_path);
1937 
1938         final_ofdm_swing_index =
1939             rtldm->default_ofdm_index +
1940             rtldm->absolute_ofdm_swing_idx[rf_path];
1941         /*BBSwing higher then Limit*/
1942         if (rf_path == RF90_PATH_A) {
1943             if (final_ofdm_swing_index > pwr_tracking_limit) {
1944                 rtldm->remnant_cck_idx =
1945                     final_ofdm_swing_index -
1946                     pwr_tracking_limit;
1947                 /* CCK Follow the same compensate value as Path A*/
1948                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1949                     final_ofdm_swing_index -
1950                     pwr_tracking_limit;
1951 
1952                 rtl_set_bbreg(hw, RA_TXSCALE,
1953                     0xFFE00000,
1954                     txscaling_tbl[pwr_tracking_limit]);
1955 
1956                 rtldm->modify_txagc_flag_path_a = true;
1957 
1958                 /*Set TxAGC Page C{};*/
1959                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1960                     rtlphy->current_channel,
1961                     RF90_PATH_A);
1962 
1963                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1964                     " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1965                     pwr_tracking_limit,
1966                     rtldm->remnant_ofdm_swing_idx[rf_path]);
1967             } else if (final_ofdm_swing_index < 0) {
1968                 rtldm->remnant_cck_idx = final_ofdm_swing_index;
1969                 /* CCK Follow the same compensate value as Path A*/
1970                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1971                     final_ofdm_swing_index;
1972 
1973                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1974                     txscaling_tbl[0]);
1975 
1976                 rtldm->modify_txagc_flag_path_a = true;
1977 
1978                 /*Set TxAGC Page C{};*/
1979                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1980                     rtlphy->current_channel, RF90_PATH_A);
1981 
1982                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1983                     "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1984                     rtldm->remnant_ofdm_swing_idx[rf_path]);
1985             } else {
1986                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1987                     txscaling_tbl[(u8)final_ofdm_swing_index]);
1988 
1989                 rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1990                     "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1991                     final_ofdm_swing_index);
1992                 /*If TxAGC has changed, reset TxAGC again*/
1993                 if (rtldm->modify_txagc_flag_path_a) {
1994                     rtldm->remnant_cck_idx = 0;
1995                     rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1996 
1997                     /*Set TxAGC Page C{};*/
1998                     rtl8821ae_phy_set_txpower_level_by_path(hw,
1999                         rtlphy->current_channel, RF90_PATH_A);
2000 
2001                     rtldm->modify_txagc_flag_path_a = false;
2002 
2003                     rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
2004                         DBG_LOUD,
2005                         "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2006                 }
2007             }
2008         }
2009     } else {
2010         return;
2011     }
2012 }
2013 
2014 void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2015     struct ieee80211_hw *hw)
2016 {
2017     struct rtl_priv *rtlpriv = rtl_priv(hw);
2018     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2019     struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
2020     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2021     struct rtl_phy *rtlphy = &rtlpriv->phy;
2022 
2023     u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
2024     u8 thermal_value_avg_count = 0;
2025     u32 thermal_value_avg = 0;
2026 
2027     u8 ofdm_min_index = 6;  /*OFDM BB Swing should be less than +3.0dB */
2028     /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
2029     u8 index_for_channel = 0;
2030 
2031     /* 1. The following TWO tables decide the final
2032      * index of OFDM/CCK swing table.
2033      */
2034     const u8 *delta_swing_table_idx_tup_a;
2035     const u8 *delta_swing_table_idx_tdown_a;
2036 
2037     /*2. Initilization ( 7 steps in total )*/
2038     rtl8821ae_get_delta_swing_table(hw,
2039                     &delta_swing_table_idx_tup_a,
2040                     &delta_swing_table_idx_tdown_a);
2041 
2042     rtldm->txpower_trackinginit = true;
2043 
2044     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2045         "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
2046         __func__,
2047         rtldm->swing_idx_cck_base,
2048         rtldm->swing_idx_ofdm_base[RF90_PATH_A],
2049         rtldm->default_ofdm_index);
2050     /*0x42: RF Reg[15:10] 88E*/
2051     thermal_value = (u8)rtl_get_rfreg(hw,
2052         RF90_PATH_A, RF_T_METER_8812A, 0xfc00);
2053     if (!rtldm->txpower_track_control ||
2054         rtlefuse->eeprom_thermalmeter == 0 ||
2055         rtlefuse->eeprom_thermalmeter == 0xFF)
2056         return;
2057 
2058     /* 3. Initialize ThermalValues of RFCalibrateInfo*/
2059 
2060     if (rtlhal->reloadtxpowerindex) {
2061         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2062             "reload ofdm index for band switch\n");
2063     }
2064 
2065     /*4. Calculate average thermal meter*/
2066     rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
2067     rtldm->thermalvalue_avg_index++;
2068     if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
2069         /*Average times =  c.AverageThermalNum*/
2070         rtldm->thermalvalue_avg_index = 0;
2071 
2072     for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
2073         if (rtldm->thermalvalue_avg[i]) {
2074             thermal_value_avg += rtldm->thermalvalue_avg[i];
2075             thermal_value_avg_count++;
2076         }
2077     }
2078     /*Calculate Average ThermalValue after average enough times*/
2079     if (thermal_value_avg_count) {
2080         thermal_value = (u8)(thermal_value_avg /
2081                 thermal_value_avg_count);
2082         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2083             "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
2084             thermal_value, rtlefuse->eeprom_thermalmeter);
2085     }
2086 
2087     /*5. Calculate delta, delta_LCK, delta_IQK.
2088      *"delta" here is used to determine whether
2089      * thermal value changes or not.
2090      */
2091     delta = (thermal_value > rtldm->thermalvalue) ?
2092         (thermal_value - rtldm->thermalvalue) :
2093         (rtldm->thermalvalue - thermal_value);
2094     delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
2095         (thermal_value - rtldm->thermalvalue_lck) :
2096         (rtldm->thermalvalue_lck - thermal_value);
2097     delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
2098         (thermal_value - rtldm->thermalvalue_iqk) :
2099         (rtldm->thermalvalue_iqk - thermal_value);
2100 
2101     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2102         "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
2103         delta, delta_lck, delta_iqk);
2104 
2105     /* 6. If necessary, do LCK. */
2106     /*Delta temperature is equal to or larger than 20 centigrade.*/
2107     if (delta_lck >= IQK_THRESHOLD) {
2108         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2109             "delta_LCK(%d) >= Threshold_IQK(%d)\n",
2110             delta_lck, IQK_THRESHOLD);
2111         rtldm->thermalvalue_lck = thermal_value;
2112         rtl8821ae_phy_lc_calibrate(hw);
2113     }
2114 
2115     /*7. If necessary, move the index of swing table to adjust Tx power.*/
2116 
2117     if (delta > 0 && rtldm->txpower_track_control) {
2118         /*"delta" here is used to record the
2119          * absolute value of differrence.
2120          */
2121         delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2122             (thermal_value - rtlefuse->eeprom_thermalmeter) :
2123             (rtlefuse->eeprom_thermalmeter - thermal_value);
2124 
2125         if (delta >= TXSCALE_TABLE_SIZE)
2126             delta = TXSCALE_TABLE_SIZE - 1;
2127 
2128         /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
2129 
2130         if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2131             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2132                 "delta_swing_table_idx_tup_a[%d] = %d\n",
2133                 delta, delta_swing_table_idx_tup_a[delta]);
2134             rtldm->delta_power_index_last[RF90_PATH_A] =
2135                 rtldm->delta_power_index[RF90_PATH_A];
2136             rtldm->delta_power_index[RF90_PATH_A] =
2137                 delta_swing_table_idx_tup_a[delta];
2138 
2139             rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2140                 delta_swing_table_idx_tup_a[delta];
2141             /*Record delta swing for mix mode power tracking*/
2142 
2143             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2144                 "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2145                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2146         } else {
2147             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2148                 "delta_swing_table_idx_tdown_a[%d] = %d\n",
2149                 delta, delta_swing_table_idx_tdown_a[delta]);
2150 
2151             rtldm->delta_power_index_last[RF90_PATH_A] =
2152                 rtldm->delta_power_index[RF90_PATH_A];
2153             rtldm->delta_power_index[RF90_PATH_A] =
2154                 -1 * delta_swing_table_idx_tdown_a[delta];
2155 
2156             rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2157                 -1 * delta_swing_table_idx_tdown_a[delta];
2158             /* Record delta swing for mix mode power tracking*/
2159             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2160                 "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2161                 rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2162         }
2163 
2164         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2165             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2166                 "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n",
2167                 (p == RF90_PATH_A ? 'A' : 'B'));
2168             /*If Thermal value changes but lookup table value
2169              * still the same
2170              */
2171             if (rtldm->delta_power_index[p] ==
2172                 rtldm->delta_power_index_last[p])
2173 
2174                 rtldm->power_index_offset[p] = 0;
2175             else
2176                 rtldm->power_index_offset[p] =
2177                     rtldm->delta_power_index[p] -
2178                     rtldm->delta_power_index_last[p];
2179             /*Power Index Diff between 2 times Power Tracking*/
2180 
2181             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2182                 "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
2183                 (p == RF90_PATH_A ? 'A' : 'B'),
2184                 rtldm->power_index_offset[p],
2185                 rtldm->delta_power_index[p] ,
2186                 rtldm->delta_power_index_last[p]);
2187 
2188             rtldm->ofdm_index[p] =
2189                     rtldm->swing_idx_ofdm_base[p] +
2190                     rtldm->power_index_offset[p];
2191             rtldm->cck_index =
2192                     rtldm->swing_idx_cck_base +
2193                     rtldm->power_index_offset[p];
2194 
2195             rtldm->swing_idx_cck = rtldm->cck_index;
2196             rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2197 
2198             /*********Print BB Swing Base and Index Offset********/
2199 
2200             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2201                 "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
2202                 rtldm->swing_idx_cck,
2203                 rtldm->swing_idx_cck_base,
2204                 rtldm->power_index_offset[p]);
2205             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2206                 "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
2207                 rtldm->swing_idx_ofdm[p],
2208                 (p == RF90_PATH_A ? 'A' : 'B'),
2209                 rtldm->swing_idx_ofdm_base[p],
2210                 rtldm->power_index_offset[p]);
2211 
2212             /*7.1 Handle boundary conditions of index.*/
2213 
2214             if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
2215                 rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
2216             else if (rtldm->ofdm_index[p] < ofdm_min_index)
2217                 rtldm->ofdm_index[p] = ofdm_min_index;
2218         }
2219         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2220             "\n\n========================================================================================================\n");
2221         if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
2222             rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
2223         else if (rtldm->cck_index < 0)
2224             rtldm->cck_index = 0;
2225     } else {
2226         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2227             "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
2228             rtldm->txpower_track_control,
2229             thermal_value,
2230             rtldm->thermalvalue);
2231 
2232         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2233             rtldm->power_index_offset[p] = 0;
2234     }
2235     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2236         "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
2237         /*Print Swing base & current*/
2238         rtldm->cck_index, rtldm->swing_idx_cck_base);
2239     for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2240         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2241             "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
2242             rtldm->ofdm_index[p],
2243             (p == RF90_PATH_A ? 'A' : 'B'),
2244             rtldm->swing_idx_ofdm_base[p]);
2245     }
2246 
2247     if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
2248         rtldm->power_index_offset[RF90_PATH_B] != 0) &&
2249         rtldm->txpower_track_control) {
2250         /*7.2 Configure the Swing Table to adjust Tx Power.*/
2251         /*Always TRUE after Tx Power is adjusted by power tracking.*/
2252         /*
2253          *  2012/04/23 MH According to Luke's suggestion,
2254          *  we can not write BB digital
2255          *  to increase TX power. Otherwise, EVM will be bad.
2256          *
2257          *  2012/04/25 MH Add for tx power tracking to
2258          *  set tx power in tx agc for 88E.
2259          */
2260         if (thermal_value > rtldm->thermalvalue) {
2261             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2262                 "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2263                 rtldm->power_index_offset[RF90_PATH_A],
2264                 delta, thermal_value,
2265                 rtlefuse->eeprom_thermalmeter,
2266                 rtldm->thermalvalue);
2267         } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
2268             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2269                 "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2270                 rtldm->power_index_offset[RF90_PATH_A],
2271                 delta, thermal_value,
2272                 rtlefuse->eeprom_thermalmeter,
2273                 rtldm->thermalvalue);
2274         }
2275 
2276         if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2277             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2278                 "Temperature(%d) higher than PG value(%d)\n",
2279                 thermal_value, rtlefuse->eeprom_thermalmeter);
2280 
2281             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2282                 "****Enter POWER Tracking MIX_MODE****\n");
2283             for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2284                     rtl8821ae_dm_txpwr_track_set_pwr(hw,
2285                         MIX_MODE, p, index_for_channel);
2286         } else {
2287             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2288                 "Temperature(%d) lower than PG value(%d)\n",
2289                 thermal_value, rtlefuse->eeprom_thermalmeter);
2290 
2291             rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2292                 "*****Enter POWER Tracking MIX_MODE*****\n");
2293             for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2294                 rtl8812ae_dm_txpwr_track_set_pwr(hw,
2295                     MIX_MODE, p, index_for_channel);
2296         }
2297         /*Record last time Power Tracking result as base.*/
2298         rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
2299         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2300             rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
2301 
2302         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2303             "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
2304             rtldm->thermalvalue, thermal_value);
2305         /*Record last Power Tracking Thermal Value*/
2306         rtldm->thermalvalue = thermal_value;
2307     }
2308     /* Delta temperature is equal to or larger than
2309      * 20 centigrade (When threshold is 8).
2310      */
2311     if (delta_iqk >= IQK_THRESHOLD) {
2312         if (!rtlphy->lck_inprogress) {
2313             spin_lock(&rtlpriv->locks.iqk_lock);
2314             rtlphy->lck_inprogress = true;
2315             spin_unlock(&rtlpriv->locks.iqk_lock);
2316 
2317             rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2318 
2319             spin_lock(&rtlpriv->locks.iqk_lock);
2320             rtlphy->lck_inprogress = false;
2321             spin_unlock(&rtlpriv->locks.iqk_lock);
2322         }
2323     }
2324 
2325     rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
2326 }
2327 
2328 void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2329 {
2330     struct rtl_priv *rtlpriv = rtl_priv(hw);
2331     if (!rtlpriv->dm.tm_trigger) {
2332         rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2333                   0x03);
2334         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2335             "Trigger 8821ae Thermal Meter!!\n");
2336         rtlpriv->dm.tm_trigger = 1;
2337         return;
2338     } else {
2339         rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2340             "Schedule TxPowerTracking !!\n");
2341 
2342         rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2343         rtlpriv->dm.tm_trigger = 0;
2344     }
2345 }
2346 
2347 static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
2348 {
2349     struct rtl_priv *rtlpriv = rtl_priv(hw);
2350     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2351     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2352     struct rate_adaptive *p_ra = &rtlpriv->ra;
2353     u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
2354     u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
2355     u8 go_up_gap = 5;
2356     struct ieee80211_sta *sta = NULL;
2357 
2358     if (is_hal_stop(rtlhal)) {
2359         rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2360             "driver is going to unload\n");
2361         return;
2362     }
2363 
2364     if (!rtlpriv->dm.useramask) {
2365         rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2366             "driver does not control rate adaptive mask\n");
2367         return;
2368     }
2369 
2370     if (mac->link_state == MAC80211_LINKED &&
2371         mac->opmode == NL80211_IFTYPE_STATION) {
2372         switch (p_ra->pre_ratr_state) {
2373         case DM_RATR_STA_MIDDLE:
2374             high_rssithresh_for_ra += go_up_gap;
2375             break;
2376         case DM_RATR_STA_LOW:
2377             high_rssithresh_for_ra += go_up_gap;
2378             low_rssithresh_for_ra += go_up_gap;
2379             break;
2380         default:
2381             break;
2382         }
2383 
2384         if (rtlpriv->dm.undec_sm_pwdb >
2385             (long)high_rssithresh_for_ra)
2386             p_ra->ratr_state = DM_RATR_STA_HIGH;
2387         else if (rtlpriv->dm.undec_sm_pwdb >
2388              (long)low_rssithresh_for_ra)
2389             p_ra->ratr_state = DM_RATR_STA_MIDDLE;
2390         else
2391             p_ra->ratr_state = DM_RATR_STA_LOW;
2392 
2393         if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2394             rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2395                 "RSSI = %ld\n",
2396                 rtlpriv->dm.undec_sm_pwdb);
2397             rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2398                 "RSSI_LEVEL = %d\n", p_ra->ratr_state);
2399             rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2400                 "PreState = %d, CurState = %d\n",
2401                 p_ra->pre_ratr_state, p_ra->ratr_state);
2402 
2403             rcu_read_lock();
2404             sta = rtl_find_sta(hw, mac->bssid);
2405             if (sta)
2406                 rtlpriv->cfg->ops->update_rate_tbl(hw,
2407                         sta, p_ra->ratr_state, true);
2408             rcu_read_unlock();
2409 
2410             p_ra->pre_ratr_state = p_ra->ratr_state;
2411         }
2412     }
2413 }
2414 
2415 static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2416 {
2417     struct rtl_priv *rtlpriv = rtl_priv(hw);
2418     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2419     struct rtl_mac *mac = &rtlpriv->mac80211;
2420     static u8 stage;
2421     u8 cur_stage = 0;
2422     u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2423 
2424     if (mac->link_state < MAC80211_LINKED)
2425         cur_stage = 0;
2426     else if (dm_digtable->rssi_val_min < 25)
2427         cur_stage = 1;
2428     else if (dm_digtable->rssi_val_min > 30)
2429         cur_stage = 3;
2430     else
2431         cur_stage = 2;
2432 
2433     if (cur_stage != stage) {
2434         if (cur_stage == 1) {
2435             basic_rate &= (!(basic_rate ^ mac->basic_rates));
2436             rtlpriv->cfg->ops->set_hw_reg(hw,
2437                 HW_VAR_BASIC_RATE, (u8 *)&basic_rate);
2438         } else if (cur_stage == 3 && (stage == 1 || stage == 2)) {
2439             rtlpriv->cfg->ops->set_hw_reg(hw,
2440                 HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates);
2441         }
2442     }
2443     stage = cur_stage;
2444 }
2445 
2446 static void rtl8821ae_dm_edca_choose_traffic_idx(
2447     struct ieee80211_hw *hw, u64 cur_tx_bytes,
2448     u64 cur_rx_bytes, bool b_bias_on_rx,
2449     bool *pb_is_cur_rdl_state)
2450 {
2451     struct rtl_priv *rtlpriv = rtl_priv(hw);
2452 
2453     if (b_bias_on_rx) {
2454         if (cur_tx_bytes > (cur_rx_bytes*4)) {
2455             *pb_is_cur_rdl_state = false;
2456             rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2457                 "Uplink Traffic\n");
2458         } else {
2459             *pb_is_cur_rdl_state = true;
2460             rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2461                 "Balance Traffic\n");
2462         }
2463     } else {
2464         if (cur_rx_bytes > (cur_tx_bytes*4)) {
2465             *pb_is_cur_rdl_state = true;
2466             rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2467                 "Downlink   Traffic\n");
2468         } else {
2469             *pb_is_cur_rdl_state = false;
2470             rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2471                 "Balance Traffic\n");
2472         }
2473     }
2474     return;
2475 }
2476 
2477 static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
2478 {
2479     struct rtl_priv *rtlpriv = rtl_priv(hw);
2480     struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2481     struct rtl_dm *rtldm =  rtl_dm(rtl_priv(hw));
2482 
2483     /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/
2484     u64 cur_tx_ok_cnt = 0;
2485     u64 cur_rx_ok_cnt = 0;
2486     u32 edca_be_ul = 0x5ea42b;
2487     u32 edca_be_dl = 0x5ea42b;
2488     u32 edca_be = 0x5ea42b;
2489     u8 iot_peer = 0;
2490     bool *pb_is_cur_rdl_state = NULL;
2491     bool b_bias_on_rx = false;
2492     bool b_edca_turbo_on = false;
2493 
2494     rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2495         "%s=====>\n", __func__);
2496     rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2497         "Original BE PARAM: 0x%x\n",
2498         rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N));
2499 
2500     if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
2501         rtlpriv->dm.is_any_nonbepkts = true;
2502     rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
2503 
2504     /*===============================
2505      * list parameter for different platform
2506      *===============================
2507      */
2508     pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
2509 
2510     cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt;
2511     cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt;
2512 
2513     rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2514     rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2515 
2516     iot_peer = rtlpriv->mac80211.vendor;
2517     b_bias_on_rx = false;
2518     b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
2519                (!rtlpriv->dm.disable_framebursting)) ?
2520                true : false;
2521 
2522     if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) {
2523         if ((iot_peer == PEER_CISCO) &&
2524             (mac->mode == WIRELESS_MODE_N_24G)) {
2525             edca_be_dl = edca_setting_dl[iot_peer];
2526             edca_be_ul = edca_setting_ul[iot_peer];
2527         }
2528     }
2529 
2530     rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2531         "bIsAnyNonBEPkts : 0x%x  bDisableFrameBursting : 0x%x\n",
2532         rtlpriv->dm.is_any_nonbepkts,
2533         rtlpriv->dm.disable_framebursting);
2534 
2535     rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2536         "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n",
2537         b_edca_turbo_on, b_bias_on_rx);
2538 
2539     if (b_edca_turbo_on) {
2540         rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2541             "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt);
2542         rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2543             "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt);
2544         if (b_bias_on_rx)
2545             rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2546                 cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2547         else
2548             rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2549                 cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2550 
2551         edca_be = (*pb_is_cur_rdl_state) ?  edca_be_dl : edca_be_ul;
2552 
2553         rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2554 
2555         rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2556             "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2557 
2558         rtlpriv->dm.current_turbo_edca = true;
2559 
2560         rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2561             "EDCA_BE_DL : 0x%x  EDCA_BE_UL : 0x%x  EDCA_BE : 0x%x\n",
2562             edca_be_dl, edca_be_ul, edca_be);
2563     } else {
2564         if (rtlpriv->dm.current_turbo_edca) {
2565             u8 tmp = AC0_BE;
2566             rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2567                               (u8 *)(&tmp));
2568         }
2569         rtlpriv->dm.current_turbo_edca = false;
2570     }
2571 
2572     rtlpriv->dm.is_any_nonbepkts = false;
2573     rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2574     rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2575 }
2576 
2577 static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2578 {
2579     struct rtl_priv *rtlpriv = rtl_priv(hw);
2580     struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2581     u8 cur_cck_cca_thresh;
2582 
2583     if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
2584         if (dm_digtable->rssi_val_min > 25) {
2585             cur_cck_cca_thresh = 0xcd;
2586         } else if ((dm_digtable->rssi_val_min <= 25) &&
2587                (dm_digtable->rssi_val_min > 10)) {
2588             cur_cck_cca_thresh = 0x83;
2589         } else {
2590             if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2591                 cur_cck_cca_thresh = 0x83;
2592             else
2593                 cur_cck_cca_thresh = 0x40;
2594         }
2595     } else {
2596         if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2597             cur_cck_cca_thresh = 0x83;
2598         else
2599             cur_cck_cca_thresh = 0x40;
2600     }
2601 
2602     if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
2603         rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC,
2604                    cur_cck_cca_thresh);
2605 
2606     dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
2607     dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
2608     rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
2609         "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
2610 }
2611 
2612 static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2613 {
2614     struct rtl_priv *rtlpriv = rtl_priv(hw);
2615     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2616     u8 crystal_cap;
2617     u32 packet_count;
2618     int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2619     int cfo_ave_diff;
2620 
2621     if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
2622         /*1.Enable ATC*/
2623         if (rtldm->atc_status == ATC_STATUS_OFF) {
2624             rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON);
2625             rtldm->atc_status = ATC_STATUS_ON;
2626         }
2627 
2628         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n");
2629         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2630             "atc_status = %d\n", rtldm->atc_status);
2631 
2632         if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
2633             rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
2634             crystal_cap = rtldm->crystal_cap & 0x3f;
2635             crystal_cap = crystal_cap & 0x3f;
2636             if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2637                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2638                           0x7ff80000, (crystal_cap |
2639                           (crystal_cap << 6)));
2640             else
2641                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2642                           0xfff000, (crystal_cap |
2643                           (crystal_cap << 6)));
2644         }
2645         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2646             rtldm->crystal_cap);
2647     } else{
2648         /*1. Calculate CFO for path-A & path-B*/
2649         cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
2650         cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
2651         packet_count = rtldm->packet_count;
2652 
2653         /*2.No new packet*/
2654         if (packet_count == rtldm->packet_count_pre) {
2655             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2656                 "packet counter doesn't change\n");
2657             return;
2658         }
2659 
2660         rtldm->packet_count_pre = packet_count;
2661         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2662             "packet counter = %d\n",
2663             rtldm->packet_count);
2664 
2665         /*3.Average CFO*/
2666         if (rtlpriv->phy.rf_type == RF_1T1R)
2667             cfo_ave = cfo_khz_a;
2668         else
2669             cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
2670 
2671         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2672             "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n",
2673             cfo_khz_a, cfo_khz_b, cfo_ave);
2674 
2675         /*4.Avoid abnormal large CFO*/
2676         cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
2677                         (rtldm->cfo_ave_pre - cfo_ave) :
2678                         (cfo_ave - rtldm->cfo_ave_pre);
2679 
2680         if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
2681             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2682                 "first large CFO hit\n");
2683             rtldm->large_cfo_hit = true;
2684             return;
2685         } else
2686             rtldm->large_cfo_hit = false;
2687 
2688         rtldm->cfo_ave_pre = cfo_ave;
2689 
2690         /*CFO tracking by adjusting Xtal cap.*/
2691 
2692         /*1.Dynamic Xtal threshold*/
2693         if (cfo_ave >= -rtldm->cfo_threshold &&
2694             cfo_ave <= rtldm->cfo_threshold &&
2695             rtldm->is_freeze == 0) {
2696             if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
2697                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
2698                 rtldm->is_freeze = 1;
2699             } else {
2700                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2701             }
2702         }
2703         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2704             "Dynamic threshold = %d\n",
2705             rtldm->cfo_threshold);
2706 
2707         /* 2.Calculate Xtal offset*/
2708         if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
2709             adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
2710         else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
2711              rtlpriv->dm.crystal_cap > 0)
2712             adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
2713         rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2714             "Crystal cap = 0x%x, Crystal cap offset = %d\n",
2715             rtldm->crystal_cap, adjust_xtal);
2716 
2717         /*3.Adjudt Crystal Cap.*/
2718         if (adjust_xtal != 0) {
2719             rtldm->is_freeze = 0;
2720             rtldm->crystal_cap += adjust_xtal;
2721 
2722             if (rtldm->crystal_cap > 0x3f)
2723                 rtldm->crystal_cap = 0x3f;
2724             else if (rtldm->crystal_cap < 0)
2725                 rtldm->crystal_cap = 0;
2726 
2727             crystal_cap = rtldm->crystal_cap & 0x3f;
2728             crystal_cap = crystal_cap & 0x3f;
2729             if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2730                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2731                           0x7ff80000, (crystal_cap |
2732                           (crystal_cap << 6)));
2733             else
2734                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2735                           0xfff000, (crystal_cap |
2736                           (crystal_cap << 6)));
2737             rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2738                 "New crystal cap = 0x%x\n",
2739                 rtldm->crystal_cap);
2740         }
2741     }
2742 }
2743 
2744 void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
2745 {
2746     struct rtl_priv *rtlpriv = rtl_priv(hw);
2747     struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2748     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2749     bool fw_current_inpsmode = false;
2750     bool fw_ps_awake = true;
2751 
2752     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2753                       (u8 *)(&fw_current_inpsmode));
2754 
2755     rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2756                       (u8 *)(&fw_ps_awake));
2757 
2758     if (ppsc->p2p_ps_info.p2p_ps_mode)
2759         fw_ps_awake = false;
2760 
2761     spin_lock(&rtlpriv->locks.rf_ps_lock);
2762     if ((ppsc->rfpwr_state == ERFON) &&
2763         ((!fw_current_inpsmode) && fw_ps_awake) &&
2764         (!ppsc->rfchange_inprogress)) {
2765         rtl8821ae_dm_common_info_self_update(hw);
2766         rtl8821ae_dm_false_alarm_counter_statistics(hw);
2767         rtl8821ae_dm_check_rssi_monitor(hw);
2768         rtl8821ae_dm_dig(hw);
2769         rtl8821ae_dm_cck_packet_detection_thresh(hw);
2770         rtl8821ae_dm_refresh_rate_adaptive_mask(hw);
2771         rtl8821ae_dm_refresh_basic_rate_mask(hw);
2772         rtl8821ae_dm_check_edca_turbo(hw);
2773         rtl8821ae_dm_dynamic_atc_switch(hw);
2774         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
2775             rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw);
2776         else
2777             rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2778         rtl8821ae_dm_iq_calibrate(hw);
2779     }
2780     spin_unlock(&rtlpriv->locks.rf_ps_lock);
2781 
2782     rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
2783     rtl_dbg(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
2784 }
2785 
2786 void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
2787                     u8 *pdesc, u32 mac_id)
2788 {
2789     struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2790     struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2791     struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2792     struct fast_ant_training *pfat_table = &rtldm->fat_table;
2793     __le32 *pdesc32 = (__le32 *)pdesc;
2794 
2795     if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
2796         return;
2797 
2798     if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
2799         set_tx_desc_tx_ant(pdesc32, pfat_table->antsel_a[mac_id]);
2800 }