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