Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[cascardo/linux.git] / drivers / net / wireless / 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         static u8 tm_trigger;
1072
1073         if (!tm_trigger) {
1074                 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E,
1075                               BIT(17) | BIT(16), 0x03);
1076                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1077                          "Trigger 8812 Thermal Meter!!\n");
1078                 tm_trigger = 1;
1079                 return;
1080         }
1081         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1082                  "Schedule TxPowerTracking direct call!!\n");
1083         rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
1084         tm_trigger = 0;
1085 }
1086
1087 static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
1088 {
1089         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1090         struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1091         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1092
1093         if (mac->link_state >= MAC80211_LINKED) {
1094                 if (rtldm->linked_interval < 3)
1095                         rtldm->linked_interval++;
1096
1097                 if (rtldm->linked_interval == 2) {
1098                         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
1099                                 rtl8812ae_phy_iq_calibrate(hw, false);
1100                         else
1101                                 rtl8821ae_phy_iq_calibrate(hw, false);
1102                 }
1103         } else {
1104                 rtldm->linked_interval = 0;
1105         }
1106 }
1107
1108 static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
1109                                             u8 **up_a, u8 **down_a,
1110                                             u8 **up_b, u8 **down_b)
1111 {
1112         struct rtl_priv *rtlpriv = rtl_priv(hw);
1113         struct rtl_phy *rtlphy = &rtlpriv->phy;
1114         struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1115         u8 channel = rtlphy->current_channel;
1116         u8 rate = rtldm->tx_rate;
1117
1118         if (1 <= channel && channel <= 14) {
1119                 if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1120                         *up_a = rtl8812ae_delta_swing_table_idx_24gccka_p;
1121                         *down_a = rtl8812ae_delta_swing_table_idx_24gccka_n;
1122                         *up_b = rtl8812ae_delta_swing_table_idx_24gcckb_p;
1123                         *down_b = rtl8812ae_delta_swing_table_idx_24gcckb_n;
1124                 } else {
1125                         *up_a = rtl8812ae_delta_swing_table_idx_24ga_p;
1126                         *down_a = rtl8812ae_delta_swing_table_idx_24ga_n;
1127                         *up_b = rtl8812ae_delta_swing_table_idx_24gb_p;
1128                         *down_b = rtl8812ae_delta_swing_table_idx_24gb_n;
1129                 }
1130         } else if (36 <= channel && channel <= 64) {
1131                 *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[0];
1132                 *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[0];
1133                 *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[0];
1134                 *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[0];
1135         } else if (100 <= channel && channel <= 140) {
1136                 *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[1];
1137                 *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[1];
1138                 *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[1];
1139                 *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[1];
1140         } else if (149 <= channel && channel <= 173) {
1141                 *up_a = rtl8812ae_delta_swing_table_idx_5ga_p[2];
1142                 *down_a = rtl8812ae_delta_swing_table_idx_5ga_n[2];
1143                 *up_b = rtl8812ae_delta_swing_table_idx_5gb_p[2];
1144                 *down_b = rtl8812ae_delta_swing_table_idx_5gb_n[2];
1145         } else {
1146             *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
1147             *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
1148             *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
1149             *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
1150         }
1151 }
1152
1153 void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
1154 {
1155         struct rtl_priv *rtlpriv = rtl_priv(hw);
1156         struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1157         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1158         u8 p = 0;
1159
1160         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1161                  "Get C2H Command! Rate=0x%x\n", rate);
1162
1163         rtldm->tx_rate = rate;
1164
1165         if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
1166                 rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
1167         } else {
1168                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1169                         rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
1170         }
1171 }
1172
1173 u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
1174 {
1175         struct rtl_priv *rtlpriv = rtl_priv(hw);
1176         u8 ret_rate = MGN_1M;
1177
1178         switch (rate) {
1179         case DESC_RATE1M:
1180                 ret_rate = MGN_1M;
1181                 break;
1182         case DESC_RATE2M:
1183                 ret_rate = MGN_2M;
1184                 break;
1185         case DESC_RATE5_5M:
1186                 ret_rate = MGN_5_5M;
1187                 break;
1188         case DESC_RATE11M:
1189                 ret_rate = MGN_11M;
1190                 break;
1191         case DESC_RATE6M:
1192                 ret_rate = MGN_6M;
1193                 break;
1194         case DESC_RATE9M:
1195                 ret_rate = MGN_9M;
1196                 break;
1197         case DESC_RATE12M:
1198                 ret_rate = MGN_12M;
1199                 break;
1200         case DESC_RATE18M:
1201                 ret_rate = MGN_18M;
1202                 break;
1203         case DESC_RATE24M:
1204                 ret_rate = MGN_24M;
1205                 break;
1206         case DESC_RATE36M:
1207                 ret_rate = MGN_36M;
1208                 break;
1209         case DESC_RATE48M:
1210                 ret_rate = MGN_48M;
1211                 break;
1212         case DESC_RATE54M:
1213                 ret_rate = MGN_54M;
1214                 break;
1215         case DESC_RATEMCS0:
1216                 ret_rate = MGN_MCS0;
1217                 break;
1218         case DESC_RATEMCS1:
1219                 ret_rate = MGN_MCS1;
1220                 break;
1221         case DESC_RATEMCS2:
1222                 ret_rate = MGN_MCS2;
1223                 break;
1224         case DESC_RATEMCS3:
1225                 ret_rate = MGN_MCS3;
1226                 break;
1227         case DESC_RATEMCS4:
1228                 ret_rate = MGN_MCS4;
1229                 break;
1230         case DESC_RATEMCS5:
1231                 ret_rate = MGN_MCS5;
1232                 break;
1233         case DESC_RATEMCS6:
1234                 ret_rate = MGN_MCS6;
1235                 break;
1236         case DESC_RATEMCS7:
1237                 ret_rate = MGN_MCS7;
1238                 break;
1239         case DESC_RATEMCS8:
1240                 ret_rate = MGN_MCS8;
1241                 break;
1242         case DESC_RATEMCS9:
1243                 ret_rate = MGN_MCS9;
1244                 break;
1245         case DESC_RATEMCS10:
1246                 ret_rate = MGN_MCS10;
1247                 break;
1248         case DESC_RATEMCS11:
1249                 ret_rate = MGN_MCS11;
1250                 break;
1251         case DESC_RATEMCS12:
1252                 ret_rate = MGN_MCS12;
1253                 break;
1254         case DESC_RATEMCS13:
1255                 ret_rate = MGN_MCS13;
1256                 break;
1257         case DESC_RATEMCS14:
1258                 ret_rate = MGN_MCS14;
1259                 break;
1260         case DESC_RATEMCS15:
1261                 ret_rate = MGN_MCS15;
1262                 break;
1263         case DESC_RATEVHT1SS_MCS0:
1264                 ret_rate = MGN_VHT1SS_MCS0;
1265                 break;
1266         case DESC_RATEVHT1SS_MCS1:
1267                 ret_rate = MGN_VHT1SS_MCS1;
1268                 break;
1269         case DESC_RATEVHT1SS_MCS2:
1270                 ret_rate = MGN_VHT1SS_MCS2;
1271                 break;
1272         case DESC_RATEVHT1SS_MCS3:
1273                 ret_rate = MGN_VHT1SS_MCS3;
1274                 break;
1275         case DESC_RATEVHT1SS_MCS4:
1276                 ret_rate = MGN_VHT1SS_MCS4;
1277                 break;
1278         case DESC_RATEVHT1SS_MCS5:
1279                 ret_rate = MGN_VHT1SS_MCS5;
1280                 break;
1281         case DESC_RATEVHT1SS_MCS6:
1282                 ret_rate = MGN_VHT1SS_MCS6;
1283                 break;
1284         case DESC_RATEVHT1SS_MCS7:
1285                 ret_rate = MGN_VHT1SS_MCS7;
1286                 break;
1287         case DESC_RATEVHT1SS_MCS8:
1288                 ret_rate = MGN_VHT1SS_MCS8;
1289                 break;
1290         case DESC_RATEVHT1SS_MCS9:
1291                 ret_rate = MGN_VHT1SS_MCS9;
1292                 break;
1293         case DESC_RATEVHT2SS_MCS0:
1294                 ret_rate = MGN_VHT2SS_MCS0;
1295                 break;
1296         case DESC_RATEVHT2SS_MCS1:
1297                 ret_rate = MGN_VHT2SS_MCS1;
1298                 break;
1299         case DESC_RATEVHT2SS_MCS2:
1300                 ret_rate = MGN_VHT2SS_MCS2;
1301                 break;
1302         case DESC_RATEVHT2SS_MCS3:
1303                 ret_rate = MGN_VHT2SS_MCS3;
1304                 break;
1305         case DESC_RATEVHT2SS_MCS4:
1306                 ret_rate = MGN_VHT2SS_MCS4;
1307                 break;
1308         case DESC_RATEVHT2SS_MCS5:
1309                 ret_rate = MGN_VHT2SS_MCS5;
1310                 break;
1311         case DESC_RATEVHT2SS_MCS6:
1312                 ret_rate = MGN_VHT2SS_MCS6;
1313                 break;
1314         case DESC_RATEVHT2SS_MCS7:
1315                 ret_rate = MGN_VHT2SS_MCS7;
1316                 break;
1317         case DESC_RATEVHT2SS_MCS8:
1318                 ret_rate = MGN_VHT2SS_MCS8;
1319                 break;
1320         case DESC_RATEVHT2SS_MCS9:
1321                 ret_rate = MGN_VHT2SS_MCS9;
1322                 break;
1323         default:
1324                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1325                          "HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1326                          rate);
1327                 break;
1328         }
1329         return ret_rate;
1330 }
1331
1332 /*-----------------------------------------------------------------------------
1333  * Function:    odm_TxPwrTrackSetPwr88E()
1334  *
1335  * Overview:    88E change all channel tx power accordign to flag.
1336  *                              OFDM & CCK are all different.
1337  *
1338  * Input:               NONE
1339  *
1340  * Output:              NONE
1341  *
1342  * Return:              NONE
1343  *
1344  * Revised History:
1345  *      When            Who             Remark
1346  *      04/23/2012      MHC             Create Version 0.
1347  *
1348  *---------------------------------------------------------------------------
1349  */
1350 void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
1351                                       enum pwr_track_control_method method,
1352                                       u8 rf_path, u8 channel_mapped_index)
1353 {
1354         struct rtl_priv *rtlpriv = rtl_priv(hw);
1355         struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1356         struct rtl_phy *rtlphy = &rtlpriv->phy;
1357         u32 final_swing_idx[2];
1358         u8 pwr_tracking_limit = 26; /*+1.0dB*/
1359         u8 tx_rate = 0xFF;
1360         char final_ofdm_swing_index = 0;
1361
1362         if (rtldm->tx_rate != 0xFF)
1363                 tx_rate =
1364                         rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
1365
1366         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1367                  "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
1368         /*20130429 Mimic Modify High Rate BBSwing Limit.*/
1369         if (tx_rate != 0xFF) {
1370                 /*CCK*/
1371                 if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1372                         pwr_tracking_limit = 32; /*+4dB*/
1373                 /*OFDM*/
1374                 else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
1375                         pwr_tracking_limit = 30; /*+3dB*/
1376                 else if (tx_rate == MGN_54M)
1377                         pwr_tracking_limit = 28; /*+2dB*/
1378                 /*HT*/
1379                  /*QPSK/BPSK*/
1380                 else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1381                         pwr_tracking_limit = 34; /*+5dB*/
1382                  /*16QAM*/
1383                 else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1384                         pwr_tracking_limit = 30; /*+3dB*/
1385                  /*64QAM*/
1386                 else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1387                         pwr_tracking_limit = 28; /*+2dB*/
1388                  /*QPSK/BPSK*/
1389                 else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1390                         pwr_tracking_limit = 34; /*+5dB*/
1391                  /*16QAM*/
1392                 else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1393                         pwr_tracking_limit = 30; /*+3dB*/
1394                  /*64QAM*/
1395                 else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1396                         pwr_tracking_limit = 28; /*+2dB*/
1397
1398                 /*2 VHT*/
1399                  /*QPSK/BPSK*/
1400                 else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1401                          (tx_rate <= MGN_VHT1SS_MCS2))
1402                         pwr_tracking_limit = 34; /*+5dB*/
1403                  /*16QAM*/
1404                 else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1405                          (tx_rate <= MGN_VHT1SS_MCS4))
1406                         pwr_tracking_limit = 30; /*+3dB*/
1407                  /*64QAM*/
1408                 else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
1409                          (tx_rate <= MGN_VHT1SS_MCS6))
1410                         pwr_tracking_limit = 28; /*+2dB*/
1411                 else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
1412                         pwr_tracking_limit = 26; /*+1dB*/
1413                 else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
1414                         pwr_tracking_limit = 24; /*+0dB*/
1415                 else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
1416                         pwr_tracking_limit = 22; /*-1dB*/
1417                  /*QPSK/BPSK*/
1418                 else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1419                          (tx_rate <= MGN_VHT2SS_MCS2))
1420                         pwr_tracking_limit = 34; /*+5dB*/
1421                  /*16QAM*/
1422                 else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1423                          (tx_rate <= MGN_VHT2SS_MCS4))
1424                         pwr_tracking_limit = 30; /*+3dB*/
1425                  /*64QAM*/
1426                 else if ((tx_rate >= MGN_VHT2SS_MCS5) &&
1427                          (tx_rate <= MGN_VHT2SS_MCS6))
1428                         pwr_tracking_limit = 28; /*+2dB*/
1429                 else if (tx_rate == MGN_VHT2SS_MCS7) /*64QAM*/
1430                         pwr_tracking_limit = 26; /*+1dB*/
1431                 else if (tx_rate == MGN_VHT2SS_MCS8) /*256QAM*/
1432                         pwr_tracking_limit = 24; /*+0dB*/
1433                 else if (tx_rate == MGN_VHT2SS_MCS9) /*256QAM*/
1434                         pwr_tracking_limit = 22; /*-1dB*/
1435                 else
1436                         pwr_tracking_limit = 24;
1437         }
1438         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1439                  "TxRate=0x%x, PwrTrackingLimit=%d\n",
1440                  tx_rate, pwr_tracking_limit);
1441
1442         if (method == BBSWING) {
1443                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1444                          "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
1445
1446                 if (rf_path == RF90_PATH_A) {
1447                         u32 tmp;
1448
1449                         final_swing_idx[RF90_PATH_A] =
1450                                 (rtldm->ofdm_index[RF90_PATH_A] >
1451                                 pwr_tracking_limit) ?
1452                                 pwr_tracking_limit :
1453                                 rtldm->ofdm_index[RF90_PATH_A];
1454                         tmp = final_swing_idx[RF90_PATH_A];
1455                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1456                                  "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
1457                                  rtldm->ofdm_index[RF90_PATH_A],
1458                                  final_swing_idx[RF90_PATH_A]);
1459
1460                         rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1461                                       txscaling_tbl[tmp]);
1462                 } else {
1463                         u32 tmp;
1464
1465                         final_swing_idx[RF90_PATH_B] =
1466                                 rtldm->ofdm_index[RF90_PATH_B] >
1467                                 pwr_tracking_limit ?
1468                                 pwr_tracking_limit :
1469                                 rtldm->ofdm_index[RF90_PATH_B];
1470                         tmp = final_swing_idx[RF90_PATH_B];
1471                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1472                                  "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_B]=%d, pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_B]=%d\n",
1473                                  rtldm->ofdm_index[RF90_PATH_B],
1474                                  final_swing_idx[RF90_PATH_B]);
1475
1476                         rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1477                                       txscaling_tbl[tmp]);
1478                 }
1479         } else if (method == MIX_MODE) {
1480                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1481                          "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
1482                          rtldm->default_ofdm_index,
1483                          rtldm->absolute_ofdm_swing_idx[rf_path],
1484                          rf_path);
1485
1486                 final_ofdm_swing_index = rtldm->default_ofdm_index +
1487                                 rtldm->absolute_ofdm_swing_idx[rf_path];
1488
1489                 if (rf_path == RF90_PATH_A) {
1490                         /*BBSwing higher then Limit*/
1491                         if (final_ofdm_swing_index > pwr_tracking_limit) {
1492                                 rtldm->remnant_cck_idx =
1493                                         final_ofdm_swing_index -
1494                                         pwr_tracking_limit;
1495                                 /* CCK Follow the same compensation value
1496                                  * as Path A
1497                                  */
1498                                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1499                                         final_ofdm_swing_index -
1500                                         pwr_tracking_limit;
1501
1502                                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1503                                               txscaling_tbl[pwr_tracking_limit]);
1504
1505                                 rtldm->modify_txagc_flag_path_a = true;
1506
1507                                 /*Set TxAGC Page C{};*/
1508                                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1509                                         rtlphy->current_channel,
1510                                         RF90_PATH_A);
1511
1512                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1513                                          "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
1514                                          pwr_tracking_limit,
1515                                          rtldm->remnant_ofdm_swing_idx[rf_path]);
1516                         } else if (final_ofdm_swing_index < 0) {
1517                                 rtldm->remnant_cck_idx = final_ofdm_swing_index;
1518                                 /* CCK Follow the same compensate value as Path A*/
1519                                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1520                                         final_ofdm_swing_index;
1521
1522                                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1523                                         txscaling_tbl[0]);
1524
1525                                 rtldm->modify_txagc_flag_path_a = true;
1526
1527                                 /*Set TxAGC Page C{};*/
1528                                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1529                                         rtlphy->current_channel, RF90_PATH_A);
1530
1531                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1532                                          "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1533                                          rtldm->remnant_ofdm_swing_idx[rf_path]);
1534                         } else {
1535                                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1536                                         txscaling_tbl[(u8)final_ofdm_swing_index]);
1537
1538                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1539                                          "******Path_A Compensate with BBSwing, Final_OFDM_Swing_Index = %d\n",
1540                                         final_ofdm_swing_index);
1541                                 /*If TxAGC has changed, reset TxAGC again*/
1542                                 if (rtldm->modify_txagc_flag_path_a) {
1543                                         rtldm->remnant_cck_idx = 0;
1544                                         rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1545
1546                                         /*Set TxAGC Page C{};*/
1547                                         rtl8821ae_phy_set_txpower_level_by_path(hw,
1548                                                 rtlphy->current_channel, RF90_PATH_A);
1549                                         rtldm->modify_txagc_flag_path_a = false;
1550
1551                                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
1552                                                  DBG_LOUD,
1553                                                  "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1554                                 }
1555                         }
1556                 }
1557                 /*BBSwing higher then Limit*/
1558                 if (rf_path == RF90_PATH_B) {
1559                         if (final_ofdm_swing_index > pwr_tracking_limit) {
1560                                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1561                                         final_ofdm_swing_index -
1562                                         pwr_tracking_limit;
1563
1564                                 rtl_set_bbreg(hw, RB_TXSCALE,
1565                                         0xFFE00000,
1566                                         txscaling_tbl[pwr_tracking_limit]);
1567
1568                                 rtldm->modify_txagc_flag_path_b = true;
1569
1570                                 /*Set TxAGC Page E{};*/
1571                                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1572                                         rtlphy->current_channel, RF90_PATH_B);
1573
1574                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1575                                          "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
1576                                          pwr_tracking_limit,
1577                                          rtldm->remnant_ofdm_swing_idx[rf_path]);
1578                         } else if (final_ofdm_swing_index < 0) {
1579                                 rtldm->remnant_ofdm_swing_idx[rf_path] =
1580                                         final_ofdm_swing_index;
1581
1582                                 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1583                                               txscaling_tbl[0]);
1584
1585                                 rtldm->modify_txagc_flag_path_b = true;
1586
1587                                 /*Set TxAGC Page E{};*/
1588                                 rtl8821ae_phy_set_txpower_level_by_path(hw,
1589                                         rtlphy->current_channel, RF90_PATH_B);
1590
1591                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1592                                          "******Path_B Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
1593                                          rtldm->remnant_ofdm_swing_idx[rf_path]);
1594                         } else {
1595                                 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1596                                         txscaling_tbl[(u8)final_ofdm_swing_index]);
1597
1598                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1599                                          "******Path_B Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
1600                                         final_ofdm_swing_index);
1601                                  /*If TxAGC has changed, reset TxAGC again*/
1602                                 if (rtldm->modify_txagc_flag_path_b) {
1603                                         rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
1604
1605                                         /*Set TxAGC Page E{};*/
1606                                         rtl8821ae_phy_set_txpower_level_by_path(hw,
1607                                         rtlphy->current_channel, RF90_PATH_B);
1608
1609                                         rtldm->modify_txagc_flag_path_b =
1610                                                 false;
1611
1612                                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1613                                                  "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1614                                 }
1615                         }
1616                 }
1617         } else {
1618                 return;
1619         }
1620 }
1621
1622 void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1623         struct ieee80211_hw *hw)
1624 {
1625         struct rtl_priv *rtlpriv = rtl_priv(hw);
1626         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
1627         struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
1628         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1629         u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
1630         u8 thermal_value_avg_count = 0;
1631         u32 thermal_value_avg = 0;
1632         /* OFDM BB Swing should be less than +3.0dB, */
1633         u8 ofdm_min_index = 6;
1634          /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
1635         u8 index_for_channel = 0;
1636         /* 1. The following TWO tables decide
1637          * the final index of OFDM/CCK swing table.
1638          */
1639         u8 *delta_swing_table_idx_tup_a;
1640         u8 *delta_swing_table_idx_tdown_a;
1641         u8 *delta_swing_table_idx_tup_b;
1642         u8 *delta_swing_table_idx_tdown_b;
1643
1644         /*2. Initilization ( 7 steps in total )*/
1645         rtl8812ae_get_delta_swing_table(hw,
1646                 (u8 **)&delta_swing_table_idx_tup_a,
1647                 (u8 **)&delta_swing_table_idx_tdown_a,
1648                 (u8 **)&delta_swing_table_idx_tup_b,
1649                 (u8 **)&delta_swing_table_idx_tdown_b);
1650
1651         rtldm->txpower_trackinginit = true;
1652
1653         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1654                  "pDM_Odm->BbSwingIdxCckBase: %d, pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
1655                  rtldm->swing_idx_cck_base,
1656                  rtldm->swing_idx_ofdm_base[RF90_PATH_A],
1657                  rtldm->default_ofdm_index);
1658
1659         thermal_value = (u8)rtl_get_rfreg(hw, RF90_PATH_A,
1660                 /*0x42: RF Reg[15:10] 88E*/
1661                 RF_T_METER_8812A, 0xfc00);
1662         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1663                  "Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1664                  thermal_value, rtlefuse->eeprom_thermalmeter);
1665         if (!rtldm->txpower_track_control ||
1666             rtlefuse->eeprom_thermalmeter == 0 ||
1667             rtlefuse->eeprom_thermalmeter == 0xFF)
1668                 return;
1669
1670         /* 3. Initialize ThermalValues of RFCalibrateInfo*/
1671
1672         if (rtlhal->reloadtxpowerindex)
1673                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1674                          "reload ofdm index for band switch\n");
1675
1676         /*4. Calculate average thermal meter*/
1677         rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
1678         rtldm->thermalvalue_avg_index++;
1679         if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
1680                 /*Average times =  c.AverageThermalNum*/
1681                 rtldm->thermalvalue_avg_index = 0;
1682
1683         for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
1684                 if (rtldm->thermalvalue_avg[i]) {
1685                         thermal_value_avg += rtldm->thermalvalue_avg[i];
1686                         thermal_value_avg_count++;
1687                 }
1688         }
1689         /*Calculate Average ThermalValue after average enough times*/
1690         if (thermal_value_avg_count) {
1691                 thermal_value = (u8)(thermal_value_avg /
1692                                 thermal_value_avg_count);
1693                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1694                          "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
1695                          thermal_value, rtlefuse->eeprom_thermalmeter);
1696         }
1697
1698         /*5. Calculate delta, delta_LCK, delta_IQK.
1699          *"delta" here is used to determine whether
1700          *thermal value changes or not.
1701          */
1702         delta = (thermal_value > rtldm->thermalvalue) ?
1703                 (thermal_value - rtldm->thermalvalue) :
1704                 (rtldm->thermalvalue - thermal_value);
1705         delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
1706                 (thermal_value - rtldm->thermalvalue_lck) :
1707                 (rtldm->thermalvalue_lck - thermal_value);
1708         delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
1709                 (thermal_value - rtldm->thermalvalue_iqk) :
1710                 (rtldm->thermalvalue_iqk - thermal_value);
1711
1712         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1713                  "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
1714                  delta, delta_lck, delta_iqk);
1715
1716         /* 6. If necessary, do LCK.
1717          * Delta temperature is equal to or larger than 20 centigrade.
1718          */
1719         if (delta_lck >= IQK_THRESHOLD) {
1720                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1721                          "delta_LCK(%d) >= Threshold_IQK(%d)\n",
1722                          delta_lck, IQK_THRESHOLD);
1723                 rtldm->thermalvalue_lck = thermal_value;
1724                 rtl8821ae_phy_lc_calibrate(hw);
1725         }
1726
1727         /*7. If necessary, move the index of swing table to adjust Tx power.*/
1728
1729         if (delta > 0 && rtldm->txpower_track_control) {
1730                 /* "delta" here is used to record the
1731                  * absolute value of differrence.
1732                  */
1733                 delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1734                         (thermal_value - rtlefuse->eeprom_thermalmeter) :
1735                         (rtlefuse->eeprom_thermalmeter - thermal_value);
1736
1737                 if (delta >= TXPWR_TRACK_TABLE_SIZE)
1738                         delta = TXPWR_TRACK_TABLE_SIZE - 1;
1739
1740                 /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
1741
1742                 if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1743                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1744                                  "delta_swing_table_idx_tup_a[%d] = %d\n",
1745                                  delta, delta_swing_table_idx_tup_a[delta]);
1746                         rtldm->delta_power_index_last[RF90_PATH_A] =
1747                                 rtldm->delta_power_index[RF90_PATH_A];
1748                         rtldm->delta_power_index[RF90_PATH_A] =
1749                                 delta_swing_table_idx_tup_a[delta];
1750
1751                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1752                                 delta_swing_table_idx_tup_a[delta];
1753                         /*Record delta swing for mix mode power tracking*/
1754
1755                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1756                                  "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1757                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1758
1759                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1760                                  "delta_swing_table_idx_tup_b[%d] = %d\n",
1761                                  delta, delta_swing_table_idx_tup_b[delta]);
1762                         rtldm->delta_power_index_last[RF90_PATH_B] =
1763                                 rtldm->delta_power_index[RF90_PATH_B];
1764                         rtldm->delta_power_index[RF90_PATH_B] =
1765                                 delta_swing_table_idx_tup_b[delta];
1766
1767                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1768                                 delta_swing_table_idx_tup_b[delta];
1769                         /*Record delta swing for mix mode power tracking*/
1770
1771                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1772                                  "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1773                                  rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1774                 } else {
1775                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1776                                  "delta_swing_table_idx_tdown_a[%d] = %d\n",
1777                                  delta, delta_swing_table_idx_tdown_a[delta]);
1778
1779                         rtldm->delta_power_index_last[RF90_PATH_A] =
1780                                 rtldm->delta_power_index[RF90_PATH_A];
1781                         rtldm->delta_power_index[RF90_PATH_A] =
1782                                 -1 * delta_swing_table_idx_tdown_a[delta];
1783
1784                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
1785                                 -1 * delta_swing_table_idx_tdown_a[delta];
1786                         /* Record delta swing for mix mode power tracking*/
1787                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1788                                  "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
1789                                  rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
1790
1791                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1792                                  "deltaSwingTableIdx_TDOWN_B[%d] = %d\n",
1793                                  delta, delta_swing_table_idx_tdown_b[delta]);
1794
1795                         rtldm->delta_power_index_last[RF90_PATH_B] =
1796                                 rtldm->delta_power_index[RF90_PATH_B];
1797                         rtldm->delta_power_index[RF90_PATH_B] =
1798                                 -1 * delta_swing_table_idx_tdown_b[delta];
1799
1800                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_B] =
1801                                 -1 * delta_swing_table_idx_tdown_b[delta];
1802                         /*Record delta swing for mix mode power tracking*/
1803
1804                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1805                                  "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n",
1806                                  rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]);
1807                 }
1808
1809                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1810                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1811                                  "============================= [Path-%c]Calculating PowerIndexOffset =============================\n",
1812                                  (p == RF90_PATH_A ? 'A' : 'B'));
1813
1814                         if (rtldm->delta_power_index[p] ==
1815                                 rtldm->delta_power_index_last[p])
1816                                 /*If Thermal value changes but lookup
1817                                 table value still the same*/
1818                                 rtldm->power_index_offset[p] = 0;
1819                         else
1820                                 rtldm->power_index_offset[p] =
1821                                         rtldm->delta_power_index[p] -
1822                                         rtldm->delta_power_index_last[p];
1823                                 /* Power Index Diff between 2
1824                                  * times Power Tracking
1825                                  */
1826                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1827                                  "[Path-%c] PowerIndexOffset(%d) =DeltaPowerIndex(%d) -DeltaPowerIndexLast(%d)\n",
1828                                  (p == RF90_PATH_A ? 'A' : 'B'),
1829                                  rtldm->power_index_offset[p],
1830                                  rtldm->delta_power_index[p] ,
1831                                  rtldm->delta_power_index_last[p]);
1832
1833                         rtldm->ofdm_index[p] =
1834                                         rtldm->swing_idx_ofdm_base[p] +
1835                                         rtldm->power_index_offset[p];
1836                         rtldm->cck_index =
1837                                         rtldm->swing_idx_cck_base +
1838                                         rtldm->power_index_offset[p];
1839
1840                         rtldm->swing_idx_cck = rtldm->cck_index;
1841                         rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1842
1843                         /****Print BB Swing Base and Index Offset */
1844
1845                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1846                                  "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
1847                                  rtldm->swing_idx_cck,
1848                                 rtldm->swing_idx_cck_base,
1849                                 rtldm->power_index_offset[p]);
1850                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1851                                  "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
1852                                  rtldm->swing_idx_ofdm[p],
1853                                  (p == RF90_PATH_A ? 'A' : 'B'),
1854                                  rtldm->swing_idx_ofdm_base[p],
1855                                  rtldm->power_index_offset[p]);
1856
1857                         /*7.1 Handle boundary conditions of index.*/
1858
1859                         if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
1860                                 rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
1861                         else if (rtldm->ofdm_index[p] < ofdm_min_index)
1862                                 rtldm->ofdm_index[p] = ofdm_min_index;
1863                 }
1864                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1865                          "\n\n====================================================================================\n");
1866                 if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
1867                         rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
1868                 else if (rtldm->cck_index < 0)
1869                         rtldm->cck_index = 0;
1870         } else {
1871                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1872                          "The thermal meter is unchanged or TxPowerTracking OFF(%d): ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
1873                          rtldm->txpower_track_control,
1874                          thermal_value,
1875                          rtldm->thermalvalue);
1876
1877                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1878                         rtldm->power_index_offset[p] = 0;
1879         }
1880         /*Print Swing base & current*/
1881         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1882                  "TxPowerTracking: [CCK] Swing Current Index: %d,Swing Base Index: %d\n",
1883                  rtldm->cck_index, rtldm->swing_idx_cck_base);
1884         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++) {
1885                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1886                          "TxPowerTracking: [OFDM] Swing Current Index: %d,Swing Base Index[%c]: %d\n",
1887                          rtldm->ofdm_index[p],
1888                          (p == RF90_PATH_A ? 'A' : 'B'),
1889                          rtldm->swing_idx_ofdm_base[p]);
1890         }
1891
1892         if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
1893                 rtldm->power_index_offset[RF90_PATH_B] != 0) &&
1894                 rtldm->txpower_track_control) {
1895                 /*7.2 Configure the Swing Table to adjust Tx Power.
1896                  *Always TRUE after Tx Power is adjusted by power tracking.
1897                  *
1898                  *2012/04/23 MH According to Luke's suggestion,
1899                  *we can not write BB digital
1900                  *to increase TX power. Otherwise, EVM will be bad.
1901                  *
1902                  *2012/04/25 MH Add for tx power tracking to set
1903                  *tx power in tx agc for 88E.
1904                  */
1905                 if (thermal_value > rtldm->thermalvalue) {
1906                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1907                                  "Temperature Increasing(A): delta_pi: %d , delta_t: %d, Now_t: %d,EFUSE_t: %d, Last_t: %d\n",
1908                                  rtldm->power_index_offset[RF90_PATH_A],
1909                                  delta, thermal_value,
1910                                  rtlefuse->eeprom_thermalmeter,
1911                                  rtldm->thermalvalue);
1912
1913                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1914                                  "Temperature Increasing(B): delta_pi: %d ,delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1915                                  rtldm->power_index_offset[RF90_PATH_B],
1916                                  delta, thermal_value,
1917                                  rtlefuse->eeprom_thermalmeter,
1918                                  rtldm->thermalvalue);
1919                 } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
1920                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1921                                  "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1922                                  rtldm->power_index_offset[RF90_PATH_A],
1923                                  delta, thermal_value,
1924                                  rtlefuse->eeprom_thermalmeter,
1925                                  rtldm->thermalvalue);
1926
1927                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1928                                  "Temperature Decreasing(B): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
1929                                  rtldm->power_index_offset[RF90_PATH_B],
1930                                  delta, thermal_value,
1931                                  rtlefuse->eeprom_thermalmeter,
1932                                  rtldm->thermalvalue);
1933                 }
1934
1935                 if (thermal_value > rtlefuse->eeprom_thermalmeter) {
1936                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1937                                  "Temperature(%d) higher than PG value(%d)\n",
1938                                  thermal_value, rtlefuse->eeprom_thermalmeter);
1939
1940                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1941                                  "**********Enter POWER Tracking MIX_MODE**********\n");
1942                         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1943                                 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1944                                                                  p, 0);
1945                 } else {
1946                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1947                                  "Temperature(%d) lower than PG value(%d)\n",
1948                                  thermal_value, rtlefuse->eeprom_thermalmeter);
1949
1950                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1951                                  "**********Enter POWER Tracking MIX_MODE**********\n");
1952                         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1953                                 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE,
1954                                                                  p, index_for_channel);
1955                 }
1956                 /*Record last time Power Tracking result as base.*/
1957                 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
1958                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1959                                 rtldm->swing_idx_ofdm_base[p] =
1960                                         rtldm->swing_idx_ofdm[p];
1961
1962                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1963                                  "pDM_Odm->RFCalibrateInfo.ThermalValue =%d ThermalValue= %d\n",
1964                                  rtldm->thermalvalue, thermal_value);
1965                 /*Record last Power Tracking Thermal Value*/
1966                 rtldm->thermalvalue = thermal_value;
1967         }
1968         /*Delta temperature is equal to or larger than
1969         20 centigrade (When threshold is 8).*/
1970         if (delta_iqk >= IQK_THRESHOLD)
1971                 rtl8812ae_do_iqk(hw, delta_iqk, thermal_value, 8);
1972
1973         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1974                  "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n");
1975 }
1976
1977 static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw, u8 **up_a,
1978                                             u8 **down_a, u8 **up_b, u8 **down_b)
1979 {
1980         struct rtl_priv *rtlpriv = rtl_priv(hw);
1981         struct rtl_phy *rtlphy = &rtlpriv->phy;
1982         struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1983         u8 channel = rtlphy->current_channel;
1984         u8 rate = rtldm->tx_rate;
1985
1986         if (1 <= channel && channel <= 14) {
1987                 if (RTL8821AE_RX_HAL_IS_CCK_RATE(rate)) {
1988                         *up_a = rtl8821ae_delta_swing_table_idx_24gccka_p;
1989                         *down_a = rtl8821ae_delta_swing_table_idx_24gccka_n;
1990                         *up_b = rtl8821ae_delta_swing_table_idx_24gcckb_p;
1991                         *down_b = rtl8821ae_delta_swing_table_idx_24gcckb_n;
1992                 } else {
1993                         *up_a = rtl8821ae_delta_swing_table_idx_24ga_p;
1994                         *down_a = rtl8821ae_delta_swing_table_idx_24ga_n;
1995                         *up_b = rtl8821ae_delta_swing_table_idx_24gb_p;
1996                         *down_b = rtl8821ae_delta_swing_table_idx_24gb_n;
1997                 }
1998         } else if (36 <= channel && channel <= 64) {
1999                 *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[0];
2000                 *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[0];
2001                 *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[0];
2002                 *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[0];
2003         } else if (100 <= channel && channel <= 140) {
2004                 *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[1];
2005                 *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[1];
2006                 *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[1];
2007                 *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[1];
2008         } else if (149 <= channel && channel <= 173) {
2009                 *up_a = rtl8821ae_delta_swing_table_idx_5ga_p[2];
2010                 *down_a = rtl8821ae_delta_swing_table_idx_5ga_n[2];
2011                 *up_b = rtl8821ae_delta_swing_table_idx_5gb_p[2];
2012                 *down_b = rtl8821ae_delta_swing_table_idx_5gb_n[2];
2013         } else {
2014             *up_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
2015             *down_a = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
2016             *up_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_p;
2017             *down_b = (u8 *)rtl8818e_delta_swing_table_idx_24gb_n;
2018         }
2019         return;
2020 }
2021
2022 /*-----------------------------------------------------------------------------
2023  * Function:    odm_TxPwrTrackSetPwr88E()
2024  *
2025  * Overview:    88E change all channel tx power accordign to flag.
2026  *                              OFDM & CCK are all different.
2027  *
2028  * Input:               NONE
2029  *
2030  * Output:              NONE
2031  *
2032  * Return:              NONE
2033  *
2034  * Revised History:
2035  *      When            Who             Remark
2036  *      04/23/2012      MHC             Create Version 0.
2037  *
2038  *---------------------------------------------------------------------------
2039  */
2040 void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw,
2041                                       enum pwr_track_control_method method,
2042                                       u8 rf_path, u8 channel_mapped_index)
2043 {
2044         struct rtl_priv *rtlpriv = rtl_priv(hw);
2045         struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
2046         struct rtl_phy *rtlphy = &rtlpriv->phy;
2047         u32 final_swing_idx[1];
2048         u8 pwr_tracking_limit = 26; /*+1.0dB*/
2049         u8 tx_rate = 0xFF;
2050         char final_ofdm_swing_index = 0;
2051
2052         if (rtldm->tx_rate != 0xFF)
2053                 tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
2054
2055         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
2056
2057         if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
2058                 /*CCK*/
2059                 if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
2060                         pwr_tracking_limit = 32; /*+4dB*/
2061                 /*OFDM*/
2062                 else if ((tx_rate >= MGN_6M) && (tx_rate <= MGN_48M))
2063                         pwr_tracking_limit = 30; /*+3dB*/
2064                 else if (tx_rate == MGN_54M)
2065                         pwr_tracking_limit = 28; /*+2dB*/
2066                 /*HT*/
2067                 /*QPSK/BPSK*/
2068                 else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
2069                         pwr_tracking_limit = 34; /*+5dB*/
2070                 /*16QAM*/
2071                 else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
2072                         pwr_tracking_limit = 30; /*+3dB*/
2073                 /*64QAM*/
2074                 else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
2075                         pwr_tracking_limit = 28; /*+2dB*/
2076                 /*2 VHT*/
2077                 /*QPSK/BPSK*/
2078                 else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
2079                         (tx_rate <= MGN_VHT1SS_MCS2))
2080                         pwr_tracking_limit = 34; /*+5dB*/
2081                 /*16QAM*/
2082                 else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
2083                         (tx_rate <= MGN_VHT1SS_MCS4))
2084                         pwr_tracking_limit = 30; /*+3dB*/
2085                 /*64QAM*/
2086                 else if ((tx_rate >= MGN_VHT1SS_MCS5) &&
2087                         (tx_rate <= MGN_VHT1SS_MCS6))
2088                         pwr_tracking_limit = 28; /*+2dB*/
2089                 else if (tx_rate == MGN_VHT1SS_MCS7) /*64QAM*/
2090                         pwr_tracking_limit = 26; /*+1dB*/
2091                 else if (tx_rate == MGN_VHT1SS_MCS8) /*256QAM*/
2092                         pwr_tracking_limit = 24; /*+0dB*/
2093                 else if (tx_rate == MGN_VHT1SS_MCS9) /*256QAM*/
2094                         pwr_tracking_limit = 22; /*-1dB*/
2095                 else
2096                         pwr_tracking_limit = 24;
2097         }
2098         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2099                  "TxRate=0x%x, PwrTrackingLimit=%d\n",
2100                  tx_rate, pwr_tracking_limit);
2101
2102         if (method == BBSWING) {
2103                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2104                          "===>%s\n", __func__);
2105                 if (rf_path == RF90_PATH_A) {
2106                         final_swing_idx[RF90_PATH_A] =
2107                                 (rtldm->ofdm_index[RF90_PATH_A] >
2108                                 pwr_tracking_limit) ?
2109                                 pwr_tracking_limit :
2110                                 rtldm->ofdm_index[RF90_PATH_A];
2111                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2112                                  "pDM_Odm->RFCalibrateInfo.OFDM_index[ODM_RF_PATH_A]=%d,pDM_Odm->RealBbSwingIdx[ODM_RF_PATH_A]=%d\n",
2113                                  rtldm->ofdm_index[RF90_PATH_A],
2114                                  final_swing_idx[RF90_PATH_A]);
2115
2116                         rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2117                                 txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
2118                 }
2119         } else if (method == MIX_MODE) {
2120                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2121                          "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n",
2122                          rtldm->default_ofdm_index,
2123                          rtldm->absolute_ofdm_swing_idx[rf_path],
2124                          rf_path);
2125
2126                 final_ofdm_swing_index =
2127                         rtldm->default_ofdm_index +
2128                         rtldm->absolute_ofdm_swing_idx[rf_path];
2129                 /*BBSwing higher then Limit*/
2130                 if (rf_path == RF90_PATH_A) {
2131                         if (final_ofdm_swing_index > pwr_tracking_limit) {
2132                                 rtldm->remnant_cck_idx =
2133                                         final_ofdm_swing_index -
2134                                         pwr_tracking_limit;
2135                                 /* CCK Follow the same compensate value as Path A*/
2136                                 rtldm->remnant_ofdm_swing_idx[rf_path] =
2137                                         final_ofdm_swing_index -
2138                                         pwr_tracking_limit;
2139
2140                                 rtl_set_bbreg(hw, RA_TXSCALE,
2141                                         0xFFE00000,
2142                                         txscaling_tbl[pwr_tracking_limit]);
2143
2144                                 rtldm->modify_txagc_flag_path_a = true;
2145
2146                                 /*Set TxAGC Page C{};*/
2147                                 rtl8821ae_phy_set_txpower_level_by_path(hw,
2148                                         rtlphy->current_channel,
2149                                         RF90_PATH_A);
2150
2151                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2152                                         " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
2153                                          pwr_tracking_limit,
2154                                          rtldm->remnant_ofdm_swing_idx[rf_path]);
2155                         } else if (final_ofdm_swing_index < 0) {
2156                                 rtldm->remnant_cck_idx = final_ofdm_swing_index;
2157                                 /* CCK Follow the same compensate value as Path A*/
2158                                 rtldm->remnant_ofdm_swing_idx[rf_path] =
2159                                         final_ofdm_swing_index;
2160
2161                                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2162                                         txscaling_tbl[0]);
2163
2164                                 rtldm->modify_txagc_flag_path_a = true;
2165
2166                                 /*Set TxAGC Page C{};*/
2167                                 rtl8821ae_phy_set_txpower_level_by_path(hw,
2168                                         rtlphy->current_channel, RF90_PATH_A);
2169
2170                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2171                                          "******Path_A Lower then BBSwing lower bound  0 , Remnant TxAGC Value = %d\n",
2172                                          rtldm->remnant_ofdm_swing_idx[rf_path]);
2173                         } else {
2174                                 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2175                                         txscaling_tbl[(u8)final_ofdm_swing_index]);
2176
2177                                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2178                                          "******Path_A Compensate with BBSwing ,Final_OFDM_Swing_Index = %d\n",
2179                                          final_ofdm_swing_index);
2180                                 /*If TxAGC has changed, reset TxAGC again*/
2181                                 if (rtldm->modify_txagc_flag_path_a) {
2182                                         rtldm->remnant_cck_idx = 0;
2183                                         rtldm->remnant_ofdm_swing_idx[rf_path] = 0;
2184
2185                                         /*Set TxAGC Page C{};*/
2186                                         rtl8821ae_phy_set_txpower_level_by_path(hw,
2187                                                 rtlphy->current_channel, RF90_PATH_A);
2188
2189                                         rtldm->modify_txagc_flag_path_a = false;
2190
2191                                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
2192                                                  DBG_LOUD,
2193                                                  "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2194                                 }
2195                         }
2196                 }
2197         } else {
2198                 return;
2199         }
2200 }
2201
2202 void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2203         struct ieee80211_hw *hw)
2204 {
2205         struct rtl_priv *rtlpriv = rtl_priv(hw);
2206         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2207         struct rtl_dm   *rtldm = rtl_dm(rtl_priv(hw));
2208         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2209         struct rtl_phy *rtlphy = &rtlpriv->phy;
2210
2211         u8 thermal_value = 0, delta, delta_lck, delta_iqk, p = 0, i = 0;
2212         u8 thermal_value_avg_count = 0;
2213         u32 thermal_value_avg = 0;
2214
2215         u8 ofdm_min_index = 6;  /*OFDM BB Swing should be less than +3.0dB */
2216         /* GetRightChnlPlaceforIQK(pHalData->CurrentChannel)*/
2217         u8 index_for_channel = 0;
2218
2219         /* 1. The following TWO tables decide the final
2220          * index of OFDM/CCK swing table.
2221          */
2222         u8 *delta_swing_table_idx_tup_a;
2223         u8 *delta_swing_table_idx_tdown_a;
2224         u8 *delta_swing_table_idx_tup_b;
2225         u8 *delta_swing_table_idx_tdown_b;
2226
2227         /*2. Initilization ( 7 steps in total )*/
2228         rtl8821ae_get_delta_swing_table(hw, (u8 **)&delta_swing_table_idx_tup_a,
2229                                         (u8 **)&delta_swing_table_idx_tdown_a,
2230                                         (u8 **)&delta_swing_table_idx_tup_b,
2231                                         (u8 **)&delta_swing_table_idx_tdown_b);
2232
2233         rtldm->txpower_trackinginit = true;
2234
2235         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2236                  "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
2237                  __func__,
2238                  rtldm->swing_idx_cck_base,
2239                  rtldm->swing_idx_ofdm_base[RF90_PATH_A],
2240                  rtldm->default_ofdm_index);
2241         /*0x42: RF Reg[15:10] 88E*/
2242         thermal_value = (u8)rtl_get_rfreg(hw,
2243                 RF90_PATH_A, RF_T_METER_8812A, 0xfc00);
2244         if (!rtldm->txpower_track_control ||
2245                 rtlefuse->eeprom_thermalmeter == 0 ||
2246                 rtlefuse->eeprom_thermalmeter == 0xFF)
2247                 return;
2248
2249         /* 3. Initialize ThermalValues of RFCalibrateInfo*/
2250
2251         if (rtlhal->reloadtxpowerindex) {
2252                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2253                          "reload ofdm index for band switch\n");
2254         }
2255
2256         /*4. Calculate average thermal meter*/
2257         rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermal_value;
2258         rtldm->thermalvalue_avg_index++;
2259         if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8812A)
2260                 /*Average times =  c.AverageThermalNum*/
2261                 rtldm->thermalvalue_avg_index = 0;
2262
2263         for (i = 0; i < AVG_THERMAL_NUM_8812A; i++) {
2264                 if (rtldm->thermalvalue_avg[i]) {
2265                         thermal_value_avg += rtldm->thermalvalue_avg[i];
2266                         thermal_value_avg_count++;
2267                 }
2268         }
2269         /*Calculate Average ThermalValue after average enough times*/
2270         if (thermal_value_avg_count) {
2271                 thermal_value = (u8)(thermal_value_avg /
2272                                 thermal_value_avg_count);
2273                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2274                          "AVG Thermal Meter = 0x%X, EFUSE Thermal Base = 0x%X\n",
2275                          thermal_value, rtlefuse->eeprom_thermalmeter);
2276         }
2277
2278         /*5. Calculate delta, delta_LCK, delta_IQK.
2279          *"delta" here is used to determine whether
2280          * thermal value changes or not.
2281          */
2282         delta = (thermal_value > rtldm->thermalvalue) ?
2283                 (thermal_value - rtldm->thermalvalue) :
2284                 (rtldm->thermalvalue - thermal_value);
2285         delta_lck = (thermal_value > rtldm->thermalvalue_lck) ?
2286                 (thermal_value - rtldm->thermalvalue_lck) :
2287                 (rtldm->thermalvalue_lck - thermal_value);
2288         delta_iqk = (thermal_value > rtldm->thermalvalue_iqk) ?
2289                 (thermal_value - rtldm->thermalvalue_iqk) :
2290                 (rtldm->thermalvalue_iqk - thermal_value);
2291
2292         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2293                  "(delta, delta_LCK, delta_IQK) = (%d, %d, %d)\n",
2294                  delta, delta_lck, delta_iqk);
2295
2296         /* 6. If necessary, do LCK.     */
2297         /*Delta temperature is equal to or larger than 20 centigrade.*/
2298         if (delta_lck >= IQK_THRESHOLD) {
2299                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2300                          "delta_LCK(%d) >= Threshold_IQK(%d)\n",
2301                          delta_lck, IQK_THRESHOLD);
2302                 rtldm->thermalvalue_lck = thermal_value;
2303                 rtl8821ae_phy_lc_calibrate(hw);
2304         }
2305
2306         /*7. If necessary, move the index of swing table to adjust Tx power.*/
2307
2308         if (delta > 0 && rtldm->txpower_track_control) {
2309                 /*"delta" here is used to record the
2310                  * absolute value of differrence.
2311                  */
2312                 delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2313                         (thermal_value - rtlefuse->eeprom_thermalmeter) :
2314                         (rtlefuse->eeprom_thermalmeter - thermal_value);
2315
2316                 if (delta >= TXSCALE_TABLE_SIZE)
2317                         delta = TXSCALE_TABLE_SIZE - 1;
2318
2319                 /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
2320
2321                 if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2322                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2323                                  "delta_swing_table_idx_tup_a[%d] = %d\n",
2324                                  delta, delta_swing_table_idx_tup_a[delta]);
2325                         rtldm->delta_power_index_last[RF90_PATH_A] =
2326                                 rtldm->delta_power_index[RF90_PATH_A];
2327                         rtldm->delta_power_index[RF90_PATH_A] =
2328                                 delta_swing_table_idx_tup_a[delta];
2329
2330                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2331                                 delta_swing_table_idx_tup_a[delta];
2332                         /*Record delta swing for mix mode power tracking*/
2333
2334                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2335                                  "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2336                                  rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2337                 } else {
2338                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2339                                  "delta_swing_table_idx_tdown_a[%d] = %d\n",
2340                                  delta, delta_swing_table_idx_tdown_a[delta]);
2341
2342                         rtldm->delta_power_index_last[RF90_PATH_A] =
2343                                 rtldm->delta_power_index[RF90_PATH_A];
2344                         rtldm->delta_power_index[RF90_PATH_A] =
2345                                 -1 * delta_swing_table_idx_tdown_a[delta];
2346
2347                         rtldm->absolute_ofdm_swing_idx[RF90_PATH_A] =
2348                                 -1 * delta_swing_table_idx_tdown_a[delta];
2349                         /* Record delta swing for mix mode power tracking*/
2350                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2351                                  "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n",
2352                                  rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]);
2353                 }
2354
2355                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2356                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2357                                  "\n\n================================ [Path-%c]Calculating PowerIndexOffset ================================\n",
2358                                  (p == RF90_PATH_A ? 'A' : 'B'));
2359                         /*If Thermal value changes but lookup table value
2360                          * still the same
2361                          */
2362                         if (rtldm->delta_power_index[p] ==
2363                                 rtldm->delta_power_index_last[p])
2364
2365                                 rtldm->power_index_offset[p] = 0;
2366                         else
2367                                 rtldm->power_index_offset[p] =
2368                                         rtldm->delta_power_index[p] -
2369                                         rtldm->delta_power_index_last[p];
2370                         /*Power Index Diff between 2 times Power Tracking*/
2371
2372                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2373                                  "[Path-%c] PowerIndexOffset(%d) = DeltaPowerIndex(%d) - DeltaPowerIndexLast(%d)\n",
2374                                  (p == RF90_PATH_A ? 'A' : 'B'),
2375                                 rtldm->power_index_offset[p],
2376                                 rtldm->delta_power_index[p] ,
2377                                 rtldm->delta_power_index_last[p]);
2378
2379                         rtldm->ofdm_index[p] =
2380                                         rtldm->swing_idx_ofdm_base[p] +
2381                                         rtldm->power_index_offset[p];
2382                         rtldm->cck_index =
2383                                         rtldm->swing_idx_cck_base +
2384                                         rtldm->power_index_offset[p];
2385
2386                         rtldm->swing_idx_cck = rtldm->cck_index;
2387                         rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2388
2389                         /*********Print BB Swing Base and Index Offset********/
2390
2391                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2392                                  "The 'CCK' final index(%d) = BaseIndex(%d) + PowerIndexOffset(%d)\n",
2393                                  rtldm->swing_idx_cck,
2394                                  rtldm->swing_idx_cck_base,
2395                                  rtldm->power_index_offset[p]);
2396                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2397                                  "The 'OFDM' final index(%d) = BaseIndex[%c](%d) + PowerIndexOffset(%d)\n",
2398                                  rtldm->swing_idx_ofdm[p],
2399                                  (p == RF90_PATH_A ? 'A' : 'B'),
2400                                  rtldm->swing_idx_ofdm_base[p],
2401                                  rtldm->power_index_offset[p]);
2402
2403                         /*7.1 Handle boundary conditions of index.*/
2404
2405                         if (rtldm->ofdm_index[p] > TXSCALE_TABLE_SIZE - 1)
2406                                 rtldm->ofdm_index[p] = TXSCALE_TABLE_SIZE - 1;
2407                         else if (rtldm->ofdm_index[p] < ofdm_min_index)
2408                                 rtldm->ofdm_index[p] = ofdm_min_index;
2409                 }
2410                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2411                          "\n\n========================================================================================================\n");
2412                 if (rtldm->cck_index > TXSCALE_TABLE_SIZE - 1)
2413                         rtldm->cck_index = TXSCALE_TABLE_SIZE - 1;
2414                 else if (rtldm->cck_index < 0)
2415                         rtldm->cck_index = 0;
2416         } else {
2417                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2418                          "The thermal meter is unchanged or TxPowerTracking OFF(%d):ThermalValue: %d , pDM_Odm->RFCalibrateInfo.ThermalValue: %d\n",
2419                          rtldm->txpower_track_control,
2420                          thermal_value,
2421                          rtldm->thermalvalue);
2422
2423                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2424                         rtldm->power_index_offset[p] = 0;
2425         }
2426         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2427                  "TxPowerTracking: [CCK] Swing Current Index: %d, Swing Base Index: %d\n",
2428                  /*Print Swing base & current*/
2429                 rtldm->cck_index, rtldm->swing_idx_cck_base);
2430         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++) {
2431                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2432                          "TxPowerTracking: [OFDM] Swing Current Index: %d, Swing Base Index[%c]: %d\n",
2433                          rtldm->ofdm_index[p],
2434                          (p == RF90_PATH_A ? 'A' : 'B'),
2435                          rtldm->swing_idx_ofdm_base[p]);
2436         }
2437
2438         if ((rtldm->power_index_offset[RF90_PATH_A] != 0 ||
2439                 rtldm->power_index_offset[RF90_PATH_B] != 0) &&
2440                 rtldm->txpower_track_control) {
2441                 /*7.2 Configure the Swing Table to adjust Tx Power.*/
2442                 /*Always TRUE after Tx Power is adjusted by power tracking.*/
2443                 /*
2444                  *  2012/04/23 MH According to Luke's suggestion,
2445                  *  we can not write BB digital
2446                  *  to increase TX power. Otherwise, EVM will be bad.
2447                  *
2448                  *  2012/04/25 MH Add for tx power tracking to
2449                  *  set tx power in tx agc for 88E.
2450                  */
2451                 if (thermal_value > rtldm->thermalvalue) {
2452                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2453                                  "Temperature Increasing(A): delta_pi: %d , delta_t: %d,Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2454                                  rtldm->power_index_offset[RF90_PATH_A],
2455                                  delta, thermal_value,
2456                                  rtlefuse->eeprom_thermalmeter,
2457                                  rtldm->thermalvalue);
2458                 } else if (thermal_value < rtldm->thermalvalue) { /*Low temperature*/
2459                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2460                                  "Temperature Decreasing(A): delta_pi: %d , delta_t: %d, Now_t: %d, EFUSE_t: %d, Last_t: %d\n",
2461                                  rtldm->power_index_offset[RF90_PATH_A],
2462                                  delta, thermal_value,
2463                                  rtlefuse->eeprom_thermalmeter,
2464                                  rtldm->thermalvalue);
2465                 }
2466
2467                 if (thermal_value > rtlefuse->eeprom_thermalmeter) {
2468                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2469                                  "Temperature(%d) higher than PG value(%d)\n",
2470                                  thermal_value, rtlefuse->eeprom_thermalmeter);
2471
2472                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2473                                  "****Enter POWER Tracking MIX_MODE****\n");
2474                         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2475                                         rtl8821ae_dm_txpwr_track_set_pwr(hw,
2476                                                 MIX_MODE, p, index_for_channel);
2477                 } else {
2478                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2479                                  "Temperature(%d) lower than PG value(%d)\n",
2480                                  thermal_value, rtlefuse->eeprom_thermalmeter);
2481
2482                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2483                                  "*****Enter POWER Tracking MIX_MODE*****\n");
2484                         for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2485                                 rtl8812ae_dm_txpwr_track_set_pwr(hw,
2486                                         MIX_MODE, p, index_for_channel);
2487                 }
2488                 /*Record last time Power Tracking result as base.*/
2489                 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
2490                 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2491                         rtldm->swing_idx_ofdm_base[p] = rtldm->swing_idx_ofdm[p];
2492
2493                         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2494                                  "pDM_Odm->RFCalibrateInfo.ThermalValue = %d ThermalValue= %d\n",
2495                                  rtldm->thermalvalue, thermal_value);
2496                 /*Record last Power Tracking Thermal Value*/
2497                 rtldm->thermalvalue = thermal_value;
2498         }
2499         /* Delta temperature is equal to or larger than
2500          * 20 centigrade (When threshold is 8).
2501          */
2502         if (delta_iqk >= IQK_THRESHOLD) {
2503                 if (!rtlphy->lck_inprogress) {
2504                         spin_lock(&rtlpriv->locks.iqk_lock);
2505                         rtlphy->lck_inprogress = true;
2506                         spin_unlock(&rtlpriv->locks.iqk_lock);
2507
2508                         rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2509
2510                         spin_lock(&rtlpriv->locks.iqk_lock);
2511                         rtlphy->lck_inprogress = false;
2512                         spin_unlock(&rtlpriv->locks.iqk_lock);
2513                 }
2514         }
2515
2516         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
2517 }
2518
2519 void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2520 {
2521         struct rtl_priv *rtlpriv = rtl_priv(hw);
2522         static u8 tm_trigger;
2523
2524         if (!tm_trigger) {
2525                 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2526                               0x03);
2527                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2528                          "Trigger 8821ae Thermal Meter!!\n");
2529                 tm_trigger = 1;
2530                 return;
2531         } else {
2532                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2533                          "Schedule TxPowerTracking !!\n");
2534
2535                 rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2536                 tm_trigger = 0;
2537         }
2538 }
2539
2540 static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
2541 {
2542         struct rtl_priv *rtlpriv = rtl_priv(hw);
2543         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2544         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2545         struct rate_adaptive *p_ra = &rtlpriv->ra;
2546         u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
2547         u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
2548         u8 go_up_gap = 5;
2549         struct ieee80211_sta *sta = NULL;
2550
2551         if (is_hal_stop(rtlhal)) {
2552                 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2553                          "driver is going to unload\n");
2554                 return;
2555         }
2556
2557         if (!rtlpriv->dm.useramask) {
2558                 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2559                          "driver does not control rate adaptive mask\n");
2560                 return;
2561         }
2562
2563         if (mac->link_state == MAC80211_LINKED &&
2564                 mac->opmode == NL80211_IFTYPE_STATION) {
2565                 switch (p_ra->pre_ratr_state) {
2566                 case DM_RATR_STA_MIDDLE:
2567                         high_rssithresh_for_ra += go_up_gap;
2568                         break;
2569                 case DM_RATR_STA_LOW:
2570                         high_rssithresh_for_ra += go_up_gap;
2571                         low_rssithresh_for_ra += go_up_gap;
2572                         break;
2573                 default:
2574                         break;
2575                 }
2576
2577                 if (rtlpriv->dm.undec_sm_pwdb >
2578                     (long)high_rssithresh_for_ra)
2579                         p_ra->ratr_state = DM_RATR_STA_HIGH;
2580                 else if (rtlpriv->dm.undec_sm_pwdb >
2581                          (long)low_rssithresh_for_ra)
2582                         p_ra->ratr_state = DM_RATR_STA_MIDDLE;
2583                 else
2584                         p_ra->ratr_state = DM_RATR_STA_LOW;
2585
2586                 if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2587                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2588                                  "RSSI = %ld\n",
2589                                   rtlpriv->dm.undec_sm_pwdb);
2590                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2591                                  "RSSI_LEVEL = %d\n", p_ra->ratr_state);
2592                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2593                                  "PreState = %d, CurState = %d\n",
2594                                   p_ra->pre_ratr_state, p_ra->ratr_state);
2595
2596                         rcu_read_lock();
2597                         sta = rtl_find_sta(hw, mac->bssid);
2598                         if (sta)
2599                                 rtlpriv->cfg->ops->update_rate_tbl(hw,
2600                                                 sta, p_ra->ratr_state);
2601                         rcu_read_unlock();
2602
2603                         p_ra->pre_ratr_state = p_ra->ratr_state;
2604                 }
2605         }
2606 }
2607
2608 static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2609 {
2610         struct rtl_priv *rtlpriv = rtl_priv(hw);
2611         struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2612         struct rtl_mac *mac = &rtlpriv->mac80211;
2613         static u8 stage;
2614         u8 cur_stage = 0;
2615         u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2616
2617         if (mac->link_state < MAC80211_LINKED)
2618                 cur_stage = 0;
2619         else if (dm_digtable->rssi_val_min < 25)
2620                 cur_stage = 1;
2621         else if (dm_digtable->rssi_val_min > 30)
2622                 cur_stage = 3;
2623         else
2624                 cur_stage = 2;
2625
2626         if (cur_stage != stage) {
2627                 if (cur_stage == 1) {
2628                         basic_rate &= (!(basic_rate ^ mac->basic_rates));
2629                         rtlpriv->cfg->ops->set_hw_reg(hw,
2630                                 HW_VAR_BASIC_RATE, (u8 *)&basic_rate);
2631                 } else if (cur_stage == 3 && (stage == 1 || stage == 2)) {
2632                         rtlpriv->cfg->ops->set_hw_reg(hw,
2633                                 HW_VAR_BASIC_RATE, (u8 *)&mac->basic_rates);
2634                 }
2635         }
2636         stage = cur_stage;
2637 }
2638
2639 static void rtl8821ae_dm_edca_choose_traffic_idx(
2640         struct ieee80211_hw *hw, u64 cur_tx_bytes,
2641         u64 cur_rx_bytes, bool b_bias_on_rx,
2642         bool *pb_is_cur_rdl_state)
2643 {
2644         struct rtl_priv *rtlpriv = rtl_priv(hw);
2645
2646         if (b_bias_on_rx) {
2647                 if (cur_tx_bytes > (cur_rx_bytes*4)) {
2648                         *pb_is_cur_rdl_state = false;
2649                         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2650                                  "Uplink Traffic\n ");
2651                 } else {
2652                         *pb_is_cur_rdl_state = true;
2653                         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2654                                  "Balance Traffic\n");
2655                 }
2656         } else {
2657                 if (cur_rx_bytes > (cur_tx_bytes*4)) {
2658                         *pb_is_cur_rdl_state = true;
2659                         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2660                                  "Downlink      Traffic\n");
2661                 } else {
2662                         *pb_is_cur_rdl_state = false;
2663                         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2664                                  "Balance Traffic\n");
2665                 }
2666         }
2667         return;
2668 }
2669
2670 static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
2671 {
2672         struct rtl_priv *rtlpriv = rtl_priv(hw);
2673         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
2674         struct rtl_dm *rtldm =  rtl_dm(rtl_priv(hw));
2675
2676         /*Keep past Tx/Rx packet count for RT-to-RT EDCA turbo.*/
2677         u64 cur_tx_ok_cnt = 0;
2678         u64 cur_rx_ok_cnt = 0;
2679         u32 edca_be_ul = 0x5ea42b;
2680         u32 edca_be_dl = 0x5ea42b;
2681         u32 edca_be = 0x5ea42b;
2682         u8 iot_peer = 0;
2683         bool *pb_is_cur_rdl_state = NULL;
2684         bool b_last_is_cur_rdl_state = false;
2685         bool b_bias_on_rx = false;
2686         bool b_edca_turbo_on = false;
2687
2688         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2689                  "rtl8821ae_dm_check_edca_turbo=====>");
2690         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2691                  "Orginial BE PARAM: 0x%x\n",
2692                  rtl_read_dword(rtlpriv, DM_REG_EDCA_BE_11N));
2693
2694         if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
2695                 rtlpriv->dm.is_any_nonbepkts = true;
2696         rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
2697
2698         /*===============================
2699          * list paramter for different platform
2700          *===============================
2701          */
2702         b_last_is_cur_rdl_state = rtlpriv->dm.is_cur_rdlstate;
2703         pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
2704
2705         cur_tx_ok_cnt = rtlpriv->stats.txbytesunicast - rtldm->last_tx_ok_cnt;
2706         cur_rx_ok_cnt = rtlpriv->stats.rxbytesunicast - rtldm->last_rx_ok_cnt;
2707
2708         rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2709         rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2710
2711         iot_peer = rtlpriv->mac80211.vendor;
2712         b_bias_on_rx = false;
2713         b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
2714                            (!rtlpriv->dm.disable_framebursting)) ?
2715                            true : false;
2716
2717         if (rtlpriv->rtlhal.hw_type != HARDWARE_TYPE_RTL8812AE) {
2718                 if ((iot_peer == PEER_CISCO) &&
2719                         (mac->mode == WIRELESS_MODE_N_24G)) {
2720                         edca_be_dl = edca_setting_dl[iot_peer];
2721                         edca_be_ul = edca_setting_ul[iot_peer];
2722                 }
2723         }
2724
2725         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2726                  "bIsAnyNonBEPkts : 0x%x  bDisableFrameBursting : 0x%x\n",
2727                  rtlpriv->dm.is_any_nonbepkts,
2728                  rtlpriv->dm.disable_framebursting);
2729
2730         RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2731                  "bEdcaTurboOn : 0x%x bBiasOnRx : 0x%x\n",
2732                  b_edca_turbo_on, b_bias_on_rx);
2733
2734         if (b_edca_turbo_on) {
2735                 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2736                          "curTxOkCnt : 0x%llx\n", cur_tx_ok_cnt);
2737                 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2738                          "curRxOkCnt : 0x%llx\n", cur_rx_ok_cnt);
2739                 if (b_bias_on_rx)
2740                         rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2741                                 cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2742                 else
2743                         rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2744                                 cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2745
2746                 edca_be = (*pb_is_cur_rdl_state) ?  edca_be_dl : edca_be_ul;
2747
2748                 rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2749
2750                 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2751                          "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2752
2753                 rtlpriv->dm.current_turbo_edca = true;
2754
2755                 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2756                          "EDCA_BE_DL : 0x%x  EDCA_BE_UL : 0x%x  EDCA_BE : 0x%x\n",
2757                          edca_be_dl, edca_be_ul, edca_be);
2758         } else {
2759                 if (rtlpriv->dm.current_turbo_edca) {
2760                         u8 tmp = AC0_BE;
2761                         rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2762                                                       (u8 *)(&tmp));
2763                 }
2764                 rtlpriv->dm.current_turbo_edca = false;
2765         }
2766
2767         rtlpriv->dm.is_any_nonbepkts = false;
2768         rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2769         rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
2770 }
2771
2772 static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2773 {
2774         struct rtl_priv *rtlpriv = rtl_priv(hw);
2775         struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2776         u8 cur_cck_cca_thresh;
2777
2778         if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
2779                 if (dm_digtable->rssi_val_min > 25) {
2780                         cur_cck_cca_thresh = 0xcd;
2781                 } else if ((dm_digtable->rssi_val_min <= 25) &&
2782                            (dm_digtable->rssi_val_min > 10)) {
2783                         cur_cck_cca_thresh = 0x83;
2784                 } else {
2785                         if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2786                                 cur_cck_cca_thresh = 0x83;
2787                         else
2788                                 cur_cck_cca_thresh = 0x40;
2789                 }
2790         } else {
2791                 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2792                         cur_cck_cca_thresh = 0x83;
2793                 else
2794                         cur_cck_cca_thresh = 0x40;
2795         }
2796
2797         if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
2798                 rtl_write_byte(rtlpriv, ODM_REG_CCK_CCA_11AC,
2799                                cur_cck_cca_thresh);
2800
2801         dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
2802         dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
2803         RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
2804                  "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
2805 }
2806
2807 static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2808 {
2809         struct rtl_priv *rtlpriv = rtl_priv(hw);
2810         struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2811         u8 crystal_cap;
2812         u32 packet_count;
2813         int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2814         int cfo_ave_diff;
2815
2816         if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
2817                 /*1.Enable ATC*/
2818                 if (rtldm->atc_status == ATC_STATUS_OFF) {
2819                         rtl_set_bbreg(hw, RFC_AREA, BIT(14), ATC_STATUS_ON);
2820                         rtldm->atc_status = ATC_STATUS_ON;
2821                 }
2822
2823                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "No link!!\n");
2824                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2825                          "atc_status = %d\n", rtldm->atc_status);
2826
2827                 if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
2828                         rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
2829                         crystal_cap = rtldm->crystal_cap & 0x3f;
2830                         crystal_cap = crystal_cap & 0x3f;
2831                         if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2832                                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2833                                               0x7ff80000, (crystal_cap |
2834                                               (crystal_cap << 6)));
2835                         else
2836                                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2837                                               0xfff000, (crystal_cap |
2838                                               (crystal_cap << 6)));
2839                 }
2840                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2841                          rtldm->crystal_cap);
2842         } else{
2843                 /*1. Calculate CFO for path-A & path-B*/
2844                 cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
2845                 cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
2846                 packet_count = rtldm->packet_count;
2847
2848                 /*2.No new packet*/
2849                 if (packet_count == rtldm->packet_count_pre) {
2850                         RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2851                                  "packet counter doesn't change\n");
2852                         return;
2853                 }
2854
2855                 rtldm->packet_count_pre = packet_count;
2856                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2857                          "packet counter = %d\n",
2858                          rtldm->packet_count);
2859
2860                 /*3.Average CFO*/
2861                 if (rtlpriv->phy.rf_type == RF_1T1R)
2862                         cfo_ave = cfo_khz_a;
2863                 else
2864                         cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
2865
2866                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2867                          "cfo_khz_a = %dkHz, cfo_khz_b = %dkHz, cfo_ave = %dkHz\n",
2868                          cfo_khz_a, cfo_khz_b, cfo_ave);
2869
2870                 /*4.Avoid abnormal large CFO*/
2871                 cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
2872                                                 (rtldm->cfo_ave_pre - cfo_ave) :
2873                                                 (cfo_ave - rtldm->cfo_ave_pre);
2874
2875                 if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
2876                         RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2877                                  "first large CFO hit\n");
2878                         rtldm->large_cfo_hit = 1;
2879                         return;
2880                 } else
2881                         rtldm->large_cfo_hit = 0;
2882
2883                 rtldm->cfo_ave_pre = cfo_ave;
2884
2885                 /*CFO tracking by adjusting Xtal cap.*/
2886
2887                 /*1.Dynamic Xtal threshold*/
2888                 if (cfo_ave >= -rtldm->cfo_threshold &&
2889                         cfo_ave <= rtldm->cfo_threshold &&
2890                         rtldm->is_freeze == 0) {
2891                         if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
2892                                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
2893                                 rtldm->is_freeze = 1;
2894                         } else {
2895                                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2896                         }
2897                 }
2898                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2899                          "Dynamic threshold = %d\n",
2900                          rtldm->cfo_threshold);
2901
2902                 /* 2.Calculate Xtal offset*/
2903                 if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
2904                         adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
2905                 else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
2906                          rtlpriv->dm.crystal_cap > 0)
2907                         adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
2908                 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2909                          "Crystal cap = 0x%x, Crystal cap offset = %d\n",
2910                          rtldm->crystal_cap, adjust_xtal);
2911
2912                 /*3.Adjudt Crystal Cap.*/
2913                 if (adjust_xtal != 0) {
2914                         rtldm->is_freeze = 0;
2915                         rtldm->crystal_cap += adjust_xtal;
2916
2917                         if (rtldm->crystal_cap > 0x3f)
2918                                 rtldm->crystal_cap = 0x3f;
2919                         else if (rtldm->crystal_cap < 0)
2920                                 rtldm->crystal_cap = 0;
2921
2922                         crystal_cap = rtldm->crystal_cap & 0x3f;
2923                         crystal_cap = crystal_cap & 0x3f;
2924                         if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8812AE)
2925                                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2926                                               0x7ff80000, (crystal_cap |
2927                                               (crystal_cap << 6)));
2928                         else
2929                                 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2930                                               0xfff000, (crystal_cap |
2931                                               (crystal_cap << 6)));
2932                         RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2933                                  "New crystal cap = 0x%x\n",
2934                                  rtldm->crystal_cap);
2935                 }
2936         }
2937 }
2938
2939 void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
2940 {
2941         struct rtl_priv *rtlpriv = rtl_priv(hw);
2942         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
2943         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2944         bool fw_current_inpsmode = false;
2945         bool fw_ps_awake = true;
2946
2947         rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2948                                       (u8 *)(&fw_current_inpsmode));
2949
2950         rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2951                                       (u8 *)(&fw_ps_awake));
2952
2953         if (ppsc->p2p_ps_info.p2p_ps_mode)
2954                 fw_ps_awake = false;
2955
2956         if ((ppsc->rfpwr_state == ERFON) &&
2957             ((!fw_current_inpsmode) && fw_ps_awake) &&
2958             (!ppsc->rfchange_inprogress)) {
2959                 rtl8821ae_dm_common_info_self_update(hw);
2960                 rtl8821ae_dm_false_alarm_counter_statistics(hw);
2961                 rtl8821ae_dm_check_rssi_monitor(hw);
2962                 rtl8821ae_dm_dig(hw);
2963                 rtl8821ae_dm_cck_packet_detection_thresh(hw);
2964                 rtl8821ae_dm_refresh_rate_adaptive_mask(hw);
2965                 rtl8821ae_dm_refresh_basic_rate_mask(hw);
2966                 rtl8821ae_dm_check_edca_turbo(hw);
2967                 rtl8821ae_dm_dynamic_atc_switch(hw);
2968                 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
2969                         rtl8812ae_dm_check_txpower_tracking_thermalmeter(hw);
2970                 else
2971                         rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2972                 rtl8821ae_dm_iq_calibrate(hw);
2973         }
2974
2975         rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
2976         RT_TRACE(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
2977 }
2978
2979 void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
2980                                         u8 *pdesc, u32 mac_id)
2981 {
2982         struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
2983         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
2984         struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2985         struct fast_ant_training *pfat_table = &rtldm->fat_table;
2986
2987         if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
2988                 return;
2989
2990         if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
2991                 SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]);
2992 }