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