Linux Audio

Check our new training course

Embedded Linux training

Mar 31-Apr 8, 2025
Register
Loading...
Note: File does not exist in v3.15.
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright(c) 2009-2010  Realtek Corporation.*/
   3
   4#include "../wifi.h"
   5#include "../base.h"
   6#include "../pci.h"
   7#include "../core.h"
   8#include "reg.h"
   9#include "def.h"
  10#include "phy.h"
  11#include "dm.h"
  12#include "fw.h"
  13#include "trx.h"
  14#include "../btcoexist/rtl_btc.h"
  15
  16static const u32 txscaling_tbl[TXSCALE_TABLE_SIZE] = {
  17	0x081, /* 0, -12.0dB */
  18	0x088, /* 1, -11.5dB */
  19	0x090, /* 2, -11.0dB */
  20	0x099, /* 3, -10.5dB */
  21	0x0A2, /* 4, -10.0dB */
  22	0x0AC, /* 5, -9.5dB */
  23	0x0B6, /* 6, -9.0dB */
  24	0x0C0, /* 7, -8.5dB */
  25	0x0CC, /* 8, -8.0dB */
  26	0x0D8, /* 9, -7.5dB */
  27	0x0E5, /* 10, -7.0dB */
  28	0x0F2, /* 11, -6.5dB */
  29	0x101, /* 12, -6.0dB */
  30	0x110, /* 13, -5.5dB */
  31	0x120, /* 14, -5.0dB */
  32	0x131, /* 15, -4.5dB */
  33	0x143, /* 16, -4.0dB */
  34	0x156, /* 17, -3.5dB */
  35	0x16A, /* 18, -3.0dB */
  36	0x180, /* 19, -2.5dB */
  37	0x197, /* 20, -2.0dB */
  38	0x1AF, /* 21, -1.5dB */
  39	0x1C8, /* 22, -1.0dB */
  40	0x1E3, /* 23, -0.5dB */
  41	0x200, /* 24, +0  dB */
  42	0x21E, /* 25, +0.5dB */
  43	0x23E, /* 26, +1.0dB */
  44	0x261, /* 27, +1.5dB */
  45	0x285, /* 28, +2.0dB */
  46	0x2AB, /* 29, +2.5dB */
  47	0x2D3, /* 30, +3.0dB */
  48	0x2FE, /* 31, +3.5dB */
  49	0x32B, /* 32, +4.0dB */
  50	0x35C, /* 33, +4.5dB */
  51	0x38E, /* 34, +5.0dB */
  52	0x3C4, /* 35, +5.5dB */
  53	0x3FE  /* 36, +6.0dB */
  54};
  55
  56static const u32 rtl8821ae_txscaling_table[TXSCALE_TABLE_SIZE] = {
  57	0x081, /* 0, -12.0dB */
  58	0x088, /* 1, -11.5dB */
  59	0x090, /* 2, -11.0dB */
  60	0x099, /* 3, -10.5dB */
  61	0x0A2, /* 4, -10.0dB */
  62	0x0AC, /* 5, -9.5dB */
  63	0x0B6, /* 6, -9.0dB */
  64	0x0C0, /* 7, -8.5dB */
  65	0x0CC, /* 8, -8.0dB */
  66	0x0D8, /* 9, -7.5dB */
  67	0x0E5, /* 10, -7.0dB */
  68	0x0F2, /* 11, -6.5dB */
  69	0x101, /* 12, -6.0dB */
  70	0x110, /* 13, -5.5dB */
  71	0x120, /* 14, -5.0dB */
  72	0x131, /* 15, -4.5dB */
  73	0x143, /* 16, -4.0dB */
  74	0x156, /* 17, -3.5dB */
  75	0x16A, /* 18, -3.0dB */
  76	0x180, /* 19, -2.5dB */
  77	0x197, /* 20, -2.0dB */
  78	0x1AF, /* 21, -1.5dB */
  79	0x1C8, /* 22, -1.0dB */
  80	0x1E3, /* 23, -0.5dB */
  81	0x200, /* 24, +0  dB */
  82	0x21E, /* 25, +0.5dB */
  83	0x23E, /* 26, +1.0dB */
  84	0x261, /* 27, +1.5dB */
  85	0x285, /* 28, +2.0dB */
  86	0x2AB, /* 29, +2.5dB */
  87	0x2D3, /* 30, +3.0dB */
  88	0x2FE, /* 31, +3.5dB */
  89	0x32B, /* 32, +4.0dB */
  90	0x35C, /* 33, +4.5dB */
  91	0x38E, /* 34, +5.0dB */
  92	0x3C4, /* 35, +5.5dB */
  93	0x3FE  /* 36, +6.0dB */
  94};
  95
  96static const u32 edca_setting_dl[PEER_MAX] = {
  97	0xa44f,		/* 0 UNKNOWN */
  98	0x5ea44f,	/* 1 REALTEK_90 */
  99	0x5e4322,	/* 2 REALTEK_92SE */
 100	0x5ea42b,		/* 3 BROAD	*/
 101	0xa44f,		/* 4 RAL */
 102	0xa630,		/* 5 ATH */
 103	0x5ea630,		/* 6 CISCO */
 104	0x5ea42b,		/* 7 MARVELL */
 105};
 106
 107static const u32 edca_setting_ul[PEER_MAX] = {
 108	0x5e4322,	/* 0 UNKNOWN */
 109	0xa44f,		/* 1 REALTEK_90 */
 110	0x5ea44f,	/* 2 REALTEK_92SE */
 111	0x5ea32b,	/* 3 BROAD */
 112	0x5ea422,	/* 4 RAL */
 113	0x5ea322,	/* 5 ATH */
 114	0x3ea430,	/* 6 CISCO */
 115	0x5ea44f,	/* 7 MARV */
 116};
 117
 118static const u8 rtl8818e_delta_swing_table_idx_24gb_p[] = {
 119	0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 4,
 120	4, 4, 4, 5, 5, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9};
 121
 122static const u8 rtl8818e_delta_swing_table_idx_24gb_n[] = {
 123	0, 0, 0, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6,
 124	7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11};
 125
 126static const u8 rtl8812ae_delta_swing_table_idx_24gb_n[]  = {
 127	0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 128	6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 129
 130static const u8 rtl8812ae_delta_swing_table_idx_24gb_p[] = {
 131	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 132	6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 133
 134static const u8 rtl8812ae_delta_swing_table_idx_24ga_n[] = {
 135	0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 136	6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 137
 138static const u8 rtl8812ae_delta_swing_table_idx_24ga_p[] = {
 139	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 140	6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 141
 142static const u8 rtl8812ae_delta_swing_table_idx_24gcckb_n[] = {
 143	0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 144	6, 6, 7, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 145
 146static const u8 rtl8812ae_delta_swing_table_idx_24gcckb_p[] = {
 147	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 148	6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 149
 150static const u8 rtl8812ae_delta_swing_table_idx_24gccka_n[] = {
 151	0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6,
 152	6, 6, 7, 8, 8, 9, 9, 9, 10, 10, 10, 10, 11, 11};
 153
 154static const u8 rtl8812ae_delta_swing_table_idx_24gccka_p[] = {
 155	0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
 156	6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 9, 9, 9};
 157
 158static const u8 rtl8812ae_delta_swing_table_idx_5gb_n[][DEL_SW_IDX_SZ] = {
 159	{0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7,
 160	7, 8, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13},
 161	{0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7,
 162	7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13},
 163	{0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11,
 164	12, 12, 13, 14, 14, 14, 15, 16, 17, 17, 17, 18, 18, 18},
 165};
 166
 167static const u8 rtl8812ae_delta_swing_table_idx_5gb_p[][DEL_SW_IDX_SZ] = {
 168	{0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8,
 169	8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 170	{0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 171	8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 172	{0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8, 9,
 173	9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 174};
 175
 176static const u8 rtl8812ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
 177	{0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 178	8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 13, 13, 13},
 179	{0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9,
 180	9, 10, 10, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13},
 181	{0, 1, 1, 2, 2, 3, 3, 4, 5, 6, 7, 8, 8, 9, 10, 11,
 182	12, 13, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18},
 183};
 184
 185static const u8 rtl8812ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
 186	{0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 7, 8,
 187	8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11},
 188	{0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 189	9, 9, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 190	{0, 1, 1, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9,
 191	10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 192};
 193
 194static const u8 rtl8821ae_delta_swing_table_idx_24ga_n[]  = {
 195	0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 196	6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 197
 198static const u8 rtl8821ae_delta_swing_table_idx_24ga_p[] = {
 199	0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 200	8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 201
 202static const u8 rtl8821ae_delta_swing_table_idx_24gccka_n[] = {
 203	0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6,
 204	6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10};
 205
 206static const u8 rtl8821ae_delta_swing_table_idx_24gccka_p[] = {
 207	0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8,
 208	8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 12, 12};
 209
 210static const u8 rtl8821ae_delta_swing_table_idx_5ga_n[][DEL_SW_IDX_SZ] = {
 211	{0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 212	12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 213	{0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 214	12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 215	{0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 216	12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 217};
 218
 219static const u8 rtl8821ae_delta_swing_table_idx_5ga_p[][DEL_SW_IDX_SZ] = {
 220	{0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 221	12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 222	{0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 223	12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 224	{0, 0, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 9, 10, 11,
 225	12, 12, 13, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16},
 226};
 227
 228void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw,
 229				       u8 type, u8 *pdirection,
 230				       u32 *poutwrite_val)
 231{
 232	struct rtl_priv *rtlpriv = rtl_priv(hw);
 233	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 234	u8 pwr_val = 0;
 235
 236	if (type == 0) {
 237		if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <=
 238			rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) {
 239			*pdirection = 1;
 240			pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] -
 241					rtldm->swing_idx_ofdm[RF90_PATH_A];
 242		} else {
 243			*pdirection = 2;
 244			pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] -
 245				rtldm->swing_idx_ofdm_base[RF90_PATH_A];
 246		}
 247	} else if (type == 1) {
 248		if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) {
 249			*pdirection = 1;
 250			pwr_val = rtldm->swing_idx_cck_base -
 251					rtldm->swing_idx_cck;
 252		} else {
 253			*pdirection = 2;
 254			pwr_val = rtldm->swing_idx_cck -
 255				rtldm->swing_idx_cck_base;
 256		}
 257	}
 258
 259	if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
 260		pwr_val = TXPWRTRACK_MAX_IDX;
 261
 262	*poutwrite_val = pwr_val | (pwr_val << 8)|
 263				(pwr_val << 16)|
 264				(pwr_val << 24);
 265}
 266
 267void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw)
 268{
 269	struct rtl_priv *rtlpriv = rtl_priv(hw);
 270	struct rtl_dm *rtldm = rtl_dm(rtlpriv);
 271	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
 272	u8 p = 0;
 273
 274	rtldm->swing_idx_cck_base = rtldm->default_cck_index;
 275	rtldm->swing_idx_cck = rtldm->default_cck_index;
 276	rtldm->cck_index = 0;
 277
 278	for (p = RF90_PATH_A; p <= RF90_PATH_B; ++p) {
 279		rtldm->swing_idx_ofdm_base[p] = rtldm->default_ofdm_index;
 280		rtldm->swing_idx_ofdm[p] = rtldm->default_ofdm_index;
 281		rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
 282
 283		rtldm->power_index_offset[p] = 0;
 284		rtldm->delta_power_index[p] = 0;
 285		rtldm->delta_power_index_last[p] = 0;
 286		/*Initial Mix mode power tracking*/
 287		rtldm->absolute_ofdm_swing_idx[p] = 0;
 288		rtldm->remnant_ofdm_swing_idx[p] = 0;
 289	}
 290	/*Initial at Modify Tx Scaling Mode*/
 291	rtldm->modify_txagc_flag_path_a = false;
 292	/*Initial at Modify Tx Scaling Mode*/
 293	rtldm->modify_txagc_flag_path_b = false;
 294	rtldm->remnant_cck_idx = 0;
 295	rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
 296	rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
 297	rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
 298}
 299
 300static u8  rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw)
 301{
 302	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 303	u8 i = 0;
 304	u32  bb_swing;
 305
 306	bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype,
 307					  RF90_PATH_A);
 308
 309	for (i = 0; i < TXSCALE_TABLE_SIZE; ++i)
 310		if (bb_swing == rtl8821ae_txscaling_table[i])
 311			break;
 312
 313	return i;
 314}
 315
 316void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(
 317				struct ieee80211_hw *hw)
 318{
 319	struct rtl_priv *rtlpriv = rtl_priv(hw);
 320	struct rtl_dm *rtldm = rtl_dm(rtlpriv);
 321	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
 322	u8 default_swing_index  = 0;
 323	u8 p = 0;
 324
 325	rtlpriv->dm.txpower_track_control = true;
 326	rtldm->thermalvalue = rtlefuse->eeprom_thermalmeter;
 327	rtldm->thermalvalue_iqk = rtlefuse->eeprom_thermalmeter;
 328	rtldm->thermalvalue_lck = rtlefuse->eeprom_thermalmeter;
 329	default_swing_index = rtl8821ae_dm_get_swing_index(hw);
 330
 331	rtldm->default_ofdm_index =
 332		(default_swing_index == TXSCALE_TABLE_SIZE) ?
 333		24 : default_swing_index;
 334	rtldm->default_cck_index = 24;
 335
 336	rtldm->swing_idx_cck_base = rtldm->default_cck_index;
 337	rtldm->cck_index = rtldm->default_cck_index;
 338
 339	for (p = RF90_PATH_A; p < MAX_RF_PATH; ++p) {
 340		rtldm->swing_idx_ofdm_base[p] =
 341			rtldm->default_ofdm_index;
 342		rtldm->ofdm_index[p] = rtldm->default_ofdm_index;
 343		rtldm->delta_power_index[p] = 0;
 344		rtldm->power_index_offset[p] = 0;
 345		rtldm->delta_power_index_last[p] = 0;
 346	}
 347}
 348
 349void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
 350{
 351	struct rtl_priv *rtlpriv = rtl_priv(hw);
 352
 353	rtlpriv->dm.current_turbo_edca = false;
 354	rtlpriv->dm.is_any_nonbepkts = false;
 355	rtlpriv->dm.is_cur_rdlstate = false;
 356}
 357
 358void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
 359{
 360	struct rtl_priv *rtlpriv = rtl_priv(hw);
 361	struct rate_adaptive *p_ra = &rtlpriv->ra;
 362
 363	p_ra->ratr_state = DM_RATR_STA_INIT;
 364	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
 365
 366	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 367	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
 368		rtlpriv->dm.useramask = true;
 369	else
 370		rtlpriv->dm.useramask = false;
 371
 372	p_ra->high_rssi_thresh_for_ra = 50;
 373	p_ra->low_rssi_thresh_for_ra40m = 20;
 374}
 375
 376static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
 377{
 378	struct rtl_priv *rtlpriv = rtl_priv(hw);
 379
 380	rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
 381
 382	rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
 383	rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
 384}
 385
 386static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw)
 387{
 388	struct rtl_priv *rtlpriv = rtl_priv(hw);
 389	struct rtl_phy *rtlphy = &rtlpriv->phy;
 390	u8 tmp;
 391
 392	rtlphy->cck_high_power =
 393		(bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC,
 394				    ODM_BIT_CCK_RPT_FORMAT_11AC);
 395
 396	tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC,
 397				ODM_BIT_BB_RX_PATH_11AC);
 398	if (tmp & BIT(0))
 399		rtlpriv->dm.rfpath_rxenable[0] = true;
 400	if (tmp & BIT(1))
 401		rtlpriv->dm.rfpath_rxenable[1] = true;
 402}
 403
 404void rtl8821ae_dm_init(struct ieee80211_hw *hw)
 405{
 406	struct rtl_priv *rtlpriv = rtl_priv(hw);
 407	struct rtl_phy *rtlphy = &rtlpriv->phy;
 408	u32 cur_igvalue = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f);
 409
 410	spin_lock(&rtlpriv->locks.iqk_lock);
 411	rtlphy->lck_inprogress = false;
 412	spin_unlock(&rtlpriv->locks.iqk_lock);
 413
 414	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
 415	rtl8821ae_dm_common_info_self_init(hw);
 416	rtl_dm_diginit(hw, cur_igvalue);
 417	rtl8821ae_dm_init_rate_adaptive_mask(hw);
 418	rtl8821ae_dm_init_edca_turbo(hw);
 419	rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(hw);
 420	rtl8821ae_dm_init_dynamic_atc_switch(hw);
 421}
 422
 423static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
 424{
 425	struct rtl_priv *rtlpriv = rtl_priv(hw);
 426	struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
 427	struct rtl_mac *mac = rtl_mac(rtlpriv);
 428
 429	/* Determine the minimum RSSI  */
 430	if ((mac->link_state < MAC80211_LINKED) &&
 431	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
 432		rtl_dm_dig->min_undec_pwdb_for_dm = 0;
 433		pr_debug("rtl8821ae: Not connected to any AP\n");
 434	}
 435	if (mac->link_state >= MAC80211_LINKED) {
 436		if (mac->opmode == NL80211_IFTYPE_AP ||
 437		    mac->opmode == NL80211_IFTYPE_ADHOC) {
 438			rtl_dm_dig->min_undec_pwdb_for_dm =
 439			    rtlpriv->dm.entry_min_undec_sm_pwdb;
 440			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 441				"AP Client PWDB = 0x%lx\n",
 442				rtlpriv->dm.entry_min_undec_sm_pwdb);
 443		} else {
 444			rtl_dm_dig->min_undec_pwdb_for_dm =
 445			    rtlpriv->dm.undec_sm_pwdb;
 446			rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 447				"STA Default Port PWDB = 0x%x\n",
 448				rtl_dm_dig->min_undec_pwdb_for_dm);
 449		}
 450	} else {
 451		rtl_dm_dig->min_undec_pwdb_for_dm =
 452		    rtlpriv->dm.entry_min_undec_sm_pwdb;
 453		rtl_dbg(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
 454			"AP Ext Port or disconnect PWDB = 0x%x\n",
 455			rtl_dm_dig->min_undec_pwdb_for_dm);
 456	}
 457	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 458		"MinUndecoratedPWDBForDM =%d\n",
 459		rtl_dm_dig->min_undec_pwdb_for_dm);
 460}
 461
 462static void  rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw)
 463{
 464	struct rtl_priv *rtlpriv = rtl_priv(hw);
 465
 466	rtl_write_byte(rtlpriv, RA_RSSI_DUMP,
 467		       rtlpriv->stats.rx_rssi_percentage[0]);
 468	rtl_write_byte(rtlpriv, RB_RSSI_DUMP,
 469		       rtlpriv->stats.rx_rssi_percentage[1]);
 470
 471	/* Rx EVM*/
 472	rtl_write_byte(rtlpriv, RS1_RX_EVM_DUMP,
 473		       rtlpriv->stats.rx_evm_dbm[0]);
 474	rtl_write_byte(rtlpriv, RS2_RX_EVM_DUMP,
 475		       rtlpriv->stats.rx_evm_dbm[1]);
 476
 477	/*Rx SNR*/
 478	rtl_write_byte(rtlpriv, RA_RX_SNR_DUMP,
 479		       (u8)(rtlpriv->stats.rx_snr_db[0]));
 480	rtl_write_byte(rtlpriv, RB_RX_SNR_DUMP,
 481		       (u8)(rtlpriv->stats.rx_snr_db[1]));
 482
 483	/*Rx Cfo_Short*/
 484	rtl_write_word(rtlpriv, RA_CFO_SHORT_DUMP,
 485		       rtlpriv->stats.rx_cfo_short[0]);
 486	rtl_write_word(rtlpriv, RB_CFO_SHORT_DUMP,
 487		       rtlpriv->stats.rx_cfo_short[1]);
 488
 489	/*Rx Cfo_Tail*/
 490	rtl_write_word(rtlpriv, RA_CFO_LONG_DUMP,
 491		       rtlpriv->stats.rx_cfo_tail[0]);
 492	rtl_write_word(rtlpriv, RB_CFO_LONG_DUMP,
 493		       rtlpriv->stats.rx_cfo_tail[1]);
 494}
 495
 496static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw)
 497{
 498	struct rtl_priv *rtlpriv = rtl_priv(hw);
 499	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 500	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
 501	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 502	struct rtl_sta_info *drv_priv;
 503	u8 h2c_parameter[4] = { 0 };
 504	long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
 505	u8 stbc_tx = 0;
 506	u64 cur_rxokcnt = 0;
 507	static u64 last_txokcnt = 0, last_rxokcnt;
 508
 509	cur_rxokcnt = rtlpriv->stats.rxbytesunicast - last_rxokcnt;
 510	last_txokcnt = rtlpriv->stats.txbytesunicast;
 511	last_rxokcnt = rtlpriv->stats.rxbytesunicast;
 512	if (cur_rxokcnt > (last_txokcnt * 6))
 513		h2c_parameter[3] = 0x01;
 514	else
 515		h2c_parameter[3] = 0x00;
 516
 517	/* AP & ADHOC & MESH */
 518	if (mac->opmode == NL80211_IFTYPE_AP ||
 519	    mac->opmode == NL80211_IFTYPE_ADHOC ||
 520	    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
 521		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 522		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
 523			if (drv_priv->rssi_stat.undec_sm_pwdb <
 524					tmp_entry_min_pwdb)
 525				tmp_entry_min_pwdb =
 526					drv_priv->rssi_stat.undec_sm_pwdb;
 527			if (drv_priv->rssi_stat.undec_sm_pwdb >
 528					tmp_entry_max_pwdb)
 529				tmp_entry_max_pwdb =
 530					drv_priv->rssi_stat.undec_sm_pwdb;
 531		}
 532		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 533
 534		/* If associated entry is found */
 535		if (tmp_entry_max_pwdb != 0) {
 536			rtlpriv->dm.entry_max_undec_sm_pwdb =
 537				tmp_entry_max_pwdb;
 538			RTPRINT(rtlpriv, FDM, DM_PWDB,
 539				"EntryMaxPWDB = 0x%lx(%ld)\n",
 540				tmp_entry_max_pwdb, tmp_entry_max_pwdb);
 541		} else {
 542			rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
 543		}
 544		/* If associated entry is found */
 545		if (tmp_entry_min_pwdb != 0xff) {
 546			rtlpriv->dm.entry_min_undec_sm_pwdb =
 547				tmp_entry_min_pwdb;
 548			RTPRINT(rtlpriv, FDM, DM_PWDB,
 549				"EntryMinPWDB = 0x%lx(%ld)\n",
 550				tmp_entry_min_pwdb, tmp_entry_min_pwdb);
 551		} else {
 552			rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
 553		}
 554	}
 555	/* Indicate Rx signal strength to FW. */
 556	if (rtlpriv->dm.useramask) {
 557		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
 558			if (mac->mode == WIRELESS_MODE_AC_24G ||
 559			    mac->mode == WIRELESS_MODE_AC_5G ||
 560			    mac->mode == WIRELESS_MODE_AC_ONLY)
 561				stbc_tx = (mac->vht_cur_stbc &
 562					   STBC_VHT_ENABLE_TX) ? 1 : 0;
 563			else
 564				stbc_tx = (mac->ht_cur_stbc &
 565					   STBC_HT_ENABLE_TX) ? 1 : 0;
 566			h2c_parameter[3] |= stbc_tx << 1;
 567		}
 568		h2c_parameter[2] =
 569			(u8)(rtlpriv->dm.undec_sm_pwdb & 0xFF);
 570		h2c_parameter[1] = 0x20;
 571		h2c_parameter[0] = 0;
 572		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 573			rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 4,
 574					       h2c_parameter);
 575		else
 576			rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3,
 577					       h2c_parameter);
 578	} else {
 579		rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
 580	}
 581	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 582		rtl8812ae_dm_rssi_dump_to_register(hw);
 583	rtl8821ae_dm_find_minimum_rssi(hw);
 584	dm_digtable->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
 585}
 586
 587void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca)
 588{
 589	struct rtl_priv *rtlpriv = rtl_priv(hw);
 590	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 591
 592	if (dm_digtable->cur_cck_cca_thres != current_cca)
 593		rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca);
 594
 595	dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
 596	dm_digtable->cur_cck_cca_thres = current_cca;
 597}
 598
 599void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
 600{
 601	struct rtl_priv *rtlpriv = rtl_priv(hw);
 602	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 603
 604	if (dm_digtable->stop_dig)
 605		return;
 606
 607	if (dm_digtable->cur_igvalue != current_igi) {
 608		rtl_set_bbreg(hw, DM_REG_IGI_A_11AC,
 609			      DM_BIT_IGI_11AC, current_igi);
 610		if (rtlpriv->phy.rf_type != RF_1T1R)
 611			rtl_set_bbreg(hw, DM_REG_IGI_B_11AC,
 612				      DM_BIT_IGI_11AC, current_igi);
 613	}
 614	dm_digtable->cur_igvalue = current_igi;
 615}
 616
 617static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
 618{
 619	struct rtl_priv *rtlpriv = rtl_priv(hw);
 620	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
 621	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 622	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 623	u8 dig_min_0;
 624	u8 dig_max_of_min;
 625	bool first_connect, first_disconnect;
 626	u8 dm_dig_max, dm_dig_min, offset;
 627	u8 current_igi = dm_digtable->cur_igvalue;
 628
 629	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "\n");
 630
 631	if (mac->act_scanning) {
 632		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 633			"Return: In Scan Progress\n");
 634		return;
 635	}
 636
 637	/*add by Neil Chen to avoid PSD is processing*/
 638	dig_min_0 = dm_digtable->dig_min_0;
 639	first_connect = (mac->link_state >= MAC80211_LINKED) &&
 640			(!dm_digtable->media_connect_0);
 641	first_disconnect = (mac->link_state < MAC80211_LINKED) &&
 642			(dm_digtable->media_connect_0);
 643
 644	/*1 Boundary Decision*/
 645
 646	dm_dig_max = 0x5A;
 647
 648	if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
 649		dm_dig_min = DM_DIG_MIN;
 650	else
 651		dm_dig_min = 0x1C;
 652
 653	dig_max_of_min = DM_DIG_MAX_AP;
 654
 655	if (mac->link_state >= MAC80211_LINKED) {
 656		if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
 657			offset = 20;
 658		else
 659			offset = 10;
 660
 661		if ((dm_digtable->rssi_val_min + offset) > dm_dig_max)
 662			dm_digtable->rx_gain_max = dm_dig_max;
 663		else if ((dm_digtable->rssi_val_min + offset) < dm_dig_min)
 664			dm_digtable->rx_gain_max = dm_dig_min;
 665		else
 666			dm_digtable->rx_gain_max =
 667				dm_digtable->rssi_val_min + offset;
 668
 669		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 670			"dm_digtable->rssi_val_min=0x%x,dm_digtable->rx_gain_max = 0x%x\n",
 671			dm_digtable->rssi_val_min,
 672			dm_digtable->rx_gain_max);
 673		if (rtlpriv->dm.one_entry_only) {
 674			offset = 0;
 675
 676			if (dm_digtable->rssi_val_min - offset < dm_dig_min)
 677				dig_min_0 = dm_dig_min;
 678			else if (dm_digtable->rssi_val_min -
 679				offset > dig_max_of_min)
 680				dig_min_0 = dig_max_of_min;
 681			else
 682				dig_min_0 =
 683					dm_digtable->rssi_val_min - offset;
 684
 685			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 686				"bOneEntryOnly=TRUE, dig_min_0=0x%x\n",
 687				dig_min_0);
 688		} else {
 689			dig_min_0 = dm_dig_min;
 690		}
 691	} else {
 692		dm_digtable->rx_gain_max = dm_dig_max;
 693		dig_min_0 = dm_dig_min;
 694		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No Link\n");
 695	}
 696
 697	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
 698		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 699			"Abnormally false alarm case.\n");
 700
 701		if (dm_digtable->large_fa_hit != 3)
 702			dm_digtable->large_fa_hit++;
 703		if (dm_digtable->forbidden_igi < current_igi) {
 704			dm_digtable->forbidden_igi = current_igi;
 705			dm_digtable->large_fa_hit = 1;
 706		}
 707
 708		if (dm_digtable->large_fa_hit >= 3) {
 709			if ((dm_digtable->forbidden_igi + 1) >
 710				dm_digtable->rx_gain_max)
 711				dm_digtable->rx_gain_min =
 712					dm_digtable->rx_gain_max;
 713			else
 714				dm_digtable->rx_gain_min =
 715					(dm_digtable->forbidden_igi + 1);
 716			dm_digtable->recover_cnt = 3600;
 717		}
 718	} else {
 719		/*Recovery mechanism for IGI lower bound*/
 720		if (dm_digtable->recover_cnt != 0) {
 721			dm_digtable->recover_cnt--;
 722		} else {
 723			if (dm_digtable->large_fa_hit < 3) {
 724				if ((dm_digtable->forbidden_igi - 1) <
 725				    dig_min_0) {
 726					dm_digtable->forbidden_igi =
 727						dig_min_0;
 728					dm_digtable->rx_gain_min =
 729						dig_min_0;
 730					rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 731						"Normal Case: At Lower Bound\n");
 732				} else {
 733					dm_digtable->forbidden_igi--;
 734					dm_digtable->rx_gain_min =
 735					  (dm_digtable->forbidden_igi + 1);
 736					rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 737						"Normal Case: Approach Lower Bound\n");
 738				}
 739			} else {
 740				dm_digtable->large_fa_hit = 0;
 741			}
 742		}
 743	}
 744	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 745		"pDM_DigTable->LargeFAHit=%d\n",
 746		dm_digtable->large_fa_hit);
 747
 748	if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10)
 749		dm_digtable->rx_gain_min = dm_dig_min;
 750
 751	if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
 752		dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
 753
 754	/*Adjust initial gain by false alarm*/
 755	if (mac->link_state >= MAC80211_LINKED) {
 756		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 757			"DIG AfterLink\n");
 758		if (first_connect) {
 759			if (dm_digtable->rssi_val_min <= dig_max_of_min)
 760				current_igi = dm_digtable->rssi_val_min;
 761			else
 762				current_igi = dig_max_of_min;
 763			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 764				"First Connect\n");
 765		} else {
 766			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 767				current_igi = current_igi + 4;
 768			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 769				current_igi = current_igi + 2;
 770			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 771				current_igi = current_igi - 2;
 772
 773			if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) &&
 774			    (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) {
 775				current_igi = dm_digtable->rx_gain_min;
 776				rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 777					"Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n");
 778			}
 779		}
 780	} else {
 781		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 782			"DIG BeforeLink\n");
 783		if (first_disconnect) {
 784			current_igi = dm_digtable->rx_gain_min;
 785			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 786				"First DisConnect\n");
 787		} else {
 788			/* 2012.03.30 LukeLee: enable DIG before
 789			 * link but with very high thresholds
 790			 */
 791			if (rtlpriv->falsealm_cnt.cnt_all > 2000)
 792				current_igi = current_igi + 4;
 793			else if (rtlpriv->falsealm_cnt.cnt_all > 600)
 794				current_igi = current_igi + 2;
 795			else if (rtlpriv->falsealm_cnt.cnt_all < 300)
 796				current_igi = current_igi - 2;
 797
 798			if (current_igi >= 0x3e)
 799				current_igi = 0x3e;
 800
 801			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n");
 802		}
 803	}
 804	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 805		"DIG End Adjust IGI\n");
 806	/* Check initial gain by upper/lower bound*/
 807
 808	if (current_igi > dm_digtable->rx_gain_max)
 809		current_igi = dm_digtable->rx_gain_max;
 810	if (current_igi < dm_digtable->rx_gain_min)
 811		current_igi = dm_digtable->rx_gain_min;
 812
 813	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 814		"rx_gain_max=0x%x, rx_gain_min=0x%x\n",
 815		dm_digtable->rx_gain_max, dm_digtable->rx_gain_min);
 816	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 817		"TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all);
 818	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 819		"CurIGValue=0x%x\n", current_igi);
 820
 821	rtl8821ae_dm_write_dig(hw, current_igi);
 822	dm_digtable->media_connect_0 =
 823		((mac->link_state >= MAC80211_LINKED) ? true : false);
 824	dm_digtable->dig_min_0 = dig_min_0;
 825}
 826
 827static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw)
 828{
 829	struct rtl_priv *rtlpriv = rtl_priv(hw);
 830	u8 cnt;
 831
 832	rtlpriv->dm.tx_rate = 0xff;
 833
 834	rtlpriv->dm.one_entry_only = false;
 835
 836	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
 837	    rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
 838		rtlpriv->dm.one_entry_only = true;
 839		return;
 840	}
 841
 842	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
 843	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
 844	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
 845		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 846		cnt = list_count_nodes(&rtlpriv->entry_list);
 847		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 848
 849		if (cnt == 1)
 850			rtlpriv->dm.one_entry_only = true;
 851	}
 852}
 853
 854static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 855{
 856	struct rtl_priv *rtlpriv = rtl_priv(hw);
 857	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
 858	u32 cck_enable = 0;
 859
 860	/*read OFDM FA counter*/
 861	falsealm_cnt->cnt_ofdm_fail =
 862		rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD);
 863	falsealm_cnt->cnt_cck_fail =
 864		rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD);
 865
 866	cck_enable =  rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28));
 867	if (cck_enable)  /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/
 868		falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
 869					falsealm_cnt->cnt_cck_fail;
 870	else
 871		falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
 872
 873	/*reset OFDM FA counter*/
 874	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
 875	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
 876	/* reset CCK FA counter*/
 877	rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
 878	rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
 879
 880	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n",
 881		falsealm_cnt->cnt_cck_fail);
 882	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n",
 883		falsealm_cnt->cnt_ofdm_fail);
 884	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n",
 885		falsealm_cnt->cnt_all);
 886}
 887
 888static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
 889		struct ieee80211_hw *hw)
 890{
 891	struct rtl_priv *rtlpriv = rtl_priv(hw);
 892
 893	if (!rtlpriv->dm.tm_trigger) {
 894		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
 895			      BIT(17) | BIT(16), 0x03);
 896		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 897			"Trigger 8812 Thermal Meter!!\n");
 898		rtlpriv->dm.tm_trigger = 1;
 899		return;
 900	}
 901	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 902		"Schedule TxPowerTracking direct call!!\n");
 903	rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
 904}
 905
 906static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
 907{
 908	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 909	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 910	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 911
 912	if (mac->link_state >= MAC80211_LINKED) {
 913		if (rtldm->linked_interval < 3)
 914			rtldm->linked_interval++;
 915
 916		if (rtldm->linked_interval == 2) {
 917			if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 918				rtl8812ae_phy_iq_calibrate(hw, false);
 919			else
 920				rtl8821ae_phy_iq_calibrate(hw, false);
 921		}
 922	} else {
 923		rtldm->linked_interval = 0;
 924	}
 925}
 926
 927static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
 928					    const u8 **up_a,
 929					    const u8 **down_a,
 930					    const u8 **up_b,
 931					    const u8 **down_b)
 932{
 933	struct rtl_priv *rtlpriv = rtl_priv(hw);
 934	struct rtl_phy *rtlphy = &rtlpriv->phy;
 935	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 936	u8 channel = rtlphy->current_channel;
 937	u8 rate = rtldm->tx_rate;
 938
 939	if (1 <= channel && channel <= 14) {
 940		if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
 941			*up_a = rtl8812ae_delta_swing_table_idx_24gccka_p;
 942			*down_a = rtl8812ae_delta_swing_table_idx_24gccka_n;
 943			*up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p;
 944			*down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n;
 945		} else {
 946			*up_a = rtl8812ae_delta_swing_table_idx_24ga_p;
 947			*down_a = rtl8812ae_delta_swing_table_idx_24ga_n;
 948			*up_b = rtl8812ae_delta_swing_table_idx_24gb_p;
 949			*down_b = rtl8812ae_delta_swing_table_idx_24gb_n;
 950		}
 951	} else if (36 <= channel && channel <= 64) {
 952		*up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0];
 953		*down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0];
 954		*up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0];
 955		*down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0];
 956	} else if (100 <= channel && channel <= 140) {
 957		*up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1];
 958		*down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1];
 959		*up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1];
 960		*down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1];
 961	} else if (149 <= channel && channel <= 173) {
 962		*up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2];
 963		*down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2];
 964		*up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2];
 965		*down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2];
 966	} else {
 967		*up_a = rtl8818e_delta_swing_table_idx_24gb_p;
 968		*down_a = rtl8818e_delta_swing_table_idx_24gb_n;
 969		*up_b = rtl8818e_delta_swing_table_idx_24gb_p;
 970		*down_b = rtl8818e_delta_swing_table_idx_24gb_n;
 971	}
 972}
 973
 974void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
 975{
 976	struct rtl_priv *rtlpriv = rtl_priv(hw);
 977	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
 978	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 979	u8 p = 0;
 980
 981	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 982		"Get C2H Command! Rate=0x%x\n", rate);
 983
 984	rtldm->tx_rate = rate;
 985
 986	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
 987		rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
 988	} else {
 989		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
 990			rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
 991	}
 992}
 993
 994u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
 995{
 996	struct rtl_priv *rtlpriv = rtl_priv(hw);
 997	u8 ret_rate = MGN_1M;
 998
 999	switch (rate) {
1000	case DESC_RATE1M:
1001		ret_rate = MGN_1M;
1002		break;
1003	case DESC_RATE2M:
1004		ret_rate = MGN_2M;
1005		break;
1006	case DESC_RATE5_5M:
1007		ret_rate = MGN_5_5M;
1008		break;
1009	case DESC_RATE11M:
1010		ret_rate = MGN_11M;
1011		break;
1012	case DESC_RATE6M:
1013		ret_rate = MGN_6M;
1014		break;
1015	case DESC_RATE9M:
1016		ret_rate = MGN_9M;
1017		break;
1018	case DESC_RATE12M:
1019		ret_rate = MGN_12M;
1020		break;
1021	case DESC_RATE18M:
1022		ret_rate = MGN_18M;
1023		break;
1024	case DESC_RATE24M:
1025		ret_rate = MGN_24M;
1026		break;
1027	case DESC_RATE36M:
1028		ret_rate = MGN_36M;
1029		break;
1030	case DESC_RATE48M:
1031		ret_rate = MGN_48M;
1032		break;
1033	case DESC_RATE54M:
1034		ret_rate = MGN_54M;
1035		break;
1036	case DESC_RATEMCS0:
1037		ret_rate = MGN_MCS0;
1038		break;
1039	case DESC_RATEMCS1:
1040		ret_rate = MGN_MCS1;
1041		break;
1042	case DESC_RATEMCS2:
1043		ret_rate = MGN_MCS2;
1044		break;
1045	case DESC_RATEMCS3:
1046		ret_rate = MGN_MCS3;
1047		break;
1048	case DESC_RATEMCS4:
1049		ret_rate = MGN_MCS4;
1050		break;
1051	case DESC_RATEMCS5:
1052		ret_rate = MGN_MCS5;
1053		break;
1054	case DESC_RATEMCS6:
1055		ret_rate = MGN_MCS6;
1056		break;
1057	case DESC_RATEMCS7:
1058		ret_rate = MGN_MCS7;
1059		break;
1060	case DESC_RATEMCS8:
1061		ret_rate = MGN_MCS8;
1062		break;
1063	case DESC_RATEMCS9:
1064		ret_rate = MGN_MCS9;
1065		break;
1066	case DESC_RATEMCS10:
1067		ret_rate = MGN_MCS10;
1068		break;
1069	case DESC_RATEMCS11:
1070		ret_rate = MGN_MCS11;
1071		break;
1072	case DESC_RATEMCS12:
1073		ret_rate = MGN_MCS12;
1074		break;
1075	case DESC_RATEMCS13:
1076		ret_rate = MGN_MCS13;
1077		break;
1078	case DESC_RATEMCS14:
1079		ret_rate = MGN_MCS14;
1080		break;
1081	case DESC_RATEMCS15:
1082		ret_rate = MGN_MCS15;
1083		break;
1084	case DESC_RATEVHT1SS_MCS0:
1085		ret_rate = MGN_VHT1SS_MCS0;
1086		break;
1087	case DESC_RATEVHT1SS_MCS1:
1088		ret_rate = MGN_VHT1SS_MCS1;
1089		break;
1090	case DESC_RATEVHT1SS_MCS2:
1091		ret_rate = MGN_VHT1SS_MCS2;
1092		break;
1093	case DESC_RATEVHT1SS_MCS3:
1094		ret_rate = MGN_VHT1SS_MCS3;
1095		break;
1096	case DESC_RATEVHT1SS_MCS4:
1097		ret_rate = MGN_VHT1SS_MCS4;
1098		break;
1099	case DESC_RATEVHT1SS_MCS5:
1100		ret_rate = MGN_VHT1SS_MCS5;
1101		break;
1102	case DESC_RATEVHT1SS_MCS6:
1103		ret_rate = MGN_VHT1SS_MCS6;
1104		break;
1105	case DESC_RATEVHT1SS_MCS7:
1106		ret_rate = MGN_VHT1SS_MCS7;
1107		break;
1108	case DESC_RATEVHT1SS_MCS8:
1109		ret_rate = MGN_VHT1SS_MCS8;
1110		break;
1111	case DESC_RATEVHT1SS_MCS9:
1112		ret_rate = MGN_VHT1SS_MCS9;
1113		break;
1114	case DESC_RATEVHT2SS_MCS0:
1115		ret_rate = MGN_VHT2SS_MCS0;
1116		break;
1117	case DESC_RATEVHT2SS_MCS1:
1118		ret_rate = MGN_VHT2SS_MCS1;
1119		break;
1120	case DESC_RATEVHT2SS_MCS2:
1121		ret_rate = MGN_VHT2SS_MCS2;
1122		break;
1123	case DESC_RATEVHT2SS_MCS3:
1124		ret_rate = MGN_VHT2SS_MCS3;
1125		break;
1126	case DESC_RATEVHT2SS_MCS4:
1127		ret_rate = MGN_VHT2SS_MCS4;
1128		break;
1129	case DESC_RATEVHT2SS_MCS5:
1130		ret_rate = MGN_VHT2SS_MCS5;
1131		break;
1132	case DESC_RATEVHT2SS_MCS6:
1133		ret_rate = MGN_VHT2SS_MCS6;
1134		break;
1135	case DESC_RATEVHT2SS_MCS7:
1136		ret_rate = MGN_VHT2SS_MCS7;
1137		break;
1138	case DESC_RATEVHT2SS_MCS8:
1139		ret_rate = MGN_VHT2SS_MCS8;
1140		break;
1141	case DESC_RATEVHT2SS_MCS9:
1142		ret_rate = MGN_VHT2SS_MCS9;
1143		break;
1144	default:
1145		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1146			"HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1147			rate);
1148		break;
1149	}
1150	return ret_rate;
1151}
1152
1153/*-----------------------------------------------------------------------------
1154 * Function:	odm_TxPwrTrackSetPwr88E()
1155 *
1156 * Overview:	88E change all channel tx power accordign to flag.
1157 *				OFDM & CCK are all different.
1158 *
1159 * Input:		NONE
1160 *
1161 * Output:		NONE
1162 *
1163 * Return:		NONE
1164 *
1165 * Revised History:
1166 *	When		Who		Remark
1167 *	04/23/2012	MHC		Create Version 0.
1168 *
1169 *---------------------------------------------------------------------------
1170 */
1171void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1172				      enum pwr_track_control_method method,
1173				      u8 rf_path, u8 channel_mapped_index)
1174{
1175	struct rtl_priv *rtlpriv = rtl_priv(hw);
1176	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
1177	struct rtl_phy *rtlphy = &rtlpriv->phy;
1178	u32 final_swing_idx[2];
1179	u8 pwr_tracking_limit = 26; /*+1.0dB*/
1180	u8 tx_rate = 0xFF;
1181	s8 final_ofdm_swing_index = 0;
1182
1183	if (rtldm->tx_rate != 0xFF)
1184		tx_rate =
1185			rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1186
1187	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1188		"===>%s\n", __func__);
1189	/*20130429 Mimic Modify High Rate BBSwing Limit.*/
1190	if (tx_rate != 0xFF) {
1191		/*CCK*/
1192		if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1193			pwr_tracking_limit = 32; /*+4dB*/
1194		/*OFDM*/
1195		else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1196			pwr_tracking_limit = 30; /*+3dB*/
1197		else if (tx_rate == MGN_54M)
1198			pwr_tracking_limit = 28; /*+2dB*/
1199		/*HT*/
1200		 /*QPSK/BPSK*/
1201		else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1202			pwr_tracking_limit = 34; /*+5dB*/
1203		 /*16QAM*/
1204		else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1205			pwr_tracking_limit = 30; /*+3dB*/
1206		 /*64QAM*/
1207		else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1208			pwr_tracking_limit = 28; /*+2dB*/
1209		 /*QPSK/BPSK*/
1210		else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1211			pwr_tracking_limit = 34; /*+5dB*/
1212		 /*16QAM*/
1213		else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1214			pwr_tracking_limit = 30; /*+3dB*/
1215		 /*64QAM*/
1216		else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1217			pwr_tracking_limit = 28; /*+2dB*/
1218
1219		/*2 VHT*/
1220		 /*QPSK/BPSK*/
1221		else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1222			 (tx_rate <= MGN_VHT1SS_MCS2))
1223			pwr_tracking_limit = 34; /*+5dB*/
1224		 /*16QAM*/
1225		else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1226			 (tx_rate <= MGN_VHT1SS_MCS4))
1227			pwr_tracking_limit = 30; /*+3dB*/
1228		 /*64QAM*/
1229		else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1230			 (tx_rate <= MGN_VHT1SS_MCS6))
1231			pwr_tracking_limit = 28; /*+2dB*/
1232		else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1233			pwr_tracking_limit = 26; /*+1dB*/
1234		else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1235			pwr_tracking_limit = 24; /*+0dB*/
1236		else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1237			pwr_tracking_limit = 22; /*-1dB*/
1238		 /*QPSK/BPSK*/
1239		else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1240			 (tx_rate <= MGN_VHT2SS_MCS2))
1241			pwr_tracking_limit = 34; /*+5dB*/
1242		 /*16QAM*/
1243		else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1244			 (tx_rate <= MGN_VHT2SS_MCS4))
1245			pwr_tracking_limit = 30; /*+3dB*/
1246		 /*64QAM*/
1247		else if ((tx_rate >= MGN_VHT2SS_MCS5) &&
1248			 (tx_rate <= MGN_VHT2SS_MCS6))
1249			pwr_tracking_limit = 28; /*+2dB*/
1250		else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/
1251			pwr_tracking_limit = 26; /*+1dB*/
1252		else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/
1253			pwr_tracking_limit = 24; /*+0dB*/
1254		else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/
1255			pwr_tracking_limit = 22; /*-1dB*/
1256		else
1257			pwr_tracking_limit = 24;
1258	}
1259	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1260		"TxRate=0x%x, PwrTrackingLimit=%d\n",
1261		tx_rate, pwr_tracking_limit);
1262
1263	if (method == BBSWING) {
1264		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1265			"===>%s\n", __func__);
1266
1267		if (rf_path == RF90_PATH_A) {
1268			u32 tmp;
1269
1270			final_swing_idx[RF90_PATH_A] =
1271				(rtldm->ofdm_index[RF90_PATH_A] >
1272				pwr_tracking_limit) ?
1273				pwr_tracking_limit :
1274				rtldm->ofdm_index[RF90_PATH_A];
1275			tmp = final_swing_idx[RF90_PATH_A];
1276			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1277				"pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1278				rtldm->ofdm_index[RF90_PATH_A],
1279				final_swing_idx[RF90_PATH_A]);
1280
1281			rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1282				      txscaling_tbl[tmp]);
1283		} else {
1284			u32 tmp;
1285
1286			final_swing_idx[RF90_PATH_B] =
1287				rtldm->ofdm_index[RF90_PATH_B] >
1288				pwr_tracking_limit ?
1289				pwr_tracking_limit :
1290				rtldm->ofdm_index[RF90_PATH_B];
1291			tmp = final_swing_idx[RF90_PATH_B];
1292			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1293				"pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n",
1294				rtldm->ofdm_index[RF90_PATH_B],
1295				final_swing_idx[RF90_PATH_B]);
1296
1297			rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1298				      txscaling_tbl[tmp]);
1299		}
1300	} else if (method == MIX_MODE) {
1301		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1302			"pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1303			rtldm->default_ofdm_index,
1304			rtldm->absolute_ofdm_swing_idx[rf_path],
1305			rf_path);
1306
1307		final_ofdm_swing_index = rtldm->default_ofdm_index +
1308				rtldm->absolute_ofdm_swing_idx[rf_path];
1309
1310		if (rf_path == RF90_PATH_A) {
1311			/*BBSwing higher then Limit*/
1312			if (final_ofdm_swing_index > pwr_tracking_limit) {
1313				rtldm->remnant_cck_idx =
1314					final_ofdm_swing_index -
1315					pwr_tracking_limit;
1316				/* CCK Follow the same compensation value
1317				 * as Path A
1318				 */
1319				rtldm->remnant_ofdm_swing_idx[rf_path] =
1320					final_ofdm_swing_index -
1321					pwr_tracking_limit;
1322
1323				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1324					      txscaling_tbl[pwr_tracking_limit]);
1325
1326				rtldm->modify_txagc_flag_path_a = true;
1327
1328				/*Set TxAGC Page C{};*/
1329				rtl8821ae_phy_set_txpower_level_by_path(hw,
1330					rtlphy->current_channel,
1331					RF90_PATH_A);
1332
1333				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1334					"******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
1335					pwr_tracking_limit,
1336					rtldm->remnant_ofdm_swing_idx[rf_path]);
1337			} else if (final_ofdm_swing_index < 0) {
1338				rtldm->remnant_cck_idx = final_ofdm_swing_index;
1339				/* CCK Follow the same compensate value as Path A*/
1340				rtldm->remnant_ofdm_swing_idx[rf_path] =
1341					final_ofdm_swing_index;
1342
1343				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1344					txscaling_tbl[0]);
1345
1346				rtldm->modify_txagc_flag_path_a = true;
1347
1348				/*Set TxAGC Page C{};*/
1349				rtl8821ae_phy_set_txpower_level_by_path(hw,
1350					rtlphy->current_channel, RF90_PATH_A);
1351
1352				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1353					"******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1354					rtldm->remnant_ofdm_swing_idx[rf_path]);
1355			} else {
1356				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1357					txscaling_tbl[(u8)final_ofdm_swing_index]);
1358
1359				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1360					"******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n",
1361					final_ofdm_swing_index);
1362				/*If TxAGC has changed, reset TxAGC again*/
1363				if (rtldm->modify_txagc_flag_path_a) {
1364					rtldm->remnant_cck_idx = 0;
1365					rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1366
1367					/*Set TxAGC Page C{};*/
1368					rtl8821ae_phy_set_txpower_level_by_path(hw,
1369						rtlphy->current_channel, RF90_PATH_A);
1370					rtldm->modify_txagc_flag_path_a = false;
1371
1372					rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
1373						DBG_LOUD,
1374						"******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1375				}
1376			}
1377		}
1378		/*BBSwing higher then Limit*/
1379		if (rf_path == RF90_PATH_B) {
1380			if (final_ofdm_swing_index > pwr_tracking_limit) {
1381				rtldm->remnant_ofdm_swing_idx[rf_path] =
1382					final_ofdm_swing_index -
1383					pwr_tracking_limit;
1384
1385				rtl_set_bbreg(hw, RB_TXSCALE,
1386					0xFFE00000,
1387					txscaling_tbl[pwr_tracking_limit]);
1388
1389				rtldm->modify_txagc_flag_path_b = true;
1390
1391				/*Set TxAGC Page E{};*/
1392				rtl8821ae_phy_set_txpower_level_by_path(hw,
1393					rtlphy->current_channel, RF90_PATH_B);
1394
1395				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1396					"******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1397					pwr_tracking_limit,
1398					 rtldm->remnant_ofdm_swing_idx[rf_path]);
1399			} else if (final_ofdm_swing_index < 0) {
1400				rtldm->remnant_ofdm_swing_idx[rf_path] =
1401					final_ofdm_swing_index;
1402
1403				rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1404					      txscaling_tbl[0]);
1405
1406				rtldm->modify_txagc_flag_path_b = true;
1407
1408				/*Set TxAGC Page E{};*/
1409				rtl8821ae_phy_set_txpower_level_by_path(hw,
1410					rtlphy->current_channel, RF90_PATH_B);
1411
1412				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1413					"******Path_B Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1414					rtldm->remnant_ofdm_swing_idx[rf_path]);
1415			} else {
1416				rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1417					txscaling_tbl[(u8)final_ofdm_swing_index]);
1418
1419				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1420					"******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1421					final_ofdm_swing_index);
1422				 /*If TxAGC has changed, reset TxAGC again*/
1423				if (rtldm->modify_txagc_flag_path_b) {
1424					rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1425
1426					/*Set TxAGC Page E{};*/
1427					rtl8821ae_phy_set_txpower_level_by_path(hw,
1428					rtlphy->current_channel, RF90_PATH_B);
1429
1430					rtldm->modify_txagc_flag_path_b =
1431						false;
1432
1433					rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1434						"******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1435				}
1436			}
1437		}
1438	} else {
1439		return;
1440	}
1441}
1442
1443void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1444	struct ieee80211_hw *hw)
1445{
1446	struct rtl_priv *rtlpriv = rtl_priv(hw);
1447	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1448	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
1449	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1450	u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
1451	u8 thermal_value_avg_count = 0;
1452	u32 thermal_value_avg = 0;
1453	/* OFDM BB Swing should be less than +3.0dB, */
1454	u8 ofdm_min_index = 6;
1455	 /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
1456	u8 index_for_channel = 0;
1457	/* 1. The following TWO tables decide
1458	 * the final index of OFDM/CCK swing table.
1459	 */
1460	const u8 *delta_swing_table_idx_tup_a;
1461	const u8 *delta_swing_table_idx_tdown_a;
1462	const u8 *delta_swing_table_idx_tup_b;
1463	const u8 *delta_swing_table_idx_tdown_b;
1464
1465	/*2. Initialization ( 7 steps in total )*/
1466	rtl8812ae_get_delta_swing_table(hw,
1467		&delta_swing_table_idx_tup_a,
1468		&delta_swing_table_idx_tdown_a,
1469		&delta_swing_table_idx_tup_b,
1470		&delta_swing_table_idx_tdown_b);
1471
1472	rtldm->txpower_trackinginit = true;
1473
1474	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1475		"pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
1476		rtldm->swing_idx_cck_base,
1477		rtldm->swing_idx_ofdm_base[RF90_PATH_A],
1478		rtldm->default_ofdm_index);
1479
1480	thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A,
1481		/*0x42: RF Reg[15:10] 88E*/
1482		RF_T_METER_8812A, 0xfc00);
1483	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1484		"Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1485		thermal_value, rtlefuse->eeprom_thermalmeter);
1486	if (!rtldm->txpower_track_control ||
1487	    rtlefuse->eeprom_thermalmeter == 0 ||
1488	    rtlefuse->eeprom_thermalmeter == 0xFF)
1489		return;
1490
1491	/* 3. Initialize ThermalValues of RFCalibrateInfo*/
1492
1493	if (rtlhal->reloadtxpowerindex)
1494		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1495			"reload ofdm index for band switch\n");
1496
1497	/*4. Calculate average thermal meter*/
1498	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
1499	rtldm->thermalvalue_avg_index++;
1500	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
1501		/*Average times =  c.AverageThermalNum*/
1502		rtldm->thermalvalue_avg_index = 0;
1503
1504	for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
1505		if (rtldm->thermalvalue_avg[i]) {
1506			thermal_value_avg += rtldm->thermalvalue_avg[i];
1507			thermal_value_avg_count++;
1508		}
1509	}
1510	/*Calculate Average ThermalValue after average enough times*/
1511	if (thermal_value_avg_count) {
1512		thermal_value = (u8)(thermal_value_avg /
1513				thermal_value_avg_count);
1514		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1515			"AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1516			thermal_value, rtlefuse->eeprom_thermalmeter);
1517	}
1518
1519	/*5. Calculate delta, delta_LCK, delta_IQK.
1520	 *"delta" here is used to determine whether
1521	 *thermal value changes or not.
1522	 */
1523	delta = (thermal_value > rtldm->thermalvalue) ?
1524		(thermal_value - rtldm->thermalvalue) :
1525		(rtldm->thermalvalue - thermal_value);
1526	delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
1527		(thermal_value - rtldm->thermalvalue_lck) :
1528		(rtldm->thermalvalue_lck - thermal_value);
1529	delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
1530		(thermal_value - rtldm->thermalvalue_iqk) :
1531		(rtldm->thermalvalue_iqk - thermal_value);
1532
1533	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1534		"(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
1535		delta, delta_lck, delta_iqk);
1536
1537	/* 6. If necessary, do LCK.
1538	 * Delta temperature is equal to or larger than 20 centigrade.
1539	 */
1540	if (delta_lck >= IQK_THRESHOLD) {
1541		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1542			"delta_LCK(%d) >= Threshold_IQK(%d)\n",
1543			delta_lck, IQK_THRESHOLD);
1544		rtldm->thermalvalue_lck = thermal_value;
1545		rtl8821ae_phy_lc_calibrate(hw);
1546	}
1547
1548	/*7. If necessary, move the index of swing table to adjust Tx power.*/
1549
1550	if (delta > 0 && rtldm->txpower_track_control) {
1551		/* "delta" here is used to record the
1552		 * absolute value of differrence.
1553		 */
1554		delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1555			(thermal_value - rtlefuse->eeprom_thermalmeter) :
1556			(rtlefuse->eeprom_thermalmeter - thermal_value);
1557
1558		if (delta >= TXPWR_TRACK_TABLE_SIZE)
1559			delta = TXPWR_TRACK_TABLE_SIZE - 1;
1560
1561		/*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
1562
1563		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1564			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1565				"delta_swing_table_idx_tup_a[%d] = %d\n",
1566				delta, delta_swing_table_idx_tup_a[delta]);
1567			rtldm->delta_power_index_last[RF90_PATH_A] =
1568				rtldm->delta_power_index[RF90_PATH_A];
1569			rtldm->delta_power_index[RF90_PATH_A] =
1570				delta_swing_table_idx_tup_a[delta];
1571
1572			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1573				delta_swing_table_idx_tup_a[delta];
1574			/*Record delta swing for mix mode power tracking*/
1575
1576			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1577				"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1578			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1579
1580			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1581				"delta_swing_table_idx_tup_b[%d] = %d\n",
1582				delta, delta_swing_table_idx_tup_b[delta]);
1583			rtldm->delta_power_index_last[RF90_PATH_B] =
1584				rtldm->delta_power_index[RF90_PATH_B];
1585			rtldm->delta_power_index[RF90_PATH_B] =
1586				delta_swing_table_idx_tup_b[delta];
1587
1588			rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1589				delta_swing_table_idx_tup_b[delta];
1590			/*Record delta swing for mix mode power tracking*/
1591
1592			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1593				"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1594				rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1595		} else {
1596			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1597				"delta_swing_table_idx_tdown_a[%d] = %d\n",
1598				delta, delta_swing_table_idx_tdown_a[delta]);
1599
1600			rtldm->delta_power_index_last[RF90_PATH_A] =
1601				rtldm->delta_power_index[RF90_PATH_A];
1602			rtldm->delta_power_index[RF90_PATH_A] =
1603				-1 * delta_swing_table_idx_tdown_a[delta];
1604
1605			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1606				-1 * delta_swing_table_idx_tdown_a[delta];
1607			/* Record delta swing for mix mode power tracking*/
1608			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1609				"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1610				rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1611
1612			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1613				"deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
1614				delta, delta_swing_table_idx_tdown_b[delta]);
1615
1616			rtldm->delta_power_index_last[RF90_PATH_B] =
1617				rtldm->delta_power_index[RF90_PATH_B];
1618			rtldm->delta_power_index[RF90_PATH_B] =
1619				-1 * delta_swing_table_idx_tdown_b[delta];
1620
1621			rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1622				-1 * delta_swing_table_idx_tdown_b[delta];
1623			/*Record delta swing for mix mode power tracking*/
1624
1625			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1626				"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1627				rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1628		}
1629
1630		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1631			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1632				"============================= [Path-%c]Calculating PowerIndexOffset =============================\n",
1633				(p == RF90_PATH_A ? 'A' : 'B'));
1634
1635			if (rtldm->delta_power_index[p] ==
1636				rtldm->delta_power_index_last[p])
1637				/*If Thermal value changes but lookup
1638				table value still the same*/
1639				rtldm->power_index_offset[p] = 0;
1640			else
1641				rtldm->power_index_offset[p] =
1642					rtldm->delta_power_index[p] -
1643					rtldm->delta_power_index_last[p];
1644				/* Power Index Diff between 2
1645				 * times Power Tracking
1646				 */
1647			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1648				"[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n",
1649				(p == RF90_PATH_A ? 'A' : 'B'),
1650				rtldm->power_index_offset[p],
1651				rtldm->delta_power_index[p],
1652				rtldm->delta_power_index_last[p]);
1653
1654			rtldm->ofdm_index[p] =
1655					rtldm->swing_idx_ofdm_base[p] +
1656					rtldm->power_index_offset[p];
1657			rtldm->cck_index =
1658					rtldm->swing_idx_cck_base +
1659					rtldm->power_index_offset[p];
1660
1661			rtldm->swing_idx_cck = rtldm->cck_index;
1662			rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1663
1664			/****Print BB Swing Base and Index Offset */
1665
1666			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1667				"The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
1668				rtldm->swing_idx_cck,
1669				rtldm->swing_idx_cck_base,
1670				rtldm->power_index_offset[p]);
1671			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1672				"The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
1673				rtldm->swing_idx_ofdm[p],
1674				(p == RF90_PATH_A ? 'A' : 'B'),
1675				rtldm->swing_idx_ofdm_base[p],
1676				rtldm->power_index_offset[p]);
1677
1678			/*7.1 Handle boundary conditions of index.*/
1679
1680			if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
1681				rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
1682			else if (rtldm->ofdm_index[p] < ofdm_min_index)
1683				rtldm->ofdm_index[p] = ofdm_min_index;
1684		}
1685		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1686			"\n\n====================================================================================\n");
1687		if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
1688			rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
1689		else if (rtldm->cck_index < 0)
1690			rtldm->cck_index = 0;
1691	} else {
1692		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1693			"The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
1694			rtldm->txpower_track_control,
1695			thermal_value,
1696			rtldm->thermalvalue);
1697
1698		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1699			rtldm->power_index_offset[p] = 0;
1700	}
1701	/*Print Swing base & current*/
1702	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1703		"TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n",
1704		rtldm->cck_index, rtldm->swing_idx_cck_base);
1705	for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1706		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1707			"TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n",
1708			rtldm->ofdm_index[p],
1709			(p == RF90_PATH_A ? 'A' : 'B'),
1710			rtldm->swing_idx_ofdm_base[p]);
1711	}
1712
1713	if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
1714		rtldm->power_index_offset[RF90_PATH_B] != 0) &&
1715		rtldm->txpower_track_control) {
1716		/*7.2 Configure the Swing Table to adjust Tx Power.
1717		 *Always TRUE after Tx Power is adjusted by power tracking.
1718		 *
1719		 *2012/04/23 MH According to Luke's suggestion,
1720		 *we can not write BB digital
1721		 *to increase TX power. Otherwise, EVM will be bad.
1722		 *
1723		 *2012/04/25 MH Add for tx power tracking to set
1724		 *tx power in tx agc for 88E.
1725		 */
1726		if (thermal_value > rtldm->thermalvalue) {
1727			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1728				"Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n",
1729				rtldm->power_index_offset[RF90_PATH_A],
1730				delta, thermal_value,
1731				rtlefuse->eeprom_thermalmeter,
1732				rtldm->thermalvalue);
1733
1734			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1735				"Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1736				rtldm->power_index_offset[RF90_PATH_B],
1737				delta, thermal_value,
1738				rtlefuse->eeprom_thermalmeter,
1739				rtldm->thermalvalue);
1740		} else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
1741			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1742				"Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1743				rtldm->power_index_offset[RF90_PATH_A],
1744				delta, thermal_value,
1745				rtlefuse->eeprom_thermalmeter,
1746				rtldm->thermalvalue);
1747
1748			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1749				"Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1750				rtldm->power_index_offset[RF90_PATH_B],
1751				delta, thermal_value,
1752				rtlefuse->eeprom_thermalmeter,
1753				rtldm->thermalvalue);
1754		}
1755
1756		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1757			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1758				"Temperature(%d) higher than PG value(%d)\n",
1759				thermal_value, rtlefuse->eeprom_thermalmeter);
1760
1761			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1762				"**********Enter POWER Tracking MIX_MODE**********\n");
1763			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1764				rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1765								 p, 0);
1766		} else {
1767			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1768				"Temperature(%d) lower than PG value(%d)\n",
1769				thermal_value, rtlefuse->eeprom_thermalmeter);
1770
1771			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1772				"**********Enter POWER Tracking MIX_MODE**********\n");
1773			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1774				rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1775								 p, index_for_channel);
1776		}
1777		/*Record last time Power Tracking result as base.*/
1778		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
1779		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1780				rtldm->swing_idx_ofdm_base[p] =
1781					rtldm->swing_idx_ofdm[p];
1782
1783		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1784			"pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n",
1785			rtldm->thermalvalue, thermal_value);
1786		/*Record last Power Tracking Thermal Value*/
1787		rtldm->thermalvalue = thermal_value;
1788	}
1789	/*Delta temperature is equal to or larger than
1790	20 centigrade (When threshold is 8).*/
1791	if (delta_iqk >= IQK_THRESHOLD)
1792		rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8);
1793
1794	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1795		"<===%s\n", __func__);
1796}
1797
1798static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw,
1799					    const u8 **up_a,
1800					    const u8 **down_a)
1801{
1802	struct rtl_priv *rtlpriv = rtl_priv(hw);
1803	struct rtl_phy *rtlphy = &rtlpriv->phy;
1804	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1805	u8 channel = rtlphy->current_channel;
1806	u8 rate = rtldm->tx_rate;
1807
1808	if (1 <= channel && channel <= 14) {
1809		if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1810			*up_a = rtl8821ae_delta_swing_table_idx_24gccka_p;
1811			*down_a = rtl8821ae_delta_swing_table_idx_24gccka_n;
1812		} else {
1813			*up_a = rtl8821ae_delta_swing_table_idx_24ga_p;
1814			*down_a = rtl8821ae_delta_swing_table_idx_24ga_n;
1815		}
1816	} else if (36 <= channel && channel <= 64) {
1817		*up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0];
1818		*down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0];
1819	} else if (100 <= channel && channel <= 140) {
1820		*up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1];
1821		*down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1];
1822	} else if (149 <= channel && channel <= 173) {
1823		*up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2];
1824		*down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2];
1825	} else {
1826		*up_a = rtl8818e_delta_swing_table_idx_24gb_p;
1827		*down_a = rtl8818e_delta_swing_table_idx_24gb_n;
1828	}
1829	return;
1830}
1831
1832/*-----------------------------------------------------------------------------
1833 * Function:	odm_TxPwrTrackSetPwr88E()
1834 *
1835 * Overview:	88E change all channel tx power accordign to flag.
1836 *				OFDM & CCK are all different.
1837 *
1838 * Input:		NONE
1839 *
1840 * Output:		NONE
1841 *
1842 * Return:		NONE
1843 *
1844 * Revised History:
1845 *	When		Who		Remark
1846 *	04/23/2012	MHC		Create Version 0.
1847 *
1848 *---------------------------------------------------------------------------
1849 */
1850void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1851				      enum pwr_track_control_method method,
1852				      u8 rf_path, u8 channel_mapped_index)
1853{
1854	struct rtl_priv *rtlpriv = rtl_priv(hw);
1855	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
1856	struct rtl_phy *rtlphy = &rtlpriv->phy;
1857	u32 final_swing_idx[1];
1858	u8 pwr_tracking_limit = 26; /*+1.0dB*/
1859	u8 tx_rate = 0xFF;
1860	s8 final_ofdm_swing_index = 0;
1861
1862	if (rtldm->tx_rate != 0xFF)
1863		tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1864
1865	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
1866
1867	if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
1868		/*CCK*/
1869		if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1870			pwr_tracking_limit = 32; /*+4dB*/
1871		/*OFDM*/
1872		else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1873			pwr_tracking_limit = 30; /*+3dB*/
1874		else if (tx_rate == MGN_54M)
1875			pwr_tracking_limit = 28; /*+2dB*/
1876		/*HT*/
1877		/*QPSK/BPSK*/
1878		else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1879			pwr_tracking_limit = 34; /*+5dB*/
1880		/*16QAM*/
1881		else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1882			pwr_tracking_limit = 30; /*+3dB*/
1883		/*64QAM*/
1884		else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1885			pwr_tracking_limit = 28; /*+2dB*/
1886		/*2 VHT*/
1887		/*QPSK/BPSK*/
1888		else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1889			(tx_rate <= MGN_VHT1SS_MCS2))
1890			pwr_tracking_limit = 34; /*+5dB*/
1891		/*16QAM*/
1892		else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1893			(tx_rate <= MGN_VHT1SS_MCS4))
1894			pwr_tracking_limit = 30; /*+3dB*/
1895		/*64QAM*/
1896		else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1897			(tx_rate <= MGN_VHT1SS_MCS6))
1898			pwr_tracking_limit = 28; /*+2dB*/
1899		else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1900			pwr_tracking_limit = 26; /*+1dB*/
1901		else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1902			pwr_tracking_limit = 24; /*+0dB*/
1903		else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1904			pwr_tracking_limit = 22; /*-1dB*/
1905		else
1906			pwr_tracking_limit = 24;
1907	}
1908	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1909		"TxRate=0x%x, PwrTrackingLimit=%d\n",
1910		tx_rate, pwr_tracking_limit);
1911
1912	if (method == BBSWING) {
1913		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1914			"===>%s\n", __func__);
1915		if (rf_path == RF90_PATH_A) {
1916			final_swing_idx[RF90_PATH_A] =
1917				(rtldm->ofdm_index[RF90_PATH_A] >
1918				pwr_tracking_limit) ?
1919				pwr_tracking_limit :
1920				rtldm->ofdm_index[RF90_PATH_A];
1921			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1922				"pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1923				rtldm->ofdm_index[RF90_PATH_A],
1924				final_swing_idx[RF90_PATH_A]);
1925
1926			rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1927				txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
1928		}
1929	} else if (method == MIX_MODE) {
1930		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1931			"pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1932			rtldm->default_ofdm_index,
1933			rtldm->absolute_ofdm_swing_idx[rf_path],
1934			rf_path);
1935
1936		final_ofdm_swing_index =
1937			rtldm->default_ofdm_index +
1938			rtldm->absolute_ofdm_swing_idx[rf_path];
1939		/*BBSwing higher then Limit*/
1940		if (rf_path == RF90_PATH_A) {
1941			if (final_ofdm_swing_index > pwr_tracking_limit) {
1942				rtldm->remnant_cck_idx =
1943					final_ofdm_swing_index -
1944					pwr_tracking_limit;
1945				/* CCK Follow the same compensate value as Path A*/
1946				rtldm->remnant_ofdm_swing_idx[rf_path] =
1947					final_ofdm_swing_index -
1948					pwr_tracking_limit;
1949
1950				rtl_set_bbreg(hw, RA_TXSCALE,
1951					0xFFE00000,
1952					txscaling_tbl[pwr_tracking_limit]);
1953
1954				rtldm->modify_txagc_flag_path_a = true;
1955
1956				/*Set TxAGC Page C{};*/
1957				rtl8821ae_phy_set_txpower_level_by_path(hw,
1958					rtlphy->current_channel,
1959					RF90_PATH_A);
1960
1961				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1962					" ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1963					pwr_tracking_limit,
1964					rtldm->remnant_ofdm_swing_idx[rf_path]);
1965			} else if (final_ofdm_swing_index < 0) {
1966				rtldm->remnant_cck_idx = final_ofdm_swing_index;
1967				/* CCK Follow the same compensate value as Path A*/
1968				rtldm->remnant_ofdm_swing_idx[rf_path] =
1969					final_ofdm_swing_index;
1970
1971				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1972					txscaling_tbl[0]);
1973
1974				rtldm->modify_txagc_flag_path_a = true;
1975
1976				/*Set TxAGC Page C{};*/
1977				rtl8821ae_phy_set_txpower_level_by_path(hw,
1978					rtlphy->current_channel, RF90_PATH_A);
1979
1980				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1981					"******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1982					rtldm->remnant_ofdm_swing_idx[rf_path]);
1983			} else {
1984				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1985					txscaling_tbl[(u8)final_ofdm_swing_index]);
1986
1987				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1988					"******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1989					final_ofdm_swing_index);
1990				/*If TxAGC has changed, reset TxAGC again*/
1991				if (rtldm->modify_txagc_flag_path_a) {
1992					rtldm->remnant_cck_idx = 0;
1993					rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1994
1995					/*Set TxAGC Page C{};*/
1996					rtl8821ae_phy_set_txpower_level_by_path(hw,
1997						rtlphy->current_channel, RF90_PATH_A);
1998
1999					rtldm->modify_txagc_flag_path_a = false;
2000
2001					rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
2002						DBG_LOUD,
2003						"******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2004				}
2005			}
2006		}
2007	} else {
2008		return;
2009	}
2010}
2011
2012void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2013	struct ieee80211_hw *hw)
2014{
2015	struct rtl_priv *rtlpriv = rtl_priv(hw);
2016	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2017	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
2018	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2019	struct rtl_phy *rtlphy = &rtlpriv->phy;
2020
2021	u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
2022	u8 thermal_value_avg_count = 0;
2023	u32 thermal_value_avg = 0;
2024
2025	u8 ofdm_min_index = 6;  /*OFDM BB Swing should be less than +3.0dB */
2026	/* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
2027	u8 index_for_channel = 0;
2028
2029	/* 1. The following TWO tables decide the final
2030	 * index of OFDM/CCK swing table.
2031	 */
2032	const u8 *delta_swing_table_idx_tup_a;
2033	const u8 *delta_swing_table_idx_tdown_a;
2034
2035	/*2. Initilization ( 7 steps in total )*/
2036	rtl8821ae_get_delta_swing_table(hw,
2037					&delta_swing_table_idx_tup_a,
2038					&delta_swing_table_idx_tdown_a);
2039
2040	rtldm->txpower_trackinginit = true;
2041
2042	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2043		"===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
2044		__func__,
2045		rtldm->swing_idx_cck_base,
2046		rtldm->swing_idx_ofdm_base[RF90_PATH_A],
2047		rtldm->default_ofdm_index);
2048	/*0x42: RF Reg[15:10] 88E*/
2049	thermal_value = (u8)rtl_get_rfreg(hw,
2050		RF90_PATH_A, RF_T_METER_8812A, 0xfc00);
2051	if (!rtldm->txpower_track_control ||
2052		rtlefuse->eeprom_thermalmeter == 0 ||
2053		rtlefuse->eeprom_thermalmeter == 0xFF)
2054		return;
2055
2056	/* 3. Initialize ThermalValues of RFCalibrateInfo*/
2057
2058	if (rtlhal->reloadtxpowerindex) {
2059		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2060			"reload ofdm index for band switch\n");
2061	}
2062
2063	/*4. Calculate average thermal meter*/
2064	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
2065	rtldm->thermalvalue_avg_index++;
2066	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
2067		/*Average times =  c.AverageThermalNum*/
2068		rtldm->thermalvalue_avg_index = 0;
2069
2070	for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
2071		if (rtldm->thermalvalue_avg[i]) {
2072			thermal_value_avg += rtldm->thermalvalue_avg[i];
2073			thermal_value_avg_count++;
2074		}
2075	}
2076	/*Calculate Average ThermalValue after average enough times*/
2077	if (thermal_value_avg_count) {
2078		thermal_value = (u8)(thermal_value_avg /
2079				thermal_value_avg_count);
2080		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2081			"AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
2082			thermal_value, rtlefuse->eeprom_thermalmeter);
2083	}
2084
2085	/*5. Calculate delta, delta_LCK, delta_IQK.
2086	 *"delta" here is used to determine whether
2087	 * thermal value changes or not.
2088	 */
2089	delta = (thermal_value > rtldm->thermalvalue) ?
2090		(thermal_value - rtldm->thermalvalue) :
2091		(rtldm->thermalvalue - thermal_value);
2092	delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
2093		(thermal_value - rtldm->thermalvalue_lck) :
2094		(rtldm->thermalvalue_lck - thermal_value);
2095	delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
2096		(thermal_value - rtldm->thermalvalue_iqk) :
2097		(rtldm->thermalvalue_iqk - thermal_value);
2098
2099	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2100		"(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
2101		delta, delta_lck, delta_iqk);
2102
2103	/* 6. If necessary, do LCK.	*/
2104	/*Delta temperature is equal to or larger than 20 centigrade.*/
2105	if (delta_lck >= IQK_THRESHOLD) {
2106		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2107			"delta_LCK(%d) >= Threshold_IQK(%d)\n",
2108			delta_lck, IQK_THRESHOLD);
2109		rtldm->thermalvalue_lck = thermal_value;
2110		rtl8821ae_phy_lc_calibrate(hw);
2111	}
2112
2113	/*7. If necessary, move the index of swing table to adjust Tx power.*/
2114
2115	if (delta > 0 && rtldm->txpower_track_control) {
2116		/*"delta" here is used to record the
2117		 * absolute value of differrence.
2118		 */
2119		delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2120			(thermal_value - rtlefuse->eeprom_thermalmeter) :
2121			(rtlefuse->eeprom_thermalmeter - thermal_value);
2122
2123		if (delta >= TXSCALE_TABLE_SIZE)
2124			delta = TXSCALE_TABLE_SIZE - 1;
2125
2126		/*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
2127
2128		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2129			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2130				"delta_swing_table_idx_tup_a[%d] = %d\n",
2131				delta, delta_swing_table_idx_tup_a[delta]);
2132			rtldm->delta_power_index_last[RF90_PATH_A] =
2133				rtldm->delta_power_index[RF90_PATH_A];
2134			rtldm->delta_power_index[RF90_PATH_A] =
2135				delta_swing_table_idx_tup_a[delta];
2136
2137			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2138				delta_swing_table_idx_tup_a[delta];
2139			/*Record delta swing for mix mode power tracking*/
2140
2141			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2142				"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2143				rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2144		} else {
2145			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2146				"delta_swing_table_idx_tdown_a[%d] = %d\n",
2147				delta, delta_swing_table_idx_tdown_a[delta]);
2148
2149			rtldm->delta_power_index_last[RF90_PATH_A] =
2150				rtldm->delta_power_index[RF90_PATH_A];
2151			rtldm->delta_power_index[RF90_PATH_A] =
2152				-1 * delta_swing_table_idx_tdown_a[delta];
2153
2154			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2155				-1 * delta_swing_table_idx_tdown_a[delta];
2156			/* Record delta swing for mix mode power tracking*/
2157			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2158				"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2159				rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2160		}
2161
2162		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2163			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2164				"\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n",
2165				(p == RF90_PATH_A ? 'A' : 'B'));
2166			/*If Thermal value changes but lookup table value
2167			 * still the same
2168			 */
2169			if (rtldm->delta_power_index[p] ==
2170				rtldm->delta_power_index_last[p])
2171
2172				rtldm->power_index_offset[p] = 0;
2173			else
2174				rtldm->power_index_offset[p] =
2175					rtldm->delta_power_index[p] -
2176					rtldm->delta_power_index_last[p];
2177			/*Power Index Diff between 2 times Power Tracking*/
2178
2179			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2180				"[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
2181				(p == RF90_PATH_A ? 'A' : 'B'),
2182				rtldm->power_index_offset[p],
2183				rtldm->delta_power_index[p] ,
2184				rtldm->delta_power_index_last[p]);
2185
2186			rtldm->ofdm_index[p] =
2187					rtldm->swing_idx_ofdm_base[p] +
2188					rtldm->power_index_offset[p];
2189			rtldm->cck_index =
2190					rtldm->swing_idx_cck_base +
2191					rtldm->power_index_offset[p];
2192
2193			rtldm->swing_idx_cck = rtldm->cck_index;
2194			rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2195
2196			/*********Print BB Swing Base and Index Offset********/
2197
2198			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2199				"The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
2200				rtldm->swing_idx_cck,
2201				rtldm->swing_idx_cck_base,
2202				rtldm->power_index_offset[p]);
2203			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2204				"The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
2205				rtldm->swing_idx_ofdm[p],
2206				(p == RF90_PATH_A ? 'A' : 'B'),
2207				rtldm->swing_idx_ofdm_base[p],
2208				rtldm->power_index_offset[p]);
2209
2210			/*7.1 Handle boundary conditions of index.*/
2211
2212			if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
2213				rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
2214			else if (rtldm->ofdm_index[p] < ofdm_min_index)
2215				rtldm->ofdm_index[p] = ofdm_min_index;
2216		}
2217		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2218			"\n\n========================================================================================================\n");
2219		if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
2220			rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
2221		else if (rtldm->cck_index < 0)
2222			rtldm->cck_index = 0;
2223	} else {
2224		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2225			"The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
2226			rtldm->txpower_track_control,
2227			thermal_value,
2228			rtldm->thermalvalue);
2229
2230		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2231			rtldm->power_index_offset[p] = 0;
2232	}
2233	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2234		"TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
2235		/*Print Swing base & current*/
2236		rtldm->cck_index, rtldm->swing_idx_cck_base);
2237	for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2238		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2239			"TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
2240			rtldm->ofdm_index[p],
2241			(p == RF90_PATH_A ? 'A' : 'B'),
2242			rtldm->swing_idx_ofdm_base[p]);
2243	}
2244
2245	if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
2246		rtldm->power_index_offset[RF90_PATH_B] != 0) &&
2247		rtldm->txpower_track_control) {
2248		/*7.2 Configure the Swing Table to adjust Tx Power.*/
2249		/*Always TRUE after Tx Power is adjusted by power tracking.*/
2250		/*
2251		 *  2012/04/23 MH According to Luke's suggestion,
2252		 *  we can not write BB digital
2253		 *  to increase TX power. Otherwise, EVM will be bad.
2254		 *
2255		 *  2012/04/25 MH Add for tx power tracking to
2256		 *  set tx power in tx agc for 88E.
2257		 */
2258		if (thermal_value > rtldm->thermalvalue) {
2259			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2260				"Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2261				rtldm->power_index_offset[RF90_PATH_A],
2262				delta, thermal_value,
2263				rtlefuse->eeprom_thermalmeter,
2264				rtldm->thermalvalue);
2265		} else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
2266			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2267				"Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2268				rtldm->power_index_offset[RF90_PATH_A],
2269				delta, thermal_value,
2270				rtlefuse->eeprom_thermalmeter,
2271				rtldm->thermalvalue);
2272		}
2273
2274		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2275			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2276				"Temperature(%d) higher than PG value(%d)\n",
2277				thermal_value, rtlefuse->eeprom_thermalmeter);
2278
2279			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2280				"****Enter POWER Tracking MIX_MODE****\n");
2281			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2282					rtl8821ae_dm_txpwr_track_set_pwr(hw,
2283						MIX_MODE, p, index_for_channel);
2284		} else {
2285			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2286				"Temperature(%d) lower than PG value(%d)\n",
2287				thermal_value, rtlefuse->eeprom_thermalmeter);
2288
2289			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2290				"*****Enter POWER Tracking MIX_MODE*****\n");
2291			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2292				rtl8812ae_dm_txpwr_track_set_pwr(hw,
2293					MIX_MODE, p, index_for_channel);
2294		}
2295		/*Record last time Power Tracking result as base.*/
2296		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
2297		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2298			rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
2299
2300		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2301			"pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
2302			rtldm->thermalvalue, thermal_value);
2303		/*Record last Power Tracking Thermal Value*/
2304		rtldm->thermalvalue = thermal_value;
2305	}
2306	/* Delta temperature is equal to or larger than
2307	 * 20 centigrade (When threshold is 8).
2308	 */
2309	if (delta_iqk >= IQK_THRESHOLD) {
2310		if (!rtlphy->lck_inprogress) {
2311			spin_lock(&rtlpriv->locks.iqk_lock);
2312			rtlphy->lck_inprogress = true;
2313			spin_unlock(&rtlpriv->locks.iqk_lock);
2314
2315			rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2316
2317			spin_lock(&rtlpriv->locks.iqk_lock);
2318			rtlphy->lck_inprogress = false;
2319			spin_unlock(&rtlpriv->locks.iqk_lock);
2320		}
2321	}
2322
2323	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
2324}
2325
2326void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2327{
2328	struct rtl_priv *rtlpriv = rtl_priv(hw);
2329	if (!rtlpriv->dm.tm_trigger) {
2330		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2331			      0x03);
2332		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2333			"Trigger 8821ae Thermal Meter!!\n");
2334		rtlpriv->dm.tm_trigger = 1;
2335		return;
2336	} else {
2337		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2338			"Schedule TxPowerTracking !!\n");
2339
2340		rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2341		rtlpriv->dm.tm_trigger = 0;
2342	}
2343}
2344
2345static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
2346{
2347	struct rtl_priv *rtlpriv = rtl_priv(hw);
2348	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2349	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2350	struct rate_adaptive *p_ra = &rtlpriv->ra;
2351	u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
2352	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
2353	u8 go_up_gap = 5;
2354	struct ieee80211_sta *sta = NULL;
2355
2356	if (is_hal_stop(rtlhal)) {
2357		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2358			"driver is going to unload\n");
2359		return;
2360	}
2361
2362	if (!rtlpriv->dm.useramask) {
2363		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2364			"driver does not control rate adaptive mask\n");
2365		return;
2366	}
2367
2368	if (mac->link_state == MAC80211_LINKED &&
2369		mac->opmode == NL80211_IFTYPE_STATION) {
2370		switch (p_ra->pre_ratr_state) {
2371		case DM_RATR_STA_MIDDLE:
2372			high_rssithresh_for_ra += go_up_gap;
2373			break;
2374		case DM_RATR_STA_LOW:
2375			high_rssithresh_for_ra += go_up_gap;
2376			low_rssithresh_for_ra += go_up_gap;
2377			break;
2378		default:
2379			break;
2380		}
2381
2382		if (rtlpriv->dm.undec_sm_pwdb >
2383		    (long)high_rssithresh_for_ra)
2384			p_ra->ratr_state = DM_RATR_STA_HIGH;
2385		else if (rtlpriv->dm.undec_sm_pwdb >
2386			 (long)low_rssithresh_for_ra)
2387			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
2388		else
2389			p_ra->ratr_state = DM_RATR_STA_LOW;
2390
2391		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2392			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2393				"RSSI = %ld\n",
2394				rtlpriv->dm.undec_sm_pwdb);
2395			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2396				"RSSI_LEVEL = %d\n", p_ra->ratr_state);
2397			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2398				"PreState = %d, CurState = %d\n",
2399				p_ra->pre_ratr_state, p_ra->ratr_state);
2400
2401			rcu_read_lock();
2402			sta = rtl_find_sta(hw, mac->bssid);
2403			if (sta)
2404				rtlpriv->cfg->ops->update_rate_tbl(hw,
2405						sta, p_ra->ratr_state, true);
2406			rcu_read_unlock();
2407
2408			p_ra->pre_ratr_state = p_ra->ratr_state;
2409		}
2410	}
2411}
2412
2413static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2414{
2415	struct rtl_priv *rtlpriv = rtl_priv(hw);
2416	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2417	struct rtl_mac *mac = &rtlpriv->mac80211;
2418	static u8 stage;
2419	u8 cur_stage = 0;
2420	u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2421
2422	if (mac->link_state < MAC80211_LINKED)
2423		cur_stage = 0;
2424	else if (dm_digtable->rssi_val_min < 25)
2425		cur_stage = 1;
2426	else if (dm_digtable->rssi_val_min > 30)
2427		cur_stage = 3;
2428	else
2429		cur_stage = 2;
2430
2431	if (cur_stage != stage) {
2432		if (cur_stage == 1) {
2433			basic_rate &= (!(basic_rate ^ mac->basic_rates));
2434			rtlpriv->cfg->ops->set_hw_reg(hw,
2435				HW_VAR_BASIC_RATE, (u8 *)&basic_rate);
2436		} else if (cur_stage == 3 && (stage == 1 || stage == 2)) {
2437			rtlpriv->cfg->ops->set_hw_reg(hw,
2438				HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates);
2439		}
2440	}
2441	stage = cur_stage;
2442}
2443
2444static void rtl8821ae_dm_edca_choose_traffic_idx(
2445	struct ieee80211_hw *hw, u64 cur_tx_bytes,
2446	u64 cur_rx_bytes, bool b_bias_on_rx,
2447	bool *pb_is_cur_rdl_state)
2448{
2449	struct rtl_priv *rtlpriv = rtl_priv(hw);
2450
2451	if (b_bias_on_rx) {
2452		if (cur_tx_bytes > (cur_rx_bytes*4)) {
2453			*pb_is_cur_rdl_state = false;
2454			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2455				"Uplink Traffic\n");
2456		} else {
2457			*pb_is_cur_rdl_state = true;
2458			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2459				"Balance Traffic\n");
2460		}
2461	} else {
2462		if (cur_rx_bytes > (cur_tx_bytes*4)) {
2463			*pb_is_cur_rdl_state = true;
2464			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2465				"Downlink	Traffic\n");
2466		} else {
2467			*pb_is_cur_rdl_state = false;
2468			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2469				"Balance Traffic\n");
2470		}
2471	}
2472	return;
2473}
2474
2475static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
2476{
2477	struct rtl_priv *rtlpriv = rtl_priv(hw);
2478	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2479	struct rtl_dm *rtldm =  rtl_dm(rtl_priv(hw));
2480
2481	/*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/
2482	u64 cur_tx_ok_cnt = 0;
2483	u64 cur_rx_ok_cnt = 0;
2484	u32 edca_be_ul = 0x5ea42b;
2485	u32 edca_be_dl = 0x5ea42b;
2486	u32 edca_be = 0x5ea42b;
2487	u8 iot_peer = 0;
2488	bool *pb_is_cur_rdl_state = NULL;
2489	bool b_bias_on_rx = false;
2490	bool b_edca_turbo_on = false;
2491
2492	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2493		"%s=====>\n", __func__);
2494	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2495		"Original BE PARAM: 0x%x\n",
2496		rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N));
2497
2498	if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
2499		rtlpriv->dm.is_any_nonbepkts = true;
2500	rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
2501
2502	/*===============================
2503	 * list parameter for different platform
2504	 *===============================
2505	 */
2506	pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
2507
2508	cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt;
2509	cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt;
2510
2511	rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2512	rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2513
2514	iot_peer = rtlpriv->mac80211.vendor;
2515	b_bias_on_rx = false;
2516	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
2517			   (!rtlpriv->dm.disable_framebursting)) ?
2518			   true : false;
2519
2520	if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) {
2521		if ((iot_peer == PEER_CISCO) &&
2522			(mac->mode == WIRELESS_MODE_N_24G)) {
2523			edca_be_dl = edca_setting_dl[iot_peer];
2524			edca_be_ul = edca_setting_ul[iot_peer];
2525		}
2526	}
2527
2528	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2529		"bIsAnyNonBEPkts : 0x%x  bDisableFrameBursting : 0x%x\n",
2530		rtlpriv->dm.is_any_nonbepkts,
2531		rtlpriv->dm.disable_framebursting);
2532
2533	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2534		"bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n",
2535		b_edca_turbo_on, b_bias_on_rx);
2536
2537	if (b_edca_turbo_on) {
2538		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2539			"curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt);
2540		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2541			"curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt);
2542		if (b_bias_on_rx)
2543			rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2544				cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2545		else
2546			rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2547				cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2548
2549		edca_be = (*pb_is_cur_rdl_state) ?  edca_be_dl : edca_be_ul;
2550
2551		rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2552
2553		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2554			"EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2555
2556		rtlpriv->dm.current_turbo_edca = true;
2557
2558		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2559			"EDCA_BE_DL : 0x%x  EDCA_BE_UL : 0x%x  EDCA_BE : 0x%x\n",
2560			edca_be_dl, edca_be_ul, edca_be);
2561	} else {
2562		if (rtlpriv->dm.current_turbo_edca) {
2563			u8 tmp = AC0_BE;
2564			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2565						      (u8 *)(&tmp));
2566		}
2567		rtlpriv->dm.current_turbo_edca = false;
2568	}
2569
2570	rtlpriv->dm.is_any_nonbepkts = false;
2571	rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2572	rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2573}
2574
2575static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2576{
2577	struct rtl_priv *rtlpriv = rtl_priv(hw);
2578	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2579	u8 cur_cck_cca_thresh;
2580
2581	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
2582		if (dm_digtable->rssi_val_min > 25) {
2583			cur_cck_cca_thresh = 0xcd;
2584		} else if ((dm_digtable->rssi_val_min <= 25) &&
2585			   (dm_digtable->rssi_val_min > 10)) {
2586			cur_cck_cca_thresh = 0x83;
2587		} else {
2588			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2589				cur_cck_cca_thresh = 0x83;
2590			else
2591				cur_cck_cca_thresh = 0x40;
2592		}
2593	} else {
2594		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2595			cur_cck_cca_thresh = 0x83;
2596		else
2597			cur_cck_cca_thresh = 0x40;
2598	}
2599
2600	if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
2601		rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC,
2602			       cur_cck_cca_thresh);
2603
2604	dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
2605	dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
2606	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
2607		"CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
2608}
2609
2610static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2611{
2612	struct rtl_priv *rtlpriv = rtl_priv(hw);
2613	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2614	u8 crystal_cap;
2615	u32 packet_count;
2616	int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2617	int cfo_ave_diff;
2618
2619	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
2620		/*1.Enable ATC*/
2621		if (rtldm->atc_status == ATC_STATUS_OFF) {
2622			rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON);
2623			rtldm->atc_status = ATC_STATUS_ON;
2624		}
2625
2626		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n");
2627		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2628			"atc_status = %d\n", rtldm->atc_status);
2629
2630		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
2631			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
2632			crystal_cap = rtldm->crystal_cap & 0x3f;
2633			crystal_cap = crystal_cap & 0x3f;
2634			if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2635				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2636					      0x7ff80000, (crystal_cap |
2637					      (crystal_cap << 6)));
2638			else
2639				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2640					      0xfff000, (crystal_cap |
2641					      (crystal_cap << 6)));
2642		}
2643		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2644			rtldm->crystal_cap);
2645	} else{
2646		/*1. Calculate CFO for path-A & path-B*/
2647		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
2648		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
2649		packet_count = rtldm->packet_count;
2650
2651		/*2.No new packet*/
2652		if (packet_count == rtldm->packet_count_pre) {
2653			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2654				"packet counter doesn't change\n");
2655			return;
2656		}
2657
2658		rtldm->packet_count_pre = packet_count;
2659		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2660			"packet counter = %d\n",
2661			rtldm->packet_count);
2662
2663		/*3.Average CFO*/
2664		if (rtlpriv->phy.rf_type == RF_1T1R)
2665			cfo_ave = cfo_khz_a;
2666		else
2667			cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
2668
2669		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2670			"cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n",
2671			cfo_khz_a, cfo_khz_b, cfo_ave);
2672
2673		/*4.Avoid abnormal large CFO*/
2674		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
2675						(rtldm->cfo_ave_pre - cfo_ave) :
2676						(cfo_ave - rtldm->cfo_ave_pre);
2677
2678		if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
2679			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2680				"first large CFO hit\n");
2681			rtldm->large_cfo_hit = true;
2682			return;
2683		} else
2684			rtldm->large_cfo_hit = false;
2685
2686		rtldm->cfo_ave_pre = cfo_ave;
2687
2688		/*CFO tracking by adjusting Xtal cap.*/
2689
2690		/*1.Dynamic Xtal threshold*/
2691		if (cfo_ave >= -rtldm->cfo_threshold &&
2692			cfo_ave <= rtldm->cfo_threshold &&
2693			rtldm->is_freeze == 0) {
2694			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
2695				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
2696				rtldm->is_freeze = 1;
2697			} else {
2698				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2699			}
2700		}
2701		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2702			"Dynamic threshold = %d\n",
2703			rtldm->cfo_threshold);
2704
2705		/* 2.Calculate Xtal offset*/
2706		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
2707			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
2708		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
2709			 rtlpriv->dm.crystal_cap > 0)
2710			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
2711		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2712			"Crystal cap = 0x%x, Crystal cap offset = %d\n",
2713			rtldm->crystal_cap, adjust_xtal);
2714
2715		/*3.Adjudt Crystal Cap.*/
2716		if (adjust_xtal != 0) {
2717			rtldm->is_freeze = 0;
2718			rtldm->crystal_cap += adjust_xtal;
2719
2720			if (rtldm->crystal_cap > 0x3f)
2721				rtldm->crystal_cap = 0x3f;
2722			else if (rtldm->crystal_cap < 0)
2723				rtldm->crystal_cap = 0;
2724
2725			crystal_cap = rtldm->crystal_cap & 0x3f;
2726			crystal_cap = crystal_cap & 0x3f;
2727			if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2728				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2729					      0x7ff80000, (crystal_cap |
2730					      (crystal_cap << 6)));
2731			else
2732				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2733					      0xfff000, (crystal_cap |
2734					      (crystal_cap << 6)));
2735			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2736				"New crystal cap = 0x%x\n",
2737				rtldm->crystal_cap);
2738		}
2739	}
2740}
2741
2742void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
2743{
2744	struct rtl_priv *rtlpriv = rtl_priv(hw);
2745	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2746	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2747	bool fw_current_inpsmode = false;
2748	bool fw_ps_awake = true;
2749
2750	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2751				      (u8 *)(&fw_current_inpsmode));
2752
2753	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2754				      (u8 *)(&fw_ps_awake));
2755
2756	if (ppsc->p2p_ps_info.p2p_ps_mode)
2757		fw_ps_awake = false;
2758
2759	spin_lock(&rtlpriv->locks.rf_ps_lock);
2760	if ((ppsc->rfpwr_state == ERFON) &&
2761	    ((!fw_current_inpsmode) && fw_ps_awake) &&
2762	    (!ppsc->rfchange_inprogress)) {
2763		rtl8821ae_dm_common_info_self_update(hw);
2764		rtl8821ae_dm_false_alarm_counter_statistics(hw);
2765		rtl8821ae_dm_check_rssi_monitor(hw);
2766		rtl8821ae_dm_dig(hw);
2767		rtl8821ae_dm_cck_packet_detection_thresh(hw);
2768		rtl8821ae_dm_refresh_rate_adaptive_mask(hw);
2769		rtl8821ae_dm_refresh_basic_rate_mask(hw);
2770		rtl8821ae_dm_check_edca_turbo(hw);
2771		rtl8821ae_dm_dynamic_atc_switch(hw);
2772		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
2773			rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw);
2774		else
2775			rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2776		rtl8821ae_dm_iq_calibrate(hw);
2777	}
2778	spin_unlock(&rtlpriv->locks.rf_ps_lock);
2779
2780	rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
2781	rtl_dbg(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
2782}
2783
2784void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
2785					u8 *pdesc, u32 mac_id)
2786{
2787	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2788	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2789	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2790	struct fast_ant_training *pfat_table = &rtldm->fat_table;
2791	__le32 *pdesc32 = (__le32 *)pdesc;
2792
2793	if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
2794		return;
2795
2796	if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
2797		set_tx_desc_tx_ant(pdesc32, pfat_table->antsel_a[mac_id]);
2798}