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