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