1 /******************************************************************************
3 * Copyright(c) 2009-2014 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
33 #include "../rtl8723com/dm_common.h"
35 #include "../rtl8723com/fw_common.h"
37 #include "../btcoexist/rtl_btc.h"
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 */
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 */
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 */
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 */
164 0x5ea630, /* 6 CISCO */
165 0x5ea42b, /* 7 MARVELL */
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 */
179 void rtl8723be_dm_txpower_track_adjust(struct ieee80211_hw
*hw
, u8 type
,
180 u8
*pdirection
, u32
*poutwrite_val
)
182 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
183 struct rtl_dm
*rtldm
= rtl_dm(rtl_priv(hw
));
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
;
191 if (ofdm_val
<= ofdm_base
) {
193 pwr_val
= ofdm_base
- ofdm_val
;
196 pwr_val
= ofdm_val
- ofdm_base
;
198 } else if (type
== 1) {
199 if (cck_val
<= cck_base
) {
201 pwr_val
= cck_base
- cck_val
;
204 pwr_val
= cck_val
- cck_base
;
208 if (pwr_val
>= TXPWRTRACK_MAX_IDX
&& (*pdirection
== 1))
209 pwr_val
= TXPWRTRACK_MAX_IDX
;
211 *poutwrite_val
= pwr_val
| (pwr_val
<< 8) |
212 (pwr_val
<< 16) | (pwr_val
<< 24);
215 static void rtl8723be_dm_diginit(struct ieee80211_hw
*hw
)
217 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
218 struct dig_t
*dm_digtable
= &rtlpriv
->dm_digtable
;
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;
245 void rtl8723be_dm_init_rate_adaptive_mask(struct ieee80211_hw
*hw
)
247 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
248 struct rate_adaptive
*ra
= &(rtlpriv
->ra
);
250 ra
->ratr_state
= DM_RATR_STA_INIT
;
251 ra
->pre_ratr_state
= DM_RATR_STA_INIT
;
253 if (rtlpriv
->dm
.dm_type
== DM_TYPE_BYDRIVER
)
254 rtlpriv
->dm
.useramask
= true;
256 rtlpriv
->dm
.useramask
= false;
258 ra
->high_rssi_thresh_for_ra
= 50;
259 ra
->low_rssi_thresh_for_ra40m
= 20;
262 static void rtl8723be_dm_init_txpower_tracking(struct ieee80211_hw
*hw
)
264 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
266 rtlpriv
->dm
.txpower_tracking
= true;
267 rtlpriv
->dm
.txpower_track_control
= true;
268 rtlpriv
->dm
.thermalvalue
= 0;
270 rtlpriv
->dm
.ofdm_index
[0] = 30;
271 rtlpriv
->dm
.cck_index
= 20;
273 rtlpriv
->dm
.swing_idx_cck_base
= rtlpriv
->dm
.cck_index
;
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;
280 RT_TRACE(rtlpriv
, COMP_POWER_TRACKING
, DBG_LOUD
,
281 " rtlpriv->dm.txpower_tracking = %d\n",
282 rtlpriv
->dm
.txpower_tracking
);
285 static void rtl8723be_dm_init_dynamic_atc_switch(struct ieee80211_hw
*hw
)
287 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
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
;
294 void rtl8723be_dm_init(struct ieee80211_hw
*hw
)
296 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
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
);
308 static void rtl8723be_dm_find_minimum_rssi(struct ieee80211_hw
*hw
)
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
);
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");
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
);
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
);
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
);
343 RT_TRACE(rtlpriv
, COMP_DIG
, DBG_LOUD
, "MinUndecoratedPWDBForDM =%d\n",
344 rtl_dm_dig
->min_undec_pwdb_for_dm
);
347 static void rtl8723be_dm_check_rssi_monitor(struct ieee80211_hw
*hw
)
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;
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
<
360 drv_priv
->rssi_stat
.undec_sm_pwdb
;
361 if (drv_priv
->rssi_stat
.undec_sm_pwdb
>
364 drv_priv
->rssi_stat
.undec_sm_pwdb
;
366 spin_unlock_bh(&rtlpriv
->locks
.entry_list_lock
);
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
);
375 rtlpriv
->dm
.entry_max_undec_sm_pwdb
= 0;
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
);
384 rtlpriv
->dm
.entry_min_undec_sm_pwdb
= 0;
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
);
393 rtl_write_byte(rtlpriv
, 0x4fe, rtlpriv
->dm
.undec_sm_pwdb
);
395 rtl8723be_dm_find_minimum_rssi(hw
);
396 rtlpriv
->dm_digtable
.rssi_val_min
=
397 rtlpriv
->dm_digtable
.min_undec_pwdb_for_dm
;
400 void rtl8723be_dm_write_dig(struct ieee80211_hw
*hw
, u8 current_igi
)
402 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
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
);
409 rtlpriv
->dm_digtable
.pre_igvalue
= rtlpriv
->dm_digtable
.cur_igvalue
;
410 rtlpriv
->dm_digtable
.cur_igvalue
= current_igi
;
413 static void rtl8723be_dm_dig(struct ieee80211_hw
*hw
)
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
;
425 if (mac
->act_scanning
)
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
;
435 dm_dig_min
= DM_DIG_MIN
;
436 dig_maxofmin
= DM_DIG_MAX_AP
;
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
;
444 dm_digtable
->rx_gain_max
=
445 dm_digtable
->rssi_val_min
+ 10;
447 if (rtlpriv
->dm
.one_entry_only
) {
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
>
453 dig_dynamic_min
= dig_maxofmin
;
456 dm_digtable
->rssi_val_min
- offset
;
458 dig_dynamic_min
= dm_dig_min
;
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");
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;
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
;
480 dm_digtable
->rx_gain_min
=
481 dm_digtable
->forbidden_igi
+ 1;
482 dm_digtable
->recover_cnt
= 3600;
485 if (dm_digtable
->recover_cnt
!= 0) {
486 dm_digtable
->recover_cnt
--;
488 if (dm_digtable
->large_fa_hit
< 3) {
489 if ((dm_digtable
->forbidden_igi
- 1) <
491 dm_digtable
->forbidden_igi
=
493 dm_digtable
->rx_gain_min
=
496 dm_digtable
->forbidden_igi
--;
497 dm_digtable
->rx_gain_min
=
498 dm_digtable
->forbidden_igi
+ 1;
501 dm_digtable
->large_fa_hit
= 0;
505 if (dm_digtable
->rx_gain_min
> dm_digtable
->rx_gain_max
)
506 dm_digtable
->rx_gain_min
= dm_digtable
->rx_gain_max
;
508 if (mac
->link_state
>= MAC80211_LINKED
) {
510 if (dm_digtable
->rssi_val_min
<= dig_maxofmin
)
511 current_igi
= dm_digtable
->rssi_val_min
;
513 current_igi
= dig_maxofmin
;
515 dm_digtable
->large_fa_hit
= 0;
517 if (rtlpriv
->falsealm_cnt
.cnt_all
> DM_DIG_FA_TH2
)
519 else if (rtlpriv
->falsealm_cnt
.cnt_all
> DM_DIG_FA_TH1
)
521 else if (rtlpriv
->falsealm_cnt
.cnt_all
< DM_DIG_FA_TH0
)
525 if (firstdisconnect
) {
526 current_igi
= dm_digtable
->rx_gain_min
;
528 if (rtlpriv
->falsealm_cnt
.cnt_all
> 10000)
530 else if (rtlpriv
->falsealm_cnt
.cnt_all
> 8000)
532 else if (rtlpriv
->falsealm_cnt
.cnt_all
< 500)
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
;
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
;
548 static void rtl8723be_dm_false_alarm_counter_statistics(struct ieee80211_hw
*hw
)
551 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
552 struct false_alarm_statistics
*falsealm_cnt
= &(rtlpriv
->falsealm_cnt
);
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);
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;
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;
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;
569 ret_value
= rtl_get_bbreg(hw
, DM_REG_OFDM_FA_TYPE4_11N
, MASKDWORD
);
570 falsealm_cnt
->cnt_mcs_fail
= ret_value
& 0xffff;
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
;
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);
582 ret_value
= rtl_get_bbreg(hw
, DM_REG_CCK_FA_RST_11N
, MASKBYTE0
);
583 falsealm_cnt
->cnt_cck_fail
= ret_value
;
585 ret_value
= rtl_get_bbreg(hw
, DM_REG_CCK_FA_MSB_11N
, MASKBYTE3
);
586 falsealm_cnt
->cnt_cck_fail
+= (ret_value
& 0xff) << 8;
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);
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
;
600 falsealm_cnt
->cnt_cca_all
= falsealm_cnt
->cnt_ofdm_cca
+
601 falsealm_cnt
->cnt_cck_cca
;
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);
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);
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);
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);
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
);
625 RT_TRACE(rtlpriv
, COMP_DIG
, DBG_TRACE
,
626 "cnt_ofdm_fail = %x, cnt_cck_fail = %x,"
628 falsealm_cnt
->cnt_ofdm_fail
,
629 falsealm_cnt
->cnt_cck_fail
,
630 falsealm_cnt
->cnt_all
);
633 static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw
*hw
)
635 /* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
639 static void rtl8723be_set_iqk_matrix(struct ieee80211_hw
*hw
, u8 ofdm_index
,
640 u8 rfpath
, long iqk_result_x
,
643 long ele_a
= 0, ele_d
, ele_c
= 0, value32
;
645 if (ofdm_index
>= 43)
648 ele_d
= (ofdmswing_table
[ofdm_index
] & 0xFFC00000) >> 22;
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;
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;
661 value32
= (ele_d
<< 22) |
662 ((ele_c
& 0x3F) << 16) | ele_a
;
663 rtl_set_bbreg(hw
, ROFDM0_XATXIQIMBALANCE
, MASKDWORD
,
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),
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);
688 static void rtl8723be_dm_tx_power_track_set_power(struct ieee80211_hw
*hw
,
689 enum pwr_track_control_method method
,
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;
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;
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]);
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]);
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
];
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
];
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]);
765 static void txpwr_track_cb_therm(struct ieee80211_hw
*hw
)
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;
775 u8 ofdm_min_index
= 6;
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};
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");
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)
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
;
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;
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
++;
821 if (thermalvalue_avg_count
)
822 thermalvalue
= (u8
)(thermalvalue_avg
/ thermalvalue_avg_count
);
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
);
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
);
847 /* 7 If necessary, move the index of
848 * swing table to adjust Tx power.
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
);
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.
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
];
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
];
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;
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
];
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
];
887 rtldm
->swing_idx_cck
= rtldm
->cck_index
;
888 rtldm
->swing_idx_ofdm
[0] = rtldm
->ofdm_index
[0];
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
;
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;
900 rtldm
->power_index_offset
[RF90_PATH_A
] = 0;
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,
910 rtl8723be_dm_tx_power_track_set_power(hw
, BBSWING
, 0,
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
;
919 if (delta_iqk
>= IQK_THRESHOLD
) {
920 rtldm
->thermalvalue_iqk
= thermalvalue
;
921 rtl8723be_phy_iq_calibrate(hw
, false);
924 rtldm
->txpowercount
= 0;
925 RT_TRACE(rtlpriv
, COMP_POWER_TRACKING
, DBG_LOUD
, "end\n");
928 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw
*hw
)
930 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
931 static u8 tm_trigger
;
933 if (!rtlpriv
->dm
.txpower_tracking
)
937 rtl_set_rfreg(hw
, RF90_PATH_A
, RF_T_METER
, BIT(17) | BIT(16),
939 RT_TRACE(rtlpriv
, COMP_POWER_TRACKING
, DBG_LOUD
,
940 "Trigger 8723be Thermal Meter!!\n");
944 RT_TRACE(rtlpriv
, COMP_POWER_TRACKING
, DBG_LOUD
,
945 "Schedule TxPowerTracking !!\n");
946 txpwr_track_cb_therm(hw
);
951 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw
*hw
)
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
;
962 if (is_hal_stop(rtlhal
)) {
963 RT_TRACE(rtlpriv
, COMP_RATE
, DBG_LOUD
,
964 "driver is going to unload\n");
968 if (!rtlpriv
->dm
.useramask
) {
969 RT_TRACE(rtlpriv
, COMP_RATE
, DBG_LOUD
,
970 "driver does not control rate adaptive mask\n");
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
;
980 case DM_RATR_STA_LOW
:
981 high_rssithresh_for_ra
+= go_up_gap
;
982 low_rssithresh_for_ra
+= go_up_gap
;
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
;
995 ra
->ratr_state
= DM_RATR_STA_LOW
;
997 if (ra
->pre_ratr_state
!= ra
->ratr_state
) {
998 RT_TRACE(rtlpriv
, COMP_RATE
, DBG_LOUD
,
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
);
1008 sta
= rtl_find_sta(hw
, mac
->bssid
);
1010 rtlpriv
->cfg
->ops
->update_rate_tbl(hw
, sta
,
1014 ra
->pre_ratr_state
= ra
->ratr_state
;
1019 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw
*hw
)
1021 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
1023 if (rtlpriv
->cfg
->ops
->get_btc_status()) {
1024 if (rtlpriv
->btcoexist
.btc_ops
->btc_is_disable_edca_turbo(rtlpriv
))
1027 if (rtlpriv
->mac80211
.mode
== WIRELESS_MODE_B
)
1033 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw
*hw
)
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;
1045 bool is_cur_rdlstate
;
1046 bool last_is_cur_rdlstate
= false;
1047 bool bias_on_rx
= false;
1048 bool edca_turbo_on
= false;
1050 last_is_cur_rdlstate
= rtlpriv
->dm
.is_cur_rdlstate
;
1052 cur_txok_cnt
= rtlpriv
->stats
.txbytesunicast
- last_txok_cnt
;
1053 cur_rxok_cnt
= rtlpriv
->stats
.rxbytesunicast
- last_rxok_cnt
;
1055 iot_peer
= rtlpriv
->mac80211
.vendor
;
1056 bias_on_rx
= (iot_peer
== PEER_RAL
|| iot_peer
== PEER_ATH
) ?
1058 edca_turbo_on
= ((!rtlpriv
->dm
.is_any_nonbepkts
) &&
1059 (!rtlpriv
->dm
.disable_framebursting
)) ?
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
];
1067 if (rtl8723be_dm_is_edca_turbo_disable(hw
))
1070 if (edca_turbo_on
) {
1072 is_cur_rdlstate
= (cur_txok_cnt
> cur_rxok_cnt
* 4) ?
1075 is_cur_rdlstate
= (cur_rxok_cnt
> cur_txok_cnt
* 4) ?
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;
1083 if (rtlpriv
->dm
.current_turbo_edca
) {
1085 rtlpriv
->cfg
->ops
->set_hw_reg(hw
, HW_VAR_AC_PARAM
,
1088 rtlpriv
->dm
.current_turbo_edca
= false;
1092 rtlpriv
->dm
.is_any_nonbepkts
= false;
1093 last_txok_cnt
= rtlpriv
->stats
.txbytesunicast
;
1094 last_rxok_cnt
= rtlpriv
->stats
.rxbytesunicast
;
1097 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw
*hw
)
1099 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
1100 u8 cur_cck_cca_thresh
;
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;
1109 if (rtlpriv
->falsealm_cnt
.cnt_cck_fail
> 1000)
1110 cur_cck_cca_thresh
= 0x83;
1112 cur_cck_cca_thresh
= 0x40;
1115 if (rtlpriv
->falsealm_cnt
.cnt_cck_fail
> 1000)
1116 cur_cck_cca_thresh
= 0x83;
1118 cur_cck_cca_thresh
= 0x40;
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
);
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
);
1131 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw
*hw
)
1133 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
1134 u8 reg_c50
, reg_c58
;
1135 bool fw_current_in_ps_mode
= false;
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
)
1142 reg_c50
= rtl_get_bbreg(hw
, ROFDM0_XAAGCCORE1
, MASKBYTE0
);
1143 reg_c58
= rtl_get_bbreg(hw
, ROFDM0_XBAGCCORE1
, MASKBYTE0
);
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);
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);
1158 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw
*hw
)
1160 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
1161 struct rtl_dm
*rtldm
= rtl_dm(rtl_priv(hw
));
1164 int cfo_khz_a
, cfo_khz_b
, cfo_ave
= 0, adjust_xtal
= 0;
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),
1171 rtldm
->atc_status
= ATC_STATUS_ON
;
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");
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)));
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
;
1193 if (packet_count
== rtldm
->packet_count_pre
)
1196 rtldm
->packet_count_pre
= packet_count
;
1198 if (rtlpriv
->phy
.rf_type
== RF_1T1R
)
1199 cfo_ave
= cfo_khz_a
;
1201 cfo_ave
= (int)(cfo_khz_a
+ cfo_khz_b
) >> 1;
1203 cfo_ave_diff
= (rtldm
->cfo_ave_pre
>= cfo_ave
) ?
1204 (rtldm
->cfo_ave_pre
- cfo_ave
) :
1205 (cfo_ave
- rtldm
->cfo_ave_pre
);
1207 if (cfo_ave_diff
> 20 && rtldm
->large_cfo_hit
== 0) {
1208 rtldm
->large_cfo_hit
= 1;
1211 rtldm
->large_cfo_hit
= 0;
1214 rtldm
->cfo_ave_pre
= cfo_ave
;
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;
1222 rtldm
->cfo_threshold
= CFO_THRESHOLD_XTAL
;
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;
1232 if (adjust_xtal
!= 0) {
1233 rtldm
->is_freeze
= 0;
1234 rtldm
->crystal_cap
+= adjust_xtal
;
1236 if (rtldm
->crystal_cap
> 0x3f)
1237 rtldm
->crystal_cap
= 0x3f;
1238 else if (rtldm
->crystal_cap
< 0)
1239 rtldm
->crystal_cap
= 0;
1241 crystal_cap
= rtldm
->crystal_cap
& 0x3f;
1242 rtl_set_bbreg(hw
, REG_MAC_PHY_CTRL
, 0xFFF000,
1243 (crystal_cap
| (crystal_cap
<< 6)));
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),
1251 rtldm
->atc_status
= ATC_STATUS_OFF
;
1254 if (rtldm
->atc_status
== ATC_STATUS_OFF
) {
1255 rtl_set_bbreg(hw
, ROFDM1_CFOTRACKING
, BIT(11),
1257 rtldm
->atc_status
= ATC_STATUS_ON
;
1263 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw
*hw
)
1265 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
1266 struct rtl_sta_info
*drv_priv
;
1269 rtlpriv
->dm
.one_entry_only
= false;
1271 if (rtlpriv
->mac80211
.opmode
== NL80211_IFTYPE_STATION
&&
1272 rtlpriv
->mac80211
.link_state
>= MAC80211_LINKED
) {
1273 rtlpriv
->dm
.one_entry_only
= true;
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
) {
1284 spin_unlock_bh(&rtlpriv
->locks
.entry_list_lock
);
1287 rtlpriv
->dm
.one_entry_only
= true;
1291 void rtl8723be_dm_watchdog(struct ieee80211_hw
*hw
)
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;
1298 rtlpriv
->cfg
->ops
->get_hw_reg(hw
, HW_VAR_FW_PSMODE_STATUS
,
1299 (u8
*)(&fw_current_inpsmode
));
1301 rtlpriv
->cfg
->ops
->get_hw_reg(hw
, HW_VAR_FWLPS_RF_ON
,
1302 (u8
*)(&fw_ps_awake
));
1304 if (ppsc
->p2p_ps_info
.p2p_ps_mode
)
1305 fw_ps_awake
= false;
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
);
1324 rtlpriv
->dm
.dbginfo
.num_qry_beacon_pkt
= 0;