1 /******************************************************************************
3 * Copyright(c) 2009-2010 Realtek Corporation.
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.
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
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
35 #include "../btcoexist/rtl_btc.h"
37 static 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 */
77 static 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 */
117 static 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 */
163 static 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 */
199 static 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 */
235 static 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 */
242 0x5ea630, /* 6 CISCO */
243 0x5ea42b, /* 7 MARVELL */
246 static 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 */
257 static 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};
261 static 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};
265 static 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};
269 static 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};
273 static 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};
277 static 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};
281 static 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};
285 static 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};
289 static 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};
293 static 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};
297 static 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},
306 static 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},
315 static 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},
324 static 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},
333 static 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};
337 static 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};
341 static 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};
345 static 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};
349 static 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};
353 static 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};
357 static 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};
361 static 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};
365 static 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},
374 static 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},
383 static 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},
392 static 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},
401 void rtl8821ae_dm_txpower_track_adjust(struct ieee80211_hw *hw,
402 u8 type, u8 *pdirection,
405 struct rtl_priv *rtlpriv = rtl_priv(hw);
406 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
410 if (rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A] <=
411 rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A]) {
413 pwr_val = rtldm->swing_idx_ofdm_base[RF90_PATH_A] -
414 rtldm->swing_idx_ofdm[RF90_PATH_A];
417 pwr_val = rtldm->swing_idx_ofdm[RF90_PATH_A] -
418 rtldm->swing_idx_ofdm_base[RF90_PATH_A];
420 } else if (type == 1) {
421 if (rtldm->swing_idx_cck <= rtldm->swing_idx_cck_base) {
423 pwr_val = rtldm->swing_idx_cck_base -
424 rtldm->swing_idx_cck;
427 pwr_val = rtldm->swing_idx_cck -
428 rtldm->swing_idx_cck_base;
432 if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
433 pwr_val = TXPWRTRACK_MAX_IDX;
435 *poutwrite_val = pwr_val | (pwr_val << 8)|
440 void rtl8821ae_dm_clear_txpower_tracking_state(struct ieee80211_hw *hw)
442 struct rtl_priv *rtlpriv = rtl_priv(hw);
443 struct rtl_dm *rtldm = rtl_dm(rtlpriv);
444 struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
447 rtldm->swing_idx_cck_base = rtldm->default_cck_index;
448 rtldm->swing_idx_cck = rtldm->default_cck_index;
449 rtldm->cck_index = 0;
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;
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;
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;
473 static u8 rtl8821ae_dm_get_swing_index(struct ieee80211_hw *hw)
475 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
479 bb_swing = phy_get_tx_swing_8812A(hw, rtlhal->current_bandtype,
482 for (i = 0; i < TXSCALE_TABLE_SIZE; ++i)
483 if (bb_swing == rtl8821ae_txscaling_table[i])
489 void rtl8821ae_dm_initialize_txpower_tracking_thermalmeter(
490 struct ieee80211_hw *hw)
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;
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);
504 rtldm->default_ofdm_index =
505 (default_swing_index == TXSCALE_TABLE_SIZE) ?
506 24 : default_swing_index;
507 rtldm->default_cck_index = 24;
509 rtldm->swing_idx_cck_base = rtldm->default_cck_index;
510 rtldm->cck_index = rtldm->default_cck_index;
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;
522 static void rtl8821ae_dm_diginit(struct ieee80211_hw *hw)
524 struct rtl_priv *rtlpriv = rtl_priv(hw);
525 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
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;
550 void rtl8821ae_dm_init_edca_turbo(struct ieee80211_hw *hw)
552 struct rtl_priv *rtlpriv = rtl_priv(hw);
554 rtlpriv->dm.current_turbo_edca = false;
555 rtlpriv->dm.is_any_nonbepkts = false;
556 rtlpriv->dm.is_cur_rdlstate = false;
559 void rtl8821ae_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
561 struct rtl_priv *rtlpriv = rtl_priv(hw);
562 struct rate_adaptive *p_ra = &rtlpriv->ra;
564 p_ra->ratr_state = DM_RATR_STA_INIT;
565 p_ra->pre_ratr_state = DM_RATR_STA_INIT;
567 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
568 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
569 rtlpriv->dm.useramask = true;
571 rtlpriv->dm.useramask = false;
573 p_ra->high_rssi_thresh_for_ra = 50;
574 p_ra->low_rssi_thresh_for_ra40m = 20;
577 static void rtl8821ae_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
579 struct rtl_priv *rtlpriv = rtl_priv(hw);
581 rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
583 rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
584 rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
587 static void rtl8821ae_dm_common_info_self_init(struct ieee80211_hw *hw)
589 struct rtl_priv *rtlpriv = rtl_priv(hw);
590 struct rtl_phy *rtlphy = &rtlpriv->phy;
593 rtlphy->cck_high_power =
594 (bool)rtl_get_bbreg(hw, ODM_REG_CCK_RPT_FORMAT_11AC,
595 ODM_BIT_CCK_RPT_FORMAT_11AC);
597 tmp = (u8)rtl_get_bbreg(hw, ODM_REG_BB_RX_PATH_11AC,
598 ODM_BIT_BB_RX_PATH_11AC);
600 rtlpriv->dm.rfpath_rxenable[0] = true;
602 rtlpriv->dm.rfpath_rxenable[1] = true;
605 void rtl8821ae_dm_init(struct ieee80211_hw *hw)
607 struct rtl_priv *rtlpriv = rtl_priv(hw);
608 struct rtl_phy *rtlphy = &rtlpriv->phy;
610 spin_lock(&rtlpriv->locks.iqk_lock);
611 rtlphy->lck_inprogress = false;
612 spin_unlock(&rtlpriv->locks.iqk_lock);
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);
623 static void rtl8821ae_dm_find_minimum_rssi(struct ieee80211_hw *hw)
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);
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");
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);
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);
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);
658 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
659 "MinUndecoratedPWDBForDM =%d\n",
660 rtl_dm_dig->min_undec_pwdb_for_dm);
663 static void rtl8812ae_dm_rssi_dump_to_register(struct ieee80211_hw *hw)
665 struct rtl_priv *rtlpriv = rtl_priv(hw);
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]);
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]);
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]));
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]);
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]);
697 static void rtl8821ae_dm_check_rssi_monitor(struct ieee80211_hw *hw)
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;
707 u64 cur_txokcnt = 0, cur_rxokcnt = 0;
708 static u64 last_txokcnt = 0, last_rxokcnt;
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;
717 h2c_parameter[3] = 0x00;
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 <
728 drv_priv->rssi_stat.undec_sm_pwdb;
729 if (drv_priv->rssi_stat.undec_sm_pwdb >
732 drv_priv->rssi_stat.undec_sm_pwdb;
734 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
736 /* If associated entry is found */
737 if (tmp_entry_max_pwdb != 0) {
738 rtlpriv->dm.entry_max_undec_sm_pwdb =
740 RTPRINT(rtlpriv, FDM, DM_PWDB,
741 "EntryMaxPWDB = 0x%lx(%ld)\n",
742 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
744 rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
746 /* If associated entry is found */
747 if (tmp_entry_min_pwdb != 0xff) {
748 rtlpriv->dm.entry_min_undec_sm_pwdb =
750 RTPRINT(rtlpriv, FDM, DM_PWDB,
751 "EntryMinPWDB = 0x%lx(%ld)\n",
752 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
754 rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
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;
766 stbc_tx = (mac->ht_cur_stbc &
767 STBC_HT_ENABLE_TX) ? 1 : 0;
768 h2c_parameter[3] |= stbc_tx << 1;
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,
778 rtl8821ae_fill_h2c_cmd(hw, H2C_RSSI_21AE_REPORT, 3,
781 rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
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;
789 void rtl8821ae_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 current_cca)
791 struct rtl_priv *rtlpriv = rtl_priv(hw);
792 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
794 if (dm_digtable->cur_cck_cca_thres != current_cca)
795 rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11AC, current_cca);
797 dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
798 dm_digtable->cur_cck_cca_thres = current_cca;
801 void rtl8821ae_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
803 struct rtl_priv *rtlpriv = rtl_priv(hw);
804 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
806 if (dm_digtable->stop_dig)
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);
816 dm_digtable->cur_igvalue = current_igi;
819 static void rtl8821ae_dm_dig(struct ieee80211_hw *hw)
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));
827 bool first_connect, first_disconnect;
828 u8 dm_dig_max, dm_dig_min, offset;
829 u8 current_igi = dm_digtable->cur_igvalue;
831 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "\n");
833 if (mac->act_scanning) {
834 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
835 "Return: In Scan Progress\n");
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);
846 /*1 Boundary Decision*/
850 if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
851 dm_dig_min = DM_DIG_MIN;
855 dig_max_of_min = DM_DIG_MAX_AP;
857 if (mac->link_state >= MAC80211_LINKED) {
858 if (rtlhal->hw_type != HARDWARE_TYPE_RTL8821AE)
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;
868 dm_digtable->rx_gain_max =
869 dm_digtable->rssi_val_min + offset;
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) {
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;
885 dm_digtable->rssi_val_min - offset;
887 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
888 "bOneEntryOnly=TRUE, dig_dynamic_min=0x%x\n",
891 dig_dynamic_min = dm_dig_min;
894 dm_digtable->rx_gain_max = dm_dig_max;
895 dig_dynamic_min = dm_dig_min;
896 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
900 if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
901 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
902 "Abnormally false alarm case.\n");
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;
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;
917 dm_digtable->rx_gain_min =
918 (dm_digtable->forbidden_igi + 1);
919 dm_digtable->recover_cnt = 3600;
922 /*Recovery mechanism for IGI lower bound*/
923 if (dm_digtable->recover_cnt != 0) {
924 dm_digtable->recover_cnt--;
926 if (dm_digtable->large_fa_hit < 3) {
927 if ((dm_digtable->forbidden_igi - 1) <
929 dm_digtable->forbidden_igi =
931 dm_digtable->rx_gain_min =
933 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
934 "Normal Case: At Lower Bound\n");
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");
943 dm_digtable->large_fa_hit = 0;
947 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
948 "pDM_DigTable->LargeFAHit=%d\n",
949 dm_digtable->large_fa_hit);
951 if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 10)
952 dm_digtable->rx_gain_min = dm_dig_min;
954 if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
955 dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
957 /*Adjust initial gain by false alarm*/
958 if (mac->link_state >= MAC80211_LINKED) {
959 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
962 if (dm_digtable->rssi_val_min <= dig_max_of_min)
963 current_igi = dm_digtable->rssi_val_min;
965 current_igi = dig_max_of_min;
966 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
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;
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");
984 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
986 if (first_disconnect) {
987 current_igi = dm_digtable->rx_gain_min;
988 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
989 "First DisConnect\n");
991 /* 2012.03.30 LukeLee: enable DIG before
992 * link but with very high thresholds
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;
1001 if (current_igi >= 0x3e)
1004 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "England DIG\n");
1007 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
1008 "DIG End Adjust IGI\n");
1009 /* Check initial gain by upper/lower bound*/
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;
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);
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;
1030 static void rtl8821ae_dm_common_info_self_update(struct ieee80211_hw *hw)
1032 struct rtl_priv *rtlpriv = rtl_priv(hw);
1034 struct rtl_sta_info *drv_priv;
1036 rtlpriv->dm.tx_rate = 0xff;
1038 rtlpriv->dm.one_entry_only = false;
1040 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1041 rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1042 rtlpriv->dm.one_entry_only = true;
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)
1052 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1055 rtlpriv->dm.one_entry_only = true;
1059 static void rtl8821ae_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
1061 struct rtl_priv *rtlpriv = rtl_priv(hw);
1062 struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
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);
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;
1076 falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail;
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);
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);
1093 static void rtl8812ae_dm_check_txpower_tracking_thermalmeter(
1094 struct ieee80211_hw *hw)
1096 struct rtl_priv *rtlpriv = rtl_priv(hw);
1097 static u8 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");
1107 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1108 "Schedule TxPowerTracking direct call!!\n");
1109 rtl8812ae_dm_txpower_tracking_callback_thermalmeter(hw);
1113 static void rtl8821ae_dm_iq_calibrate(struct ieee80211_hw *hw)
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));
1119 if (mac->link_state >= MAC80211_LINKED) {
1120 if (rtldm->linked_interval < 3)
1121 rtldm->linked_interval++;
1123 if (rtldm->linked_interval == 2) {
1124 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE)
1125 rtl8812ae_phy_iq_calibrate(hw, false);
1127 rtl8821ae_phy_iq_calibrate(hw, false);
1130 rtldm->linked_interval = 0;
1134 static void rtl8812ae_get_delta_swing_table(struct ieee80211_hw *hw,
1135 u8 **up_a, u8 **down_a,
1136 u8 **up_b, u8 **down_b)
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;
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;
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;
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];
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;
1179 void rtl8821ae_dm_update_init_rate(struct ieee80211_hw *hw, u8 rate)
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));
1186 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1187 "Get C2H Command! Rate=0x%x\n", rate);
1189 rtldm->tx_rate = rate;
1191 if (rtlhal->hw_type == HARDWARE_TYPE_RTL8821AE) {
1192 rtl8821ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, RF90_PATH_A, 0);
1194 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1195 rtl8812ae_dm_txpwr_track_set_pwr(hw, MIX_MODE, p, 0);
1199 u8 rtl8821ae_hw_rate_to_mrate(struct ieee80211_hw *hw, u8 rate)
1201 struct rtl_priv *rtlpriv = rtl_priv(hw);
1202 u8 ret_rate = MGN_1M;
1212 ret_rate = MGN_5_5M;
1242 ret_rate = MGN_MCS0;
1245 ret_rate = MGN_MCS1;
1248 ret_rate = MGN_MCS2;
1251 ret_rate = MGN_MCS3;
1254 ret_rate = MGN_MCS4;
1257 ret_rate = MGN_MCS5;
1260 ret_rate = MGN_MCS6;
1263 ret_rate = MGN_MCS7;
1266 ret_rate = MGN_MCS8;
1269 ret_rate = MGN_MCS9;
1271 case DESC_RATEMCS10:
1272 ret_rate = MGN_MCS10;
1274 case DESC_RATEMCS11:
1275 ret_rate = MGN_MCS11;
1277 case DESC_RATEMCS12:
1278 ret_rate = MGN_MCS12;
1280 case DESC_RATEMCS13:
1281 ret_rate = MGN_MCS13;
1283 case DESC_RATEMCS14:
1284 ret_rate = MGN_MCS14;
1286 case DESC_RATEMCS15:
1287 ret_rate = MGN_MCS15;
1289 case DESC_RATEVHT1SS_MCS0:
1290 ret_rate = MGN_VHT1SS_MCS0;
1292 case DESC_RATEVHT1SS_MCS1:
1293 ret_rate = MGN_VHT1SS_MCS1;
1295 case DESC_RATEVHT1SS_MCS2:
1296 ret_rate = MGN_VHT1SS_MCS2;
1298 case DESC_RATEVHT1SS_MCS3:
1299 ret_rate = MGN_VHT1SS_MCS3;
1301 case DESC_RATEVHT1SS_MCS4:
1302 ret_rate = MGN_VHT1SS_MCS4;
1304 case DESC_RATEVHT1SS_MCS5:
1305 ret_rate = MGN_VHT1SS_MCS5;
1307 case DESC_RATEVHT1SS_MCS6:
1308 ret_rate = MGN_VHT1SS_MCS6;
1310 case DESC_RATEVHT1SS_MCS7:
1311 ret_rate = MGN_VHT1SS_MCS7;
1313 case DESC_RATEVHT1SS_MCS8:
1314 ret_rate = MGN_VHT1SS_MCS8;
1316 case DESC_RATEVHT1SS_MCS9:
1317 ret_rate = MGN_VHT1SS_MCS9;
1319 case DESC_RATEVHT2SS_MCS0:
1320 ret_rate = MGN_VHT2SS_MCS0;
1322 case DESC_RATEVHT2SS_MCS1:
1323 ret_rate = MGN_VHT2SS_MCS1;
1325 case DESC_RATEVHT2SS_MCS2:
1326 ret_rate = MGN_VHT2SS_MCS2;
1328 case DESC_RATEVHT2SS_MCS3:
1329 ret_rate = MGN_VHT2SS_MCS3;
1331 case DESC_RATEVHT2SS_MCS4:
1332 ret_rate = MGN_VHT2SS_MCS4;
1334 case DESC_RATEVHT2SS_MCS5:
1335 ret_rate = MGN_VHT2SS_MCS5;
1337 case DESC_RATEVHT2SS_MCS6:
1338 ret_rate = MGN_VHT2SS_MCS6;
1340 case DESC_RATEVHT2SS_MCS7:
1341 ret_rate = MGN_VHT2SS_MCS7;
1343 case DESC_RATEVHT2SS_MCS8:
1344 ret_rate = MGN_VHT2SS_MCS8;
1346 case DESC_RATEVHT2SS_MCS9:
1347 ret_rate = MGN_VHT2SS_MCS9;
1350 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1351 "HwRateToMRate8812(): Non supported Rate [%x]!!!\n",
1358 /*-----------------------------------------------------------------------------
1359 * Function: odm_TxPwrTrackSetPwr88E()
1361 * Overview: 88E change all channel tx power accordign to flag.
1362 * OFDM & CCK are all different.
1372 * 04/23/2012 MHC Create Version 0.
1374 *---------------------------------------------------------------------------
1376 void 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)
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*/
1386 char final_ofdm_swing_index = 0;
1388 if (rtldm->tx_rate != 0xFF)
1390 rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
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) {
1397 if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
1398 pwr_tracking_limit = 32; /*+4dB*/
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*/
1406 else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
1407 pwr_tracking_limit = 34; /*+5dB*/
1409 else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
1410 pwr_tracking_limit = 30; /*+3dB*/
1412 else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
1413 pwr_tracking_limit = 28; /*+2dB*/
1415 else if ((tx_rate >= MGN_MCS8) && (tx_rate <= MGN_MCS10))
1416 pwr_tracking_limit = 34; /*+5dB*/
1418 else if ((tx_rate >= MGN_MCS11) && (tx_rate <= MGN_MCS12))
1419 pwr_tracking_limit = 30; /*+3dB*/
1421 else if ((tx_rate >= MGN_MCS13) && (tx_rate <= MGN_MCS15))
1422 pwr_tracking_limit = 28; /*+2dB*/
1426 else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
1427 (tx_rate <= MGN_VHT1SS_MCS2))
1428 pwr_tracking_limit = 34; /*+5dB*/
1430 else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
1431 (tx_rate <= MGN_VHT1SS_MCS4))
1432 pwr_tracking_limit = 30; /*+3dB*/
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*/
1444 else if ((tx_rate >= MGN_VHT2SS_MCS0) &&
1445 (tx_rate <= MGN_VHT2SS_MCS2))
1446 pwr_tracking_limit = 34; /*+5dB*/
1448 else if ((tx_rate >= MGN_VHT2SS_MCS3) &&
1449 (tx_rate <= MGN_VHT2SS_MCS4))
1450 pwr_tracking_limit = 30; /*+3dB*/
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*/
1462 pwr_tracking_limit = 24;
1464 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1465 "TxRate=0x%x, PwrTrackingLimit=%d\n",
1466 tx_rate, pwr_tracking_limit);
1468 if (method == BBSWING) {
1469 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1470 "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
1472 if (rf_path == RF90_PATH_A) {
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]);
1486 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1487 txscaling_tbl[tmp]);
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]);
1502 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1503 txscaling_tbl[tmp]);
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],
1512 final_ofdm_swing_index = rtldm->default_ofdm_index +
1513 rtldm->absolute_ofdm_swing_idx[rf_path];
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 -
1521 /* CCK Follow the same compensation value
1524 rtldm->remnant_ofdm_swing_idx[rf_path] =
1525 final_ofdm_swing_index -
1528 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1529 txscaling_tbl[pwr_tracking_limit]);
1531 rtldm->modify_txagc_flag_path_a = true;
1533 /*Set TxAGC Page C{};*/
1534 rtl8821ae_phy_set_txpower_level_by_path(hw,
1535 rtlphy->current_channel,
1538 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1539 "******Path_A Over BBSwing Limit ,PwrTrackingLimit = %d ,Remnant TxAGC Value = %d\n",
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;
1548 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1551 rtldm->modify_txagc_flag_path_a = true;
1553 /*Set TxAGC Page C{};*/
1554 rtl8821ae_phy_set_txpower_level_by_path(hw,
1555 rtlphy->current_channel, RF90_PATH_A);
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]);
1561 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
1562 txscaling_tbl[(u8)final_ofdm_swing_index]);
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;
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;
1577 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
1579 "******Path_A pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
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 -
1590 rtl_set_bbreg(hw, RB_TXSCALE,
1592 txscaling_tbl[pwr_tracking_limit]);
1594 rtldm->modify_txagc_flag_path_b = true;
1596 /*Set TxAGC Page E{};*/
1597 rtl8821ae_phy_set_txpower_level_by_path(hw,
1598 rtlphy->current_channel, RF90_PATH_B);
1600 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1601 "******Path_B Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
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;
1608 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1611 rtldm->modify_txagc_flag_path_b = true;
1613 /*Set TxAGC Page E{};*/
1614 rtl8821ae_phy_set_txpower_level_by_path(hw,
1615 rtlphy->current_channel, RF90_PATH_B);
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]);
1621 rtl_set_bbreg(hw, RB_TXSCALE, 0xFFE00000,
1622 txscaling_tbl[(u8)final_ofdm_swing_index]);
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;
1631 /*Set TxAGC Page E{};*/
1632 rtl8821ae_phy_set_txpower_level_by_path(hw,
1633 rtlphy->current_channel, RF90_PATH_B);
1635 rtldm->modify_txagc_flag_path_b =
1638 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1639 "******Path_B pDM_Odm->Modify_TxAGC_Flag = FALSE\n");
1648 void rtl8812ae_dm_txpower_tracking_callback_thermalmeter(
1649 struct ieee80211_hw *hw)
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.
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;
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);
1677 rtldm->txpower_trackinginit = true;
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);
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)
1696 /* 3. Initialize ThermalValues of RFCalibrateInfo*/
1698 if (rtlhal->reloadtxpowerindex)
1699 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1700 "reload ofdm index for band switch\n");
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;
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++;
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);
1724 /*5. Calculate delta, delta_LCK, delta_IQK.
1725 *"delta" here is used to determine whether
1726 *thermal value changes or not.
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);
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);
1742 /* 6. If necessary, do LCK.
1743 * Delta temperature is equal to or larger than 20 centigrade.
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);
1753 /*7. If necessary, move the index of swing table to adjust Tx power.*/
1755 if (delta > 0 && rtldm->txpower_track_control) {
1756 /* "delta" here is used to record the
1757 * absolute value of differrence.
1759 delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
1760 (thermal_value - rtlefuse->eeprom_thermalmeter) :
1761 (rtlefuse->eeprom_thermalmeter - thermal_value);
1763 if (delta >= TXPWR_TRACK_TABLE_SIZE)
1764 delta = TXPWR_TRACK_TABLE_SIZE - 1;
1766 /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
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];
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*/
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]);
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];
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*/
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]);
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]);
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];
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]);
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]);
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];
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*/
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]);
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'));
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;
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
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]);
1859 rtldm->ofdm_index[p] =
1860 rtldm->swing_idx_ofdm_base[p] +
1861 rtldm->power_index_offset[p];
1863 rtldm->swing_idx_cck_base +
1864 rtldm->power_index_offset[p];
1866 rtldm->swing_idx_cck = rtldm->cck_index;
1867 rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
1869 /****Print BB Swing Base and Index Offset */
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]);
1883 /*7.1 Handle boundary conditions of index.*/
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;
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;
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,
1901 rtldm->thermalvalue);
1903 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8812A; p++)
1904 rtldm->power_index_offset[p] = 0;
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]);
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.
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.
1928 *2012/04/25 MH Add for tx power tracking to set
1929 *tx power in tx agc for 88E.
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);
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);
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);
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);
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,
1972 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1973 "Temperature(%d) lower than PG value(%d)\n",
1974 thermal_value, rtlefuse->eeprom_thermalmeter);
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);
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];
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;
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);
1999 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2000 "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n");
2003 static void rtl8821ae_get_delta_swing_table(struct ieee80211_hw *hw, u8 **up_a,
2004 u8 **down_a, u8 **up_b, u8 **down_b)
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;
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;
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;
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];
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;
2048 /*-----------------------------------------------------------------------------
2049 * Function: odm_TxPwrTrackSetPwr88E()
2051 * Overview: 88E change all channel tx power accordign to flag.
2052 * OFDM & CCK are all different.
2062 * 04/23/2012 MHC Create Version 0.
2064 *---------------------------------------------------------------------------
2066 void 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)
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*/
2076 char final_ofdm_swing_index = 0;
2078 if (rtldm->tx_rate != 0xFF)
2079 tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
2081 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2082 "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
2084 if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
2086 if ((tx_rate >= MGN_1M) && (tx_rate <= MGN_11M))
2087 pwr_tracking_limit = 32; /*+4dB*/
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*/
2095 else if ((tx_rate >= MGN_MCS0) && (tx_rate <= MGN_MCS2))
2096 pwr_tracking_limit = 34; /*+5dB*/
2098 else if ((tx_rate >= MGN_MCS3) && (tx_rate <= MGN_MCS4))
2099 pwr_tracking_limit = 30; /*+3dB*/
2101 else if ((tx_rate >= MGN_MCS5) && (tx_rate <= MGN_MCS7))
2102 pwr_tracking_limit = 28; /*+2dB*/
2105 else if ((tx_rate >= MGN_VHT1SS_MCS0) &&
2106 (tx_rate <= MGN_VHT1SS_MCS2))
2107 pwr_tracking_limit = 34; /*+5dB*/
2109 else if ((tx_rate >= MGN_VHT1SS_MCS3) &&
2110 (tx_rate <= MGN_VHT1SS_MCS4))
2111 pwr_tracking_limit = 30; /*+3dB*/
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*/
2123 pwr_tracking_limit = 24;
2125 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2126 "TxRate=0x%x, PwrTrackingLimit=%d\n",
2127 tx_rate, pwr_tracking_limit);
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]);
2143 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2144 txscaling_tbl[final_swing_idx[RF90_PATH_A]]);
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],
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 -
2162 /* CCK Follow the same compensate value as Path A*/
2163 rtldm->remnant_ofdm_swing_idx[rf_path] =
2164 final_ofdm_swing_index -
2167 rtl_set_bbreg(hw, RA_TXSCALE,
2169 txscaling_tbl[pwr_tracking_limit]);
2171 rtldm->modify_txagc_flag_path_a = true;
2173 /*Set TxAGC Page C{};*/
2174 rtl8821ae_phy_set_txpower_level_by_path(hw,
2175 rtlphy->current_channel,
2178 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2179 " ******Path_A Over BBSwing Limit , PwrTrackingLimit = %d , Remnant TxAGC Value = %d\n",
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;
2188 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2191 rtldm->modify_txagc_flag_path_a = true;
2193 /*Set TxAGC Page C{};*/
2194 rtl8821ae_phy_set_txpower_level_by_path(hw,
2195 rtlphy->current_channel, RF90_PATH_A);
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]);
2201 rtl_set_bbreg(hw, RA_TXSCALE, 0xFFE00000,
2202 txscaling_tbl[(u8)final_ofdm_swing_index]);
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;
2212 /*Set TxAGC Page C{};*/
2213 rtl8821ae_phy_set_txpower_level_by_path(hw,
2214 rtlphy->current_channel, RF90_PATH_A);
2216 rtldm->modify_txagc_flag_path_a = false;
2218 RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
2220 "******Path_A pDM_Odm->Modify_TxAGC_Flag= FALSE\n");
2229 void rtl8821ae_dm_txpower_tracking_callback_thermalmeter(
2230 struct ieee80211_hw *hw)
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;
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;
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;
2246 /* 1. The following TWO tables decide the final
2247 * index of OFDM/CCK swing table.
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;
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);
2260 rtldm->txpower_trackinginit = true;
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)
2275 /* 3. Initialize ThermalValues of RFCalibrateInfo*/
2277 if (rtlhal->reloadtxpowerindex) {
2278 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2279 "reload ofdm index for band switch\n");
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;
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++;
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);
2304 /*5. Calculate delta, delta_LCK, delta_IQK.
2305 *"delta" here is used to determine whether
2306 * thermal value changes or not.
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);
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);
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);
2332 /*7. If necessary, move the index of swing table to adjust Tx power.*/
2334 if (delta > 0 && rtldm->txpower_track_control) {
2335 /*"delta" here is used to record the
2336 * absolute value of differrence.
2338 delta = thermal_value > rtlefuse->eeprom_thermalmeter ?
2339 (thermal_value - rtlefuse->eeprom_thermalmeter) :
2340 (rtlefuse->eeprom_thermalmeter - thermal_value);
2342 if (delta >= TXSCALE_TABLE_SIZE)
2343 delta = TXSCALE_TABLE_SIZE - 1;
2345 /*7.1 The Final Power Index = BaseIndex + PowerIndexOffset*/
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];
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*/
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]);
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]);
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];
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]);
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
2388 if (rtldm->delta_power_index[p] ==
2389 rtldm->delta_power_index_last[p])
2391 rtldm->power_index_offset[p] = 0;
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*/
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]);
2405 rtldm->ofdm_index[p] =
2406 rtldm->swing_idx_ofdm_base[p] +
2407 rtldm->power_index_offset[p];
2409 rtldm->swing_idx_cck_base +
2410 rtldm->power_index_offset[p];
2412 rtldm->swing_idx_cck = rtldm->cck_index;
2413 rtldm->swing_idx_ofdm[p] = rtldm->ofdm_index[p];
2415 /*********Print BB Swing Base and Index Offset********/
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]);
2429 /*7.1 Handle boundary conditions of index.*/
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;
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;
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,
2447 rtldm->thermalvalue);
2449 for (p = RF90_PATH_A; p < MAX_PATH_NUM_8821A; p++)
2450 rtldm->power_index_offset[p] = 0;
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]);
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.*/
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.
2474 * 2012/04/25 MH Add for tx power tracking to
2475 * set tx power in tx agc for 88E.
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);
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);
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);
2504 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2505 "Temperature(%d) lower than PG value(%d)\n",
2506 thermal_value, rtlefuse->eeprom_thermalmeter);
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);
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];
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;
2525 /* Delta temperature is equal to or larger than
2526 * 20 centigrade (When threshold is 8).
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);
2534 rtl8821ae_do_iqk(hw, delta_iqk, thermal_value, 8);
2536 spin_lock(&rtlpriv->locks.iqk_lock);
2537 rtlphy->lck_inprogress = false;
2538 spin_unlock(&rtlpriv->locks.iqk_lock);
2542 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2543 "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n");
2546 void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
2548 struct rtl_priv *rtlpriv = rtl_priv(hw);
2549 static u8 tm_trigger;
2552 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER_88E, BIT(17)|BIT(16),
2554 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2555 "Trigger 8821ae Thermal Meter!!\n");
2559 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
2560 "Schedule TxPowerTracking !!\n");
2562 rtl8821ae_dm_txpower_tracking_callback_thermalmeter(hw);
2567 static void rtl8821ae_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
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;
2576 struct ieee80211_sta *sta = NULL;
2578 if (is_hal_stop(rtlhal)) {
2579 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2580 "driver is going to unload\n");
2584 if (!rtlpriv->dm.useramask) {
2585 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
2586 "driver does not control rate adaptive mask\n");
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;
2596 case DM_RATR_STA_LOW:
2597 high_rssithresh_for_ra += go_up_gap;
2598 low_rssithresh_for_ra += go_up_gap;
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;
2611 p_ra->ratr_state = DM_RATR_STA_LOW;
2613 if (p_ra->pre_ratr_state != p_ra->ratr_state) {
2614 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
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);
2624 sta = rtl_find_sta(hw, mac->bssid);
2626 rtlpriv->cfg->ops->update_rate_tbl(hw,
2627 sta, p_ra->ratr_state);
2630 p_ra->pre_ratr_state = p_ra->ratr_state;
2635 static void rtl8821ae_dm_refresh_basic_rate_mask(struct ieee80211_hw *hw)
2637 struct rtl_priv *rtlpriv = rtl_priv(hw);
2638 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2639 struct rtl_mac *mac = &rtlpriv->mac80211;
2642 u16 basic_rate = RRSR_1M | RRSR_2M | RRSR_5_5M | RRSR_11M | RRSR_6M;
2644 if (mac->link_state < MAC80211_LINKED)
2646 else if (dm_digtable->rssi_val_min < 25)
2648 else if (dm_digtable->rssi_val_min > 30)
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);
2666 static 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)
2671 struct rtl_priv *rtlpriv = rtl_priv(hw);
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 ");
2679 *pb_is_cur_rdl_state = true;
2680 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2681 "Balance Traffic\n");
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");
2689 *pb_is_cur_rdl_state = false;
2690 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2691 "Balance Traffic\n");
2697 static void rtl8821ae_dm_check_edca_turbo(struct ieee80211_hw *hw)
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));
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;
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;
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));
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;
2725 /*===============================
2726 * list paramter for different platform
2727 *===============================
2729 b_last_is_cur_rdl_state = rtlpriv->dm.is_cur_rdlstate;
2730 pb_is_cur_rdl_state = &rtlpriv->dm.is_cur_rdlstate;
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;
2735 rtldm->last_tx_ok_cnt = rtlpriv->stats.txbytesunicast;
2736 rtldm->last_rx_ok_cnt = rtlpriv->stats.rxbytesunicast;
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)) ?
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];
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);
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);
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);
2767 rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2768 cur_rx_ok_cnt, true, pb_is_cur_rdl_state);
2770 rtl8821ae_dm_edca_choose_traffic_idx(hw, cur_tx_ok_cnt,
2771 cur_rx_ok_cnt, false, pb_is_cur_rdl_state);
2773 edca_be = (*pb_is_cur_rdl_state) ? edca_be_dl : edca_be_ul;
2775 rtl_write_dword(rtlpriv, DM_REG_EDCA_BE_11N, edca_be);
2777 RT_TRACE(rtlpriv, COMP_TURBO, DBG_LOUD,
2778 "EDCA Turbo on: EDCA_BE:0x%x\n", edca_be);
2780 rtlpriv->dm.current_turbo_edca = true;
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);
2786 if (rtlpriv->dm.current_turbo_edca) {
2788 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
2791 rtlpriv->dm.current_turbo_edca = false;
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;
2799 static void rtl8821ae_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
2801 struct rtl_priv *rtlpriv = rtl_priv(hw);
2802 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
2803 u8 cur_cck_cca_thresh;
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;
2812 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2813 cur_cck_cca_thresh = 0x83;
2815 cur_cck_cca_thresh = 0x40;
2818 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
2819 cur_cck_cca_thresh = 0x83;
2821 cur_cck_cca_thresh = 0x40;
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);
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);
2834 static void rtl8821ae_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
2836 struct rtl_priv *rtlpriv = rtl_priv(hw);
2837 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
2840 int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
2843 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
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;
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);
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)));
2863 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL,
2864 0xfff000, (crystal_cap |
2865 (crystal_cap << 6)));
2867 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "crystal_cap = 0x%x\n",
2868 rtldm->crystal_cap);
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;
2876 if (packet_count == rtldm->packet_count_pre) {
2877 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2878 "packet counter doesn't change\n");
2882 rtldm->packet_count_pre = packet_count;
2883 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2884 "packet counter = %d\n",
2885 rtldm->packet_count);
2888 if (rtlpriv->phy.rf_type == RF_1T1R)
2889 cfo_ave = cfo_khz_a;
2891 cfo_ave = (cfo_khz_a + cfo_khz_b) >> 1;
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);
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);
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;
2908 rtldm->large_cfo_hit = 0;
2910 rtldm->cfo_ave_pre = cfo_ave;
2912 /*CFO tracking by adjusting Xtal cap.*/
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;
2922 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
2925 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
2926 "Dynamic threshold = %d\n",
2927 rtldm->cfo_threshold);
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);
2939 /*3.Adjudt Crystal Cap.*/
2940 if (adjust_xtal != 0) {
2941 rtldm->is_freeze = 0;
2942 rtldm->crystal_cap += adjust_xtal;
2944 if (rtldm->crystal_cap > 0x3f)
2945 rtldm->crystal_cap = 0x3f;
2946 else if (rtldm->crystal_cap < 0)
2947 rtldm->crystal_cap = 0;
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)));
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);
2966 void rtl8821ae_dm_watchdog(struct ieee80211_hw *hw)
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;
2974 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
2975 (u8 *)(&fw_current_inpsmode));
2977 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
2978 (u8 *)(&fw_ps_awake));
2980 if (ppsc->p2p_ps_info.p2p_ps_mode)
2981 fw_ps_awake = false;
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);
2998 rtl8821ae_dm_check_txpower_tracking_thermalmeter(hw);
2999 rtl8821ae_dm_iq_calibrate(hw);
3002 rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
3003 RT_TRACE(rtlpriv, COMP_DIG, DBG_DMESG, "\n");
3006 void rtl8821ae_dm_set_tx_ant_by_tx_info(struct ieee80211_hw *hw,
3007 u8 *pdesc, u32 mac_id)
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;
3014 if (rtlhal->hw_type != HARDWARE_TYPE_RTL8812AE)
3017 if (rtlefuse->antenna_div_type == CG_TRX_HW_ANTDIV)
3018 SET_TX_DESC_TX_ANT(pdesc, pfat_table->antsel_a[mac_id]);