Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/trivial
[cascardo/linux.git] / drivers / net / wireless / rtlwifi / rtl8723be / dm.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2009-2014  Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  *
14  * The full GNU General Public License is included in this distribution in the
15  * file called LICENSE.
16  *
17  * Contact Information:
18  * wlanfae <wlanfae@realtek.com>
19  * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20  * Hsinchu 300, Taiwan.
21  *
22  * Larry Finger <Larry.Finger@lwfinger.net>
23  *
24  *****************************************************************************/
25
26 #include "../wifi.h"
27 #include "../base.h"
28 #include "../pci.h"
29 #include "../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         char 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         char 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                 if (thermalvalue > rtlefuse->eeprom_thermalmeter)
887                         rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
888                                                              index_for_channel);
889                 else
890                         rtl8723be_dm_tx_power_track_set_power(hw, BBSWING, 0,
891                                                              index_for_channel);
892
893                 rtldm->swing_idx_cck_base = rtldm->swing_idx_cck;
894                 rtldm->swing_idx_ofdm_base[RF90_PATH_A] =
895                                                 rtldm->swing_idx_ofdm[0];
896                 rtldm->thermalvalue = thermalvalue;
897         }
898
899         if (delta_iqk >= IQK_THRESHOLD) {
900                 rtldm->thermalvalue_iqk = thermalvalue;
901                 rtl8723be_phy_iq_calibrate(hw, false);
902         }
903
904         rtldm->txpowercount = 0;
905         RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "end\n");
906
907 }
908
909 void rtl8723be_dm_check_txpower_tracking(struct ieee80211_hw *hw)
910 {
911         struct rtl_priv *rtlpriv = rtl_priv(hw);
912         static u8 tm_trigger;
913
914         if (!rtlpriv->dm.txpower_tracking)
915                 return;
916
917         if (!tm_trigger) {
918                 rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, BIT(17) | BIT(16),
919                               0x03);
920                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
921                          "Trigger 8723be Thermal Meter!!\n");
922                 tm_trigger = 1;
923                 return;
924         } else {
925                 RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
926                          "Schedule TxPowerTracking !!\n");
927                 rtl8723be_dm_txpower_tracking_callback_thermalmeter(hw);
928                 tm_trigger = 0;
929         }
930 }
931
932 static void rtl8723be_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
933 {
934         struct rtl_priv *rtlpriv = rtl_priv(hw);
935         struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
936         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
937         struct rate_adaptive *p_ra = &rtlpriv->ra;
938         u32 low_rssithresh_for_ra = p_ra->low2high_rssi_thresh_for_ra40m;
939         u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
940         u8 go_up_gap = 5;
941         struct ieee80211_sta *sta = NULL;
942
943         if (is_hal_stop(rtlhal)) {
944                 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
945                          "driver is going to unload\n");
946                 return;
947         }
948
949         if (!rtlpriv->dm.useramask) {
950                 RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
951                          "driver does not control rate adaptive mask\n");
952                 return;
953         }
954
955         if (mac->link_state == MAC80211_LINKED &&
956                 mac->opmode == NL80211_IFTYPE_STATION) {
957                 switch (p_ra->pre_ratr_state) {
958                 case DM_RATR_STA_MIDDLE:
959                         high_rssithresh_for_ra += go_up_gap;
960                         break;
961                 case DM_RATR_STA_LOW:
962                         high_rssithresh_for_ra += go_up_gap;
963                         low_rssithresh_for_ra += go_up_gap;
964                         break;
965                 default:
966                         break;
967                 }
968
969                 if (rtlpriv->dm.undec_sm_pwdb >
970                     (long)high_rssithresh_for_ra)
971                         p_ra->ratr_state = DM_RATR_STA_HIGH;
972                 else if (rtlpriv->dm.undec_sm_pwdb >
973                          (long)low_rssithresh_for_ra)
974                         p_ra->ratr_state = DM_RATR_STA_MIDDLE;
975                 else
976                         p_ra->ratr_state = DM_RATR_STA_LOW;
977
978                 if (p_ra->pre_ratr_state != p_ra->ratr_state) {
979                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
980                                  "RSSI = %ld\n",
981                                  rtlpriv->dm.undec_sm_pwdb);
982                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
983                                  "RSSI_LEVEL = %d\n", p_ra->ratr_state);
984                         RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
985                                  "PreState = %d, CurState = %d\n",
986                                   p_ra->pre_ratr_state, p_ra->ratr_state);
987
988                         rcu_read_lock();
989                         sta = rtl_find_sta(hw, mac->bssid);
990                         if (sta)
991                                 rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
992                                                            p_ra->ratr_state);
993                         rcu_read_unlock();
994
995                         p_ra->pre_ratr_state = p_ra->ratr_state;
996                 }
997         }
998 }
999
1000 static bool rtl8723be_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
1001 {
1002         struct rtl_priv *rtlpriv = rtl_priv(hw);
1003
1004         if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
1005                 return true;
1006
1007         return false;
1008 }
1009
1010 static void rtl8723be_dm_check_edca_turbo(struct ieee80211_hw *hw)
1011 {
1012         struct rtl_priv *rtlpriv = rtl_priv(hw);
1013         struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1014
1015         static u64 last_txok_cnt;
1016         static u64 last_rxok_cnt;
1017         u64 cur_txok_cnt = 0;
1018         u64 cur_rxok_cnt = 0;
1019         u32 edca_be_ul = 0x6ea42b;
1020         u32 edca_be_dl = 0x6ea42b;/*not sure*/
1021         u32 edca_be = 0x5ea42b;
1022         u32 iot_peer = 0;
1023         bool b_is_cur_rdlstate;
1024         bool b_last_is_cur_rdlstate = false;
1025         bool b_bias_on_rx = false;
1026         bool b_edca_turbo_on = false;
1027
1028         b_last_is_cur_rdlstate = rtlpriv->dm.is_cur_rdlstate;
1029
1030         cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
1031         cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
1032
1033         iot_peer = rtlpriv->mac80211.vendor;
1034         b_bias_on_rx = (iot_peer == PEER_RAL || iot_peer == PEER_ATH) ?
1035                        true : false;
1036         b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
1037                            (!rtlpriv->dm.disable_framebursting)) ?
1038                            true : false;
1039
1040         if ((iot_peer == PEER_CISCO) &&
1041             (mac->mode == WIRELESS_MODE_N_24G)) {
1042                 edca_be_dl = edca_setting_dl[iot_peer];
1043                 edca_be_ul = edca_setting_ul[iot_peer];
1044         }
1045         if (rtl8723be_dm_is_edca_turbo_disable(hw))
1046                 goto exit;
1047
1048         if (b_edca_turbo_on) {
1049                 if (b_bias_on_rx)
1050                         b_is_cur_rdlstate = (cur_txok_cnt > cur_rxok_cnt * 4) ?
1051                                             false : true;
1052                 else
1053                         b_is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
1054                                             true : false;
1055
1056                 edca_be = (b_is_cur_rdlstate) ? edca_be_dl : edca_be_ul;
1057                 rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, edca_be);
1058                 rtlpriv->dm.is_cur_rdlstate = b_is_cur_rdlstate;
1059                 rtlpriv->dm.current_turbo_edca = true;
1060         } else {
1061                 if (rtlpriv->dm.current_turbo_edca) {
1062                         u8 tmp = AC0_BE;
1063                         rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
1064                                                       (u8 *)(&tmp));
1065                 }
1066                 rtlpriv->dm.current_turbo_edca = false;
1067         }
1068
1069 exit:
1070         rtlpriv->dm.is_any_nonbepkts = false;
1071         last_txok_cnt = rtlpriv->stats.txbytesunicast;
1072         last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1073 }
1074
1075 static void rtl8723be_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
1076 {
1077         struct rtl_priv *rtlpriv = rtl_priv(hw);
1078         struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
1079         u8 cur_cck_cca_thresh;
1080
1081         if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1082                 if (dm_digtable->rssi_val_min > 25) {
1083                         cur_cck_cca_thresh = 0xcd;
1084                 } else if ((dm_digtable->rssi_val_min <= 25) &&
1085                            (dm_digtable->rssi_val_min > 10)) {
1086                         cur_cck_cca_thresh = 0x83;
1087                 } else {
1088                         if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1089                                 cur_cck_cca_thresh = 0x83;
1090                         else
1091                                 cur_cck_cca_thresh = 0x40;
1092                 }
1093         } else {
1094                 if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
1095                         cur_cck_cca_thresh = 0x83;
1096                 else
1097                         cur_cck_cca_thresh = 0x40;
1098         }
1099
1100         if (dm_digtable->cur_cck_cca_thres != cur_cck_cca_thresh)
1101                 rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, cur_cck_cca_thresh);
1102
1103         dm_digtable->pre_cck_cca_thres = dm_digtable->cur_cck_cca_thres;
1104         dm_digtable->cur_cck_cca_thres = cur_cck_cca_thresh;
1105         RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
1106                  "CCK cca thresh hold =%x\n", dm_digtable->cur_cck_cca_thres);
1107 }
1108
1109 static void rtl8723be_dm_dynamic_edcca(struct ieee80211_hw *hw)
1110 {
1111         struct rtl_priv *rtlpriv = rtl_priv(hw);
1112         u8 reg_c50, reg_c58;
1113         bool fw_current_in_ps_mode = false;
1114
1115         rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1116                                       (u8 *)(&fw_current_in_ps_mode));
1117         if (fw_current_in_ps_mode)
1118                 return;
1119
1120         reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
1121         reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
1122
1123         if (reg_c50 > 0x28 && reg_c58 > 0x28) {
1124                 if (!rtlpriv->rtlhal.pre_edcca_enable) {
1125                         rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
1126                         rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
1127                 }
1128         } else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
1129                 if (rtlpriv->rtlhal.pre_edcca_enable) {
1130                         rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
1131                         rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
1132                 }
1133         }
1134 }
1135
1136 static void rtl8723be_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
1137 {
1138         struct rtl_priv *rtlpriv = rtl_priv(hw);
1139         struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
1140         u8 crystal_cap;
1141         u32 packet_count;
1142         int cfo_khz_a, cfo_khz_b, cfo_ave = 0, adjust_xtal = 0;
1143         int cfo_ave_diff;
1144
1145         if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1146                 if (rtldm->atc_status == ATC_STATUS_OFF) {
1147                         rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1148                                       ATC_STATUS_ON);
1149                         rtldm->atc_status = ATC_STATUS_ON;
1150                 }
1151                 if (rtlpriv->cfg->ops->get_btc_status()) {
1152                         if (!rtlpriv->btcoexist.btc_ops->btc_is_bt_disabled(rtlpriv)) {
1153                                 RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
1154                                          "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
1155                                 return;
1156                         }
1157                 }
1158
1159                 if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
1160                         rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
1161                         crystal_cap = rtldm->crystal_cap & 0x3f;
1162                         rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1163                                       (crystal_cap | (crystal_cap << 6)));
1164                 }
1165         } else {
1166                 cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
1167                 cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
1168                 packet_count = rtldm->packet_count;
1169
1170                 if (packet_count == rtldm->packet_count_pre)
1171                         return;
1172
1173                 rtldm->packet_count_pre = packet_count;
1174
1175                 if (rtlpriv->phy.rf_type == RF_1T1R)
1176                         cfo_ave = cfo_khz_a;
1177                 else
1178                         cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
1179
1180                 cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
1181                                (rtldm->cfo_ave_pre - cfo_ave) :
1182                                (cfo_ave - rtldm->cfo_ave_pre);
1183
1184                 if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
1185                         rtldm->large_cfo_hit = 1;
1186                         return;
1187                 } else
1188                         rtldm->large_cfo_hit = 0;
1189
1190                 rtldm->cfo_ave_pre = cfo_ave;
1191
1192                 if (cfo_ave >= -rtldm->cfo_threshold &&
1193                     cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
1194                         if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
1195                                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
1196                                 rtldm->is_freeze = 1;
1197                         } else {
1198                                 rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
1199                         }
1200                 }
1201
1202                 if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
1203                         adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 1) + 1;
1204                 else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
1205                                         rtlpriv->dm.crystal_cap > 0)
1206                         adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 1) - 1;
1207
1208                 if (adjust_xtal != 0) {
1209                         rtldm->is_freeze = 0;
1210                         rtldm->crystal_cap += adjust_xtal;
1211
1212                         if (rtldm->crystal_cap > 0x3f)
1213                                 rtldm->crystal_cap = 0x3f;
1214                         else if (rtldm->crystal_cap < 0)
1215                                 rtldm->crystal_cap = 0;
1216
1217                         crystal_cap = rtldm->crystal_cap & 0x3f;
1218                         rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
1219                                       (crystal_cap | (crystal_cap << 6)));
1220                 }
1221
1222                 if (cfo_ave < CFO_THRESHOLD_ATC &&
1223                     cfo_ave > -CFO_THRESHOLD_ATC) {
1224                         if (rtldm->atc_status == ATC_STATUS_ON) {
1225                                 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1226                                               ATC_STATUS_OFF);
1227                                 rtldm->atc_status = ATC_STATUS_OFF;
1228                         }
1229                 } else {
1230                         if (rtldm->atc_status == ATC_STATUS_OFF) {
1231                                 rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
1232                                               ATC_STATUS_ON);
1233                                 rtldm->atc_status = ATC_STATUS_ON;
1234                         }
1235                 }
1236         }
1237 }
1238
1239 static void rtl8723be_dm_common_info_self_update(struct ieee80211_hw *hw)
1240 {
1241         struct rtl_priv *rtlpriv = rtl_priv(hw);
1242         u8 cnt = 0;
1243         struct rtl_sta_info *drv_priv;
1244
1245         rtlpriv->dm.one_entry_only = false;
1246
1247         if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1248                 rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1249                 rtlpriv->dm.one_entry_only = true;
1250                 return;
1251         }
1252
1253         if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1254                 rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1255                 rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1256                 spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1257                 list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1258                         cnt++;
1259                 }
1260                 spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1261
1262                 if (cnt == 1)
1263                         rtlpriv->dm.one_entry_only = true;
1264         }
1265 }
1266
1267 void rtl8723be_dm_watchdog(struct ieee80211_hw *hw)
1268 {
1269         struct rtl_priv *rtlpriv = rtl_priv(hw);
1270         struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1271         bool fw_current_inpsmode = false;
1272         bool fw_ps_awake = true;
1273
1274         rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1275                                       (u8 *)(&fw_current_inpsmode));
1276
1277         rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1278                                       (u8 *)(&fw_ps_awake));
1279
1280         if (ppsc->p2p_ps_info.p2p_ps_mode)
1281                 fw_ps_awake = false;
1282
1283         if ((ppsc->rfpwr_state == ERFON) &&
1284                 ((!fw_current_inpsmode) && fw_ps_awake) &&
1285                 (!ppsc->rfchange_inprogress)) {
1286                 rtl8723be_dm_common_info_self_update(hw);
1287                 rtl8723be_dm_false_alarm_counter_statistics(hw);
1288                 rtl8723be_dm_check_rssi_monitor(hw);
1289                 rtl8723be_dm_dig(hw);
1290                 rtl8723be_dm_dynamic_edcca(hw);
1291                 rtl8723be_dm_cck_packet_detection_thresh(hw);
1292                 rtl8723be_dm_refresh_rate_adaptive_mask(hw);
1293                 rtl8723be_dm_check_edca_turbo(hw);
1294                 rtl8723be_dm_dynamic_atc_switch(hw);
1295                 rtl8723be_dm_check_txpower_tracking(hw);
1296                 rtl8723be_dm_dynamic_txpower(hw);
1297         }
1298         rtlpriv->dm.dbginfo.num_qry_beacon_pkt = 0;
1299 }