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 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
16 *
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
21 *
22 * Larry Finger <Larry.Finger@lwfinger.net>
23 *
24 *****************************************************************************/
25
26#include "../wifi.h"
27#include "../base.h"
28#include "../pci.h"
29#include "../core.h"
30#include "reg.h"
31#include "def.h"
32#include "phy.h"
33#include "dm.h"
34#include "../rtl8723com/dm_common.h"
35#include "fw.h"
36#include "hal_btc.h"
37
38static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
39	0x7f8001fe,
40	0x788001e2,
41	0x71c001c7,
42	0x6b8001ae,
43	0x65400195,
44	0x5fc0017f,
45	0x5a400169,
46	0x55400155,
47	0x50800142,
48	0x4c000130,
49	0x47c0011f,
50	0x43c0010f,
51	0x40000100,
52	0x3c8000f2,
53	0x390000e4,
54	0x35c000d7,
55	0x32c000cb,
56	0x300000c0,
57	0x2d4000b5,
58	0x2ac000ab,
59	0x288000a2,
60	0x26000098,
61	0x24000090,
62	0x22000088,
63	0x20000080,
64	0x1e400079,
65	0x1c800072,
66	0x1b00006c,
67	0x19800066,
68	0x18000060,
69	0x16c0005b,
70	0x15800056,
71	0x14400051,
72	0x1300004c,
73	0x12000048,
74	0x11000044,
75	0x10000040,
76};
77
78static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
79	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
80	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
81	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
82	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
83	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
84	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
85	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
86	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
87	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
88	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
89	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
90	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
91	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
92	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
93	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
94	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
95	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
96	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
97	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
98	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
99	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
100	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
101	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
102	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
103	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
104	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
105	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
106	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
107	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
108	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
109	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
110	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
111	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
112};
113
114static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
115	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
116	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
117	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
118	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
119	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
120	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
121	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
122	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
123	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
124	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
125	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
126	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
127	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
128	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
129	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
130	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
131	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
132	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
133	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
134	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
135	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
136	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
137	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
138	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
139	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
140	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
141	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
142	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
143	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
144	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
145	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
146	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
147	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
148};
149
150static u8 rtl8723e_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
151{
152	struct rtl_priv *rtlpriv = rtl_priv(hw);
153	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
154	long rssi_val_min = 0;
155
156	if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) &&
157	    (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) {
158		if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0)
159			rssi_val_min =
160			    (rtlpriv->dm.entry_min_undec_sm_pwdb >
161			     rtlpriv->dm.undec_sm_pwdb) ?
162			    rtlpriv->dm.undec_sm_pwdb :
163			    rtlpriv->dm.entry_min_undec_sm_pwdb;
164		else
165			rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
166	} else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT ||
167		   dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) {
168		rssi_val_min = rtlpriv->dm.undec_sm_pwdb;
169	} else if (dm_digtable->curmultista_cstate ==
170		DIG_MULTISTA_CONNECT) {
171		rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb;
172	}
173
174	return (u8) rssi_val_min;
175}
176
177static void rtl8723e_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
178{
179	u32 ret_value;
180	struct rtl_priv *rtlpriv = rtl_priv(hw);
181	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
182
183	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
184	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
185
186	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
187	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
188	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
189
190	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
191	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
192	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
193	    falsealm_cnt->cnt_rate_illegal +
194	    falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
195
196	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
197	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
198	falsealm_cnt->cnt_cck_fail = ret_value;
199
200	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
201	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
202	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
203				 falsealm_cnt->cnt_rate_illegal +
204				 falsealm_cnt->cnt_crc8_fail +
205				 falsealm_cnt->cnt_mcs_fail +
206				 falsealm_cnt->cnt_cck_fail);
207
208	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
209	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
210	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
211	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
212
213	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
214		 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
215		 falsealm_cnt->cnt_parity_fail,
216		 falsealm_cnt->cnt_rate_illegal,
217		 falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
218
219	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
220		 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
221		 falsealm_cnt->cnt_ofdm_fail,
222		 falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
223}
224
225static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
226{
227	struct rtl_priv *rtlpriv = rtl_priv(hw);
228	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
229	u8 value_igi = dm_digtable->cur_igvalue;
230
231	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
232		value_igi--;
233	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
234		value_igi += 0;
235	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
236		value_igi++;
237	else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
238		value_igi += 2;
239	if (value_igi > DM_DIG_FA_UPPER)
240		value_igi = DM_DIG_FA_UPPER;
241	else if (value_igi < DM_DIG_FA_LOWER)
242		value_igi = DM_DIG_FA_LOWER;
243	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
244		value_igi = 0x32;
245
246	dm_digtable->cur_igvalue = value_igi;
247	rtl8723e_dm_write_dig(hw);
248}
249
250static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
251{
252	struct rtl_priv *rtlpriv = rtl_priv(hw);
253	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
254
255	if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) {
256		if ((dm_digtable->back_val - 2) <
257		    dm_digtable->back_range_min)
258			dm_digtable->back_val =
259			    dm_digtable->back_range_min;
260		else
261			dm_digtable->back_val -= 2;
262	} else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) {
263		if ((dm_digtable->back_val + 2) >
264		    dm_digtable->back_range_max)
265			dm_digtable->back_val =
266			    dm_digtable->back_range_max;
267		else
268			dm_digtable->back_val += 2;
269	}
270
271	if ((dm_digtable->rssi_val_min + 10 - dm_digtable->back_val) >
272	    dm_digtable->rx_gain_max)
273		dm_digtable->cur_igvalue = dm_digtable->rx_gain_max;
274	else if ((dm_digtable->rssi_val_min + 10 -
275		  dm_digtable->back_val) < dm_digtable->rx_gain_min)
276		dm_digtable->cur_igvalue = dm_digtable->rx_gain_min;
277	else
278		dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 -
279		    dm_digtable->back_val;
280
281	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
282		 "rssi_val_min = %x back_val %x\n",
283		  dm_digtable->rssi_val_min, dm_digtable->back_val);
284
285	rtl8723e_dm_write_dig(hw);
286}
287
288static void rtl8723e_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
289{
290	static u8 binitialized;
291	struct rtl_priv *rtlpriv = rtl_priv(hw);
292	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
293	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
294	long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb;
295	bool multi_sta = false;
296
297	if (mac->opmode == NL80211_IFTYPE_ADHOC)
298		multi_sta = true;
299
300	if (!multi_sta || (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT)) {
301		binitialized = false;
302		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
303		return;
304	} else if (!binitialized) {
305		binitialized = true;
306		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
307		dm_digtable->cur_igvalue = 0x20;
308		rtl8723e_dm_write_dig(hw);
309	}
310
311	if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) {
312		if ((rssi_strength < dm_digtable->rssi_lowthresh) &&
313		    (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
314
315			if (dm_digtable->dig_ext_port_stage ==
316			    DIG_EXT_PORT_STAGE_2) {
317				dm_digtable->cur_igvalue = 0x20;
318				rtl8723e_dm_write_dig(hw);
319			}
320
321			dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
322		} else if (rssi_strength > dm_digtable->rssi_highthresh) {
323			dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
324			rtl92c_dm_ctrl_initgain_by_fa(hw);
325		}
326	} else if (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
327		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
328		dm_digtable->cur_igvalue = 0x20;
329		rtl8723e_dm_write_dig(hw);
330	}
331
332	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
333		 "curmultista_cstate = %x dig_ext_port_stage %x\n",
334		 dm_digtable->curmultista_cstate,
335		 dm_digtable->dig_ext_port_stage);
336}
337
338static void rtl8723e_dm_initial_gain_sta(struct ieee80211_hw *hw)
339{
340	struct rtl_priv *rtlpriv = rtl_priv(hw);
341	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
342
343	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
344		 "presta_cstate = %x, cursta_cstate = %x\n",
345		  dm_digtable->presta_cstate,
346		  dm_digtable->cursta_cstate);
347
348	if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate ||
349	    dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT ||
350	    dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
351		if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) {
352			dm_digtable->rssi_val_min =
353			    rtl8723e_dm_initial_gain_min_pwdb(hw);
354			rtl92c_dm_ctrl_initgain_by_rssi(hw);
355		}
356	} else {
357		dm_digtable->rssi_val_min = 0;
358		dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
359		dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT;
360		dm_digtable->cur_igvalue = 0x20;
361		dm_digtable->pre_igvalue = 0;
362		rtl8723e_dm_write_dig(hw);
363	}
364}
365
366static void rtl8723e_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
367{
368	struct rtl_priv *rtlpriv = rtl_priv(hw);
369	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
370
371	if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) {
372		dm_digtable->rssi_val_min = rtl8723e_dm_initial_gain_min_pwdb(hw);
373
374		if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
375			if (dm_digtable->rssi_val_min <= 25)
376				dm_digtable->cur_cck_pd_state =
377				    CCK_PD_STAGE_LOWRSSI;
378			else
379				dm_digtable->cur_cck_pd_state =
380				    CCK_PD_STAGE_HIGHRSSI;
381		} else {
382			if (dm_digtable->rssi_val_min <= 20)
383				dm_digtable->cur_cck_pd_state =
384				    CCK_PD_STAGE_LOWRSSI;
385			else
386				dm_digtable->cur_cck_pd_state =
387				    CCK_PD_STAGE_HIGHRSSI;
388		}
389	} else {
390		dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX;
391	}
392
393	if (dm_digtable->pre_cck_pd_state != dm_digtable->cur_cck_pd_state) {
394		if (dm_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI) {
395			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
396				dm_digtable->cur_cck_fa_state =
397				    CCK_FA_STAGE_HIGH;
398			else
399				dm_digtable->cur_cck_fa_state =
400				    CCK_FA_STAGE_LOW;
401			if (dm_digtable->pre_cck_fa_state !=
402			    dm_digtable->cur_cck_fa_state) {
403				if (dm_digtable->cur_cck_fa_state ==
404				    CCK_FA_STAGE_LOW)
405					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
406						      0x83);
407				else
408					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
409						      0xcd);
410
411				dm_digtable->pre_cck_fa_state =
412				    dm_digtable->cur_cck_fa_state;
413			}
414
415			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
416
417		} else {
418			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
419			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
420
421		}
422		dm_digtable->pre_cck_pd_state = dm_digtable->cur_cck_pd_state;
423	}
424
425	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
426		 "CCKPDStage=%x\n", dm_digtable->cur_cck_pd_state);
427
428}
429
430static void rtl8723e_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
431{
432	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
433	struct rtl_priv *rtlpriv = rtl_priv(hw);
434	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
435
436	if (mac->act_scanning)
437		return;
438
439	if (mac->link_state >= MAC80211_LINKED)
440		dm_digtable->cursta_cstate = DIG_STA_CONNECT;
441	else
442		dm_digtable->cursta_cstate = DIG_STA_DISCONNECT;
443
444	rtl8723e_dm_initial_gain_sta(hw);
445	rtl8723e_dm_initial_gain_multi_sta(hw);
446	rtl8723e_dm_cck_packet_detection_thresh(hw);
447
448	dm_digtable->presta_cstate = dm_digtable->cursta_cstate;
449
450}
451
452static void rtl8723e_dm_dig(struct ieee80211_hw *hw)
453{
454	struct rtl_priv *rtlpriv = rtl_priv(hw);
455	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
456
457	if (!rtlpriv->dm.dm_initialgain_enable)
458		return;
459	if (!dm_digtable->dig_enable_flag)
460		return;
461
462	rtl8723e_dm_ctrl_initgain_by_twoport(hw);
463
464}
465
466static void rtl8723e_dm_dynamic_txpower(struct ieee80211_hw *hw)
467{
468	struct rtl_priv *rtlpriv = rtl_priv(hw);
469	struct rtl_phy *rtlphy = &(rtlpriv->phy);
470	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
471	long undec_sm_pwdb;
472
473	if (!rtlpriv->dm.dynamic_txpower_enable)
474		return;
475
476	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
477		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
478		return;
479	}
480
481	if ((mac->link_state < MAC80211_LINKED) &&
482	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
483		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
484			 "Not connected to any\n");
485
486		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
487
488		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
489		return;
490	}
491
492	if (mac->link_state >= MAC80211_LINKED) {
493		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
494			undec_sm_pwdb =
495			    rtlpriv->dm.entry_min_undec_sm_pwdb;
496			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
497				 "AP Client PWDB = 0x%lx\n",
498				  undec_sm_pwdb);
499		} else {
500			undec_sm_pwdb =
501			    rtlpriv->dm.undec_sm_pwdb;
502			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
503				 "STA Default Port PWDB = 0x%lx\n",
504				  undec_sm_pwdb);
505		}
506	} else {
507		undec_sm_pwdb =
508		    rtlpriv->dm.entry_min_undec_sm_pwdb;
509
510		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
511			 "AP Ext Port PWDB = 0x%lx\n",
512			  undec_sm_pwdb);
513	}
514
515	if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
516		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
517		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
518			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n");
519	} else if ((undec_sm_pwdb <
520		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
521		   (undec_sm_pwdb >=
522		    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
523		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
524		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
525			 "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n");
526	} else if (undec_sm_pwdb <
527		   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
528		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
529		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
530			 "TXHIGHPWRLEVEL_NORMAL\n");
531	}
532
533	if (rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl) {
534		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
535			 "PHY_SetTxPowerLevel8192S() Channel = %d\n",
536			  rtlphy->current_channel);
537		rtl8723e_phy_set_txpower_level(hw, rtlphy->current_channel);
538	}
539
540	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
541}
542
543void rtl8723e_dm_write_dig(struct ieee80211_hw *hw)
544{
545	struct rtl_priv *rtlpriv = rtl_priv(hw);
546	struct dig_t *dm_digtable = &rtlpriv->dm_digtable;
547
548	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
549		 "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n",
550		  dm_digtable->cur_igvalue, dm_digtable->pre_igvalue,
551		  dm_digtable->back_val);
552
553	if (dm_digtable->pre_igvalue != dm_digtable->cur_igvalue) {
554		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
555			      dm_digtable->cur_igvalue);
556		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
557			      dm_digtable->cur_igvalue);
558
559		dm_digtable->pre_igvalue = dm_digtable->cur_igvalue;
560	}
561}
562
563static void rtl8723e_dm_pwdb_monitor(struct ieee80211_hw *hw)
564{
565}
566
567static void rtl8723e_dm_check_edca_turbo(struct ieee80211_hw *hw)
568{
569	struct rtl_priv *rtlpriv = rtl_priv(hw);
570	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
571
572	static u64 last_txok_cnt;
573	static u64 last_rxok_cnt;
574	static u32 last_bt_edca_ul;
575	static u32 last_bt_edca_dl;
576	u64 cur_txok_cnt = 0;
577	u64 cur_rxok_cnt = 0;
578	u32 edca_be_ul = 0x5ea42b;
579	u32 edca_be_dl = 0x5ea42b;
580	bool bt_change_edca = false;
581
582	if ((last_bt_edca_ul != rtlpriv->btcoexist.bt_edca_ul) ||
583	    (last_bt_edca_dl != rtlpriv->btcoexist.bt_edca_dl)) {
584		rtlpriv->dm.current_turbo_edca = false;
585		last_bt_edca_ul = rtlpriv->btcoexist.bt_edca_ul;
586		last_bt_edca_dl = rtlpriv->btcoexist.bt_edca_dl;
587	}
588
589	if (rtlpriv->btcoexist.bt_edca_ul != 0) {
590		edca_be_ul = rtlpriv->btcoexist.bt_edca_ul;
591		bt_change_edca = true;
592	}
593
594	if (rtlpriv->btcoexist.bt_edca_dl != 0) {
595		edca_be_ul = rtlpriv->btcoexist.bt_edca_dl;
596		bt_change_edca = true;
597	}
598
599	if (mac->link_state != MAC80211_LINKED) {
600		rtlpriv->dm.current_turbo_edca = false;
601		return;
602	}
603	if ((bt_change_edca) || ((!rtlpriv->dm.is_any_nonbepkts) &&
604	     (!rtlpriv->dm.disable_framebursting))) {
605
606		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
607		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
608
609		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
610			if (!rtlpriv->dm.is_cur_rdlstate ||
611			    !rtlpriv->dm.current_turbo_edca) {
612				rtl_write_dword(rtlpriv,
613						REG_EDCA_BE_PARAM,
614						edca_be_dl);
615				rtlpriv->dm.is_cur_rdlstate = true;
616			}
617		} else {
618			if (rtlpriv->dm.is_cur_rdlstate ||
619			    !rtlpriv->dm.current_turbo_edca) {
620				rtl_write_dword(rtlpriv,
621						REG_EDCA_BE_PARAM,
622						edca_be_ul);
623				rtlpriv->dm.is_cur_rdlstate = false;
624			}
625		}
626		rtlpriv->dm.current_turbo_edca = true;
627	} else {
628		if (rtlpriv->dm.current_turbo_edca) {
629			u8 tmp = AC0_BE;
630			rtlpriv->cfg->ops->set_hw_reg(hw,
631						      HW_VAR_AC_PARAM,
632						      (u8 *)(&tmp));
633			rtlpriv->dm.current_turbo_edca = false;
634		}
635	}
636
637	rtlpriv->dm.is_any_nonbepkts = false;
638	last_txok_cnt = rtlpriv->stats.txbytesunicast;
639	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
640}
641
642static void rtl8723e_dm_initialize_txpower_tracking_thermalmeter(
643				struct ieee80211_hw *hw)
644{
645	struct rtl_priv *rtlpriv = rtl_priv(hw);
646
647	rtlpriv->dm.txpower_tracking = true;
648	rtlpriv->dm.txpower_trackinginit = false;
649
650	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
651		 "pMgntInfo->txpower_tracking = %d\n",
652		  rtlpriv->dm.txpower_tracking);
653}
654
655static void rtl8723e_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
656{
657	rtl8723e_dm_initialize_txpower_tracking_thermalmeter(hw);
658}
659
660void rtl8723e_dm_check_txpower_tracking(struct ieee80211_hw *hw)
661{
662	return;
663}
664
665void rtl8723e_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
666{
667	struct rtl_priv *rtlpriv = rtl_priv(hw);
668	struct rate_adaptive *p_ra = &(rtlpriv->ra);
669
670	p_ra->ratr_state = DM_RATR_STA_INIT;
671	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
672
673	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
674		rtlpriv->dm.useramask = true;
675	else
676		rtlpriv->dm.useramask = false;
677
678}
679
680void rtl8723e_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
681{
682	struct rtl_priv *rtlpriv = rtl_priv(hw);
683	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
684	static u8 initialize;
685	static u32 reg_874, reg_c70, reg_85c, reg_a74;
686
687	if (initialize == 0) {
688		reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
689					 MASKDWORD) & 0x1CC000) >> 14;
690
691		reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
692					 MASKDWORD) & BIT(3)) >> 3;
693
694		reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
695					 MASKDWORD) & 0xFF000000) >> 24;
696
697		reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
698
699		initialize = 1;
700	}
701
702	if (!bforce_in_normal) {
703		if (dm_pstable->rssi_val_min != 0) {
704			if (dm_pstable->pre_rfstate == RF_NORMAL) {
705				if (dm_pstable->rssi_val_min >= 30)
706					dm_pstable->cur_rfstate = RF_SAVE;
707				else
708					dm_pstable->cur_rfstate = RF_NORMAL;
709			} else {
710				if (dm_pstable->rssi_val_min <= 25)
711					dm_pstable->cur_rfstate = RF_NORMAL;
712				else
713					dm_pstable->cur_rfstate = RF_SAVE;
714			}
715		} else {
716			dm_pstable->cur_rfstate = RF_MAX;
717		}
718	} else {
719		dm_pstable->cur_rfstate = RF_NORMAL;
720	}
721
722	if (dm_pstable->pre_rfstate != dm_pstable->cur_rfstate) {
723		if (dm_pstable->cur_rfstate == RF_SAVE) {
724			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
725				      BIT(5), 0x1);
726			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
727				      0x1C0000, 0x2);
728			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
729			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
730				      0xFF000000, 0x63);
731			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
732				      0xC000, 0x2);
733			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
734			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
735			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
736		} else {
737			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
738				      0x1CC000, reg_874);
739			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
740				      reg_c70);
741			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
742				      reg_85c);
743			rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
744			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
745			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
746				      BIT(5), 0x0);
747		}
748
749		dm_pstable->pre_rfstate = dm_pstable->cur_rfstate;
750	}
751}
752
753static void rtl8723e_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
754{
755	struct rtl_priv *rtlpriv = rtl_priv(hw);
756	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
757	struct ps_t *dm_pstable = &rtlpriv->dm_pstable;
758
759	if (((mac->link_state == MAC80211_NOLINK)) &&
760	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
761		dm_pstable->rssi_val_min = 0;
762		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
763			 "Not connected to any\n");
764	}
765
766	if (mac->link_state == MAC80211_LINKED) {
767		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
768			dm_pstable->rssi_val_min =
769			    rtlpriv->dm.entry_min_undec_sm_pwdb;
770			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
771				 "AP Client PWDB = 0x%lx\n",
772				  dm_pstable->rssi_val_min);
773		} else {
774			dm_pstable->rssi_val_min =
775			    rtlpriv->dm.undec_sm_pwdb;
776			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
777				 "STA Default Port PWDB = 0x%lx\n",
778				  dm_pstable->rssi_val_min);
779		}
780	} else {
781		dm_pstable->rssi_val_min =
782		    rtlpriv->dm.entry_min_undec_sm_pwdb;
783
784		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
785			 "AP Ext Port PWDB = 0x%lx\n",
786			  dm_pstable->rssi_val_min);
787	}
788
789	rtl8723e_dm_rf_saving(hw, false);
790}
791
792void rtl8723e_dm_init(struct ieee80211_hw *hw)
793{
794	struct rtl_priv *rtlpriv = rtl_priv(hw);
795
796	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
797	rtl_dm_diginit(hw, 0x20);
798	rtl8723_dm_init_dynamic_txpower(hw);
799	rtl8723_dm_init_edca_turbo(hw);
800	rtl8723e_dm_init_rate_adaptive_mask(hw);
801	rtl8723e_dm_initialize_txpower_tracking(hw);
802	rtl8723_dm_init_dynamic_bb_powersaving(hw);
803}
804
805void rtl8723e_dm_watchdog(struct ieee80211_hw *hw)
806{
807	struct rtl_priv *rtlpriv = rtl_priv(hw);
808	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
809	bool fw_current_inpsmode = false;
810	bool fw_ps_awake = true;
811	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
812				      (u8 *)(&fw_current_inpsmode));
813	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
814				      (u8 *)(&fw_ps_awake));
815
816	if (ppsc->p2p_ps_info.p2p_ps_mode)
817		fw_ps_awake = false;
818
819	if ((ppsc->rfpwr_state == ERFON) &&
820	    ((!fw_current_inpsmode) && fw_ps_awake) &&
821	    (!ppsc->rfchange_inprogress)) {
822		rtl8723e_dm_pwdb_monitor(hw);
823		rtl8723e_dm_dig(hw);
824		rtl8723e_dm_false_alarm_counter_statistics(hw);
825		rtl8723e_dm_dynamic_bb_powersaving(hw);
826		rtl8723e_dm_dynamic_txpower(hw);
827		rtl8723e_dm_check_txpower_tracking(hw);
828		/* rtl92c_dm_refresh_rate_adaptive_mask(hw); */
829		rtl8723e_dm_bt_coexist(hw);
830		rtl8723e_dm_check_edca_turbo(hw);
831	}
832	if (rtlpriv->btcoexist.init_set)
833		rtl_write_byte(rtlpriv, 0x76e, 0xc);
834}
835
836static void rtl8723e_dm_init_bt_coexist(struct ieee80211_hw *hw)
837{
838	struct rtl_priv *rtlpriv = rtl_priv(hw);
839
840	rtlpriv->btcoexist.bt_rfreg_origin_1e
841		= rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK1, 0xfffff);
842	rtlpriv->btcoexist.bt_rfreg_origin_1f
843		= rtl_get_rfreg(hw, (enum radio_path)0, RF_RCK2, 0xf0);
844
845	rtlpriv->btcoexist.cstate = 0;
846	rtlpriv->btcoexist.previous_state = 0;
847	rtlpriv->btcoexist.cstate_h = 0;
848	rtlpriv->btcoexist.previous_state_h = 0;
849	rtlpriv->btcoexist.lps_counter = 0;
850
851	/*  Enable counter statistics */
852	rtl_write_byte(rtlpriv, 0x76e, 0x4);
853	rtl_write_byte(rtlpriv, 0x778, 0x3);
854	rtl_write_byte(rtlpriv, 0x40, 0x20);
855
856	rtlpriv->btcoexist.init_set = true;
857}
858
859void rtl8723e_dm_bt_coexist(struct ieee80211_hw *hw)
860{
861	struct rtl_priv *rtlpriv = rtl_priv(hw);
862	u8 tmp_byte = 0;
863	if (!rtlpriv->btcoexist.bt_coexistence) {
864		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
865			 "[DM]{BT], BT not exist!!\n");
866		return;
867	}
868
869	if (!rtlpriv->btcoexist.init_set) {
870		RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
871			 "[DM][BT], rtl8723e_dm_bt_coexist()\n");
872		rtl8723e_dm_init_bt_coexist(hw);
873	}
874
875	tmp_byte = rtl_read_byte(rtlpriv, 0x40);
876	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
877		 "[DM][BT], 0x40 is 0x%x", tmp_byte);
878	RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG,
879		 "[DM][BT], bt_dm_coexist start");
880	rtl8723e_dm_bt_coexist_8723(hw);
881}
882