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