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