Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide
[deliverable/linux.git] / drivers / net / wireless / rtlwifi / rtl8723be / dm.c
1 /******************************************************************************
2 *
3 * Copyright(c) 2009-2014 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
16 *
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
21 *
22 * Larry Finger <Larry.Finger@lwfinger.net>
23 *
24 *****************************************************************************/
25
26 #include "../wifi.h"
27 #include "../base.h"
28 #include "../pci.h"
29 #include "reg.h"
30 #include "def.h"
31 #include "phy.h"
32 #include "dm.h"
33 #include "../rtl8723com/dm_common.h"
34 #include "fw.h"
35 #include "../rtl8723com/fw_common.h"
36 #include "trx.h"
37 #include "../btcoexist/rtl_btc.h"
38
39 static const u32 ofdmswing_table[] = {
40 0x0b40002d, /* 0, -15.0dB */
41 0x0c000030, /* 1, -14.5dB */
42 0x0cc00033, /* 2, -14.0dB */
43 0x0d800036, /* 3, -13.5dB */
44 0x0e400039, /* 4, -13.0dB */
45 0x0f00003c, /* 5, -12.5dB */
46 0x10000040, /* 6, -12.0dB */
47 0x11000044, /* 7, -11.5dB */
48 0x12000048, /* 8, -11.0dB */
49 0x1300004c, /* 9, -10.5dB */
50 0x14400051, /* 10, -10.0dB */
51 0x15800056, /* 11, -9.5dB */
52 0x16c0005b, /* 12, -9.0dB */
53 0x18000060, /* 13, -8.5dB */
54 0x19800066, /* 14, -8.0dB */
55 0x1b00006c, /* 15, -7.5dB */
56 0x1c800072, /* 16, -7.0dB */
57 0x1e400079, /* 17, -6.5dB */
58 0x20000080, /* 18, -6.0dB */
59 0x22000088, /* 19, -5.5dB */
60 0x24000090, /* 20, -5.0dB */
61 0x26000098, /* 21, -4.5dB */
62 0x288000a2, /* 22, -4.0dB */
63 0x2ac000ab, /* 23, -3.5dB */
64 0x2d4000b5, /* 24, -3.0dB */
65 0x300000c0, /* 25, -2.5dB */
66 0x32c000cb, /* 26, -2.0dB */
67 0x35c000d7, /* 27, -1.5dB */
68 0x390000e4, /* 28, -1.0dB */
69 0x3c8000f2, /* 29, -0.5dB */
70 0x40000100, /* 30, +0dB */
71 0x43c0010f, /* 31, +0.5dB */
72 0x47c0011f, /* 32, +1.0dB */
73 0x4c000130, /* 33, +1.5dB */
74 0x50800142, /* 34, +2.0dB */
75 0x55400155, /* 35, +2.5dB */
76 0x5a400169, /* 36, +3.0dB */
77 0x5fc0017f, /* 37, +3.5dB */
78 0x65400195, /* 38, +4.0dB */
79 0x6b8001ae, /* 39, +4.5dB */
80 0x71c001c7, /* 40, +5.0dB */
81 0x788001e2, /* 41, +5.5dB */
82 0x7f8001fe /* 42, +6.0dB */
83 };
84
85 static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
86 {0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}, /* 0, -16.0dB */
87 {0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 1, -15.5dB */
88 {0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 2, -15.0dB */
89 {0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 3, -14.5dB */
90 {0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 4, -14.0dB */
91 {0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 5, -13.5dB */
92 {0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 6, -13.0dB */
93 {0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 7, -12.5dB */
94 {0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 8, -12.0dB */
95 {0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 9, -11.5dB */
96 {0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 10, -11.0dB */
97 {0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 11, -10.5dB */
98 {0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 12, -10.0dB */
99 {0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 13, -9.5dB */
100 {0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 14, -9.0dB */
101 {0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 15, -8.5dB */
102 {0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
103 {0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 17, -7.5dB */
104 {0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 18, -7.0dB */
105 {0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 19, -6.5dB */
106 {0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 20, -6.0dB */
107 {0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 21, -5.5dB */
108 {0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 22, -5.0dB */
109 {0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 23, -4.5dB */
110 {0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 24, -4.0dB */
111 {0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 25, -3.5dB */
112 {0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 26, -3.0dB */
113 {0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 27, -2.5dB */
114 {0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 28, -2.0dB */
115 {0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 29, -1.5dB */
116 {0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 30, -1.0dB */
117 {0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 31, -0.5dB */
118 {0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04} /* 32, +0dB */
119 };
120
121 static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
122 {0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}, /* 0, -16.0dB */
123 {0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 1, -15.5dB */
124 {0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 2, -15.0dB */
125 {0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 3, -14.5dB */
126 {0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 4, -14.0dB */
127 {0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 5, -13.5dB */
128 {0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 6, -13.0dB */
129 {0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 7, -12.5dB */
130 {0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 8, -12.0dB */
131 {0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 9, -11.5dB */
132 {0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 10, -11.0dB */
133 {0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 11, -10.5dB */
134 {0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 12, -10.0dB */
135 {0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 13, -9.5dB */
136 {0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 14, -9.0dB */
137 {0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 15, -8.5dB */
138 {0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
139 {0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 17, -7.5dB */
140 {0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 18, -7.0dB */
141 {0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 19, -6.5dB */
142 {0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 20, -6.0dB */
143 {0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 21, -5.5dB */
144 {0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 22, -5.0dB */
145 {0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 23, -4.5dB */
146 {0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 24, -4.0dB */
147 {0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 25, -3.5dB */
148 {0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 26, -3.0dB */
149 {0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 27, -2.5dB */
150 {0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 28, -2.0dB */
151 {0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 29, -1.5dB */
152 {0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 30, -1.0dB */
153 {0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 31, -0.5dB */
154 {0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00} /* 32, +0dB */
155 };
156
157 static const u32 edca_setting_dl[PEER_MAX] = {
158 0xa44f, /* 0 UNKNOWN */
159 0x5ea44f, /* 1 REALTEK_90 */
160 0x5e4322, /* 2 REALTEK_92SE */
161 0x5ea42b, /* 3 BROAD */
162 0xa44f, /* 4 RAL */
163 0xa630, /* 5 ATH */
164 0x5ea630, /* 6 CISCO */
165 0x5ea42b, /* 7 MARVELL */
166 };
167
168 static const u32 edca_setting_ul[PEER_MAX] = {
169 0x5e4322, /* 0 UNKNOWN */
170 0xa44f, /* 1 REALTEK_90 */
171 0x5ea44f, /* 2 REALTEK_92SE */
172 0x5ea32b, /* 3 BROAD */
173 0x5ea422, /* 4 RAL */
174 0x5ea322, /* 5 ATH */
175 0x3ea430, /* 6 CISCO */
176 0x5ea44f, /* 7 MARV */
177 };
178
179 void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw *hw, u8 type,
180 u8 *pdirection, u32 *poutwrite_val)
181 {
182 struct rtl_priv *rtlpriv = rtl_priv(hw);
183 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
184 u8 pwr_val = 0;
185 u8 ofdm_base = rtlpriv->dm.swing_idx_ofdm_base[RF90_PATH_A];
186 u8 ofdm_val = rtlpriv->dm.swing_idx_ofdm[RF90_PATH_A];
187 u8 cck_base = rtldm->swing_idx_cck_base;
188 u8 cck_val = rtldm->swing_idx_cck;
189
190 if (type == 0) {
191 if (ofdm_val <= ofdm_base) {
192 *pdirection = 1;
193 pwr_val = ofdm_base - ofdm_val;
194 } else {
195 *pdirection = 2;
196 pwr_val = ofdm_val - ofdm_base;
197 }
198 } else if (type == 1) {
199 if (cck_val <= cck_base) {
200 *pdirection = 1;
201 pwr_val = cck_base - cck_val;
202 } else {
203 *pdirection = 2;
204 pwr_val = cck_val - cck_base;
205 }
206 }
207
208 if (pwr_val >= TXPWRTRACK_MAX_IDX && (*pdirection == 1))
209 pwr_val = TXPWRTRACK_MAX_IDX;
210
211 *poutwrite_val = pwr_val | (pwr_val << 8) |
212 (pwr_val << 16) | (pwr_val << 24);
213 }
214
215 static void rtl8723be_dm_diginit(struct ieee80211_hw *hw)
216 {
217 struct rtl_priv *rtlpriv = rtl_priv(hw);
218 struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
219
220 dm_digtable->dig_enable_flag = true;
221 dm_digtable->cur_igvalue = rtl_get_bbreg(hw,
222 ROFDM0_XAAGCCORE1, 0x7f);
223 dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
224 dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
225 dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
226 dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
227 dm_digtable->rx_gain_max = DM_DIG_MAX;
228 dm_digtable->rx_gain_min = DM_DIG_MIN;
229 dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
230 dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
231 dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
232 dm_digtable->pre_cck_cca_thres = 0xff;
233 dm_digtable->cur_cck_cca_thres = 0x83;
234 dm_digtable->forbidden_igi = DM_DIG_MIN;
235 dm_digtable->large_fa_hit = 0;
236 dm_digtable->recover_cnt = 0;
237 dm_digtable->dig_min_0 = DM_DIG_MIN;
238 dm_digtable->dig_min_1 = DM_DIG_MIN;
239 dm_digtable->media_connect_0 = false;
240 dm_digtable->media_connect_1 = false;
241 rtlpriv->dm.dm_initialgain_enable = true;
242 dm_digtable->bt30_cur_igi = 0x32;
243 }
244
245 void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
246 {
247 struct rtl_priv *rtlpriv = rtl_priv(hw);
248 struct rate_adaptive *ra = &(rtlpriv->ra);
249
250 ra->ratr_state = DM_RATR_STA_INIT;
251 ra->pre_ratr_state = DM_RATR_STA_INIT;
252
253 if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
254 rtlpriv->dm.useramask = true;
255 else
256 rtlpriv->dm.useramask = false;
257
258 ra->high_rssi_thresh_for_ra = 50;
259 ra->low_rssi_thresh_for_ra40m = 20;
260 }
261
262 static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw *hw)
263 {
264 struct rtl_priv *rtlpriv = rtl_priv(hw);
265
266 rtlpriv->dm.txpower_tracking = true;
267 rtlpriv->dm.txpower_track_control = true;
268 rtlpriv->dm.thermalvalue = 0;
269
270 rtlpriv->dm.ofdm_index[0] = 30;
271 rtlpriv->dm.cck_index = 20;
272
273 rtlpriv->dm.swing_idx_cck_base = rtlpriv->dm.cck_index;
274
275 rtlpriv->dm.swing_idx_ofdm_base[0] = rtlpriv->dm.ofdm_index[0];
276 rtlpriv->dm.delta_power_index[RF90_PATH_A] = 0;
277 rtlpriv->dm.delta_power_index_last[RF90_PATH_A] = 0;
278 rtlpriv->dm.power_index_offset[RF90_PATH_A] = 0;
279
280 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
281 " rtlpriv->dm.txpower_tracking = %d\n",
282 rtlpriv->dm.txpower_tracking);
283 }
284
285 static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
286 {
287 struct rtl_priv *rtlpriv = rtl_priv(hw);
288
289 rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
290 rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, 0x800);
291 rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
292 }
293
294 void rtl8723be_dm_init(struct ieee80211_hw *hw)
295 {
296 struct rtl_priv *rtlpriv = rtl_priv(hw);
297
298 rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
299 rtl8723be_dm_diginit(hw);
300 rtl8723be_dm_init_rate_adaptive_mask(hw);
301 rtl8723_dm_init_edca_turbo(hw);
302 rtl8723_dm_init_dynamic_bb_powersaving(hw);
303 rtl8723_dm_init_dynamic_txpower(hw);
304 rtl8723be_dm_init_txpower_tracking(hw);
305 rtl8723be_dm_init_dynamic_atc_switch(hw);
306 }
307
308 static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw *hw)
309 {
310 struct rtl_priv *rtlpriv = rtl_priv(hw);
311 struct dig_t *rtl_dm_dig = &(rtlpriv->dm_digtable);
312 struct rtl_mac *mac = rtl_mac(rtlpriv);
313
314 /* Determine the minimum RSSI */
315 if ((mac->link_state < MAC80211_LINKED) &&
316 (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
317 rtl_dm_dig->min_undec_pwdb_for_dm = 0;
318 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
319 "Not connected to any\n");
320 }
321 if (mac->link_state >= MAC80211_LINKED) {
322 if (mac->opmode == NL80211_IFTYPE_AP ||
323 mac->opmode == NL80211_IFTYPE_ADHOC) {
324 rtl_dm_dig->min_undec_pwdb_for_dm =
325 rtlpriv->dm.entry_min_undec_sm_pwdb;
326 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
327 "AP Client PWDB = 0x%lx\n",
328 rtlpriv->dm.entry_min_undec_sm_pwdb);
329 } else {
330 rtl_dm_dig->min_undec_pwdb_for_dm =
331 rtlpriv->dm.undec_sm_pwdb;
332 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
333 "STA Default Port PWDB = 0x%x\n",
334 rtl_dm_dig->min_undec_pwdb_for_dm);
335 }
336 } else {
337 rtl_dm_dig->min_undec_pwdb_for_dm =
338 rtlpriv->dm.entry_min_undec_sm_pwdb;
339 RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
340 "AP Ext Port or disconnet PWDB = 0x%x\n",
341 rtl_dm_dig->min_undec_pwdb_for_dm);
342 }
343 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n",
344 rtl_dm_dig->min_undec_pwdb_for_dm);
345 }
346
347 static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw *hw)
348 {
349 struct rtl_priv *rtlpriv = rtl_priv(hw);
350 struct rtl_sta_info *drv_priv;
351 u8 h2c_parameter[3] = { 0 };
352 long tmp_entry_max_pwdb = 0, tmp_entry_min_pwdb = 0xff;
353
354 /* AP & ADHOC & MESH */
355 spin_lock_bh(&rtlpriv->locks.entry_list_lock);
356 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
357 if (drv_priv->rssi_stat.undec_sm_pwdb <
358 tmp_entry_min_pwdb)
359 tmp_entry_min_pwdb =
360 drv_priv->rssi_stat.undec_sm_pwdb;
361 if (drv_priv->rssi_stat.undec_sm_pwdb >
362 tmp_entry_max_pwdb)
363 tmp_entry_max_pwdb =
364 drv_priv->rssi_stat.undec_sm_pwdb;
365 }
366 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
367
368 /* If associated entry is found */
369 if (tmp_entry_max_pwdb != 0) {
370 rtlpriv->dm.entry_max_undec_sm_pwdb = tmp_entry_max_pwdb;
371 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
372 "EntryMaxPWDB = 0x%lx(%ld)\n",
373 tmp_entry_max_pwdb, tmp_entry_max_pwdb);
374 } else {
375 rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
376 }
377 /* If associated entry is found */
378 if (tmp_entry_min_pwdb != 0xff) {
379 rtlpriv->dm.entry_min_undec_sm_pwdb = tmp_entry_min_pwdb;
380 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
381 "EntryMinPWDB = 0x%lx(%ld)\n",
382 tmp_entry_min_pwdb, tmp_entry_min_pwdb);
383 } else {
384 rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
385 }
386 /* Indicate Rx signal strength to FW. */
387 if (rtlpriv->dm.useramask) {
388 h2c_parameter[2] = (u8) (rtlpriv->dm.undec_sm_pwdb & 0xFF);
389 h2c_parameter[1] = 0x20;
390 h2c_parameter[0] = 0;
391 rtl8723be_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
392 } else {
393 rtl_write_byte(rtlpriv, 0x4fe, rtlpriv->dm.undec_sm_pwdb);
394 }
395 rtl8723be_dm_find_minimum_rssi(hw);
396 rtlpriv->dm_digtable.rssi_val_min =
397 rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
398 }
399
400 void rtl8723be_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
401 {
402 struct rtl_priv *rtlpriv = rtl_priv(hw);
403
404 if (rtlpriv->dm_digtable.cur_igvalue != current_igi) {
405 rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
406 if (rtlpriv->phy.rf_type != RF_1T1R)
407 rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, current_igi);
408 }
409 rtlpriv->dm_digtable.pre_igvalue = rtlpriv->dm_digtable.cur_igvalue;
410 rtlpriv->dm_digtable.cur_igvalue = current_igi;
411 }
412
413 static void rtl8723be_dm_dig(struct ieee80211_hw *hw)
414 {
415 struct rtl_priv *rtlpriv = rtl_priv(hw);
416 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
417 struct dig_t *dm_digtable = &(rtlpriv->dm_digtable);
418 u8 dig_dynamic_min, dig_maxofmin;
419 bool firstconnect, firstdisconnect;
420 u8 dm_dig_max, dm_dig_min;
421 u8 current_igi = dm_digtable->cur_igvalue;
422 u8 offset;
423
424 /* AP, BT */
425 if (mac->act_scanning)
426 return;
427
428 dig_dynamic_min = dm_digtable->dig_min_0;
429 firstconnect = (mac->link_state >= MAC80211_LINKED) &&
430 !dm_digtable->media_connect_0;
431 firstdisconnect = (mac->link_state < MAC80211_LINKED) &&
432 dm_digtable->media_connect_0;
433
434 dm_dig_max = 0x5a;
435 dm_dig_min = DM_DIG_MIN;
436 dig_maxofmin = DM_DIG_MAX_AP;
437
438 if (mac->link_state >= MAC80211_LINKED) {
439 if ((dm_digtable->rssi_val_min + 10) > dm_dig_max)
440 dm_digtable->rx_gain_max = dm_dig_max;
441 else if ((dm_digtable->rssi_val_min + 10) < dm_dig_min)
442 dm_digtable->rx_gain_max = dm_dig_min;
443 else
444 dm_digtable->rx_gain_max =
445 dm_digtable->rssi_val_min + 10;
446
447 if (rtlpriv->dm.one_entry_only) {
448 offset = 12;
449 if (dm_digtable->rssi_val_min - offset < dm_dig_min)
450 dig_dynamic_min = dm_dig_min;
451 else if (dm_digtable->rssi_val_min - offset >
452 dig_maxofmin)
453 dig_dynamic_min = dig_maxofmin;
454 else
455 dig_dynamic_min =
456 dm_digtable->rssi_val_min - offset;
457 } else {
458 dig_dynamic_min = dm_dig_min;
459 }
460 } else {
461 dm_digtable->rx_gain_max = dm_dig_max;
462 dig_dynamic_min = dm_dig_min;
463 RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
464 }
465
466 if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
467 if (dm_digtable->large_fa_hit != 3)
468 dm_digtable->large_fa_hit++;
469 if (dm_digtable->forbidden_igi < current_igi) {
470 dm_digtable->forbidden_igi = current_igi;
471 dm_digtable->large_fa_hit = 1;
472 }
473
474 if (dm_digtable->large_fa_hit >= 3) {
475 if ((dm_digtable->forbidden_igi + 1) >
476 dm_digtable->rx_gain_max)
477 dm_digtable->rx_gain_min =
478 dm_digtable->rx_gain_max;
479 else
480 dm_digtable->rx_gain_min =
481 dm_digtable->forbidden_igi + 1;
482 dm_digtable->recover_cnt = 3600;
483 }
484 } else {
485 if (dm_digtable->recover_cnt != 0) {
486 dm_digtable->recover_cnt--;
487 } else {
488 if (dm_digtable->large_fa_hit < 3) {
489 if ((dm_digtable->forbidden_igi - 1) <
490 dig_dynamic_min) {
491 dm_digtable->forbidden_igi =
492 dig_dynamic_min;
493 dm_digtable->rx_gain_min =
494 dig_dynamic_min;
495 } else {
496 dm_digtable->forbidden_igi--;
497 dm_digtable->rx_gain_min =
498 dm_digtable->forbidden_igi + 1;
499 }
500 } else {
501 dm_digtable->large_fa_hit = 0;
502 }
503 }
504 }
505 if (dm_digtable->rx_gain_min > dm_digtable->rx_gain_max)
506 dm_digtable->rx_gain_min = dm_digtable->rx_gain_max;
507
508 if (mac->link_state >= MAC80211_LINKED) {
509 if (firstconnect) {
510 if (dm_digtable->rssi_val_min <= dig_maxofmin)
511 current_igi = dm_digtable->rssi_val_min;
512 else
513 current_igi = dig_maxofmin;
514
515 dm_digtable->large_fa_hit = 0;
516 } else {
517 if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
518 current_igi += 4;
519 else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
520 current_igi += 2;
521 else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
522 current_igi -= 2;
523 }
524 } else {
525 if (firstdisconnect) {
526 current_igi = dm_digtable->rx_gain_min;
527 } else {
528 if (rtlpriv->falsealm_cnt.cnt_all > 10000)
529 current_igi += 4;
530 else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
531 current_igi += 2;
532 else if (rtlpriv->falsealm_cnt.cnt_all < 500)
533 current_igi -= 2;
534 }
535 }
536
537 if (current_igi > dm_digtable->rx_gain_max)
538 current_igi = dm_digtable->rx_gain_max;
539 else if (current_igi < dm_digtable->rx_gain_min)
540 current_igi = dm_digtable->rx_gain_min;
541
542 rtl8723be_dm_write_dig(hw, current_igi);
543 dm_digtable->media_connect_0 =
544 ((mac->link_state >= MAC80211_LINKED) ? true : false);
545 dm_digtable->dig_min_0 = dig_dynamic_min;
546 }
547
548 static void rtl8723be_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
549 {
550 u32 ret_value;
551 struct rtl_priv *rtlpriv = rtl_priv(hw);
552 struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
553
554 rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
555 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
556
557 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
558 falsealm_cnt->cnt_fast_fsync_fail = ret_value & 0xffff;
559 falsealm_cnt->cnt_sb_search_fail = (ret_value & 0xffff0000) >> 16;
560
561 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
562 falsealm_cnt->cnt_ofdm_cca = ret_value & 0xffff;
563 falsealm_cnt->cnt_parity_fail = (ret_value & 0xffff0000) >> 16;
564
565 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
566 falsealm_cnt->cnt_rate_illegal = ret_value & 0xffff;
567 falsealm_cnt->cnt_crc8_fail = (ret_value & 0xffff0000) >> 16;
568
569 ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
570 falsealm_cnt->cnt_mcs_fail = ret_value & 0xffff;
571
572 falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
573 falsealm_cnt->cnt_rate_illegal +
574 falsealm_cnt->cnt_crc8_fail +
575 falsealm_cnt->cnt_mcs_fail +
576 falsealm_cnt->cnt_fast_fsync_fail +
577 falsealm_cnt->cnt_sb_search_fail;
578
579 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
580 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
581
582 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_RST_11N, MASKBYTE0);
583 falsealm_cnt->cnt_cck_fail = ret_value;
584
585 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
586 falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
587
588 ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
589 falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
590 ((ret_value & 0xff00) >> 8);
591
592 falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
593 falsealm_cnt->cnt_sb_search_fail +
594 falsealm_cnt->cnt_parity_fail +
595 falsealm_cnt->cnt_rate_illegal +
596 falsealm_cnt->cnt_crc8_fail +
597 falsealm_cnt->cnt_mcs_fail +
598 falsealm_cnt->cnt_cck_fail;
599
600 falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
601 falsealm_cnt->cnt_cck_cca;
602
603 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
604 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
605 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
606 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
607
608 rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
609 rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
610
611 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
612 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
613
614 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
615 rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
616
617 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
618 "cnt_parity_fail = %d, cnt_rate_illegal = %d, "
619 "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
620 falsealm_cnt->cnt_parity_fail,
621 falsealm_cnt->cnt_rate_illegal,
622 falsealm_cnt->cnt_crc8_fail,
623 falsealm_cnt->cnt_mcs_fail);
624
625 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
626 "cnt_ofdm_fail = %x, cnt_cck_fail = %x,"
627 " cnt_all = %x\n",
628 falsealm_cnt->cnt_ofdm_fail,
629 falsealm_cnt->cnt_cck_fail,
630 falsealm_cnt->cnt_all);
631 }
632
633 static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
634 {
635 /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
636 return;
637 }
638
639 static void rtl8723be_set_iqk_matrix(struct ieee80211_hw *hw, u8 ofdm_index,
640 u8 rfpath, long iqk_result_x,
641 long iqk_result_y)
642 {
643 long ele_a = 0, ele_d, ele_c = 0, value32;
644
645 if (ofdm_index >= 43)
646 ofdm_index = 43 - 1;
647
648 ele_d = (ofdmswing_table[ofdm_index] & 0xFFC00000) >> 22;
649
650 if (iqk_result_x != 0) {
651 if ((iqk_result_x & 0x00000200) != 0)
652 iqk_result_x = iqk_result_x | 0xFFFFFC00;
653 ele_a = ((iqk_result_x * ele_d) >> 8) & 0x000003FF;
654
655 if ((iqk_result_y & 0x00000200) != 0)
656 iqk_result_y = iqk_result_y | 0xFFFFFC00;
657 ele_c = ((iqk_result_y * ele_d) >> 8) & 0x000003FF;
658
659 switch (rfpath) {
660 case RF90_PATH_A:
661 value32 = (ele_d << 22) |
662 ((ele_c & 0x3F) << 16) | ele_a;
663 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
664 value32);
665 value32 = (ele_c & 0x000003C0) >> 6;
666 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, value32);
667 value32 = ((iqk_result_x * ele_d) >> 7) & 0x01;
668 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24),
669 value32);
670 break;
671 default:
672 break;
673 }
674 } else {
675 switch (rfpath) {
676 case RF90_PATH_A:
677 rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, MASKDWORD,
678 ofdmswing_table[ofdm_index]);
679 rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS, 0x00);
680 rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(24), 0x00);
681 break;
682 default:
683 break;
684 }
685 }
686 }
687
688 static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw *hw,
689 enum pwr_track_control_method method,
690 u8 rfpath, u8 idx)
691 {
692 struct rtl_priv *rtlpriv = rtl_priv(hw);
693 struct rtl_phy *rtlphy = &(rtlpriv->phy);
694 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
695 u8 swing_idx_ofdm_limit = 36;
696
697 if (method == TXAGC) {
698 rtl8723be_phy_set_txpower_level(hw, rtlphy->current_channel);
699 } else if (method == BBSWING) {
700 if (rtldm->swing_idx_cck >= CCK_TABLE_SIZE)
701 rtldm->swing_idx_cck = CCK_TABLE_SIZE - 1;
702
703 if (!rtldm->cck_inch14) {
704 rtl_write_byte(rtlpriv, 0xa22,
705 cckswing_table_ch1ch13[rtldm->swing_idx_cck][0]);
706 rtl_write_byte(rtlpriv, 0xa23,
707 cckswing_table_ch1ch13[rtldm->swing_idx_cck][1]);
708 rtl_write_byte(rtlpriv, 0xa24,
709 cckswing_table_ch1ch13[rtldm->swing_idx_cck][2]);
710 rtl_write_byte(rtlpriv, 0xa25,
711 cckswing_table_ch1ch13[rtldm->swing_idx_cck][3]);
712 rtl_write_byte(rtlpriv, 0xa26,
713 cckswing_table_ch1ch13[rtldm->swing_idx_cck][4]);
714 rtl_write_byte(rtlpriv, 0xa27,
715 cckswing_table_ch1ch13[rtldm->swing_idx_cck][5]);
716 rtl_write_byte(rtlpriv, 0xa28,
717 cckswing_table_ch1ch13[rtldm->swing_idx_cck][6]);
718 rtl_write_byte(rtlpriv, 0xa29,
719 cckswing_table_ch1ch13[rtldm->swing_idx_cck][7]);
720 } else {
721 rtl_write_byte(rtlpriv, 0xa22,
722 cckswing_table_ch14[rtldm->swing_idx_cck][0]);
723 rtl_write_byte(rtlpriv, 0xa23,
724 cckswing_table_ch14[rtldm->swing_idx_cck][1]);
725 rtl_write_byte(rtlpriv, 0xa24,
726 cckswing_table_ch14[rtldm->swing_idx_cck][2]);
727 rtl_write_byte(rtlpriv, 0xa25,
728 cckswing_table_ch14[rtldm->swing_idx_cck][3]);
729 rtl_write_byte(rtlpriv, 0xa26,
730 cckswing_table_ch14[rtldm->swing_idx_cck][4]);
731 rtl_write_byte(rtlpriv, 0xa27,
732 cckswing_table_ch14[rtldm->swing_idx_cck][5]);
733 rtl_write_byte(rtlpriv, 0xa28,
734 cckswing_table_ch14[rtldm->swing_idx_cck][6]);
735 rtl_write_byte(rtlpriv, 0xa29,
736 cckswing_table_ch14[rtldm->swing_idx_cck][7]);
737 }
738
739 if (rfpath == RF90_PATH_A) {
740 if (rtldm->swing_idx_ofdm[RF90_PATH_A] <
741 swing_idx_ofdm_limit)
742 swing_idx_ofdm_limit =
743 rtldm->swing_idx_ofdm[RF90_PATH_A];
744
745 rtl8723be_set_iqk_matrix(hw,
746 rtldm->swing_idx_ofdm[rfpath], rfpath,
747 rtlphy->iqk_matrix[idx].value[0][0],
748 rtlphy->iqk_matrix[idx].value[0][1]);
749 } else if (rfpath == RF90_PATH_B) {
750 if (rtldm->swing_idx_ofdm[RF90_PATH_B] <
751 swing_idx_ofdm_limit)
752 swing_idx_ofdm_limit =
753 rtldm->swing_idx_ofdm[RF90_PATH_B];
754
755 rtl8723be_set_iqk_matrix(hw,
756 rtldm->swing_idx_ofdm[rfpath], rfpath,
757 rtlphy->iqk_matrix[idx].value[0][4],
758 rtlphy->iqk_matrix[idx].value[0][5]);
759 }
760 } else {
761 return;
762 }
763 }
764
765 static void txpwr_track_cb_therm(struct ieee80211_hw *hw)
766 {
767 struct rtl_priv *rtlpriv = rtl_priv(hw);
768 struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
769 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
770 u8 thermalvalue = 0, delta, delta_lck, delta_iqk;
771 u8 thermalvalue_avg_count = 0;
772 u32 thermalvalue_avg = 0;
773 int i = 0;
774
775 u8 ofdm_min_index = 6;
776 u8 index = 0;
777
778 char delta_swing_table_idx_tup_a[] = {
779 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5,
780 5, 6, 6, 7, 7, 8, 8, 9, 9, 9, 10,
781 10, 11, 11, 12, 12, 13, 14, 15};
782 char delta_swing_table_idx_tdown_a[] = {
783 0, 0, 1, 2, 2, 2, 3, 3, 3, 4, 5,
784 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 9,
785 9, 10, 10, 11, 12, 13, 14, 15};
786
787 /*Initilization ( 7 steps in total)*/
788 rtlpriv->dm.txpower_trackinginit = true;
789 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
790 "rtl8723be_dm_txpower_tracking"
791 "_callback_thermalmeter\n");
792
793 thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0xfc00);
794 if (!rtlpriv->dm.txpower_track_control || thermalvalue == 0 ||
795 rtlefuse->eeprom_thermalmeter == 0xFF)
796 return;
797 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
798 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
799 "eeprom_thermalmeter 0x%x\n",
800 thermalvalue, rtldm->thermalvalue,
801 rtlefuse->eeprom_thermalmeter);
802 /*3 Initialize ThermalValues of RFCalibrateInfo*/
803 if (!rtldm->thermalvalue) {
804 rtlpriv->dm.thermalvalue_lck = thermalvalue;
805 rtlpriv->dm.thermalvalue_iqk = thermalvalue;
806 }
807
808 /*4 Calculate average thermal meter*/
809 rtldm->thermalvalue_avg[rtldm->thermalvalue_avg_index] = thermalvalue;
810 rtldm->thermalvalue_avg_index++;
811 if (rtldm->thermalvalue_avg_index == AVG_THERMAL_NUM_8723BE)
812 rtldm->thermalvalue_avg_index = 0;
813
814 for (i = 0; i < AVG_THERMAL_NUM_8723BE; i++) {
815 if (rtldm->thermalvalue_avg[i]) {
816 thermalvalue_avg += rtldm->thermalvalue_avg[i];
817 thermalvalue_avg_count++;
818 }
819 }
820
821 if (thermalvalue_avg_count)
822 thermalvalue = (u8)(thermalvalue_avg / thermalvalue_avg_count);
823
824 /* 5 Calculate delta, delta_LCK, delta_IQK.*/
825 delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
826 (thermalvalue - rtlpriv->dm.thermalvalue) :
827 (rtlpriv->dm.thermalvalue - thermalvalue);
828 delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
829 (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
830 (rtlpriv->dm.thermalvalue_lck - thermalvalue);
831 delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
832 (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
833 (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
834
835 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
836 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
837 "eeprom_thermalmeter 0x%x delta 0x%x "
838 "delta_lck 0x%x delta_iqk 0x%x\n",
839 thermalvalue, rtlpriv->dm.thermalvalue,
840 rtlefuse->eeprom_thermalmeter, delta, delta_lck, delta_iqk);
841 /* 6 If necessary, do LCK.*/
842 if (delta_lck >= IQK_THRESHOLD) {
843 rtlpriv->dm.thermalvalue_lck = thermalvalue;
844 rtl8723be_phy_lc_calibrate(hw);
845 }
846
847 /* 7 If necessary, move the index of
848 * swing table to adjust Tx power.
849 */
850 if (delta > 0 && rtlpriv->dm.txpower_track_control) {
851 delta = (thermalvalue > rtlefuse->eeprom_thermalmeter) ?
852 (thermalvalue - rtlefuse->eeprom_thermalmeter) :
853 (rtlefuse->eeprom_thermalmeter - thermalvalue);
854
855 if (delta >= TXSCALE_TABLE_SIZE)
856 delta = TXSCALE_TABLE_SIZE - 1;
857 /* 7.1 Get the final CCK_index and
858 * OFDM_index for each swing table.
859 */
860 if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
861 rtldm->delta_power_index_last[RF90_PATH_A] =
862 rtldm->delta_power_index[RF90_PATH_A];
863 rtldm->delta_power_index[RF90_PATH_A] =
864 delta_swing_table_idx_tup_a[delta];
865 } else {
866 rtldm->delta_power_index_last[RF90_PATH_A] =
867 rtldm->delta_power_index[RF90_PATH_A];
868 rtldm->delta_power_index[RF90_PATH_A] =
869 -1 * delta_swing_table_idx_tdown_a[delta];
870 }
871
872 /* 7.2 Handle boundary conditions of index.*/
873 if (rtldm->delta_power_index[RF90_PATH_A] ==
874 rtldm->delta_power_index_last[RF90_PATH_A])
875 rtldm->power_index_offset[RF90_PATH_A] = 0;
876 else
877 rtldm->power_index_offset[RF90_PATH_A] =
878 rtldm->delta_power_index[RF90_PATH_A] -
879 rtldm->delta_power_index_last[RF90_PATH_A];
880
881 rtldm->ofdm_index[0] =
882 rtldm->swing_idx_ofdm_base[RF90_PATH_A] +
883 rtldm->power_index_offset[RF90_PATH_A];
884 rtldm->cck_index = rtldm->swing_idx_cck_base +
885 rtldm->power_index_offset[RF90_PATH_A];
886
887 rtldm->swing_idx_cck = rtldm->cck_index;
888 rtldm->swing_idx_ofdm[0] = rtldm->ofdm_index[0];
889
890 if (rtldm->ofdm_index[0] > OFDM_TABLE_SIZE - 1)
891 rtldm->ofdm_index[0] = OFDM_TABLE_SIZE - 1;
892 else if (rtldm->ofdm_index[0] < ofdm_min_index)
893 rtldm->ofdm_index[0] = ofdm_min_index;
894
895 if (rtldm->cck_index > CCK_TABLE_SIZE - 1)
896 rtldm->cck_index = CCK_TABLE_SIZE - 1;
897 else if (rtldm->cck_index < 0)
898 rtldm->cck_index = 0;
899 } else {
900 rtldm->power_index_offset[RF90_PATH_A] = 0;
901 }
902
903 if ((rtldm->power_index_offset[RF90_PATH_A] != 0) &&
904 (rtldm->txpower_track_control)) {
905 rtldm->done_txpower = true;
906 if (thermalvalue > rtlefuse->eeprom_thermalmeter)
907 rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
908 index);
909 else
910 rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
911 index);
912
913 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
914 rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
915 rtldm->swing_idx_ofdm[0];
916 rtldm->thermalvalue = thermalvalue;
917 }
918
919 if (delta_iqk >= IQK_THRESHOLD) {
920 rtldm->thermalvalue_iqk = thermalvalue;
921 rtl8723be_phy_iq_calibrate(hw, false);
922 }
923
924 rtldm->txpowercount = 0;
925 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
926 }
927
928 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
929 {
930 struct rtl_priv *rtlpriv = rtl_priv(hw);
931 static u8 tm_trigger;
932
933 if (!rtlpriv->dm.txpower_tracking)
934 return;
935
936 if (!tm_trigger) {
937 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
938 0x03);
939 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
940 "Trigger 8723be Thermal Meter!!\n");
941 tm_trigger = 1;
942 return;
943 } else {
944 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
945 "Schedule TxPowerTracking !!\n");
946 txpwr_track_cb_therm(hw);
947 tm_trigger = 0;
948 }
949 }
950
951 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
952 {
953 struct rtl_priv *rtlpriv = rtl_priv(hw);
954 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
955 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
956 struct rate_adaptive *ra = &(rtlpriv->ra);
957 struct ieee80211_sta *sta = NULL;
958 u32 low_rssithresh_for_ra = ra->low2high_rssi_thresh_for_ra40m;
959 u32 high_rssithresh_for_ra = ra->high_rssi_thresh_for_ra;
960 u8 go_up_gap = 5;
961
962 if (is_hal_stop(rtlhal)) {
963 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
964 "driver is going to unload\n");
965 return;
966 }
967
968 if (!rtlpriv->dm.useramask) {
969 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
970 "driver does not control rate adaptive mask\n");
971 return;
972 }
973
974 if (mac->link_state == MAC80211_LINKED &&
975 mac->opmode == NL80211_IFTYPE_STATION) {
976 switch (ra->pre_ratr_state) {
977 case DM_RATR_STA_MIDDLE:
978 high_rssithresh_for_ra += go_up_gap;
979 break;
980 case DM_RATR_STA_LOW:
981 high_rssithresh_for_ra += go_up_gap;
982 low_rssithresh_for_ra += go_up_gap;
983 break;
984 default:
985 break;
986 }
987
988 if (rtlpriv->dm.undec_sm_pwdb >
989 (long)high_rssithresh_for_ra)
990 ra->ratr_state = DM_RATR_STA_HIGH;
991 else if (rtlpriv->dm.undec_sm_pwdb >
992 (long)low_rssithresh_for_ra)
993 ra->ratr_state = DM_RATR_STA_MIDDLE;
994 else
995 ra->ratr_state = DM_RATR_STA_LOW;
996
997 if (ra->pre_ratr_state != ra->ratr_state) {
998 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
999 "RSSI = %ld\n",
1000 rtlpriv->dm.undec_sm_pwdb);
1001 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1002 "RSSI_LEVEL = %d\n", ra->ratr_state);
1003 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1004 "PreState = %d, CurState = %d\n",
1005 ra->pre_ratr_state, ra->ratr_state);
1006
1007 rcu_read_lock();
1008 sta = rtl_find_sta(hw, mac->bssid);
1009 if (sta)
1010 rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
1011 ra->ratr_state);
1012 rcu_read_unlock();
1013
1014 ra->pre_ratr_state = ra->ratr_state;
1015 }
1016 }
1017 }
1018
1019 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
1020 {
1021 struct rtl_priv *rtlpriv = rtl_priv(hw);
1022
1023 if (rtlpriv->cfg->ops->get_btc_status()) {
1024 if (rtlpriv->btcoexist.btc_ops->btc_is_disable_edca_turbo(rtlpriv))
1025 return true;
1026 }
1027 if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
1028 return true;
1029
1030 return false;
1031 }
1032
1033 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
1034 {
1035 struct rtl_priv *rtlpriv = rtl_priv(hw);
1036 struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1037 static u64 last_txok_cnt;
1038 static u64 last_rxok_cnt;
1039 u64 cur_txok_cnt = 0;
1040 u64 cur_rxok_cnt = 0;
1041 u32 edca_be_ul = 0x6ea42b;
1042 u32 edca_be_dl = 0x6ea42b;/*not sure*/
1043 u32 edca_be = 0x5ea42b;
1044 u32 iot_peer = 0;
1045 bool is_cur_rdlstate;
1046 bool last_is_cur_rdlstate = false;
1047 bool bias_on_rx = false;
1048 bool edca_turbo_on = false;
1049
1050 last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate;
1051
1052 cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1053 cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1054
1055 iot_peer = rtlpriv->mac80211.vendor;
1056 bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1057 true : false;
1058 edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1059 (!rtlpriv->dm.disable_framebursting)) ?
1060 true : false;
1061
1062 if ((iot_peer == PEER_CISCO) &&
1063 (mac->mode == WIRELESS_MODE_N_24G)) {
1064 edca_be_dl = edca_setting_dl[iot_peer];
1065 edca_be_ul = edca_setting_ul[iot_peer];
1066 }
1067 if (rtl8723be_dm_is_edca_turbo_disable(hw))
1068 goto exit;
1069
1070 if (edca_turbo_on) {
1071 if (bias_on_rx)
1072 is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1073 false : true;
1074 else
1075 is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1076 true : false;
1077
1078 edca_be = (is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1079 rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1080 rtlpriv->dm.is_cur_rdlstate = is_cur_rdlstate;
1081 rtlpriv->dm.current_turbo_edca = true;
1082 } else {
1083 if (rtlpriv->dm.current_turbo_edca) {
1084 u8 tmp = AC0_BE;
1085 rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1086 &tmp);
1087 }
1088 rtlpriv->dm.current_turbo_edca = false;
1089 }
1090
1091 exit:
1092 rtlpriv->dm.is_any_nonbepkts = false;
1093 last_txok_cnt = rtlpriv->stats.txbytesunicast;
1094 last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1095 }
1096
1097 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1098 {
1099 struct rtl_priv *rtlpriv = rtl_priv(hw);
1100 u8 cur_cck_cca_thresh;
1101
1102 if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1103 if (rtlpriv->dm_digtable.rssi_val_min > 25) {
1104 cur_cck_cca_thresh = 0xcd;
1105 } else if ((rtlpriv->dm_digtable.rssi_val_min <= 25) &&
1106 (rtlpriv->dm_digtable.rssi_val_min > 10)) {
1107 cur_cck_cca_thresh = 0x83;
1108 } else {
1109 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1110 cur_cck_cca_thresh = 0x83;
1111 else
1112 cur_cck_cca_thresh = 0x40;
1113 }
1114 } else {
1115 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1116 cur_cck_cca_thresh = 0x83;
1117 else
1118 cur_cck_cca_thresh = 0x40;
1119 }
1120
1121 if (rtlpriv->dm_digtable.cur_cck_cca_thres != cur_cck_cca_thresh)
1122 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1123
1124 rtlpriv->dm_digtable.pre_cck_cca_thres = rtlpriv->dm_digtable.cur_cck_cca_thres;
1125 rtlpriv->dm_digtable.cur_cck_cca_thres = cur_cck_cca_thresh;
1126 RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
1127 "CCK cca thresh hold =%x\n",
1128 rtlpriv->dm_digtable.cur_cck_cca_thres);
1129 }
1130
1131 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1132 {
1133 struct rtl_priv *rtlpriv = rtl_priv(hw);
1134 u8 reg_c50, reg_c58;
1135 bool fw_current_in_ps_mode = false;
1136
1137 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1138 (u8 *)(&fw_current_in_ps_mode));
1139 if (fw_current_in_ps_mode)
1140 return;
1141
1142 reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1143 reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1144
1145 if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1146 if (!rtlpriv->rtlhal.pre_edcca_enable) {
1147 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1148 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1149 }
1150 } else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1151 if (rtlpriv->rtlhal.pre_edcca_enable) {
1152 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1153 rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1154 }
1155 }
1156 }
1157
1158 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1159 {
1160 struct rtl_priv *rtlpriv = rtl_priv(hw);
1161 struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1162 u8 crystal_cap;
1163 u32 packet_count;
1164 int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1165 int cfo_ave_diff;
1166
1167 if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1168 if (rtldm->atc_status == ATC_STATUS_OFF) {
1169 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1170 ATC_STATUS_ON);
1171 rtldm->atc_status = ATC_STATUS_ON;
1172 }
1173 if (rtlpriv->cfg->ops->get_btc_status()) {
1174 if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1175 RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1176 "odm_DynamicATCSwitch(): Disable"
1177 " CFO tracking for BT!!\n");
1178 return;
1179 }
1180 }
1181
1182 if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1183 rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1184 crystal_cap = rtldm->crystal_cap & 0x3f;
1185 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1186 (crystal_cap | (crystal_cap << 6)));
1187 }
1188 } else {
1189 cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1190 cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1191 packet_count = rtldm->packet_count;
1192
1193 if (packet_count == rtldm->packet_count_pre)
1194 return;
1195
1196 rtldm->packet_count_pre = packet_count;
1197
1198 if (rtlpriv->phy.rf_type == RF_1T1R)
1199 cfo_ave = cfo_khz_a;
1200 else
1201 cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1202
1203 cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1204 (rtldm->cfo_ave_pre - cfo_ave) :
1205 (cfo_ave - rtldm->cfo_ave_pre);
1206
1207 if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
1208 rtldm->large_cfo_hit = 1;
1209 return;
1210 } else {
1211 rtldm->large_cfo_hit = 0;
1212 }
1213
1214 rtldm->cfo_ave_pre = cfo_ave;
1215
1216 if (cfo_ave >= -rtldm->cfo_threshold &&
1217 cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1218 if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1219 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1220 rtldm->is_freeze = 1;
1221 } else {
1222 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1223 }
1224 }
1225
1226 if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1227 adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1228 else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1229 rtlpriv->dm.crystal_cap > 0)
1230 adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1231
1232 if (adjust_xtal != 0) {
1233 rtldm->is_freeze = 0;
1234 rtldm->crystal_cap += adjust_xtal;
1235
1236 if (rtldm->crystal_cap > 0x3f)
1237 rtldm->crystal_cap = 0x3f;
1238 else if (rtldm->crystal_cap < 0)
1239 rtldm->crystal_cap = 0;
1240
1241 crystal_cap = rtldm->crystal_cap & 0x3f;
1242 rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1243 (crystal_cap | (crystal_cap << 6)));
1244 }
1245
1246 if (cfo_ave < CFO_THRESHOLD_ATC &&
1247 cfo_ave > -CFO_THRESHOLD_ATC) {
1248 if (rtldm->atc_status == ATC_STATUS_ON) {
1249 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1250 ATC_STATUS_OFF);
1251 rtldm->atc_status = ATC_STATUS_OFF;
1252 }
1253 } else {
1254 if (rtldm->atc_status == ATC_STATUS_OFF) {
1255 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1256 ATC_STATUS_ON);
1257 rtldm->atc_status = ATC_STATUS_ON;
1258 }
1259 }
1260 }
1261 }
1262
1263 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1264 {
1265 struct rtl_priv *rtlpriv = rtl_priv(hw);
1266 struct rtl_sta_info *drv_priv;
1267 u8 cnt = 0;
1268
1269 rtlpriv->dm.one_entry_only = false;
1270
1271 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1272 rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1273 rtlpriv->dm.one_entry_only = true;
1274 return;
1275 }
1276
1277 if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1278 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1279 rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1280 spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1281 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1282 cnt++;
1283 }
1284 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1285
1286 if (cnt == 1)
1287 rtlpriv->dm.one_entry_only = true;
1288 }
1289 }
1290
1291 void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1292 {
1293 struct rtl_priv *rtlpriv = rtl_priv(hw);
1294 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1295 bool fw_current_inpsmode = false;
1296 bool fw_ps_awake = true;
1297
1298 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1299 (u8 *)(&fw_current_inpsmode));
1300
1301 rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1302 (u8 *)(&fw_ps_awake));
1303
1304 if (ppsc->p2p_ps_info.p2p_ps_mode)
1305 fw_ps_awake = false;
1306
1307 if ((ppsc->rfpwr_state == ERFON) &&
1308 ((!fw_current_inpsmode) && fw_ps_awake) &&
1309 (!ppsc->rfchange_inprogress)) {
1310 rtl8723be_dm_common_info_self_update(hw);
1311 rtl8723be_dm_false_alarm_counter_statistics(hw);
1312 rtl8723be_dm_check_rssi_monitor(hw);
1313 rtl8723be_dm_dig(hw);
1314 rtl8723be_dm_dynamic_edcca(hw);
1315 rtl8723be_dm_cck_packet_detection_thresh(hw);
1316 rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1317 rtl8723be_dm_check_edca_turbo(hw);
1318 rtl8723be_dm_dynamic_atc_switch(hw);
1319 rtl8723be_dm_check_txpower_tracking(hw);
1320 rtl8723be_dm_dynamic_txpower(hw);
1321 if (rtlpriv->cfg->ops->get_btc_status())
1322 rtlpriv->btcoexist.btc_ops->btc_periodical(rtlpriv);
1323 }
1324 rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1325 }
This page took 0.076806 seconds and 5 git commands to generate.