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
39static 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
85static 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
121static 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
157static 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
168static 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
179void 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
215void 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
232static 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
255static 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
265void 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
280static 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
319static 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
377void 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
395static 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
531static 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
615static void rtl8723be_dm_dynamic_txpower(struct ieee80211_hw *hw)
616{
617	/* 8723BE does not support ODM_BB_DYNAMIC_TXPWR*/
618	return;
619}
620
621static 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
670static 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
747static 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
909void 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
932static 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
1000static 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
1010static 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
1069exit:
1070	rtlpriv->dm.is_any_nonbepkts = false;
1071	last_txok_cnt = rtlpriv->stats.txbytesunicast;
1072	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
1073}
1074
1075static 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
1109static 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
1136static 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
1239static 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
1267void 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}
1300