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