[go: nahoru, domu]

1/******************************************************************************
2 *
3 * Copyright(c) 2009-2012  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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
21 * Contact Information:
22 * wlanfae <wlanfae@realtek.com>
23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
24 * Hsinchu 300, Taiwan.
25 *
26 * Larry Finger <Larry.Finger@lwfinger.net>
27 *
28 *****************************************************************************/
29
30#include <linux/export.h>
31#include "dm_common.h"
32#include "phy_common.h"
33#include "../pci.h"
34#include "../base.h"
35
36#define BT_RSSI_STATE_NORMAL_POWER	BIT_OFFSET_LEN_MASK_32(0, 1)
37#define BT_RSSI_STATE_AMDPU_OFF		BIT_OFFSET_LEN_MASK_32(1, 1)
38#define BT_RSSI_STATE_SPECIAL_LOW	BIT_OFFSET_LEN_MASK_32(2, 1)
39#define BT_RSSI_STATE_BG_EDCA_LOW	BIT_OFFSET_LEN_MASK_32(3, 1)
40#define BT_RSSI_STATE_TXPOWER_LOW	BIT_OFFSET_LEN_MASK_32(4, 1)
41
42#define RTLPRIV			(struct rtl_priv *)
43#define GET_UNDECORATED_AVERAGE_RSSI(_priv)	\
44	((RTLPRIV(_priv))->mac80211.opmode == \
45			     NL80211_IFTYPE_ADHOC) ?	\
46	((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \
47	((RTLPRIV(_priv))->dm.undec_sm_pwdb)
48
49static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
50	0x7f8001fe,
51	0x788001e2,
52	0x71c001c7,
53	0x6b8001ae,
54	0x65400195,
55	0x5fc0017f,
56	0x5a400169,
57	0x55400155,
58	0x50800142,
59	0x4c000130,
60	0x47c0011f,
61	0x43c0010f,
62	0x40000100,
63	0x3c8000f2,
64	0x390000e4,
65	0x35c000d7,
66	0x32c000cb,
67	0x300000c0,
68	0x2d4000b5,
69	0x2ac000ab,
70	0x288000a2,
71	0x26000098,
72	0x24000090,
73	0x22000088,
74	0x20000080,
75	0x1e400079,
76	0x1c800072,
77	0x1b00006c,
78	0x19800066,
79	0x18000060,
80	0x16c0005b,
81	0x15800056,
82	0x14400051,
83	0x1300004c,
84	0x12000048,
85	0x11000044,
86	0x10000040,
87};
88
89static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
90	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
91	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
92	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
93	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
94	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
95	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
96	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
97	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
98	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
99	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
100	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
101	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
102	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
103	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
104	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
105	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
106	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
107	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
108	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
109	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
110	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
111	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
112	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
113	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
114	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
115	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
116	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
117	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
118	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
119	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
120	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
121	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
122	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
123};
124
125static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
126	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
127	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
128	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
129	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
130	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
131	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
132	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
133	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
134	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
135	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
136	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
137	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
138	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
139	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
140	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
141	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
142	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
143	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
144	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
145	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
146	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
147	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
148	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
149	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
150	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
151	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
152	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
153	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
154	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
155	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
156	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
157	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
158	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
159};
160
161static u32 power_index_reg[6] = {0xc90, 0xc91, 0xc92, 0xc98, 0xc99, 0xc9a};
162
163void dm_restorepowerindex(struct ieee80211_hw *hw)
164{
165	struct rtl_priv *rtlpriv = rtl_priv(hw);
166	u8	index;
167
168	for (index = 0; index < 6; index++)
169		rtl_write_byte(rtlpriv, power_index_reg[index],
170			       rtlpriv->dm.powerindex_backup[index]);
171}
172EXPORT_SYMBOL_GPL(dm_restorepowerindex);
173
174void dm_writepowerindex(struct ieee80211_hw *hw, u8 value)
175{
176	struct rtl_priv *rtlpriv = rtl_priv(hw);
177	u8 index;
178
179	for (index = 0; index < 6; index++)
180		rtl_write_byte(rtlpriv, power_index_reg[index], value);
181}
182EXPORT_SYMBOL_GPL(dm_writepowerindex);
183
184void dm_savepowerindex(struct ieee80211_hw *hw)
185{
186	struct rtl_priv *rtlpriv = rtl_priv(hw);
187	u8 index;
188	u8 tmp;
189
190	for (index = 0; index < 6; index++) {
191		tmp = rtl_read_byte(rtlpriv, power_index_reg[index]);
192		rtlpriv->dm.powerindex_backup[index] = tmp;
193	}
194}
195EXPORT_SYMBOL_GPL(dm_savepowerindex);
196
197static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
198{
199	struct rtl_priv *rtlpriv = rtl_priv(hw);
200	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
201
202	dm_digtable->dig_enable_flag = true;
203	dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
204	dm_digtable->cur_igvalue = 0x20;
205	dm_digtable->pre_igvalue = 0x0;
206	dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
207	dm_digtable->presta_cstate = DIG_STA_DISCONNECT;
208	dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
209	dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW;
210	dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH;
211	dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
212	dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
213	dm_digtable->rx_gain_max = DM_DIG_MAX;
214	dm_digtable->rx_gain_min = DM_DIG_MIN;
215	dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
216	dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX;
217	dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN;
218	dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX;
219	dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_LowRssi;
220
221	dm_digtable->forbidden_igi = DM_DIG_MIN;
222	dm_digtable->large_fa_hit = 0;
223	dm_digtable->recover_cnt = 0;
224	dm_digtable->dig_dynamic_min  = 0x25;
225}
226
227static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
228{
229	struct rtl_priv *rtlpriv = rtl_priv(hw);
230	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
231	long rssi_val_min = 0;
232
233	if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
234	    (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
235		if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
236			rssi_val_min =
237			    (rtlpriv->dm.entry_min_undec_sm_pwdb >
238			     rtlpriv->dm.undec_sm_pwdb) ?
239			    rtlpriv->dm.undec_sm_pwdb :
240			    rtlpriv->dm.entry_min_undec_sm_pwdb;
241		else
242			rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
243	} else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
244		   dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
245		rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
246	} else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
247		rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
248	}
249
250	if (rssi_val_min > 100)
251		rssi_val_min = 100;
252	return (u8)rssi_val_min;
253}
254
255static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
256{
257	u32 ret_value;
258	struct rtl_priv *rtlpriv = rtl_priv(hw);
259	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
260
261	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
262	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
263
264	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
265	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
266	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
267
268	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
269	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
270
271	 ret_value = rtl_get_bbreg(hw, ROFDM0_FRAMESYNC, MASKDWORD);
272	falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
273	falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
274
275	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
276				      falsealm_cnt->cnt_rate_illegal +
277				      falsealm_cnt->cnt_crc8_fail +
278				      falsealm_cnt->cnt_mcs_fail +
279				      falsealm_cnt->cnt_fast_fsync_fail +
280				      falsealm_cnt->cnt_sb_search_fail;
281
282	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
283	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
284	falsealm_cnt->cnt_cck_fail = ret_value;
285
286	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
287	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
288	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
289				 falsealm_cnt->cnt_rate_illegal +
290				 falsealm_cnt->cnt_crc8_fail +
291				 falsealm_cnt->cnt_mcs_fail +
292				 falsealm_cnt->cnt_cck_fail);
293
294	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
295	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
296	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
297	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
298
299	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
300		 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
301		 falsealm_cnt->cnt_parity_fail,
302		 falsealm_cnt->cnt_rate_illegal,
303		 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
304
305	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
306		 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
307		 falsealm_cnt->cnt_ofdm_fail,
308		 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
309}
310
311static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
312{
313	struct rtl_priv *rtlpriv = rtl_priv(hw);
314	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
315	u8 value_igi = dm_digtable->cur_igvalue;
316
317	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
318		value_igi--;
319	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
320		value_igi += 0;
321	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
322		value_igi++;
323	else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
324		value_igi += 2;
325
326	if (value_igi > DM_DIG_FA_UPPER)
327		value_igi = DM_DIG_FA_UPPER;
328	else if (value_igi < DM_DIG_FA_LOWER)
329		value_igi = DM_DIG_FA_LOWER;
330
331	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
332		value_igi = DM_DIG_FA_UPPER;
333
334	dm_digtable->cur_igvalue = value_igi;
335	rtl92c_dm_write_dig(hw);
336}
337
338static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
339{
340	struct rtl_priv *rtlpriv = rtl_priv(hw);
341	struct dig_t *digtable = &rtlpriv->dm_digtable;
342	u32 isbt;
343
344	/* modify DIG lower bound, deal with abnorally large false alarm */
345	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
346		digtable->large_fa_hit++;
347		if (digtable->forbidden_igi < digtable->cur_igvalue) {
348			digtable->forbidden_igi = digtable->cur_igvalue;
349			digtable->large_fa_hit = 1;
350		}
351
352		if (digtable->large_fa_hit >= 3) {
353			if ((digtable->forbidden_igi + 1) >
354			    digtable->rx_gain_max)
355				digtable->rx_gain_min = digtable->rx_gain_max;
356			else
357				digtable->rx_gain_min = (digtable->forbidden_igi + 1);
358			digtable->recover_cnt = 3600; /* 3600=2hr */
359		}
360	} else {
361		/* Recovery mechanism for IGI lower bound */
362		if (digtable->recover_cnt != 0) {
363			digtable->recover_cnt--;
364		} else {
365			if (digtable->large_fa_hit == 0) {
366				if ((digtable->forbidden_igi-1) < DM_DIG_MIN) {
367					digtable->forbidden_igi = DM_DIG_MIN;
368					digtable->rx_gain_min = DM_DIG_MIN;
369				} else {
370					digtable->forbidden_igi--;
371					digtable->rx_gain_min = digtable->forbidden_igi + 1;
372				}
373			} else if (digtable->large_fa_hit == 3) {
374				digtable->large_fa_hit = 0;
375			}
376		}
377	}
378	if (rtlpriv->falsealm_cnt.cnt_all < 250) {
379		isbt = rtl_read_byte(rtlpriv, 0x4fd) & 0x01;
380
381		if (!isbt) {
382			if (rtlpriv->falsealm_cnt.cnt_all >
383			    digtable->fa_lowthresh) {
384				if ((digtable->back_val - 2) <
385				   digtable->back_range_min)
386					digtable->back_val = digtable->back_range_min;
387				else
388					digtable->back_val -= 2;
389			} else if (rtlpriv->falsealm_cnt.cnt_all <
390				   digtable->fa_lowthresh) {
391				if ((digtable->back_val + 2) >
392				    digtable->back_range_max)
393					digtable->back_val = digtable->back_range_max;
394				else
395					digtable->back_val += 2;
396			}
397		} else {
398			digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
399		}
400	} else {
401		/* Adjust initial gain by false alarm */
402		if (rtlpriv->falsealm_cnt.cnt_all > 1000)
403			digtable->cur_igvalue = digtable->pre_igvalue + 2;
404		else if (rtlpriv->falsealm_cnt.cnt_all > 750)
405			digtable->cur_igvalue = digtable->pre_igvalue + 1;
406		else if (rtlpriv->falsealm_cnt.cnt_all < 500)
407			digtable->cur_igvalue = digtable->pre_igvalue - 1;
408	}
409
410	/* Check initial gain by upper/lower bound */
411	if (digtable->cur_igvalue > digtable->rx_gain_max)
412		digtable->cur_igvalue = digtable->rx_gain_max;
413
414	if (digtable->cur_igvalue < digtable->rx_gain_min)
415		digtable->cur_igvalue = digtable->rx_gain_min;
416
417	rtl92c_dm_write_dig(hw);
418}
419
420static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
421{
422	static u8 initialized; /* initialized to false */
423	struct rtl_priv *rtlpriv = rtl_priv(hw);
424	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
425	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
426	long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
427	bool multi_sta = false;
428
429	if (mac->opmode == NL80211_IFTYPE_ADHOC)
430		multi_sta = true;
431
432	if (!multi_sta ||
433	    dm_digtable->cursta_cstate == DIG_STA_DISCONNECT) {
434		initialized = false;
435		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
436		return;
437	} else if (initialized == false) {
438		initialized = true;
439		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
440		dm_digtable->cur_igvalue = 0x20;
441		rtl92c_dm_write_dig(hw);
442	}
443
444	if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
445		if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
446		    (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
447
448			if (dm_digtable->dig_ext_port_stage ==
449			    DIG_EXT_PORT_STAGE_2) {
450				dm_digtable->cur_igvalue = 0x20;
451				rtl92c_dm_write_dig(hw);
452			}
453
454			dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
455		} else if (rssi_strength > dm_digtable->rssi_highthresh) {
456			dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
457			rtl92c_dm_ctrl_initgain_by_fa(hw);
458		}
459	} else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
460		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
461		dm_digtable->cur_igvalue = 0x20;
462		rtl92c_dm_write_dig(hw);
463	}
464
465	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
466		 "curmultista_cstate = %x dig_ext_port_stage %x\n",
467		 dm_digtable->curmultista_cstate,
468		 dm_digtable->dig_ext_port_stage);
469}
470
471static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
472{
473	struct rtl_priv *rtlpriv = rtl_priv(hw);
474	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
475
476	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
477		 "presta_cstate = %x, cursta_cstate = %x\n",
478		 dm_digtable->presta_cstate, dm_digtable->cursta_cstate);
479	if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
480	    dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
481	    dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
482
483		if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
484			dm_digtable->rssi_val_min =
485			    rtl92c_dm_initial_gain_min_pwdb(hw);
486			if (dm_digtable->rssi_val_min > 100)
487				dm_digtable->rssi_val_min = 100;
488			rtl92c_dm_ctrl_initgain_by_rssi(hw);
489		}
490	} else {
491		dm_digtable->rssi_val_min = 0;
492		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
493		dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
494		dm_digtable->cur_igvalue = 0x20;
495		dm_digtable->pre_igvalue = 0;
496		rtl92c_dm_write_dig(hw);
497	}
498}
499
500static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
501{
502	struct rtl_priv *rtlpriv = rtl_priv(hw);
503	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
504
505	if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
506		dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
507		if (dm_digtable->rssi_val_min > 100)
508			dm_digtable->rssi_val_min = 100;
509
510		if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
511			if (dm_digtable->rssi_val_min <= 25)
512				dm_digtable->cur_cck_pd_state =
513				    CCK_PD_STAGE_LowRssi;
514			else
515				dm_digtable->cur_cck_pd_state =
516				    CCK_PD_STAGE_HighRssi;
517		} else {
518			if (dm_digtable->rssi_val_min <= 20)
519				dm_digtable->cur_cck_pd_state =
520				    CCK_PD_STAGE_LowRssi;
521			else
522				dm_digtable->cur_cck_pd_state =
523				    CCK_PD_STAGE_HighRssi;
524		}
525	} else {
526		dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
527	}
528
529	if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
530		if ((dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LowRssi) ||
531		    (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_MAX))
532			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x83);
533		else
534			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
535
536		dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
537	}
538}
539
540static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
541{
542	struct rtl_priv *rtlpriv = rtl_priv(hw);
543	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
544	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
545
546	if (mac->act_scanning)
547		return;
548
549	if (mac->link_state >= MAC80211_LINKED)
550		dm_digtable->cursta_cstate = DIG_STA_CONNECT;
551	else
552		dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
553
554	dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT;
555
556	rtl92c_dm_initial_gain_sta(hw);
557	rtl92c_dm_initial_gain_multi_sta(hw);
558	rtl92c_dm_cck_packet_detection_thresh(hw);
559
560	dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
561
562}
563
564static void rtl92c_dm_dig(struct ieee80211_hw *hw)
565{
566	struct rtl_priv *rtlpriv = rtl_priv(hw);
567
568	if (rtlpriv->dm.dm_initialgain_enable == false)
569		return;
570	if (!(rtlpriv->dm.dm_flag & DYNAMIC_FUNC_DIG))
571		return;
572
573	rtl92c_dm_ctrl_initgain_by_twoport(hw);
574}
575
576static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
577{
578	struct rtl_priv *rtlpriv = rtl_priv(hw);
579
580	if (rtlpriv->rtlhal.interface == INTF_USB &&
581	    rtlpriv->rtlhal.board_type & 0x1) {
582		dm_savepowerindex(hw);
583		rtlpriv->dm.dynamic_txpower_enable = true;
584	} else {
585		rtlpriv->dm.dynamic_txpower_enable = false;
586	}
587	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
588	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
589}
590
591void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
592{
593	struct rtl_priv *rtlpriv = rtl_priv(hw);
594	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
595
596	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
597		 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
598		 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
599		 dm_digtable->back_val);
600
601	if (rtlpriv->rtlhal.interface == INTF_USB &&
602	    !dm_digtable->dig_enable_flag) {
603		dm_digtable->pre_igvalue = 0x17;
604		return;
605	}
606	dm_digtable->cur_igvalue -= 1;
607	if (dm_digtable->cur_igvalue < DM_DIG_MIN)
608		dm_digtable->cur_igvalue = DM_DIG_MIN;
609
610	if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
611		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
612			      dm_digtable->cur_igvalue);
613		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
614			      dm_digtable->cur_igvalue);
615
616		dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
617	}
618	RT_TRACE(rtlpriv, COMP_DIG, DBG_WARNING,
619		 "dig values 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
620		 dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
621		 dm_digtable->rssi_val_min, dm_digtable->back_val,
622		 dm_digtable->rx_gain_max, dm_digtable->rx_gain_min,
623		 dm_digtable->large_fa_hit, dm_digtable->forbidden_igi);
624}
625EXPORT_SYMBOL(rtl92c_dm_write_dig);
626
627static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
628{
629	struct rtl_priv *rtlpriv = rtl_priv(hw);
630	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
631	long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
632
633	if (mac->link_state != MAC80211_LINKED)
634		return;
635
636	if (mac->opmode == NL80211_IFTYPE_ADHOC ||
637	    mac->opmode == NL80211_IFTYPE_AP) {
638		/* TODO: Handle ADHOC and AP Mode */
639	}
640
641	if (tmpentry_max_pwdb != 0)
642		rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb;
643	else
644		rtlpriv->dm.entry_max_undec_sm_pwdb = 0;
645
646	if (tmpentry_min_pwdb != 0xff)
647		rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb;
648	else
649		rtlpriv->dm.entry_min_undec_sm_pwdb = 0;
650
651/* TODO:
652 *	if (mac->opmode == NL80211_IFTYPE_STATION) {
653 *		if (rtlpriv->rtlhal.fw_ready) {
654 *			u32 param = (u32)(rtlpriv->dm.undec_sm_pwdb << 16);
655 *			rtl8192c_set_rssi_cmd(hw, param);
656 *		}
657 *	}
658 */
659}
660
661void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
662{
663	struct rtl_priv *rtlpriv = rtl_priv(hw);
664	rtlpriv->dm.current_turbo_edca = false;
665	rtlpriv->dm.is_any_nonbepkts = false;
666	rtlpriv->dm.is_cur_rdlstate = false;
667}
668EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
669
670static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
671{
672	struct rtl_priv *rtlpriv = rtl_priv(hw);
673	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
674	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
675
676	static u64 last_txok_cnt;
677	static u64 last_rxok_cnt;
678	static u32 last_bt_edca_ul;
679	static u32 last_bt_edca_dl;
680	u64 cur_txok_cnt = 0;
681	u64 cur_rxok_cnt = 0;
682	u32 edca_be_ul = 0x5ea42b;
683	u32 edca_be_dl = 0x5ea42b;
684	bool bt_change_edca = false;
685
686	if ((last_bt_edca_ul != rtlpcipriv->bt_coexist.bt_edca_ul) ||
687	    (last_bt_edca_dl != rtlpcipriv->bt_coexist.bt_edca_dl)) {
688		rtlpriv->dm.current_turbo_edca = false;
689		last_bt_edca_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
690		last_bt_edca_dl = rtlpcipriv->bt_coexist.bt_edca_dl;
691	}
692
693	if (rtlpcipriv->bt_coexist.bt_edca_ul != 0) {
694		edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_ul;
695		bt_change_edca = true;
696	}
697
698	if (rtlpcipriv->bt_coexist.bt_edca_dl != 0) {
699		edca_be_ul = rtlpcipriv->bt_coexist.bt_edca_dl;
700		bt_change_edca = true;
701	}
702
703	if (mac->link_state != MAC80211_LINKED) {
704		rtlpriv->dm.current_turbo_edca = false;
705		return;
706	}
707
708	if ((!mac->ht_enable) && (!rtlpcipriv->bt_coexist.bt_coexistence)) {
709		if (!(edca_be_ul & 0xffff0000))
710			edca_be_ul |= 0x005e0000;
711
712		if (!(edca_be_dl & 0xffff0000))
713			edca_be_dl |= 0x005e0000;
714	}
715
716	if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
717	     (!rtlpriv->dm.disable_framebursting))) {
718
719		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
720		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
721
722		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
723			if (!rtlpriv->dm.is_cur_rdlstate ||
724			    !rtlpriv->dm.current_turbo_edca) {
725				rtl_write_dword(rtlpriv,
726						REG_EDCA_BE_PARAM,
727						edca_be_dl);
728				rtlpriv->dm.is_cur_rdlstate = true;
729			}
730		} else {
731			if (rtlpriv->dm.is_cur_rdlstate ||
732			    !rtlpriv->dm.current_turbo_edca) {
733				rtl_write_dword(rtlpriv,
734						REG_EDCA_BE_PARAM,
735						edca_be_ul);
736				rtlpriv->dm.is_cur_rdlstate = false;
737			}
738		}
739		rtlpriv->dm.current_turbo_edca = true;
740	} else {
741		if (rtlpriv->dm.current_turbo_edca) {
742			u8 tmp = AC0_BE;
743			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
744						      &tmp);
745			rtlpriv->dm.current_turbo_edca = false;
746		}
747	}
748
749	rtlpriv->dm.is_any_nonbepkts = false;
750	last_txok_cnt = rtlpriv->stats.txbytesunicast;
751	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
752}
753
754static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
755							     *hw)
756{
757	struct rtl_priv *rtlpriv = rtl_priv(hw);
758	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
759	struct rtl_phy *rtlphy = &(rtlpriv->phy);
760	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
761	u8 thermalvalue, delta, delta_lck, delta_iqk;
762	long ele_a, ele_d, temp_cck, val_x, value32;
763	long val_y, ele_c = 0;
764	u8 ofdm_index[2], ofdm_index_old[2] = {0, 0}, cck_index_old = 0;
765	s8 cck_index = 0;
766	int i;
767	bool is2t = IS_92C_SERIAL(rtlhal->version);
768	s8 txpwr_level[3] = {0, 0, 0};
769	u8 ofdm_min_index = 6, rf;
770
771	rtlpriv->dm.txpower_trackinginit = true;
772	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
773		 "rtl92c_dm_txpower_tracking_callback_thermalmeter\n");
774
775	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
776
777	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
778		 "Readback Thermal Meter = 0x%x pre thermal meter 0x%x eeprom_thermalmeter 0x%x\n",
779		 thermalvalue, rtlpriv->dm.thermalvalue,
780		 rtlefuse->eeprom_thermalmeter);
781
782	rtl92c_phy_ap_calibrate(hw, (thermalvalue -
783				     rtlefuse->eeprom_thermalmeter));
784	if (is2t)
785		rf = 2;
786	else
787		rf = 1;
788
789	if (thermalvalue) {
790		ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
791				      MASKDWORD) & MASKOFDM_D;
792
793		for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
794			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
795				ofdm_index_old[0] = (u8) i;
796
797				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
798					 "Initial pathA ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
799					 ROFDM0_XATXIQIMBALANCE,
800					 ele_d, ofdm_index_old[0]);
801				break;
802			}
803		}
804
805		if (is2t) {
806			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
807					      MASKDWORD) & MASKOFDM_D;
808
809			for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
810				if (ele_d == (ofdmswing_table[i] &
811				    MASKOFDM_D)) {
812					ofdm_index_old[1] = (u8) i;
813					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
814						 DBG_LOUD,
815						 "Initial pathB ele_d reg0x%x = 0x%lx, ofdm_index=0x%x\n",
816						 ROFDM0_XBTXIQIMBALANCE, ele_d,
817						 ofdm_index_old[1]);
818					break;
819				}
820			}
821		}
822
823		temp_cck =
824		    rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
825
826		for (i = 0; i < CCK_TABLE_LENGTH; i++) {
827			if (rtlpriv->dm.cck_inch14) {
828				if (memcmp((void *)&temp_cck,
829					   (void *)&cckswing_table_ch14[i][2],
830					   4) == 0) {
831					cck_index_old = (u8) i;
832
833					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
834						 DBG_LOUD,
835						 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch 14 %d\n",
836						 RCCK0_TXFILTER2, temp_cck,
837						 cck_index_old,
838						 rtlpriv->dm.cck_inch14);
839					break;
840				}
841			} else {
842				if (memcmp((void *)&temp_cck,
843					   (void *)
844					   &cckswing_table_ch1ch13[i][2],
845					   4) == 0) {
846					cck_index_old = (u8) i;
847
848					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
849						 DBG_LOUD,
850						 "Initial reg0x%x = 0x%lx, cck_index=0x%x, ch14 %d\n",
851						 RCCK0_TXFILTER2, temp_cck,
852						 cck_index_old,
853						 rtlpriv->dm.cck_inch14);
854					break;
855				}
856			}
857		}
858
859		if (!rtlpriv->dm.thermalvalue) {
860			rtlpriv->dm.thermalvalue =
861			    rtlefuse->eeprom_thermalmeter;
862			rtlpriv->dm.thermalvalue_lck = thermalvalue;
863			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
864			for (i = 0; i < rf; i++)
865				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
866			rtlpriv->dm.cck_index = cck_index_old;
867		}
868		/* Handle USB High PA boards */
869
870		delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
871		    (thermalvalue - rtlpriv->dm.thermalvalue) :
872		    (rtlpriv->dm.thermalvalue - thermalvalue);
873
874		delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
875		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
876		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
877
878		delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
879		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
880		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
881
882		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
883			 "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",
884			 thermalvalue, rtlpriv->dm.thermalvalue,
885			 rtlefuse->eeprom_thermalmeter, delta, delta_lck,
886			 delta_iqk);
887
888		if (delta_lck > 1) {
889			rtlpriv->dm.thermalvalue_lck = thermalvalue;
890			rtl92c_phy_lc_calibrate(hw);
891		}
892
893		if (delta > 0 && rtlpriv->dm.txpower_track_control) {
894			if (thermalvalue > rtlpriv->dm.thermalvalue) {
895				for (i = 0; i < rf; i++)
896					rtlpriv->dm.ofdm_index[i] -= delta;
897				rtlpriv->dm.cck_index -= delta;
898			} else {
899				for (i = 0; i < rf; i++)
900					rtlpriv->dm.ofdm_index[i] += delta;
901				rtlpriv->dm.cck_index += delta;
902			}
903
904			if (is2t) {
905				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
906					 "temp OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
907					 rtlpriv->dm.ofdm_index[0],
908					 rtlpriv->dm.ofdm_index[1],
909					 rtlpriv->dm.cck_index);
910			} else {
911				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
912					 "temp OFDM_A_index=0x%x, cck_index=0x%x\n",
913					 rtlpriv->dm.ofdm_index[0],
914					 rtlpriv->dm.cck_index);
915			}
916
917			if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
918				for (i = 0; i < rf; i++)
919					ofdm_index[i] =
920					    rtlpriv->dm.ofdm_index[i]
921					    + 1;
922				cck_index = rtlpriv->dm.cck_index + 1;
923			} else {
924				for (i = 0; i < rf; i++)
925					ofdm_index[i] =
926					    rtlpriv->dm.ofdm_index[i];
927				cck_index = rtlpriv->dm.cck_index;
928			}
929
930			for (i = 0; i < rf; i++) {
931				if (txpwr_level[i] >= 0 &&
932				    txpwr_level[i] <= 26) {
933					if (thermalvalue >
934					    rtlefuse->eeprom_thermalmeter) {
935						if (delta < 5)
936							ofdm_index[i] -= 1;
937
938						else
939							ofdm_index[i] -= 2;
940					} else if (delta > 5 && thermalvalue <
941						   rtlefuse->
942						   eeprom_thermalmeter) {
943						ofdm_index[i] += 1;
944					}
945				} else if (txpwr_level[i] >= 27 &&
946					   txpwr_level[i] <= 32
947					   && thermalvalue >
948					   rtlefuse->eeprom_thermalmeter) {
949					if (delta < 5)
950						ofdm_index[i] -= 1;
951
952					else
953						ofdm_index[i] -= 2;
954				} else if (txpwr_level[i] >= 32 &&
955					   txpwr_level[i] <= 38 &&
956					   thermalvalue >
957					   rtlefuse->eeprom_thermalmeter
958					   && delta > 5) {
959					ofdm_index[i] -= 1;
960				}
961			}
962
963			if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
964				if (thermalvalue >
965				    rtlefuse->eeprom_thermalmeter) {
966					if (delta < 5)
967						cck_index -= 1;
968
969					else
970						cck_index -= 2;
971				} else if (delta > 5 && thermalvalue <
972					   rtlefuse->eeprom_thermalmeter) {
973					cck_index += 1;
974				}
975			} else if (txpwr_level[i] >= 27 &&
976				   txpwr_level[i] <= 32 &&
977				   thermalvalue >
978				   rtlefuse->eeprom_thermalmeter) {
979				if (delta < 5)
980					cck_index -= 1;
981
982				else
983					cck_index -= 2;
984			} else if (txpwr_level[i] >= 32 &&
985				   txpwr_level[i] <= 38 &&
986				   thermalvalue > rtlefuse->eeprom_thermalmeter
987				   && delta > 5) {
988				cck_index -= 1;
989			}
990
991			for (i = 0; i < rf; i++) {
992				if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
993					ofdm_index[i] = OFDM_TABLE_SIZE - 1;
994
995				else if (ofdm_index[i] < ofdm_min_index)
996					ofdm_index[i] = ofdm_min_index;
997			}
998
999			if (cck_index > CCK_TABLE_SIZE - 1)
1000				cck_index = CCK_TABLE_SIZE - 1;
1001			else if (cck_index < 0)
1002				cck_index = 0;
1003
1004			if (is2t) {
1005				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1006					 "new OFDM_A_index=0x%x, OFDM_B_index=0x%x, cck_index=0x%x\n",
1007					 ofdm_index[0], ofdm_index[1],
1008					 cck_index);
1009			} else {
1010				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1011					 "new OFDM_A_index=0x%x, cck_index=0x%x\n",
1012					 ofdm_index[0], cck_index);
1013			}
1014		}
1015
1016		if (rtlpriv->dm.txpower_track_control && delta != 0) {
1017			ele_d =
1018			    (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
1019			val_x = rtlphy->reg_e94;
1020			val_y = rtlphy->reg_e9c;
1021
1022			if (val_x != 0) {
1023				if ((val_x & 0x00000200) != 0)
1024					val_x = val_x | 0xFFFFFC00;
1025				ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
1026
1027				if ((val_y & 0x00000200) != 0)
1028					val_y = val_y | 0xFFFFFC00;
1029				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
1030
1031				value32 = (ele_d << 22) |
1032				    ((ele_c & 0x3F) << 16) | ele_a;
1033
1034				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
1035					      MASKDWORD, value32);
1036
1037				value32 = (ele_c & 0x000003C0) >> 6;
1038				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
1039					      value32);
1040
1041				value32 = ((val_x * ele_d) >> 7) & 0x01;
1042				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1043					      BIT(31), value32);
1044
1045				value32 = ((val_y * ele_d) >> 7) & 0x01;
1046				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1047					      BIT(29), value32);
1048			} else {
1049				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
1050					      MASKDWORD,
1051					      ofdmswing_table[ofdm_index[0]]);
1052
1053				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
1054					      0x00);
1055				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1056					      BIT(31) | BIT(29), 0x00);
1057			}
1058
1059			if (!rtlpriv->dm.cck_inch14) {
1060				rtl_write_byte(rtlpriv, 0xa22,
1061					       cckswing_table_ch1ch13[cck_index]
1062					       [0]);
1063				rtl_write_byte(rtlpriv, 0xa23,
1064					       cckswing_table_ch1ch13[cck_index]
1065					       [1]);
1066				rtl_write_byte(rtlpriv, 0xa24,
1067					       cckswing_table_ch1ch13[cck_index]
1068					       [2]);
1069				rtl_write_byte(rtlpriv, 0xa25,
1070					       cckswing_table_ch1ch13[cck_index]
1071					       [3]);
1072				rtl_write_byte(rtlpriv, 0xa26,
1073					       cckswing_table_ch1ch13[cck_index]
1074					       [4]);
1075				rtl_write_byte(rtlpriv, 0xa27,
1076					       cckswing_table_ch1ch13[cck_index]
1077					       [5]);
1078				rtl_write_byte(rtlpriv, 0xa28,
1079					       cckswing_table_ch1ch13[cck_index]
1080					       [6]);
1081				rtl_write_byte(rtlpriv, 0xa29,
1082					       cckswing_table_ch1ch13[cck_index]
1083					       [7]);
1084			} else {
1085				rtl_write_byte(rtlpriv, 0xa22,
1086					       cckswing_table_ch14[cck_index]
1087					       [0]);
1088				rtl_write_byte(rtlpriv, 0xa23,
1089					       cckswing_table_ch14[cck_index]
1090					       [1]);
1091				rtl_write_byte(rtlpriv, 0xa24,
1092					       cckswing_table_ch14[cck_index]
1093					       [2]);
1094				rtl_write_byte(rtlpriv, 0xa25,
1095					       cckswing_table_ch14[cck_index]
1096					       [3]);
1097				rtl_write_byte(rtlpriv, 0xa26,
1098					       cckswing_table_ch14[cck_index]
1099					       [4]);
1100				rtl_write_byte(rtlpriv, 0xa27,
1101					       cckswing_table_ch14[cck_index]
1102					       [5]);
1103				rtl_write_byte(rtlpriv, 0xa28,
1104					       cckswing_table_ch14[cck_index]
1105					       [6]);
1106				rtl_write_byte(rtlpriv, 0xa29,
1107					       cckswing_table_ch14[cck_index]
1108					       [7]);
1109			}
1110
1111			if (is2t) {
1112				ele_d = (ofdmswing_table[ofdm_index[1]] &
1113					 0xFFC00000) >> 22;
1114
1115				val_x = rtlphy->reg_eb4;
1116				val_y = rtlphy->reg_ebc;
1117
1118				if (val_x != 0) {
1119					if ((val_x & 0x00000200) != 0)
1120						val_x = val_x | 0xFFFFFC00;
1121					ele_a = ((val_x * ele_d) >> 8) &
1122					    0x000003FF;
1123
1124					if ((val_y & 0x00000200) != 0)
1125						val_y = val_y | 0xFFFFFC00;
1126					ele_c = ((val_y * ele_d) >> 8) &
1127					    0x00003FF;
1128
1129					value32 = (ele_d << 22) |
1130					    ((ele_c & 0x3F) << 16) | ele_a;
1131					rtl_set_bbreg(hw,
1132						      ROFDM0_XBTXIQIMBALANCE,
1133						      MASKDWORD, value32);
1134
1135					value32 = (ele_c & 0x000003C0) >> 6;
1136					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1137						      MASKH4BITS, value32);
1138
1139					value32 = ((val_x * ele_d) >> 7) & 0x01;
1140					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1141						      BIT(27), value32);
1142
1143					value32 = ((val_y * ele_d) >> 7) & 0x01;
1144					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1145						      BIT(25), value32);
1146				} else {
1147					rtl_set_bbreg(hw,
1148						      ROFDM0_XBTXIQIMBALANCE,
1149						      MASKDWORD,
1150						      ofdmswing_table[ofdm_index
1151								      [1]]);
1152					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
1153						      MASKH4BITS, 0x00);
1154					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
1155						      BIT(27) | BIT(25), 0x00);
1156				}
1157
1158			}
1159		}
1160
1161		if (delta_iqk > 3) {
1162			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
1163			rtl92c_phy_iq_calibrate(hw, false);
1164		}
1165
1166		if (rtlpriv->dm.txpower_track_control)
1167			rtlpriv->dm.thermalvalue = thermalvalue;
1168	}
1169
1170	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===\n");
1171
1172}
1173
1174static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
1175						struct ieee80211_hw *hw)
1176{
1177	struct rtl_priv *rtlpriv = rtl_priv(hw);
1178
1179	rtlpriv->dm.txpower_tracking = true;
1180	rtlpriv->dm.txpower_trackinginit = false;
1181
1182	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1183		 "pMgntInfo->txpower_tracking = %d\n",
1184		 rtlpriv->dm.txpower_tracking);
1185}
1186
1187static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
1188{
1189	rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
1190}
1191
1192static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
1193{
1194	rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
1195}
1196
1197static void rtl92c_dm_check_txpower_tracking_thermal_meter(
1198						struct ieee80211_hw *hw)
1199{
1200	struct rtl_priv *rtlpriv = rtl_priv(hw);
1201	static u8 tm_trigger;
1202
1203	if (!rtlpriv->dm.txpower_tracking)
1204		return;
1205
1206	if (!tm_trigger) {
1207		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
1208			      0x60);
1209		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1210			 "Trigger 92S Thermal Meter!!\n");
1211		tm_trigger = 1;
1212		return;
1213	} else {
1214		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
1215			 "Schedule TxPowerTracking direct call!!\n");
1216		rtl92c_dm_txpower_tracking_directcall(hw);
1217		tm_trigger = 0;
1218	}
1219}
1220
1221void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
1222{
1223	rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
1224}
1225EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
1226
1227void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
1228{
1229	struct rtl_priv *rtlpriv = rtl_priv(hw);
1230	struct rate_adaptive *p_ra = &(rtlpriv->ra);
1231
1232	p_ra->ratr_state = DM_RATR_STA_INIT;
1233	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
1234
1235	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
1236		rtlpriv->dm.useramask = true;
1237	else
1238		rtlpriv->dm.useramask = false;
1239
1240}
1241EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
1242
1243static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1244{
1245	struct rtl_priv *rtlpriv = rtl_priv(hw);
1246	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1247
1248	dm_pstable->pre_ccastate = CCA_MAX;
1249	dm_pstable->cur_ccasate = CCA_MAX;
1250	dm_pstable->pre_rfstate = RF_MAX;
1251	dm_pstable->cur_rfstate = RF_MAX;
1252	dm_pstable->rssi_val_min = 0;
1253}
1254
1255void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
1256{
1257	struct rtl_priv *rtlpriv = rtl_priv(hw);
1258	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1259
1260	if (!rtlpriv->reg_init) {
1261		rtlpriv->reg_874 = (rtl_get_bbreg(hw,
1262						  RFPGA0_XCD_RFINTERFACESW,
1263						  MASKDWORD) & 0x1CC000) >> 14;
1264
1265		rtlpriv->reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
1266				    MASKDWORD) & BIT(3)) >> 3;
1267
1268		rtlpriv->reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1269				    MASKDWORD) & 0xFF000000) >> 24;
1270
1271		rtlpriv->reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) &
1272				    0xF000) >> 12;
1273
1274		rtlpriv->reg_init = true;
1275	}
1276
1277	if (!bforce_in_normal) {
1278		if (dm_pstable->rssi_val_min != 0) {
1279			if (dm_pstable->pre_rfstate == RF_NORMAL) {
1280				if (dm_pstable->rssi_val_min >= 30)
1281					dm_pstable->cur_rfstate = RF_SAVE;
1282				else
1283					dm_pstable->cur_rfstate = RF_NORMAL;
1284			} else {
1285				if (dm_pstable->rssi_val_min <= 25)
1286					dm_pstable->cur_rfstate = RF_NORMAL;
1287				else
1288					dm_pstable->cur_rfstate = RF_SAVE;
1289			}
1290		} else {
1291			dm_pstable->cur_rfstate = RF_MAX;
1292		}
1293	} else {
1294		dm_pstable->cur_rfstate = RF_NORMAL;
1295	}
1296
1297	if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
1298		if (dm_pstable->cur_rfstate == RF_SAVE) {
1299			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1300				      0x1C0000, 0x2);
1301			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
1302			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
1303				      0xFF000000, 0x63);
1304			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1305				      0xC000, 0x2);
1306			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
1307			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1308			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
1309		} else {
1310			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
1311				      0x1CC000, rtlpriv->reg_874);
1312			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
1313				      rtlpriv->reg_c70);
1314			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
1315				      rtlpriv->reg_85c);
1316			rtl_set_bbreg(hw, 0xa74, 0xF000, rtlpriv->reg_a74);
1317			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
1318		}
1319
1320		dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
1321	}
1322}
1323EXPORT_SYMBOL(rtl92c_dm_rf_saving);
1324
1325static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
1326{
1327	struct rtl_priv *rtlpriv = rtl_priv(hw);
1328	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
1329	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1330	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1331
1332	/* Determine the minimum RSSI */
1333	if (((mac->link_state == MAC80211_NOLINK)) &&
1334	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1335		dm_pstable->rssi_val_min = 0;
1336		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n");
1337	}
1338
1339	if (mac->link_state == MAC80211_LINKED) {
1340		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1341			dm_pstable->rssi_val_min =
1342			    rtlpriv->dm.entry_min_undec_sm_pwdb;
1343			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1344				 "AP Client PWDB = 0x%lx\n",
1345				 dm_pstable->rssi_val_min);
1346		} else {
1347			dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
1348			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1349				 "STA Default Port PWDB = 0x%lx\n",
1350				 dm_pstable->rssi_val_min);
1351		}
1352	} else {
1353		dm_pstable->rssi_val_min =
1354		    rtlpriv->dm.entry_min_undec_sm_pwdb;
1355
1356		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
1357			 "AP Ext Port PWDB = 0x%lx\n",
1358			 dm_pstable->rssi_val_min);
1359	}
1360
1361	/* Power Saving for 92C */
1362	if (IS_92C_SERIAL(rtlhal->version))
1363		;/* rtl92c_dm_1r_cca(hw); */
1364	else
1365		rtl92c_dm_rf_saving(hw, false);
1366}
1367
1368void rtl92c_dm_init(struct ieee80211_hw *hw)
1369{
1370	struct rtl_priv *rtlpriv = rtl_priv(hw);
1371
1372	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1373	rtlpriv->dm.dm_flag = DYNAMIC_FUNC_DISABLE | DYNAMIC_FUNC_DIG;
1374	rtlpriv->dm.undec_sm_pwdb = -1;
1375	rtlpriv->dm.undec_sm_cck = -1;
1376	rtlpriv->dm.dm_initialgain_enable = true;
1377	rtl92c_dm_diginit(hw);
1378
1379	rtlpriv->dm.dm_flag |= HAL_DM_HIPWR_DISABLE;
1380	rtl92c_dm_init_dynamic_txpower(hw);
1381
1382	rtl92c_dm_init_edca_turbo(hw);
1383	rtl92c_dm_init_rate_adaptive_mask(hw);
1384	rtlpriv->dm.dm_flag |= DYNAMIC_FUNC_SS;
1385	rtl92c_dm_initialize_txpower_tracking(hw);
1386	rtl92c_dm_init_dynamic_bb_powersaving(hw);
1387
1388	rtlpriv->dm.ofdm_pkt_cnt = 0;
1389	rtlpriv->dm.dm_rssi_sel = RSSI_DEFAULT;
1390}
1391EXPORT_SYMBOL(rtl92c_dm_init);
1392
1393void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
1394{
1395	struct rtl_priv *rtlpriv = rtl_priv(hw);
1396	struct rtl_phy *rtlphy = &(rtlpriv->phy);
1397	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1398	long undec_sm_pwdb;
1399
1400	if (!rtlpriv->dm.dynamic_txpower_enable)
1401		return;
1402
1403	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
1404		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1405		return;
1406	}
1407
1408	if ((mac->link_state < MAC80211_LINKED) &&
1409	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
1410		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
1411			 "Not connected to any\n");
1412
1413		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1414
1415		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
1416		return;
1417	}
1418
1419	if (mac->link_state >= MAC80211_LINKED) {
1420		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
1421			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1422			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1423				 "AP Client PWDB = 0x%lx\n",
1424				 undec_sm_pwdb);
1425		} else {
1426			undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
1427			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1428				 "STA Default Port PWDB = 0x%lx\n",
1429				 undec_sm_pwdb);
1430		}
1431	} else {
1432		undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1433
1434		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1435			 "AP Ext Port PWDB = 0x%lx\n",
1436			 undec_sm_pwdb);
1437	}
1438
1439	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
1440		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL2;
1441		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1442			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
1443	} else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
1444		   (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
1445
1446		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
1447		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1448			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
1449	} else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
1450		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
1451		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1452			 "TXHIGHPWRLEVEL_NORMAL\n");
1453	}
1454
1455	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
1456		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
1457			 "PHY_SetTxPowerLevel8192S() Channel = %d\n",
1458			 rtlphy->current_channel);
1459		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
1460		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1461		    TXHIGHPWRLEVEL_NORMAL)
1462			dm_restorepowerindex(hw);
1463		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1464			 TXHIGHPWRLEVEL_LEVEL1)
1465			dm_writepowerindex(hw, 0x14);
1466		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
1467			 TXHIGHPWRLEVEL_LEVEL2)
1468			dm_writepowerindex(hw, 0x10);
1469	}
1470	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
1471}
1472
1473void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
1474{
1475	struct rtl_priv *rtlpriv = rtl_priv(hw);
1476	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1477	bool fw_current_inpsmode = false;
1478	bool fw_ps_awake = true;
1479
1480	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1481				      (u8 *) (&fw_current_inpsmode));
1482	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1483				      (u8 *) (&fw_ps_awake));
1484
1485	if (ppsc->p2p_ps_info.p2p_ps_mode)
1486		fw_ps_awake = false;
1487
1488	if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
1489					     fw_ps_awake)
1490	    && (!ppsc->rfchange_inprogress)) {
1491		rtl92c_dm_pwdb_monitor(hw);
1492		rtl92c_dm_dig(hw);
1493		rtl92c_dm_false_alarm_counter_statistics(hw);
1494		rtl92c_dm_dynamic_bb_powersaving(hw);
1495		rtl92c_dm_dynamic_txpower(hw);
1496		rtl92c_dm_check_txpower_tracking(hw);
1497		/* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
1498		rtl92c_dm_bt_coexist(hw);
1499		rtl92c_dm_check_edca_turbo(hw);
1500	}
1501}
1502EXPORT_SYMBOL(rtl92c_dm_watchdog);
1503
1504u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw)
1505{
1506	struct rtl_priv *rtlpriv = rtl_priv(hw);
1507	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1508	long undec_sm_pwdb;
1509	u8 curr_bt_rssi_state = 0x00;
1510
1511	if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
1512		undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv);
1513	} else {
1514		if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)
1515			undec_sm_pwdb = 100;
1516		else
1517			undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb;
1518	}
1519
1520	/* Check RSSI to determine HighPower/NormalPower state for
1521	 * BT coexistence. */
1522	if (undec_sm_pwdb >= 67)
1523		curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER);
1524	else if (undec_sm_pwdb < 62)
1525		curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER;
1526
1527	/* Check RSSI to determine AMPDU setting for BT coexistence. */
1528	if (undec_sm_pwdb >= 40)
1529		curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF);
1530	else if (undec_sm_pwdb <= 32)
1531		curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF;
1532
1533	/* Marked RSSI state. It will be used to determine BT coexistence
1534	 * setting later. */
1535	if (undec_sm_pwdb < 35)
1536		curr_bt_rssi_state |=  BT_RSSI_STATE_SPECIAL_LOW;
1537	else
1538		curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW);
1539
1540	/* Check BT state related to BT_Idle in B/G mode. */
1541	if (undec_sm_pwdb < 15)
1542		curr_bt_rssi_state |=  BT_RSSI_STATE_BG_EDCA_LOW;
1543	else
1544		curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW);
1545
1546	if (curr_bt_rssi_state != rtlpcipriv->bt_coexist.bt_rssi_state) {
1547		rtlpcipriv->bt_coexist.bt_rssi_state = curr_bt_rssi_state;
1548		return true;
1549	} else {
1550		return false;
1551	}
1552}
1553EXPORT_SYMBOL(rtl92c_bt_rssi_state_change);
1554
1555static bool rtl92c_bt_state_change(struct ieee80211_hw *hw)
1556{
1557	struct rtl_priv *rtlpriv = rtl_priv(hw);
1558	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1559
1560	u32 polling, ratio_tx, ratio_pri;
1561	u32 bt_tx, bt_pri;
1562	u8 bt_state;
1563	u8 cur_service_type;
1564
1565	if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
1566		return false;
1567
1568	bt_state = rtl_read_byte(rtlpriv, 0x4fd);
1569	bt_tx = rtl_read_dword(rtlpriv, 0x488);
1570	bt_tx = bt_tx & 0x00ffffff;
1571	bt_pri = rtl_read_dword(rtlpriv, 0x48c);
1572	bt_pri = bt_pri & 0x00ffffff;
1573	polling = rtl_read_dword(rtlpriv, 0x490);
1574
1575	if (bt_tx == 0xffffffff && bt_pri == 0xffffffff &&
1576	    polling == 0xffffffff && bt_state == 0xff)
1577		return false;
1578
1579	bt_state &= BIT_OFFSET_LEN_MASK_32(0, 1);
1580	if (bt_state != rtlpcipriv->bt_coexist.bt_cur_state) {
1581		rtlpcipriv->bt_coexist.bt_cur_state = bt_state;
1582
1583		if (rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
1584			rtlpcipriv->bt_coexist.bt_service = BT_IDLE;
1585
1586			bt_state = bt_state |
1587			  ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
1588			  0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1589			  BIT_OFFSET_LEN_MASK_32(2, 1);
1590			rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1591		}
1592		return true;
1593	}
1594
1595	ratio_tx = bt_tx * 1000 / polling;
1596	ratio_pri = bt_pri * 1000 / polling;
1597	rtlpcipriv->bt_coexist.ratio_tx = ratio_tx;
1598	rtlpcipriv->bt_coexist.ratio_pri = ratio_pri;
1599
1600	if (bt_state && rtlpcipriv->bt_coexist.reg_bt_sco == 3) {
1601
1602		if ((ratio_tx < 30)  && (ratio_pri < 30))
1603			cur_service_type = BT_IDLE;
1604		else if ((ratio_pri > 110) && (ratio_pri < 250))
1605			cur_service_type = BT_SCO;
1606		else if ((ratio_tx >= 200) && (ratio_pri >= 200))
1607			cur_service_type = BT_BUSY;
1608		else if ((ratio_tx >= 350) && (ratio_tx < 500))
1609			cur_service_type = BT_OTHERBUSY;
1610		else if (ratio_tx >= 500)
1611			cur_service_type = BT_PAN;
1612		else
1613			cur_service_type = BT_OTHER_ACTION;
1614
1615		if (cur_service_type != rtlpcipriv->bt_coexist.bt_service) {
1616			rtlpcipriv->bt_coexist.bt_service = cur_service_type;
1617			bt_state = bt_state |
1618			   ((rtlpcipriv->bt_coexist.bt_ant_isolation == 1) ?
1619			   0 : BIT_OFFSET_LEN_MASK_32(1, 1)) |
1620			   ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) ?
1621			   0 : BIT_OFFSET_LEN_MASK_32(2, 1));
1622
1623			/* Add interrupt migration when bt is not ini
1624			 * idle state (no traffic). */
1625			if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1626				rtl_write_word(rtlpriv, 0x504, 0x0ccc);
1627				rtl_write_byte(rtlpriv, 0x506, 0x54);
1628				rtl_write_byte(rtlpriv, 0x507, 0x54);
1629			} else {
1630				rtl_write_byte(rtlpriv, 0x506, 0x00);
1631				rtl_write_byte(rtlpriv, 0x507, 0x00);
1632			}
1633
1634			rtl_write_byte(rtlpriv, 0x4fd, bt_state);
1635			return true;
1636		}
1637	}
1638
1639	return false;
1640
1641}
1642
1643static bool rtl92c_bt_wifi_connect_change(struct ieee80211_hw *hw)
1644{
1645	struct rtl_priv *rtlpriv = rtl_priv(hw);
1646	static bool media_connect;
1647
1648	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
1649		media_connect = false;
1650	} else {
1651		if (!media_connect) {
1652			media_connect = true;
1653			return true;
1654		}
1655		media_connect = true;
1656	}
1657
1658	return false;
1659}
1660
1661static void rtl92c_bt_set_normal(struct ieee80211_hw *hw)
1662{
1663	struct rtl_priv *rtlpriv = rtl_priv(hw);
1664	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1665
1666
1667	if (rtlpcipriv->bt_coexist.bt_service == BT_OTHERBUSY) {
1668		rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72b;
1669		rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72b;
1670	} else if (rtlpcipriv->bt_coexist.bt_service == BT_BUSY) {
1671		rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82f;
1672		rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82f;
1673	} else if (rtlpcipriv->bt_coexist.bt_service == BT_SCO) {
1674		if (rtlpcipriv->bt_coexist.ratio_tx > 160) {
1675			rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea72f;
1676			rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea72f;
1677		} else {
1678			rtlpcipriv->bt_coexist.bt_edca_ul = 0x5ea32b;
1679			rtlpcipriv->bt_coexist.bt_edca_dl = 0x5ea42b;
1680		}
1681	} else {
1682		rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1683		rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1684	}
1685
1686	if ((rtlpcipriv->bt_coexist.bt_service != BT_IDLE) &&
1687	     (rtlpriv->mac80211.mode == WIRELESS_MODE_G ||
1688	     (rtlpriv->mac80211.mode == (WIRELESS_MODE_G | WIRELESS_MODE_B))) &&
1689	     (rtlpcipriv->bt_coexist.bt_rssi_state &
1690	     BT_RSSI_STATE_BG_EDCA_LOW)) {
1691		rtlpcipriv->bt_coexist.bt_edca_ul = 0x5eb82b;
1692		rtlpcipriv->bt_coexist.bt_edca_dl = 0x5eb82b;
1693	}
1694}
1695
1696static void rtl92c_bt_ant_isolation(struct ieee80211_hw *hw, u8 tmp1byte)
1697{
1698	struct rtl_priv *rtlpriv = rtl_priv(hw);
1699	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1700
1701
1702	/* Only enable HW BT coexist when BT in "Busy" state. */
1703	if (rtlpriv->mac80211.vendor == PEER_CISCO &&
1704	    rtlpcipriv->bt_coexist.bt_service == BT_OTHER_ACTION) {
1705		rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1706	} else {
1707		if ((rtlpcipriv->bt_coexist.bt_service == BT_BUSY) &&
1708		    (rtlpcipriv->bt_coexist.bt_rssi_state &
1709		     BT_RSSI_STATE_NORMAL_POWER)) {
1710			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1711		} else if ((rtlpcipriv->bt_coexist.bt_service ==
1712			    BT_OTHER_ACTION) && (rtlpriv->mac80211.mode <
1713			    WIRELESS_MODE_N_24G) &&
1714			    (rtlpcipriv->bt_coexist.bt_rssi_state &
1715			    BT_RSSI_STATE_SPECIAL_LOW)) {
1716			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, 0xa0);
1717		} else if (rtlpcipriv->bt_coexist.bt_service == BT_PAN) {
1718			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1719		} else {
1720			rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1721		}
1722	}
1723
1724	if (rtlpcipriv->bt_coexist.bt_service == BT_PAN)
1725		rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x10100);
1726	else
1727		rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, 0x0);
1728
1729	if (rtlpcipriv->bt_coexist.bt_rssi_state &
1730	    BT_RSSI_STATE_NORMAL_POWER) {
1731		rtl92c_bt_set_normal(hw);
1732	} else {
1733		rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1734		rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1735	}
1736
1737	if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1738		rtlpriv->cfg->ops->set_rfreg(hw,
1739				 RF90_PATH_A,
1740				 0x1e,
1741				 0xf0, 0xf);
1742	} else {
1743		rtlpriv->cfg->ops->set_rfreg(hw,
1744		     RF90_PATH_A, 0x1e, 0xf0,
1745		     rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
1746	}
1747
1748	if (!rtlpriv->dm.dynamic_txpower_enable) {
1749		if (rtlpcipriv->bt_coexist.bt_service != BT_IDLE) {
1750			if (rtlpcipriv->bt_coexist.bt_rssi_state &
1751				BT_RSSI_STATE_TXPOWER_LOW) {
1752				rtlpriv->dm.dynamic_txhighpower_lvl =
1753							TXHIGHPWRLEVEL_BT2;
1754			} else {
1755				rtlpriv->dm.dynamic_txhighpower_lvl =
1756					TXHIGHPWRLEVEL_BT1;
1757			}
1758		} else {
1759			rtlpriv->dm.dynamic_txhighpower_lvl =
1760				TXHIGHPWRLEVEL_NORMAL;
1761		}
1762		rtl92c_phy_set_txpower_level(hw,
1763			rtlpriv->phy.current_channel);
1764	}
1765}
1766
1767static void rtl92c_check_bt_change(struct ieee80211_hw *hw)
1768{
1769	struct rtl_priv *rtlpriv = rtl_priv(hw);
1770	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1771	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1772	u8 tmp1byte = 0;
1773
1774	if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version) &&
1775	    rtlpcipriv->bt_coexist.bt_coexistence)
1776		tmp1byte |= BIT(5);
1777	if (rtlpcipriv->bt_coexist.bt_cur_state) {
1778		if (rtlpcipriv->bt_coexist.bt_ant_isolation)
1779			rtl92c_bt_ant_isolation(hw, tmp1byte);
1780	} else {
1781		rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG, tmp1byte);
1782		rtlpriv->cfg->ops->set_rfreg(hw, RF90_PATH_A, 0x1e, 0xf0,
1783				rtlpcipriv->bt_coexist.bt_rfreg_origin_1e);
1784
1785		rtlpcipriv->bt_coexist.bt_edca_ul = 0;
1786		rtlpcipriv->bt_coexist.bt_edca_dl = 0;
1787	}
1788}
1789
1790void rtl92c_dm_bt_coexist(struct ieee80211_hw *hw)
1791{
1792	struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw);
1793
1794	bool wifi_connect_change;
1795	bool bt_state_change;
1796	bool rssi_state_change;
1797
1798	if ((rtlpcipriv->bt_coexist.bt_coexistence) &&
1799	     (rtlpcipriv->bt_coexist.bt_coexist_type == BT_CSR_BC4)) {
1800
1801		wifi_connect_change = rtl92c_bt_wifi_connect_change(hw);
1802		bt_state_change = rtl92c_bt_state_change(hw);
1803		rssi_state_change = rtl92c_bt_rssi_state_change(hw);
1804
1805		if (wifi_connect_change || bt_state_change || rssi_state_change)
1806			rtl92c_check_bt_change(hw);
1807	}
1808}
1809EXPORT_SYMBOL(rtl92c_dm_bt_coexist);
1810