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