File Index
Files and directories
Sign in
FILE

dm.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c C
   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			current_igi = min(dm_digtable->rssi_val_min, dig_max_of_min);
 760			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 761				"First Connect\n");
 762		} else {
 763			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
 764				current_igi = current_igi + 4;
 765			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
 766				current_igi = current_igi + 2;
 767			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
 768				current_igi = current_igi - 2;
 769
 770			if ((rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10) &&
 771			    (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)) {
 772				current_igi = dm_digtable->rx_gain_min;
 773				rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 774					"Beacon is less than 10 and FA is less than 768, IGI GOES TO 0x1E!!!!!!!!!!!!\n");
 775			}
 776		}
 777	} else {
 778		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 779			"DIG BeforeLink\n");
 780		if (first_disconnect) {
 781			current_igi = dm_digtable->rx_gain_min;
 782			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 783				"First DisConnect\n");
 784		} else {
 785			/* 2012.03.30 LukeLee: enable DIG before
 786			 * link but with very high thresholds
 787			 */
 788			if (rtlpriv->falsealm_cnt.cnt_all > 2000)
 789				current_igi = current_igi + 4;
 790			else if (rtlpriv->falsealm_cnt.cnt_all > 600)
 791				current_igi = current_igi + 2;
 792			else if (rtlpriv->falsealm_cnt.cnt_all < 300)
 793				current_igi = current_igi - 2;
 794
 795			if (current_igi >= 0x3e)
 796				current_igi = 0x3e;
 797
 798			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n");
 799		}
 800	}
 801	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 802		"DIG End Adjust IGI\n");
 803	/* Check initial gain by upper/lower bound*/
 804
 805	if (current_igi > dm_digtable->rx_gain_max)
 806		current_igi = dm_digtable->rx_gain_max;
 807	if (current_igi < dm_digtable->rx_gain_min)
 808		current_igi = dm_digtable->rx_gain_min;
 809
 810	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 811		"rx_gain_max=0x%x, rx_gain_min=0x%x\n",
 812		dm_digtable->rx_gain_max, dm_digtable->rx_gain_min);
 813	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 814		"TotalFA=%d\n", rtlpriv->falsealm_cnt.cnt_all);
 815	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
 816		"CurIGValue=0x%x\n", current_igi);
 817
 818	rtl8821ae_dm_write_dig(hw, current_igi);
 819	dm_digtable->media_connect_0 =
 820		((mac->link_state >= MAC80211_LINKED) ? true : false);
 821	dm_digtable->dig_min_0 = dig_min_0;
 822}
 823
 824static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw)
 825{
 826	struct rtl_priv *rtlpriv = rtl_priv(hw);
 827	u8 cnt;
 828
 829	rtlpriv->dm.tx_rate = 0xff;
 830
 831	rtlpriv->dm.one_entry_only = false;
 832
 833	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
 834	    rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
 835		rtlpriv->dm.one_entry_only = true;
 836		return;
 837	}
 838
 839	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
 840	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
 841	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
 842		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
 843		cnt = list_count_nodes(&rtlpriv->entry_list);
 844		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
 845
 846		if (cnt == 1)
 847			rtlpriv->dm.one_entry_only = true;
 848	}
 849}
 850
 851static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
 852{
 853	struct rtl_priv *rtlpriv = rtl_priv(hw);
 854	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
 855	u32 cck_enable = 0;
 856
 857	/*read OFDM FA counter*/
 858	falsealm_cnt->cnt_ofdm_fail =
 859		rtl_get_bbreg(hw, ODM_REG_OFDM_FA_11AC, BMASKLWORD);
 860	falsealm_cnt->cnt_cck_fail =
 861		rtl_get_bbreg(hw, ODM_REG_CCK_FA_11AC, BMASKLWORD);
 862
 863	cck_enable =  rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC, BIT(28));
 864	if (cck_enable)  /*if(pDM_Odm->pBandType == ODM_BAND_2_4G)*/
 865		falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail +
 866					falsealm_cnt->cnt_cck_fail;
 867	else
 868		falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
 869
 870	/*reset OFDM FA counter*/
 871	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 1);
 872	rtl_set_bbreg(hw, ODM_REG_OFDM_FA_RST_11AC, BIT(17), 0);
 873	/* reset CCK FA counter*/
 874	rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 0);
 875	rtl_set_bbreg(hw, ODM_REG_CCK_FA_RST_11AC, BIT(15), 1);
 876
 877	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Cnt_Cck_fail=%d\n",
 878		falsealm_cnt->cnt_cck_fail);
 879	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "cnt_ofdm_fail=%d\n",
 880		falsealm_cnt->cnt_ofdm_fail);
 881	rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "Total False Alarm=%d\n",
 882		falsealm_cnt->cnt_all);
 883}
 884
 885static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
 886		struct ieee80211_hw *hw)
 887{
 888	struct rtl_priv *rtlpriv = rtl_priv(hw);
 889
 890	if (!rtlpriv->dm.tm_trigger) {
 891		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
 892			      BIT(17) | BIT(16), 0x03);
 893		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 894			"Trigger 8812 Thermal Meter!!\n");
 895		rtlpriv->dm.tm_trigger = 1;
 896		return;
 897	}
 898	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 899		"Schedule TxPowerTracking direct call!!\n");
 900	rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
 901}
 902
 903static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
 904{
 905	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 906	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 907	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 908
 909	if (mac->link_state >= MAC80211_LINKED) {
 910		if (rtldm->linked_interval < 3)
 911			rtldm->linked_interval++;
 912
 913		if (rtldm->linked_interval == 2) {
 914			if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
 915				rtl8812ae_phy_iq_calibrate(hw, false);
 916			else
 917				rtl8821ae_phy_iq_calibrate(hw, false);
 918		}
 919	} else {
 920		rtldm->linked_interval = 0;
 921	}
 922}
 923
 924static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
 925					    const u8 **up_a,
 926					    const u8 **down_a,
 927					    const u8 **up_b,
 928					    const u8 **down_b)
 929{
 930	struct rtl_priv *rtlpriv = rtl_priv(hw);
 931	struct rtl_phy *rtlphy = &rtlpriv->phy;
 932	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
 933	u8 channel = rtlphy->current_channel;
 934	u8 rate = rtldm->tx_rate;
 935
 936	if (1 <= channel && channel <= 14) {
 937		if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
 938			*up_a = rtl8812ae_delta_swing_table_idx_24gccka_p;
 939			*down_a = rtl8812ae_delta_swing_table_idx_24gccka_n;
 940			*up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p;
 941			*down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n;
 942		} else {
 943			*up_a = rtl8812ae_delta_swing_table_idx_24ga_p;
 944			*down_a = rtl8812ae_delta_swing_table_idx_24ga_n;
 945			*up_b = rtl8812ae_delta_swing_table_idx_24gb_p;
 946			*down_b = rtl8812ae_delta_swing_table_idx_24gb_n;
 947		}
 948	} else if (36 <= channel && channel <= 64) {
 949		*up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0];
 950		*down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0];
 951		*up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0];
 952		*down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0];
 953	} else if (100 <= channel && channel <= 140) {
 954		*up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1];
 955		*down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1];
 956		*up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1];
 957		*down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1];
 958	} else if (149 <= channel && channel <= 173) {
 959		*up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2];
 960		*down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2];
 961		*up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2];
 962		*down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2];
 963	} else {
 964		*up_a = rtl8818e_delta_swing_table_idx_24gb_p;
 965		*down_a = rtl8818e_delta_swing_table_idx_24gb_n;
 966		*up_b = rtl8818e_delta_swing_table_idx_24gb_p;
 967		*down_b = rtl8818e_delta_swing_table_idx_24gb_n;
 968	}
 969}
 970
 971void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
 972{
 973	struct rtl_priv *rtlpriv = rtl_priv(hw);
 974	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
 975	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 976	u8 p = 0;
 977
 978	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
 979		"Get C2H Command! Rate=0x%x\n", rate);
 980
 981	rtldm->tx_rate = rate;
 982
 983	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
 984		rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
 985	} else {
 986		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
 987			rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
 988	}
 989}
 990
 991u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
 992{
 993	struct rtl_priv *rtlpriv = rtl_priv(hw);
 994	u8 ret_rate = MGN_1M;
 995
 996	switch (rate) {
 997	case DESC_RATE1M:
 998		ret_rate = MGN_1M;
 999		break;
1000	case DESC_RATE2M:
1001		ret_rate = MGN_2M;
1002		break;
1003	case DESC_RATE5_5M:
1004		ret_rate = MGN_5_5M;
1005		break;
1006	case DESC_RATE11M:
1007		ret_rate = MGN_11M;
1008		break;
1009	case DESC_RATE6M:
1010		ret_rate = MGN_6M;
1011		break;
1012	case DESC_RATE9M:
1013		ret_rate = MGN_9M;
1014		break;
1015	case DESC_RATE12M:
1016		ret_rate = MGN_12M;
1017		break;
1018	case DESC_RATE18M:
1019		ret_rate = MGN_18M;
1020		break;
1021	case DESC_RATE24M:
1022		ret_rate = MGN_24M;
1023		break;
1024	case DESC_RATE36M:
1025		ret_rate = MGN_36M;
1026		break;
1027	case DESC_RATE48M:
1028		ret_rate = MGN_48M;
1029		break;
1030	case DESC_RATE54M:
1031		ret_rate = MGN_54M;
1032		break;
1033	case DESC_RATEMCS0:
1034		ret_rate = MGN_MCS0;
1035		break;
1036	case DESC_RATEMCS1:
1037		ret_rate = MGN_MCS1;
1038		break;
1039	case DESC_RATEMCS2:
1040		ret_rate = MGN_MCS2;
1041		break;
1042	case DESC_RATEMCS3:
1043		ret_rate = MGN_MCS3;
1044		break;
1045	case DESC_RATEMCS4:
1046		ret_rate = MGN_MCS4;
1047		break;
1048	case DESC_RATEMCS5:
1049		ret_rate = MGN_MCS5;
1050		break;
1051	case DESC_RATEMCS6:
1052		ret_rate = MGN_MCS6;
1053		break;
1054	case DESC_RATEMCS7:
1055		ret_rate = MGN_MCS7;
1056		break;
1057	case DESC_RATEMCS8:
1058		ret_rate = MGN_MCS8;
1059		break;
1060	case DESC_RATEMCS9:
1061		ret_rate = MGN_MCS9;
1062		break;
1063	case DESC_RATEMCS10:
1064		ret_rate = MGN_MCS10;
1065		break;
1066	case DESC_RATEMCS11:
1067		ret_rate = MGN_MCS11;
1068		break;
1069	case DESC_RATEMCS12:
1070		ret_rate = MGN_MCS12;
1071		break;
1072	case DESC_RATEMCS13:
1073		ret_rate = MGN_MCS13;
1074		break;
1075	case DESC_RATEMCS14:
1076		ret_rate = MGN_MCS14;
1077		break;
1078	case DESC_RATEMCS15:
1079		ret_rate = MGN_MCS15;
1080		break;
1081	case DESC_RATEVHT1SS_MCS0:
1082		ret_rate = MGN_VHT1SS_MCS0;
1083		break;
1084	case DESC_RATEVHT1SS_MCS1:
1085		ret_rate = MGN_VHT1SS_MCS1;
1086		break;
1087	case DESC_RATEVHT1SS_MCS2:
1088		ret_rate = MGN_VHT1SS_MCS2;
1089		break;
1090	case DESC_RATEVHT1SS_MCS3:
1091		ret_rate = MGN_VHT1SS_MCS3;
1092		break;
1093	case DESC_RATEVHT1SS_MCS4:
1094		ret_rate = MGN_VHT1SS_MCS4;
1095		break;
1096	case DESC_RATEVHT1SS_MCS5:
1097		ret_rate = MGN_VHT1SS_MCS5;
1098		break;
1099	case DESC_RATEVHT1SS_MCS6:
1100		ret_rate = MGN_VHT1SS_MCS6;
1101		break;
1102	case DESC_RATEVHT1SS_MCS7:
1103		ret_rate = MGN_VHT1SS_MCS7;
1104		break;
1105	case DESC_RATEVHT1SS_MCS8:
1106		ret_rate = MGN_VHT1SS_MCS8;
1107		break;
1108	case DESC_RATEVHT1SS_MCS9:
1109		ret_rate = MGN_VHT1SS_MCS9;
1110		break;
1111	case DESC_RATEVHT2SS_MCS0:
1112		ret_rate = MGN_VHT2SS_MCS0;
1113		break;
1114	case DESC_RATEVHT2SS_MCS1:
1115		ret_rate = MGN_VHT2SS_MCS1;
1116		break;
1117	case DESC_RATEVHT2SS_MCS2:
1118		ret_rate = MGN_VHT2SS_MCS2;
1119		break;
1120	case DESC_RATEVHT2SS_MCS3:
1121		ret_rate = MGN_VHT2SS_MCS3;
1122		break;
1123	case DESC_RATEVHT2SS_MCS4:
1124		ret_rate = MGN_VHT2SS_MCS4;
1125		break;
1126	case DESC_RATEVHT2SS_MCS5:
1127		ret_rate = MGN_VHT2SS_MCS5;
1128		break;
1129	case DESC_RATEVHT2SS_MCS6:
1130		ret_rate = MGN_VHT2SS_MCS6;
1131		break;
1132	case DESC_RATEVHT2SS_MCS7:
1133		ret_rate = MGN_VHT2SS_MCS7;
1134		break;
1135	case DESC_RATEVHT2SS_MCS8:
1136		ret_rate = MGN_VHT2SS_MCS8;
1137		break;
1138	case DESC_RATEVHT2SS_MCS9:
1139		ret_rate = MGN_VHT2SS_MCS9;
1140		break;
1141	default:
1142		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1143			"HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1144			rate);
1145		break;
1146	}
1147	return ret_rate;
1148}
1149
1150/*-----------------------------------------------------------------------------
1151 * Function:	odm_TxPwrTrackSetPwr88E()
1152 *
1153 * Overview:	88E change all channel tx power accordign to flag.
1154 *				OFDM & CCK are all different.
1155 *
1156 * Input:		NONE
1157 *
1158 * Output:		NONE
1159 *
1160 * Return:		NONE
1161 *
1162 * Revised History:
1163 *	When		Who		Remark
1164 *	04/23/2012	MHC		Create Version 0.
1165 *
1166 *---------------------------------------------------------------------------
1167 */
1168void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1169				      enum pwr_track_control_method method,
1170				      u8 rf_path, u8 channel_mapped_index)
1171{
1172	struct rtl_priv *rtlpriv = rtl_priv(hw);
1173	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
1174	struct rtl_phy *rtlphy = &rtlpriv->phy;
1175	u32 final_swing_idx[2];
1176	u8 pwr_tracking_limit = 26; /*+1.0dB*/
1177	u8 tx_rate = 0xFF;
1178	s8 final_ofdm_swing_index = 0;
1179
1180	if (rtldm->tx_rate != 0xFF)
1181		tx_rate =
1182			rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1183
1184	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1185		"===>%s\n", __func__);
1186	/*20130429 Mimic Modify High Rate BBSwing Limit.*/
1187	if (tx_rate != 0xFF) {
1188		/*CCK*/
1189		if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1190			pwr_tracking_limit = 32; /*+4dB*/
1191		/*OFDM*/
1192		else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1193			pwr_tracking_limit = 30; /*+3dB*/
1194		else if (tx_rate == MGN_54M)
1195			pwr_tracking_limit = 28; /*+2dB*/
1196		/*HT*/
1197		 /*QPSK/BPSK*/
1198		else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1199			pwr_tracking_limit = 34; /*+5dB*/
1200		 /*16QAM*/
1201		else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1202			pwr_tracking_limit = 30; /*+3dB*/
1203		 /*64QAM*/
1204		else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1205			pwr_tracking_limit = 28; /*+2dB*/
1206		 /*QPSK/BPSK*/
1207		else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1208			pwr_tracking_limit = 34; /*+5dB*/
1209		 /*16QAM*/
1210		else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1211			pwr_tracking_limit = 30; /*+3dB*/
1212		 /*64QAM*/
1213		else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1214			pwr_tracking_limit = 28; /*+2dB*/
1215
1216		/*2 VHT*/
1217		 /*QPSK/BPSK*/
1218		else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1219			 (tx_rate <= MGN_VHT1SS_MCS2))
1220			pwr_tracking_limit = 34; /*+5dB*/
1221		 /*16QAM*/
1222		else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1223			 (tx_rate <= MGN_VHT1SS_MCS4))
1224			pwr_tracking_limit = 30; /*+3dB*/
1225		 /*64QAM*/
1226		else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1227			 (tx_rate <= MGN_VHT1SS_MCS6))
1228			pwr_tracking_limit = 28; /*+2dB*/
1229		else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1230			pwr_tracking_limit = 26; /*+1dB*/
1231		else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1232			pwr_tracking_limit = 24; /*+0dB*/
1233		else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1234			pwr_tracking_limit = 22; /*-1dB*/
1235		 /*QPSK/BPSK*/
1236		else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1237			 (tx_rate <= MGN_VHT2SS_MCS2))
1238			pwr_tracking_limit = 34; /*+5dB*/
1239		 /*16QAM*/
1240		else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1241			 (tx_rate <= MGN_VHT2SS_MCS4))
1242			pwr_tracking_limit = 30; /*+3dB*/
1243		 /*64QAM*/
1244		else if ((tx_rate >= MGN_VHT2SS_MCS5) &&
1245			 (tx_rate <= MGN_VHT2SS_MCS6))
1246			pwr_tracking_limit = 28; /*+2dB*/
1247		else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/
1248			pwr_tracking_limit = 26; /*+1dB*/
1249		else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/
1250			pwr_tracking_limit = 24; /*+0dB*/
1251		else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/
1252			pwr_tracking_limit = 22; /*-1dB*/
1253		else
1254			pwr_tracking_limit = 24;
1255	}
1256	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1257		"TxRate=0x%x, PwrTrackingLimit=%d\n",
1258		tx_rate, pwr_tracking_limit);
1259
1260	if (method == BBSWING) {
1261		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1262			"===>%s\n", __func__);
1263
1264		if (rf_path == RF90_PATH_A) {
1265			u32 tmp;
1266
1267			final_swing_idx[RF90_PATH_A] =
1268				(rtldm->ofdm_index[RF90_PATH_A] >
1269				pwr_tracking_limit) ?
1270				pwr_tracking_limit :
1271				rtldm->ofdm_index[RF90_PATH_A];
1272			tmp = final_swing_idx[RF90_PATH_A];
1273			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1274				"pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1275				rtldm->ofdm_index[RF90_PATH_A],
1276				final_swing_idx[RF90_PATH_A]);
1277
1278			rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1279				      txscaling_tbl[tmp]);
1280		} else {
1281			u32 tmp;
1282
1283			final_swing_idx[RF90_PATH_B] =
1284				rtldm->ofdm_index[RF90_PATH_B] >
1285				pwr_tracking_limit ?
1286				pwr_tracking_limit :
1287				rtldm->ofdm_index[RF90_PATH_B];
1288			tmp = final_swing_idx[RF90_PATH_B];
1289			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1290				"pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n",
1291				rtldm->ofdm_index[RF90_PATH_B],
1292				final_swing_idx[RF90_PATH_B]);
1293
1294			rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1295				      txscaling_tbl[tmp]);
1296		}
1297	} else if (method == MIX_MODE) {
1298		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1299			"pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1300			rtldm->default_ofdm_index,
1301			rtldm->absolute_ofdm_swing_idx[rf_path],
1302			rf_path);
1303
1304		final_ofdm_swing_index = rtldm->default_ofdm_index +
1305				rtldm->absolute_ofdm_swing_idx[rf_path];
1306
1307		if (rf_path == RF90_PATH_A) {
1308			/*BBSwing higher then Limit*/
1309			if (final_ofdm_swing_index > pwr_tracking_limit) {
1310				rtldm->remnant_cck_idx =
1311					final_ofdm_swing_index -
1312					pwr_tracking_limit;
1313				/* CCK Follow the same compensation value
1314				 * as Path A
1315				 */
1316				rtldm->remnant_ofdm_swing_idx[rf_path] =
1317					final_ofdm_swing_index -
1318					pwr_tracking_limit;
1319
1320				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1321					      txscaling_tbl[pwr_tracking_limit]);
1322
1323				rtldm->modify_txagc_flag_path_a = true;
1324
1325				/*Set TxAGC Page C{};*/
1326				rtl8821ae_phy_set_txpower_level_by_path(hw,
1327					rtlphy->current_channel,
1328					RF90_PATH_A);
1329
1330				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1331					"******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
1332					pwr_tracking_limit,
1333					rtldm->remnant_ofdm_swing_idx[rf_path]);
1334			} else if (final_ofdm_swing_index < 0) {
1335				rtldm->remnant_cck_idx = final_ofdm_swing_index;
1336				/* CCK Follow the same compensate value as Path A*/
1337				rtldm->remnant_ofdm_swing_idx[rf_path] =
1338					final_ofdm_swing_index;
1339
1340				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1341					txscaling_tbl[0]);
1342
1343				rtldm->modify_txagc_flag_path_a = true;
1344
1345				/*Set TxAGC Page C{};*/
1346				rtl8821ae_phy_set_txpower_level_by_path(hw,
1347					rtlphy->current_channel, RF90_PATH_A);
1348
1349				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1350					"******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1351					rtldm->remnant_ofdm_swing_idx[rf_path]);
1352			} else {
1353				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1354					txscaling_tbl[(u8)final_ofdm_swing_index]);
1355
1356				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1357					"******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n",
1358					final_ofdm_swing_index);
1359				/*If TxAGC has changed, reset TxAGC again*/
1360				if (rtldm->modify_txagc_flag_path_a) {
1361					rtldm->remnant_cck_idx = 0;
1362					rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1363
1364					/*Set TxAGC Page C{};*/
1365					rtl8821ae_phy_set_txpower_level_by_path(hw,
1366						rtlphy->current_channel, RF90_PATH_A);
1367					rtldm->modify_txagc_flag_path_a = false;
1368
1369					rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
1370						DBG_LOUD,
1371						"******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1372				}
1373			}
1374		}
1375		/*BBSwing higher then Limit*/
1376		if (rf_path == RF90_PATH_B) {
1377			if (final_ofdm_swing_index > pwr_tracking_limit) {
1378				rtldm->remnant_ofdm_swing_idx[rf_path] =
1379					final_ofdm_swing_index -
1380					pwr_tracking_limit;
1381
1382				rtl_set_bbreg(hw, RB_TXSCALE,
1383					0xFFE00000,
1384					txscaling_tbl[pwr_tracking_limit]);
1385
1386				rtldm->modify_txagc_flag_path_b = true;
1387
1388				/*Set TxAGC Page E{};*/
1389				rtl8821ae_phy_set_txpower_level_by_path(hw,
1390					rtlphy->current_channel, RF90_PATH_B);
1391
1392				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1393					"******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1394					pwr_tracking_limit,
1395					 rtldm->remnant_ofdm_swing_idx[rf_path]);
1396			} else if (final_ofdm_swing_index < 0) {
1397				rtldm->remnant_ofdm_swing_idx[rf_path] =
1398					final_ofdm_swing_index;
1399
1400				rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1401					      txscaling_tbl[0]);
1402
1403				rtldm->modify_txagc_flag_path_b = true;
1404
1405				/*Set TxAGC Page E{};*/
1406				rtl8821ae_phy_set_txpower_level_by_path(hw,
1407					rtlphy->current_channel, RF90_PATH_B);
1408
1409				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1410					"******Path_B Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1411					rtldm->remnant_ofdm_swing_idx[rf_path]);
1412			} else {
1413				rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1414					txscaling_tbl[(u8)final_ofdm_swing_index]);
1415
1416				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1417					"******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1418					final_ofdm_swing_index);
1419				 /*If TxAGC has changed, reset TxAGC again*/
1420				if (rtldm->modify_txagc_flag_path_b) {
1421					rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1422
1423					/*Set TxAGC Page E{};*/
1424					rtl8821ae_phy_set_txpower_level_by_path(hw,
1425					rtlphy->current_channel, RF90_PATH_B);
1426
1427					rtldm->modify_txagc_flag_path_b =
1428						false;
1429
1430					rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1431						"******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1432				}
1433			}
1434		}
1435	} else {
1436		return;
1437	}
1438}
1439
1440void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1441	struct ieee80211_hw *hw)
1442{
1443	struct rtl_priv *rtlpriv = rtl_priv(hw);
1444	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1445	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
1446	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1447	u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
1448	u8 thermal_value_avg_count = 0;
1449	u32 thermal_value_avg = 0;
1450	/* OFDM BB Swing should be less than +3.0dB, */
1451	u8 ofdm_min_index = 6;
1452	 /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
1453	u8 index_for_channel = 0;
1454	/* 1. The following TWO tables decide
1455	 * the final index of OFDM/CCK swing table.
1456	 */
1457	const u8 *delta_swing_table_idx_tup_a;
1458	const u8 *delta_swing_table_idx_tdown_a;
1459	const u8 *delta_swing_table_idx_tup_b;
1460	const u8 *delta_swing_table_idx_tdown_b;
1461
1462	/*2. Initialization ( 7 steps in total )*/
1463	rtl8812ae_get_delta_swing_table(hw,
1464		&delta_swing_table_idx_tup_a,
1465		&delta_swing_table_idx_tdown_a,
1466		&delta_swing_table_idx_tup_b,
1467		&delta_swing_table_idx_tdown_b);
1468
1469	rtldm->txpower_trackinginit = true;
1470
1471	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1472		"pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
1473		rtldm->swing_idx_cck_base,
1474		rtldm->swing_idx_ofdm_base[RF90_PATH_A],
1475		rtldm->default_ofdm_index);
1476
1477	thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A,
1478		/*0x42: RF Reg[15:10] 88E*/
1479		RF_T_METER_8812A, 0xfc00);
1480	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1481		"Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1482		thermal_value, rtlefuse->eeprom_thermalmeter);
1483	if (!rtldm->txpower_track_control ||
1484	    rtlefuse->eeprom_thermalmeter == 0 ||
1485	    rtlefuse->eeprom_thermalmeter == 0xFF)
1486		return;
1487
1488	/* 3. Initialize ThermalValues of RFCalibrateInfo*/
1489
1490	if (rtlhal->reloadtxpowerindex)
1491		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1492			"reload ofdm index for band switch\n");
1493
1494	/*4. Calculate average thermal meter*/
1495	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
1496	rtldm->thermalvalue_avg_index++;
1497	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
1498		/*Average times =  c.AverageThermalNum*/
1499		rtldm->thermalvalue_avg_index = 0;
1500
1501	for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
1502		if (rtldm->thermalvalue_avg[i]) {
1503			thermal_value_avg += rtldm->thermalvalue_avg[i];
1504			thermal_value_avg_count++;
1505		}
1506	}
1507	/*Calculate Average ThermalValue after average enough times*/
1508	if (thermal_value_avg_count) {
1509		thermal_value = (u8)(thermal_value_avg /
1510				thermal_value_avg_count);
1511		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1512			"AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1513			thermal_value, rtlefuse->eeprom_thermalmeter);
1514	}
1515
1516	/*5. Calculate delta, delta_LCK, delta_IQK.
1517	 *"delta" here is used to determine whether
1518	 *thermal value changes or not.
1519	 */
1520	delta = (thermal_value > rtldm->thermalvalue) ?
1521		(thermal_value - rtldm->thermalvalue) :
1522		(rtldm->thermalvalue - thermal_value);
1523	delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
1524		(thermal_value - rtldm->thermalvalue_lck) :
1525		(rtldm->thermalvalue_lck - thermal_value);
1526	delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
1527		(thermal_value - rtldm->thermalvalue_iqk) :
1528		(rtldm->thermalvalue_iqk - thermal_value);
1529
1530	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1531		"(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
1532		delta, delta_lck, delta_iqk);
1533
1534	/* 6. If necessary, do LCK.
1535	 * Delta temperature is equal to or larger than 20 centigrade.
1536	 */
1537	if (delta_lck >= IQK_THRESHOLD) {
1538		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1539			"delta_LCK(%d) >= Threshold_IQK(%d)\n",
1540			delta_lck, IQK_THRESHOLD);
1541		rtldm->thermalvalue_lck = thermal_value;
1542		rtl8821ae_phy_lc_calibrate(hw);
1543	}
1544
1545	/*7. If necessary, move the index of swing table to adjust Tx power.*/
1546
1547	if (delta > 0 && rtldm->txpower_track_control) {
1548		/* "delta" here is used to record the
1549		 * absolute value of differrence.
1550		 */
1551		delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1552			(thermal_value - rtlefuse->eeprom_thermalmeter) :
1553			(rtlefuse->eeprom_thermalmeter - thermal_value);
1554
1555		if (delta >= TXPWR_TRACK_TABLE_SIZE)
1556			delta = TXPWR_TRACK_TABLE_SIZE - 1;
1557
1558		/*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
1559
1560		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1561			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1562				"delta_swing_table_idx_tup_a[%d] = %d\n",
1563				delta, delta_swing_table_idx_tup_a[delta]);
1564			rtldm->delta_power_index_last[RF90_PATH_A] =
1565				rtldm->delta_power_index[RF90_PATH_A];
1566			rtldm->delta_power_index[RF90_PATH_A] =
1567				delta_swing_table_idx_tup_a[delta];
1568
1569			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1570				delta_swing_table_idx_tup_a[delta];
1571			/*Record delta swing for mix mode power tracking*/
1572
1573			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1574				"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1575			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1576
1577			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1578				"delta_swing_table_idx_tup_b[%d] = %d\n",
1579				delta, delta_swing_table_idx_tup_b[delta]);
1580			rtldm->delta_power_index_last[RF90_PATH_B] =
1581				rtldm->delta_power_index[RF90_PATH_B];
1582			rtldm->delta_power_index[RF90_PATH_B] =
1583				delta_swing_table_idx_tup_b[delta];
1584
1585			rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1586				delta_swing_table_idx_tup_b[delta];
1587			/*Record delta swing for mix mode power tracking*/
1588
1589			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1590				"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1591				rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1592		} else {
1593			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1594				"delta_swing_table_idx_tdown_a[%d] = %d\n",
1595				delta, delta_swing_table_idx_tdown_a[delta]);
1596
1597			rtldm->delta_power_index_last[RF90_PATH_A] =
1598				rtldm->delta_power_index[RF90_PATH_A];
1599			rtldm->delta_power_index[RF90_PATH_A] =
1600				-1 * delta_swing_table_idx_tdown_a[delta];
1601
1602			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1603				-1 * delta_swing_table_idx_tdown_a[delta];
1604			/* Record delta swing for mix mode power tracking*/
1605			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1606				"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1607				rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1608
1609			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1610				"deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
1611				delta, delta_swing_table_idx_tdown_b[delta]);
1612
1613			rtldm->delta_power_index_last[RF90_PATH_B] =
1614				rtldm->delta_power_index[RF90_PATH_B];
1615			rtldm->delta_power_index[RF90_PATH_B] =
1616				-1 * delta_swing_table_idx_tdown_b[delta];
1617
1618			rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1619				-1 * delta_swing_table_idx_tdown_b[delta];
1620			/*Record delta swing for mix mode power tracking*/
1621
1622			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1623				"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1624				rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1625		}
1626
1627		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1628			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1629				"============================= [Path-%c]Calculating PowerIndexOffset =============================\n",
1630				(p == RF90_PATH_A ? 'A' : 'B'));
1631
1632			if (rtldm->delta_power_index[p] ==
1633				rtldm->delta_power_index_last[p])
1634				/*If Thermal value changes but lookup
1635				table value still the same*/
1636				rtldm->power_index_offset[p] = 0;
1637			else
1638				rtldm->power_index_offset[p] =
1639					rtldm->delta_power_index[p] -
1640					rtldm->delta_power_index_last[p];
1641				/* Power Index Diff between 2
1642				 * times Power Tracking
1643				 */
1644			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1645				"[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n",
1646				(p == RF90_PATH_A ? 'A' : 'B'),
1647				rtldm->power_index_offset[p],
1648				rtldm->delta_power_index[p],
1649				rtldm->delta_power_index_last[p]);
1650
1651			rtldm->ofdm_index[p] =
1652					rtldm->swing_idx_ofdm_base[p] +
1653					rtldm->power_index_offset[p];
1654			rtldm->cck_index =
1655					rtldm->swing_idx_cck_base +
1656					rtldm->power_index_offset[p];
1657
1658			rtldm->swing_idx_cck = rtldm->cck_index;
1659			rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1660
1661			/****Print BB Swing Base and Index Offset */
1662
1663			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1664				"The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
1665				rtldm->swing_idx_cck,
1666				rtldm->swing_idx_cck_base,
1667				rtldm->power_index_offset[p]);
1668			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1669				"The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
1670				rtldm->swing_idx_ofdm[p],
1671				(p == RF90_PATH_A ? 'A' : 'B'),
1672				rtldm->swing_idx_ofdm_base[p],
1673				rtldm->power_index_offset[p]);
1674
1675			/*7.1 Handle boundary conditions of index.*/
1676
1677			if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
1678				rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
1679			else if (rtldm->ofdm_index[p] < ofdm_min_index)
1680				rtldm->ofdm_index[p] = ofdm_min_index;
1681		}
1682		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1683			"\n\n====================================================================================\n");
1684		if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
1685			rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
1686		else if (rtldm->cck_index < 0)
1687			rtldm->cck_index = 0;
1688	} else {
1689		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1690			"The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
1691			rtldm->txpower_track_control,
1692			thermal_value,
1693			rtldm->thermalvalue);
1694
1695		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1696			rtldm->power_index_offset[p] = 0;
1697	}
1698	/*Print Swing base & current*/
1699	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1700		"TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n",
1701		rtldm->cck_index, rtldm->swing_idx_cck_base);
1702	for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1703		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1704			"TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n",
1705			rtldm->ofdm_index[p],
1706			(p == RF90_PATH_A ? 'A' : 'B'),
1707			rtldm->swing_idx_ofdm_base[p]);
1708	}
1709
1710	if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
1711		rtldm->power_index_offset[RF90_PATH_B] != 0) &&
1712		rtldm->txpower_track_control) {
1713		/*7.2 Configure the Swing Table to adjust Tx Power.
1714		 *Always TRUE after Tx Power is adjusted by power tracking.
1715		 *
1716		 *2012/04/23 MH According to Luke's suggestion,
1717		 *we can not write BB digital
1718		 *to increase TX power. Otherwise, EVM will be bad.
1719		 *
1720		 *2012/04/25 MH Add for tx power tracking to set
1721		 *tx power in tx agc for 88E.
1722		 */
1723		if (thermal_value > rtldm->thermalvalue) {
1724			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1725				"Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n",
1726				rtldm->power_index_offset[RF90_PATH_A],
1727				delta, thermal_value,
1728				rtlefuse->eeprom_thermalmeter,
1729				rtldm->thermalvalue);
1730
1731			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1732				"Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1733				rtldm->power_index_offset[RF90_PATH_B],
1734				delta, thermal_value,
1735				rtlefuse->eeprom_thermalmeter,
1736				rtldm->thermalvalue);
1737		} else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
1738			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1739				"Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1740				rtldm->power_index_offset[RF90_PATH_A],
1741				delta, thermal_value,
1742				rtlefuse->eeprom_thermalmeter,
1743				rtldm->thermalvalue);
1744
1745			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1746				"Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1747				rtldm->power_index_offset[RF90_PATH_B],
1748				delta, thermal_value,
1749				rtlefuse->eeprom_thermalmeter,
1750				rtldm->thermalvalue);
1751		}
1752
1753		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1754			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1755				"Temperature(%d) higher than PG value(%d)\n",
1756				thermal_value, rtlefuse->eeprom_thermalmeter);
1757
1758			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1759				"**********Enter POWER Tracking MIX_MODE**********\n");
1760			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1761				rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1762								 p, 0);
1763		} else {
1764			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1765				"Temperature(%d) lower than PG value(%d)\n",
1766				thermal_value, rtlefuse->eeprom_thermalmeter);
1767
1768			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1769				"**********Enter POWER Tracking MIX_MODE**********\n");
1770			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1771				rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1772								 p, index_for_channel);
1773		}
1774		/*Record last time Power Tracking result as base.*/
1775		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
1776		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1777				rtldm->swing_idx_ofdm_base[p] =
1778					rtldm->swing_idx_ofdm[p];
1779
1780		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1781			"pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n",
1782			rtldm->thermalvalue, thermal_value);
1783		/*Record last Power Tracking Thermal Value*/
1784		rtldm->thermalvalue = thermal_value;
1785	}
1786	/*Delta temperature is equal to or larger than
1787	20 centigrade (When threshold is 8).*/
1788	if (delta_iqk >= IQK_THRESHOLD)
1789		rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8);
1790
1791	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1792		"<===%s\n", __func__);
1793}
1794
1795static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw,
1796					    const u8 **up_a,
1797					    const u8 **down_a)
1798{
1799	struct rtl_priv *rtlpriv = rtl_priv(hw);
1800	struct rtl_phy *rtlphy = &rtlpriv->phy;
1801	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1802	u8 channel = rtlphy->current_channel;
1803	u8 rate = rtldm->tx_rate;
1804
1805	if (1 <= channel && channel <= 14) {
1806		if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1807			*up_a = rtl8821ae_delta_swing_table_idx_24gccka_p;
1808			*down_a = rtl8821ae_delta_swing_table_idx_24gccka_n;
1809		} else {
1810			*up_a = rtl8821ae_delta_swing_table_idx_24ga_p;
1811			*down_a = rtl8821ae_delta_swing_table_idx_24ga_n;
1812		}
1813	} else if (36 <= channel && channel <= 64) {
1814		*up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0];
1815		*down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0];
1816	} else if (100 <= channel && channel <= 140) {
1817		*up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1];
1818		*down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1];
1819	} else if (149 <= channel && channel <= 173) {
1820		*up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2];
1821		*down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2];
1822	} else {
1823		*up_a = rtl8818e_delta_swing_table_idx_24gb_p;
1824		*down_a = rtl8818e_delta_swing_table_idx_24gb_n;
1825	}
1826	return;
1827}
1828
1829/*-----------------------------------------------------------------------------
1830 * Function:	odm_TxPwrTrackSetPwr88E()
1831 *
1832 * Overview:	88E change all channel tx power accordign to flag.
1833 *				OFDM & CCK are all different.
1834 *
1835 * Input:		NONE
1836 *
1837 * Output:		NONE
1838 *
1839 * Return:		NONE
1840 *
1841 * Revised History:
1842 *	When		Who		Remark
1843 *	04/23/2012	MHC		Create Version 0.
1844 *
1845 *---------------------------------------------------------------------------
1846 */
1847void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1848				      enum pwr_track_control_method method,
1849				      u8 rf_path, u8 channel_mapped_index)
1850{
1851	struct rtl_priv *rtlpriv = rtl_priv(hw);
1852	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
1853	struct rtl_phy *rtlphy = &rtlpriv->phy;
1854	u32 final_swing_idx[1];
1855	u8 pwr_tracking_limit = 26; /*+1.0dB*/
1856	u8 tx_rate = 0xFF;
1857	s8 final_ofdm_swing_index = 0;
1858
1859	if (rtldm->tx_rate != 0xFF)
1860		tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1861
1862	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
1863
1864	if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
1865		/*CCK*/
1866		if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1867			pwr_tracking_limit = 32; /*+4dB*/
1868		/*OFDM*/
1869		else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1870			pwr_tracking_limit = 30; /*+3dB*/
1871		else if (tx_rate == MGN_54M)
1872			pwr_tracking_limit = 28; /*+2dB*/
1873		/*HT*/
1874		/*QPSK/BPSK*/
1875		else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1876			pwr_tracking_limit = 34; /*+5dB*/
1877		/*16QAM*/
1878		else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1879			pwr_tracking_limit = 30; /*+3dB*/
1880		/*64QAM*/
1881		else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1882			pwr_tracking_limit = 28; /*+2dB*/
1883		/*2 VHT*/
1884		/*QPSK/BPSK*/
1885		else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1886			(tx_rate <= MGN_VHT1SS_MCS2))
1887			pwr_tracking_limit = 34; /*+5dB*/
1888		/*16QAM*/
1889		else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1890			(tx_rate <= MGN_VHT1SS_MCS4))
1891			pwr_tracking_limit = 30; /*+3dB*/
1892		/*64QAM*/
1893		else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1894			(tx_rate <= MGN_VHT1SS_MCS6))
1895			pwr_tracking_limit = 28; /*+2dB*/
1896		else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1897			pwr_tracking_limit = 26; /*+1dB*/
1898		else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1899			pwr_tracking_limit = 24; /*+0dB*/
1900		else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1901			pwr_tracking_limit = 22; /*-1dB*/
1902		else
1903			pwr_tracking_limit = 24;
1904	}
1905	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1906		"TxRate=0x%x, PwrTrackingLimit=%d\n",
1907		tx_rate, pwr_tracking_limit);
1908
1909	if (method == BBSWING) {
1910		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1911			"===>%s\n", __func__);
1912		if (rf_path == RF90_PATH_A) {
1913			final_swing_idx[RF90_PATH_A] =
1914				(rtldm->ofdm_index[RF90_PATH_A] >
1915				pwr_tracking_limit) ?
1916				pwr_tracking_limit :
1917				rtldm->ofdm_index[RF90_PATH_A];
1918			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1919				"pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1920				rtldm->ofdm_index[RF90_PATH_A],
1921				final_swing_idx[RF90_PATH_A]);
1922
1923			rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1924				txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
1925		}
1926	} else if (method == MIX_MODE) {
1927		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1928			"pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1929			rtldm->default_ofdm_index,
1930			rtldm->absolute_ofdm_swing_idx[rf_path],
1931			rf_path);
1932
1933		final_ofdm_swing_index =
1934			rtldm->default_ofdm_index +
1935			rtldm->absolute_ofdm_swing_idx[rf_path];
1936		/*BBSwing higher then Limit*/
1937		if (rf_path == RF90_PATH_A) {
1938			if (final_ofdm_swing_index > pwr_tracking_limit) {
1939				rtldm->remnant_cck_idx =
1940					final_ofdm_swing_index -
1941					pwr_tracking_limit;
1942				/* CCK Follow the same compensate value as Path A*/
1943				rtldm->remnant_ofdm_swing_idx[rf_path] =
1944					final_ofdm_swing_index -
1945					pwr_tracking_limit;
1946
1947				rtl_set_bbreg(hw, RA_TXSCALE,
1948					0xFFE00000,
1949					txscaling_tbl[pwr_tracking_limit]);
1950
1951				rtldm->modify_txagc_flag_path_a = true;
1952
1953				/*Set TxAGC Page C{};*/
1954				rtl8821ae_phy_set_txpower_level_by_path(hw,
1955					rtlphy->current_channel,
1956					RF90_PATH_A);
1957
1958				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1959					" ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1960					pwr_tracking_limit,
1961					rtldm->remnant_ofdm_swing_idx[rf_path]);
1962			} else if (final_ofdm_swing_index < 0) {
1963				rtldm->remnant_cck_idx = final_ofdm_swing_index;
1964				/* CCK Follow the same compensate value as Path A*/
1965				rtldm->remnant_ofdm_swing_idx[rf_path] =
1966					final_ofdm_swing_index;
1967
1968				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1969					txscaling_tbl[0]);
1970
1971				rtldm->modify_txagc_flag_path_a = true;
1972
1973				/*Set TxAGC Page C{};*/
1974				rtl8821ae_phy_set_txpower_level_by_path(hw,
1975					rtlphy->current_channel, RF90_PATH_A);
1976
1977				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1978					"******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1979					rtldm->remnant_ofdm_swing_idx[rf_path]);
1980			} else {
1981				rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1982					txscaling_tbl[(u8)final_ofdm_swing_index]);
1983
1984				rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1985					"******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1986					final_ofdm_swing_index);
1987				/*If TxAGC has changed, reset TxAGC again*/
1988				if (rtldm->modify_txagc_flag_path_a) {
1989					rtldm->remnant_cck_idx = 0;
1990					rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1991
1992					/*Set TxAGC Page C{};*/
1993					rtl8821ae_phy_set_txpower_level_by_path(hw,
1994						rtlphy->current_channel, RF90_PATH_A);
1995
1996					rtldm->modify_txagc_flag_path_a = false;
1997
1998					rtl_dbg(rtlpriv, COMP_POWER_TRACKING,
1999						DBG_LOUD,
2000						"******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2001				}
2002			}
2003		}
2004	} else {
2005		return;
2006	}
2007}
2008
2009void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2010	struct ieee80211_hw *hw)
2011{
2012	struct rtl_priv *rtlpriv = rtl_priv(hw);
2013	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2014	struct rtl_dm	*rtldm = rtl_dm(rtl_priv(hw));
2015	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2016	struct rtl_phy *rtlphy = &rtlpriv->phy;
2017
2018	u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
2019	u8 thermal_value_avg_count = 0;
2020	u32 thermal_value_avg = 0;
2021
2022	u8 ofdm_min_index = 6;  /*OFDM BB Swing should be less than +3.0dB */
2023	/* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
2024	u8 index_for_channel = 0;
2025
2026	/* 1. The following TWO tables decide the final
2027	 * index of OFDM/CCK swing table.
2028	 */
2029	const u8 *delta_swing_table_idx_tup_a;
2030	const u8 *delta_swing_table_idx_tdown_a;
2031
2032	/*2. Initilization ( 7 steps in total )*/
2033	rtl8821ae_get_delta_swing_table(hw,
2034					&delta_swing_table_idx_tup_a,
2035					&delta_swing_table_idx_tdown_a);
2036
2037	rtldm->txpower_trackinginit = true;
2038
2039	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2040		"===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
2041		__func__,
2042		rtldm->swing_idx_cck_base,
2043		rtldm->swing_idx_ofdm_base[RF90_PATH_A],
2044		rtldm->default_ofdm_index);
2045	/*0x42: RF Reg[15:10] 88E*/
2046	thermal_value = (u8)rtl_get_rfreg(hw,
2047		RF90_PATH_A, RF_T_METER_8812A, 0xfc00);
2048	if (!rtldm->txpower_track_control ||
2049		rtlefuse->eeprom_thermalmeter == 0 ||
2050		rtlefuse->eeprom_thermalmeter == 0xFF)
2051		return;
2052
2053	/* 3. Initialize ThermalValues of RFCalibrateInfo*/
2054
2055	if (rtlhal->reloadtxpowerindex) {
2056		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2057			"reload ofdm index for band switch\n");
2058	}
2059
2060	/*4. Calculate average thermal meter*/
2061	rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
2062	rtldm->thermalvalue_avg_index++;
2063	if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
2064		/*Average times =  c.AverageThermalNum*/
2065		rtldm->thermalvalue_avg_index = 0;
2066
2067	for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
2068		if (rtldm->thermalvalue_avg[i]) {
2069			thermal_value_avg += rtldm->thermalvalue_avg[i];
2070			thermal_value_avg_count++;
2071		}
2072	}
2073	/*Calculate Average ThermalValue after average enough times*/
2074	if (thermal_value_avg_count) {
2075		thermal_value = (u8)(thermal_value_avg /
2076				thermal_value_avg_count);
2077		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2078			"AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
2079			thermal_value, rtlefuse->eeprom_thermalmeter);
2080	}
2081
2082	/*5. Calculate delta, delta_LCK, delta_IQK.
2083	 *"delta" here is used to determine whether
2084	 * thermal value changes or not.
2085	 */
2086	delta = (thermal_value > rtldm->thermalvalue) ?
2087		(thermal_value - rtldm->thermalvalue) :
2088		(rtldm->thermalvalue - thermal_value);
2089	delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
2090		(thermal_value - rtldm->thermalvalue_lck) :
2091		(rtldm->thermalvalue_lck - thermal_value);
2092	delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
2093		(thermal_value - rtldm->thermalvalue_iqk) :
2094		(rtldm->thermalvalue_iqk - thermal_value);
2095
2096	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2097		"(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
2098		delta, delta_lck, delta_iqk);
2099
2100	/* 6. If necessary, do LCK.	*/
2101	/*Delta temperature is equal to or larger than 20 centigrade.*/
2102	if (delta_lck >= IQK_THRESHOLD) {
2103		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2104			"delta_LCK(%d) >= Threshold_IQK(%d)\n",
2105			delta_lck, IQK_THRESHOLD);
2106		rtldm->thermalvalue_lck = thermal_value;
2107		rtl8821ae_phy_lc_calibrate(hw);
2108	}
2109
2110	/*7. If necessary, move the index of swing table to adjust Tx power.*/
2111
2112	if (delta > 0 && rtldm->txpower_track_control) {
2113		/*"delta" here is used to record the
2114		 * absolute value of differrence.
2115		 */
2116		delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2117			(thermal_value - rtlefuse->eeprom_thermalmeter) :
2118			(rtlefuse->eeprom_thermalmeter - thermal_value);
2119
2120		if (delta >= TXSCALE_TABLE_SIZE)
2121			delta = TXSCALE_TABLE_SIZE - 1;
2122
2123		/*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
2124
2125		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2126			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2127				"delta_swing_table_idx_tup_a[%d] = %d\n",
2128				delta, delta_swing_table_idx_tup_a[delta]);
2129			rtldm->delta_power_index_last[RF90_PATH_A] =
2130				rtldm->delta_power_index[RF90_PATH_A];
2131			rtldm->delta_power_index[RF90_PATH_A] =
2132				delta_swing_table_idx_tup_a[delta];
2133
2134			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2135				delta_swing_table_idx_tup_a[delta];
2136			/*Record delta swing for mix mode power tracking*/
2137
2138			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2139				"******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2140				rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2141		} else {
2142			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2143				"delta_swing_table_idx_tdown_a[%d] = %d\n",
2144				delta, delta_swing_table_idx_tdown_a[delta]);
2145
2146			rtldm->delta_power_index_last[RF90_PATH_A] =
2147				rtldm->delta_power_index[RF90_PATH_A];
2148			rtldm->delta_power_index[RF90_PATH_A] =
2149				-1 * delta_swing_table_idx_tdown_a[delta];
2150
2151			rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2152				-1 * delta_swing_table_idx_tdown_a[delta];
2153			/* Record delta swing for mix mode power tracking*/
2154			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2155				"******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2156				rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2157		}
2158
2159		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2160			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2161				"\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n",
2162				(p == RF90_PATH_A ? 'A' : 'B'));
2163			/*If Thermal value changes but lookup table value
2164			 * still the same
2165			 */
2166			if (rtldm->delta_power_index[p] ==
2167				rtldm->delta_power_index_last[p])
2168
2169				rtldm->power_index_offset[p] = 0;
2170			else
2171				rtldm->power_index_offset[p] =
2172					rtldm->delta_power_index[p] -
2173					rtldm->delta_power_index_last[p];
2174			/*Power Index Diff between 2 times Power Tracking*/
2175
2176			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2177				"[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
2178				(p == RF90_PATH_A ? 'A' : 'B'),
2179				rtldm->power_index_offset[p],
2180				rtldm->delta_power_index[p] ,
2181				rtldm->delta_power_index_last[p]);
2182
2183			rtldm->ofdm_index[p] =
2184					rtldm->swing_idx_ofdm_base[p] +
2185					rtldm->power_index_offset[p];
2186			rtldm->cck_index =
2187					rtldm->swing_idx_cck_base +
2188					rtldm->power_index_offset[p];
2189
2190			rtldm->swing_idx_cck = rtldm->cck_index;
2191			rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2192
2193			/*********Print BB Swing Base and Index Offset********/
2194
2195			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2196				"The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
2197				rtldm->swing_idx_cck,
2198				rtldm->swing_idx_cck_base,
2199				rtldm->power_index_offset[p]);
2200			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2201				"The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
2202				rtldm->swing_idx_ofdm[p],
2203				(p == RF90_PATH_A ? 'A' : 'B'),
2204				rtldm->swing_idx_ofdm_base[p],
2205				rtldm->power_index_offset[p]);
2206
2207			/*7.1 Handle boundary conditions of index.*/
2208
2209			if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
2210				rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
2211			else if (rtldm->ofdm_index[p] < ofdm_min_index)
2212				rtldm->ofdm_index[p] = ofdm_min_index;
2213		}
2214		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2215			"\n\n========================================================================================================\n");
2216		if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
2217			rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
2218		else if (rtldm->cck_index < 0)
2219			rtldm->cck_index = 0;
2220	} else {
2221		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2222			"The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
2223			rtldm->txpower_track_control,
2224			thermal_value,
2225			rtldm->thermalvalue);
2226
2227		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2228			rtldm->power_index_offset[p] = 0;
2229	}
2230	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2231		"TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
2232		/*Print Swing base & current*/
2233		rtldm->cck_index, rtldm->swing_idx_cck_base);
2234	for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2235		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2236			"TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
2237			rtldm->ofdm_index[p],
2238			(p == RF90_PATH_A ? 'A' : 'B'),
2239			rtldm->swing_idx_ofdm_base[p]);
2240	}
2241
2242	if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
2243		rtldm->power_index_offset[RF90_PATH_B] != 0) &&
2244		rtldm->txpower_track_control) {
2245		/*7.2 Configure the Swing Table to adjust Tx Power.*/
2246		/*Always TRUE after Tx Power is adjusted by power tracking.*/
2247		/*
2248		 *  2012/04/23 MH According to Luke's suggestion,
2249		 *  we can not write BB digital
2250		 *  to increase TX power. Otherwise, EVM will be bad.
2251		 *
2252		 *  2012/04/25 MH Add for tx power tracking to
2253		 *  set tx power in tx agc for 88E.
2254		 */
2255		if (thermal_value > rtldm->thermalvalue) {
2256			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2257				"Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2258				rtldm->power_index_offset[RF90_PATH_A],
2259				delta, thermal_value,
2260				rtlefuse->eeprom_thermalmeter,
2261				rtldm->thermalvalue);
2262		} else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
2263			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2264				"Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2265				rtldm->power_index_offset[RF90_PATH_A],
2266				delta, thermal_value,
2267				rtlefuse->eeprom_thermalmeter,
2268				rtldm->thermalvalue);
2269		}
2270
2271		if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2272			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2273				"Temperature(%d) higher than PG value(%d)\n",
2274				thermal_value, rtlefuse->eeprom_thermalmeter);
2275
2276			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2277				"****Enter POWER Tracking MIX_MODE****\n");
2278			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2279					rtl8821ae_dm_txpwr_track_set_pwr(hw,
2280						MIX_MODE, p, index_for_channel);
2281		} else {
2282			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2283				"Temperature(%d) lower than PG value(%d)\n",
2284				thermal_value, rtlefuse->eeprom_thermalmeter);
2285
2286			rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2287				"*****Enter POWER Tracking MIX_MODE*****\n");
2288			for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2289				rtl8812ae_dm_txpwr_track_set_pwr(hw,
2290					MIX_MODE, p, index_for_channel);
2291		}
2292		/*Record last time Power Tracking result as base.*/
2293		rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
2294		for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2295			rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
2296
2297		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2298			"pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
2299			rtldm->thermalvalue, thermal_value);
2300		/*Record last Power Tracking Thermal Value*/
2301		rtldm->thermalvalue = thermal_value;
2302	}
2303	/* Delta temperature is equal to or larger than
2304	 * 20 centigrade (When threshold is 8).
2305	 */
2306	if (delta_iqk >= IQK_THRESHOLD) {
2307		if (!rtlphy->lck_inprogress) {
2308			spin_lock(&rtlpriv->locks.iqk_lock);
2309			rtlphy->lck_inprogress = true;
2310			spin_unlock(&rtlpriv->locks.iqk_lock);
2311
2312			rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2313
2314			spin_lock(&rtlpriv->locks.iqk_lock);
2315			rtlphy->lck_inprogress = false;
2316			spin_unlock(&rtlpriv->locks.iqk_lock);
2317		}
2318	}
2319
2320	rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
2321}
2322
2323void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2324{
2325	struct rtl_priv *rtlpriv = rtl_priv(hw);
2326	if (!rtlpriv->dm.tm_trigger) {
2327		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2328			      0x03);
2329		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2330			"Trigger 8821ae Thermal Meter!!\n");
2331		rtlpriv->dm.tm_trigger = 1;
2332		return;
2333	} else {
2334		rtl_dbg(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2335			"Schedule TxPowerTracking !!\n");
2336
2337		rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2338		rtlpriv->dm.tm_trigger = 0;
2339	}
2340}
2341
2342static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
2343{
2344	struct rtl_priv *rtlpriv = rtl_priv(hw);
2345	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2346	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2347	struct rate_adaptive *p_ra = &rtlpriv->ra;
2348	u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
2349	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
2350	u8 go_up_gap = 5;
2351	struct ieee80211_sta *sta = NULL;
2352
2353	if (is_hal_stop(rtlhal)) {
2354		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2355			"driver is going to unload\n");
2356		return;
2357	}
2358
2359	if (!rtlpriv->dm.useramask) {
2360		rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2361			"driver does not control rate adaptive mask\n");
2362		return;
2363	}
2364
2365	if (mac->link_state == MAC80211_LINKED &&
2366		mac->opmode == NL80211_IFTYPE_STATION) {
2367		switch (p_ra->pre_ratr_state) {
2368		case DM_RATR_STA_MIDDLE:
2369			high_rssithresh_for_ra += go_up_gap;
2370			break;
2371		case DM_RATR_STA_LOW:
2372			high_rssithresh_for_ra += go_up_gap;
2373			low_rssithresh_for_ra += go_up_gap;
2374			break;
2375		default:
2376			break;
2377		}
2378
2379		if (rtlpriv->dm.undec_sm_pwdb >
2380		    (long)high_rssithresh_for_ra)
2381			p_ra->ratr_state = DM_RATR_STA_HIGH;
2382		else if (rtlpriv->dm.undec_sm_pwdb >
2383			 (long)low_rssithresh_for_ra)
2384			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
2385		else
2386			p_ra->ratr_state = DM_RATR_STA_LOW;
2387
2388		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2389			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2390				"RSSI = %ld\n",
2391				rtlpriv->dm.undec_sm_pwdb);
2392			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2393				"RSSI_LEVEL = %d\n", p_ra->ratr_state);
2394			rtl_dbg(rtlpriv, COMP_RATE, DBG_LOUD,
2395				"PreState = %d, CurState = %d\n",
2396				p_ra->pre_ratr_state, p_ra->ratr_state);
2397
2398			rcu_read_lock();
2399			sta = rtl_find_sta(hw, mac->bssid);
2400			if (sta)
2401				rtlpriv->cfg->ops->update_rate_tbl(hw,
2402						sta, p_ra->ratr_state, true);
2403			rcu_read_unlock();
2404
2405			p_ra->pre_ratr_state = p_ra->ratr_state;
2406		}
2407	}
2408}
2409
2410static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2411{
2412	struct rtl_priv *rtlpriv = rtl_priv(hw);
2413	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2414	struct rtl_mac *mac = &rtlpriv->mac80211;
2415	static u8 stage;
2416	u8 cur_stage = 0;
2417	u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2418
2419	if (mac->link_state < MAC80211_LINKED)
2420		cur_stage = 0;
2421	else if (dm_digtable->rssi_val_min < 25)
2422		cur_stage = 1;
2423	else if (dm_digtable->rssi_val_min > 30)
2424		cur_stage = 3;
2425	else
2426		cur_stage = 2;
2427
2428	if (cur_stage != stage) {
2429		if (cur_stage == 1) {
2430			basic_rate &= (!(basic_rate ^ mac->basic_rates));
2431			rtlpriv->cfg->ops->set_hw_reg(hw,
2432				HW_VAR_BASIC_RATE, (u8 *)&basic_rate);
2433		} else if (cur_stage == 3 && (stage == 1 || stage == 2)) {
2434			rtlpriv->cfg->ops->set_hw_reg(hw,
2435				HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates);
2436		}
2437	}
2438	stage = cur_stage;
2439}
2440
2441static void rtl8821ae_dm_edca_choose_traffic_idx(
2442	struct ieee80211_hw *hw, u64 cur_tx_bytes,
2443	u64 cur_rx_bytes, bool b_bias_on_rx,
2444	bool *pb_is_cur_rdl_state)
2445{
2446	struct rtl_priv *rtlpriv = rtl_priv(hw);
2447
2448	if (b_bias_on_rx) {
2449		if (cur_tx_bytes > (cur_rx_bytes*4)) {
2450			*pb_is_cur_rdl_state = false;
2451			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2452				"Uplink Traffic\n");
2453		} else {
2454			*pb_is_cur_rdl_state = true;
2455			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2456				"Balance Traffic\n");
2457		}
2458	} else {
2459		if (cur_rx_bytes > (cur_tx_bytes*4)) {
2460			*pb_is_cur_rdl_state = true;
2461			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2462				"Downlink	Traffic\n");
2463		} else {
2464			*pb_is_cur_rdl_state = false;
2465			rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2466				"Balance Traffic\n");
2467		}
2468	}
2469	return;
2470}
2471
2472static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
2473{
2474	struct rtl_priv *rtlpriv = rtl_priv(hw);
2475	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2476	struct rtl_dm *rtldm =  rtl_dm(rtl_priv(hw));
2477
2478	/*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/
2479	u64 cur_tx_ok_cnt = 0;
2480	u64 cur_rx_ok_cnt = 0;
2481	u32 edca_be_ul = 0x5ea42b;
2482	u32 edca_be_dl = 0x5ea42b;
2483	u32 edca_be = 0x5ea42b;
2484	u8 iot_peer = 0;
2485	bool *pb_is_cur_rdl_state = NULL;
2486	bool b_bias_on_rx = false;
2487	bool b_edca_turbo_on = false;
2488
2489	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2490		"%s=====>\n", __func__);
2491	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2492		"Original BE PARAM: 0x%x\n",
2493		rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N));
2494
2495	if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
2496		rtlpriv->dm.is_any_nonbepkts = true;
2497	rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
2498
2499	/*===============================
2500	 * list parameter for different platform
2501	 *===============================
2502	 */
2503	pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
2504
2505	cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt;
2506	cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt;
2507
2508	rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2509	rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2510
2511	iot_peer = rtlpriv->mac80211.vendor;
2512	b_bias_on_rx = false;
2513	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
2514			   (!rtlpriv->dm.disable_framebursting)) ?
2515			   true : false;
2516
2517	if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) {
2518		if ((iot_peer == PEER_CISCO) &&
2519			(mac->mode == WIRELESS_MODE_N_24G)) {
2520			edca_be_dl = edca_setting_dl[iot_peer];
2521			edca_be_ul = edca_setting_ul[iot_peer];
2522		}
2523	}
2524
2525	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2526		"bIsAnyNonBEPkts : 0x%x  bDisableFrameBursting : 0x%x\n",
2527		rtlpriv->dm.is_any_nonbepkts,
2528		rtlpriv->dm.disable_framebursting);
2529
2530	rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2531		"bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n",
2532		b_edca_turbo_on, b_bias_on_rx);
2533
2534	if (b_edca_turbo_on) {
2535		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2536			"curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt);
2537		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2538			"curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt);
2539		if (b_bias_on_rx)
2540			rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2541				cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2542		else
2543			rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2544				cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2545
2546		edca_be = (*pb_is_cur_rdl_state) ?  edca_be_dl : edca_be_ul;
2547
2548		rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2549
2550		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2551			"EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2552
2553		rtlpriv->dm.current_turbo_edca = true;
2554
2555		rtl_dbg(rtlpriv, COMP_TURBO, DBG_LOUD,
2556			"EDCA_BE_DL : 0x%x  EDCA_BE_UL : 0x%x  EDCA_BE : 0x%x\n",
2557			edca_be_dl, edca_be_ul, edca_be);
2558	} else {
2559		if (rtlpriv->dm.current_turbo_edca) {
2560			u8 tmp = AC0_BE;
2561			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2562						      (u8 *)(&tmp));
2563		}
2564		rtlpriv->dm.current_turbo_edca = false;
2565	}
2566
2567	rtlpriv->dm.is_any_nonbepkts = false;
2568	rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2569	rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2570}
2571
2572static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2573{
2574	struct rtl_priv *rtlpriv = rtl_priv(hw);
2575	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2576	u8 cur_cck_cca_thresh;
2577
2578	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
2579		if (dm_digtable->rssi_val_min > 25) {
2580			cur_cck_cca_thresh = 0xcd;
2581		} else if ((dm_digtable->rssi_val_min <= 25) &&
2582			   (dm_digtable->rssi_val_min > 10)) {
2583			cur_cck_cca_thresh = 0x83;
2584		} else {
2585			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2586				cur_cck_cca_thresh = 0x83;
2587			else
2588				cur_cck_cca_thresh = 0x40;
2589		}
2590	} else {
2591		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2592			cur_cck_cca_thresh = 0x83;
2593		else
2594			cur_cck_cca_thresh = 0x40;
2595	}
2596
2597	if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
2598		rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC,
2599			       cur_cck_cca_thresh);
2600
2601	dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
2602	dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
2603	rtl_dbg(rtlpriv, COMP_DIG, DBG_TRACE,
2604		"CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
2605}
2606
2607static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2608{
2609	struct rtl_priv *rtlpriv = rtl_priv(hw);
2610	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2611	u8 crystal_cap;
2612	u32 packet_count;
2613	int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2614	int cfo_ave_diff;
2615
2616	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
2617		/*1.Enable ATC*/
2618		if (rtldm->atc_status == ATC_STATUS_OFF) {
2619			rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON);
2620			rtldm->atc_status = ATC_STATUS_ON;
2621		}
2622
2623		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n");
2624		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2625			"atc_status = %d\n", rtldm->atc_status);
2626
2627		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
2628			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
2629			crystal_cap = rtldm->crystal_cap & 0x3f;
2630			crystal_cap = crystal_cap & 0x3f;
2631			if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2632				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2633					      0x7ff80000, (crystal_cap |
2634					      (crystal_cap << 6)));
2635			else
2636				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2637					      0xfff000, (crystal_cap |
2638					      (crystal_cap << 6)));
2639		}
2640		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2641			rtldm->crystal_cap);
2642	} else{
2643		/*1. Calculate CFO for path-A & path-B*/
2644		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
2645		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
2646		packet_count = rtldm->packet_count;
2647
2648		/*2.No new packet*/
2649		if (packet_count == rtldm->packet_count_pre) {
2650			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2651				"packet counter doesn't change\n");
2652			return;
2653		}
2654
2655		rtldm->packet_count_pre = packet_count;
2656		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2657			"packet counter = %d\n",
2658			rtldm->packet_count);
2659
2660		/*3.Average CFO*/
2661		if (rtlpriv->phy.rf_type == RF_1T1R)
2662			cfo_ave = cfo_khz_a;
2663		else
2664			cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
2665
2666		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2667			"cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n",
2668			cfo_khz_a, cfo_khz_b, cfo_ave);
2669
2670		/*4.Avoid abnormal large CFO*/
2671		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
2672						(rtldm->cfo_ave_pre - cfo_ave) :
2673						(cfo_ave - rtldm->cfo_ave_pre);
2674
2675		if (cfo_ave_diff > 20 && !rtldm->large_cfo_hit) {
2676			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2677				"first large CFO hit\n");
2678			rtldm->large_cfo_hit = true;
2679			return;
2680		} else
2681			rtldm->large_cfo_hit = false;
2682
2683		rtldm->cfo_ave_pre = cfo_ave;
2684
2685		/*CFO tracking by adjusting Xtal cap.*/
2686
2687		/*1.Dynamic Xtal threshold*/
2688		if (cfo_ave >= -rtldm->cfo_threshold &&
2689			cfo_ave <= rtldm->cfo_threshold &&
2690			rtldm->is_freeze == 0) {
2691			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
2692				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
2693				rtldm->is_freeze = 1;
2694			} else {
2695				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2696			}
2697		}
2698		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2699			"Dynamic threshold = %d\n",
2700			rtldm->cfo_threshold);
2701
2702		/* 2.Calculate Xtal offset*/
2703		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
2704			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
2705		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
2706			 rtlpriv->dm.crystal_cap > 0)
2707			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
2708		rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2709			"Crystal cap = 0x%x, Crystal cap offset = %d\n",
2710			rtldm->crystal_cap, adjust_xtal);
2711
2712		/*3.Adjudt Crystal Cap.*/
2713		if (adjust_xtal != 0) {
2714			rtldm->is_freeze = 0;
2715			rtldm->crystal_cap += adjust_xtal;
2716
2717			if (rtldm->crystal_cap > 0x3f)
2718				rtldm->crystal_cap = 0x3f;
2719			else if (rtldm->crystal_cap < 0)
2720				rtldm->crystal_cap = 0;
2721
2722			crystal_cap = rtldm->crystal_cap & 0x3f;
2723			crystal_cap = crystal_cap & 0x3f;
2724			if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2725				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2726					      0x7ff80000, (crystal_cap |
2727					      (crystal_cap << 6)));
2728			else
2729				rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2730					      0xfff000, (crystal_cap |
2731					      (crystal_cap << 6)));
2732			rtl_dbg(rtlpriv, COMP_DIG, DBG_LOUD,
2733				"New crystal cap = 0x%x\n",
2734				rtldm->crystal_cap);
2735		}
2736	}
2737}
2738
2739void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
2740{
2741	struct rtl_priv *rtlpriv = rtl_priv(hw);
2742	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2743	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2744	bool fw_current_inpsmode = false;
2745	bool fw_ps_awake = true;
2746
2747	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2748				      (u8 *)(&fw_current_inpsmode));
2749
2750	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2751				      (u8 *)(&fw_ps_awake));
2752
2753	if (ppsc->p2p_ps_info.p2p_ps_mode)
2754		fw_ps_awake = false;
2755
2756	spin_lock(&rtlpriv->locks.rf_ps_lock);
2757	if ((ppsc->rfpwr_state == ERFON) &&
2758	    ((!fw_current_inpsmode) && fw_ps_awake) &&
2759	    (!ppsc->rfchange_inprogress)) {
2760		rtl8821ae_dm_common_info_self_update(hw);
2761		rtl8821ae_dm_false_alarm_counter_statistics(hw);
2762		rtl8821ae_dm_check_rssi_monitor(hw);
2763		rtl8821ae_dm_dig(hw);
2764		rtl8821ae_dm_cck_packet_detection_thresh(hw);
2765		rtl8821ae_dm_refresh_rate_adaptive_mask(hw);
2766		rtl8821ae_dm_refresh_basic_rate_mask(hw);
2767		rtl8821ae_dm_check_edca_turbo(hw);
2768		rtl8821ae_dm_dynamic_atc_switch(hw);
2769		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
2770			rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw);
2771		else
2772			rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2773		rtl8821ae_dm_iq_calibrate(hw);
2774	}
2775	spin_unlock(&rtlpriv->locks.rf_ps_lock);
2776
2777	rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
2778	rtl_dbg(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
2779}
2780
2781void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
2782					u8 *pdesc, u32 mac_id)
2783{
2784	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2785	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2786	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2787	struct fast_ant_training *pfat_table = &rtldm->fat_table;
2788	__le32 *pdesc32 = (__le32 *)pdesc;
2789
2790	if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
2791		return;
2792
2793	if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
2794		set_tx_desc_tx_ant(pdesc32, pfat_table->antsel_a[mac_id]);
2795}
~/ Read-only file preview.