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