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