brintos

brintos / linux-shallow public Read only

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