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