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