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