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