[go: nahoru, domu]

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