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