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