[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 "fw.h"
34#include "trx.h"
35
36static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
37	0x7f8001fe,		/* 0, +6.0dB */
38	0x788001e2,		/* 1, +5.5dB */
39	0x71c001c7,		/* 2, +5.0dB */
40	0x6b8001ae,		/* 3, +4.5dB */
41	0x65400195,		/* 4, +4.0dB */
42	0x5fc0017f,		/* 5, +3.5dB */
43	0x5a400169,		/* 6, +3.0dB */
44	0x55400155,		/* 7, +2.5dB */
45	0x50800142,		/* 8, +2.0dB */
46	0x4c000130,		/* 9, +1.5dB */
47	0x47c0011f,		/* 10, +1.0dB */
48	0x43c0010f,		/* 11, +0.5dB */
49	0x40000100,		/* 12, +0dB */
50	0x3c8000f2,		/* 13, -0.5dB */
51	0x390000e4,		/* 14, -1.0dB */
52	0x35c000d7,		/* 15, -1.5dB */
53	0x32c000cb,		/* 16, -2.0dB */
54	0x300000c0,		/* 17, -2.5dB */
55	0x2d4000b5,		/* 18, -3.0dB */
56	0x2ac000ab,		/* 19, -3.5dB */
57	0x288000a2,		/* 20, -4.0dB */
58	0x26000098,		/* 21, -4.5dB */
59	0x24000090,		/* 22, -5.0dB */
60	0x22000088,		/* 23, -5.5dB */
61	0x20000080,		/* 24, -6.0dB */
62	0x1e400079,		/* 25, -6.5dB */
63	0x1c800072,		/* 26, -7.0dB */
64	0x1b00006c,		/* 27. -7.5dB */
65	0x19800066,		/* 28, -8.0dB */
66	0x18000060,		/* 29, -8.5dB */
67	0x16c0005b,		/* 30, -9.0dB */
68	0x15800056,		/* 31, -9.5dB */
69	0x14400051,		/* 32, -10.0dB */
70	0x1300004c,		/* 33, -10.5dB */
71	0x12000048,		/* 34, -11.0dB */
72	0x11000044,		/* 35, -11.5dB */
73	0x10000040,		/* 36, -12.0dB */
74	0x0f00003c,		/* 37, -12.5dB */
75	0x0e400039,		/* 38, -13.0dB */
76	0x0d800036,		/* 39, -13.5dB */
77	0x0cc00033,		/* 40, -14.0dB */
78	0x0c000030,		/* 41, -14.5dB */
79	0x0b40002d,		/* 42, -15.0dB */
80};
81
82static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
83	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04}, /* 0, +0dB */
84	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04}, /* 1, -0.5dB */
85	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03}, /* 2, -1.0dB */
86	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03}, /* 3, -1.5dB */
87	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03}, /* 4, -2.0dB */
88	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03}, /* 5, -2.5dB */
89	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03}, /* 6, -3.0dB */
90	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03}, /* 7, -3.5dB */
91	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02}, /* 8, -4.0dB */
92	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02}, /* 9, -4.5dB */
93	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02}, /* 10, -5.0dB */
94	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02}, /* 11, -5.5dB */
95	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02}, /* 12, -6.0dB */
96	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02}, /* 13, -6.5dB */
97	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02}, /* 14, -7.0dB */
98	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02}, /* 15, -7.5dB */
99	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01}, /* 16, -8.0dB */
100	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02}, /* 17, -8.5dB */
101	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01}, /* 18, -9.0dB */
102	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 19, -9.5dB */
103	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01}, /* 20, -10.0dB */
104	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 21, -10.5dB */
105	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01}, /* 22, -11.0dB */
106	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01}, /* 23, -11.5dB */
107	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01}, /* 24, -12.0dB */
108	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01}, /* 25, -12.5dB */
109	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01}, /* 26, -13.0dB */
110	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 27, -13.5dB */
111	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01}, /* 28, -14.0dB */
112	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 29, -14.5dB */
113	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01}, /* 30, -15.0dB */
114	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01}, /* 31, -15.5dB */
115	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}  /* 32, -16.0dB */
116};
117
118static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
119	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00}, /* 0, +0dB */
120	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00}, /* 1, -0.5dB */
121	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00}, /* 2, -1.0dB */
122	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00}, /* 3, -1.5dB */
123	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00}, /* 4, -2.0dB */
124	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00}, /* 5, -2.5dB */
125	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00}, /* 6, -3.0dB */
126	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00}, /* 7, -3.5dB */
127	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00}, /* 8, -4.0dB */
128	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00}, /* 9, -4.5dB */
129	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00}, /* 10, -5.0dB */
130	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 11, -5.5dB */
131	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00}, /* 12, -6.0dB */
132	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00}, /* 13, -6.5dB */
133	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00}, /* 14, -7.0dB */
134	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 15, -7.5dB */
135	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00}, /* 16, -8.0dB */
136	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 17, -8.5dB */
137	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00}, /* 18, -9.0dB */
138	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 19, -9.5dB */
139	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00}, /* 20, -10.0dB */
140	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 21, -10.5dB */
141	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00}, /* 22, -11.0dB */
142	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 23, -11.5dB */
143	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00}, /* 24, -12.0dB */
144	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 25, -12.5dB */
145	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 26, -13.0dB */
146	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00}, /* 27, -13.5dB */
147	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 28, -14.0dB */
148	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 29, -14.5dB */
149	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 30, -15.0dB */
150	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00}, /* 31, -15.5dB */
151	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}  /* 32, -16.0dB */
152};
153
154static void rtl92ee_dm_diginit(struct ieee80211_hw *hw)
155{
156	struct rtl_priv *rtlpriv = rtl_priv(hw);
157	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
158
159	dm_dig->cur_igvalue = rtl_get_bbreg(hw, DM_REG_IGI_A_11N,
160					    DM_BIT_IGI_11N);
161	dm_dig->rssi_lowthresh = DM_DIG_THRESH_LOW;
162	dm_dig->rssi_highthresh = DM_DIG_THRESH_HIGH;
163	dm_dig->fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
164	dm_dig->fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
165	dm_dig->rx_gain_max = DM_DIG_MAX;
166	dm_dig->rx_gain_min = DM_DIG_MIN;
167	dm_dig->back_val = DM_DIG_BACKOFF_DEFAULT;
168	dm_dig->back_range_max = DM_DIG_BACKOFF_MAX;
169	dm_dig->back_range_min = DM_DIG_BACKOFF_MIN;
170	dm_dig->pre_cck_cca_thres = 0xff;
171	dm_dig->cur_cck_cca_thres = 0x83;
172	dm_dig->forbidden_igi = DM_DIG_MIN;
173	dm_dig->large_fa_hit = 0;
174	dm_dig->recover_cnt = 0;
175	dm_dig->dig_dynamic_min = DM_DIG_MIN;
176	dm_dig->dig_dynamic_min_1 = DM_DIG_MIN;
177	dm_dig->media_connect_0 = false;
178	dm_dig->media_connect_1 = false;
179	rtlpriv->dm.dm_initialgain_enable = true;
180	dm_dig->bt30_cur_igi = 0x32;
181}
182
183static void rtl92ee_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
184{
185	u32 ret_value;
186	struct rtl_priv *rtlpriv = rtl_priv(hw);
187	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
188
189	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 1);
190	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 1);
191
192	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE1_11N, MASKDWORD);
193	falsealm_cnt->cnt_fast_fsync_fail = (ret_value & 0xffff);
194	falsealm_cnt->cnt_sb_search_fail = ((ret_value & 0xffff0000) >> 16);
195
196	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE2_11N, MASKDWORD);
197	falsealm_cnt->cnt_ofdm_cca = (ret_value & 0xffff);
198	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
199
200	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE3_11N, MASKDWORD);
201	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
202	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
203
204	ret_value = rtl_get_bbreg(hw, DM_REG_OFDM_FA_TYPE4_11N, MASKDWORD);
205	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
206
207	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
208				      falsealm_cnt->cnt_rate_illegal +
209				      falsealm_cnt->cnt_crc8_fail +
210				      falsealm_cnt->cnt_mcs_fail +
211				      falsealm_cnt->cnt_fast_fsync_fail +
212				      falsealm_cnt->cnt_sb_search_fail;
213
214	ret_value = rtl_get_bbreg(hw, DM_REG_SC_CNT_11N, MASKDWORD);
215	falsealm_cnt->cnt_bw_lsc = (ret_value & 0xffff);
216	falsealm_cnt->cnt_bw_usc = ((ret_value & 0xffff0000) >> 16);
217
218	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(12), 1);
219	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(14), 1);
220
221	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_LSB_11N, MASKBYTE0);
222	falsealm_cnt->cnt_cck_fail = ret_value;
223
224	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_FA_MSB_11N, MASKBYTE3);
225	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
226
227	ret_value = rtl_get_bbreg(hw, DM_REG_CCK_CCA_CNT_11N, MASKDWORD);
228	falsealm_cnt->cnt_cck_cca = ((ret_value & 0xff) << 8) |
229				    ((ret_value & 0xFF00) >> 8);
230
231	falsealm_cnt->cnt_all = falsealm_cnt->cnt_fast_fsync_fail +
232				falsealm_cnt->cnt_sb_search_fail +
233				falsealm_cnt->cnt_parity_fail +
234				falsealm_cnt->cnt_rate_illegal +
235				falsealm_cnt->cnt_crc8_fail +
236				falsealm_cnt->cnt_mcs_fail +
237				falsealm_cnt->cnt_cck_fail;
238
239	falsealm_cnt->cnt_cca_all = falsealm_cnt->cnt_ofdm_cca +
240				    falsealm_cnt->cnt_cck_cca;
241
242	/*reset false alarm counter registers*/
243	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 1);
244	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTC_11N, BIT(31), 0);
245	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 1);
246	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(27), 0);
247	/*update ofdm counter*/
248	rtl_set_bbreg(hw, DM_REG_OFDM_FA_HOLDC_11N, BIT(31), 0);
249	rtl_set_bbreg(hw, DM_REG_OFDM_FA_RSTD_11N, BIT(31), 0);
250	/*reset CCK CCA counter*/
251	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 0);
252	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(13) | BIT(12), 2);
253	/*reset CCK FA counter*/
254	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 0);
255	rtl_set_bbreg(hw, DM_REG_CCK_FA_RST_11N, BIT(15) | BIT(14), 2);
256
257	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
258		 "cnt_parity_fail = %d, cnt_rate_illegal = %d, cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
259		  falsealm_cnt->cnt_parity_fail,
260		  falsealm_cnt->cnt_rate_illegal,
261		  falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail);
262
263	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
264		 "cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
265		  falsealm_cnt->cnt_ofdm_fail,
266		  falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all);
267}
268
269static void rtl92ee_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
270{
271	struct rtl_priv *rtlpriv = rtl_priv(hw);
272	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
273	u8 cur_cck_cca_thresh;
274
275	if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
276		if (dm_dig->rssi_val_min > 25) {
277			cur_cck_cca_thresh = 0xcd;
278		} else if ((dm_dig->rssi_val_min <= 25) &&
279			   (dm_dig->rssi_val_min > 10)) {
280			cur_cck_cca_thresh = 0x83;
281		} else {
282			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
283				cur_cck_cca_thresh = 0x83;
284			else
285				cur_cck_cca_thresh = 0x40;
286		}
287	} else {
288		if (rtlpriv->falsealm_cnt.cnt_cck_fail > 1000)
289			cur_cck_cca_thresh = 0x83;
290		else
291			cur_cck_cca_thresh = 0x40;
292	}
293	rtl92ee_dm_write_cck_cca_thres(hw, cur_cck_cca_thresh);
294}
295
296static void rtl92ee_dm_dig(struct ieee80211_hw *hw)
297{
298	struct rtl_priv *rtlpriv = rtl_priv(hw);
299	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
300	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
301	u8 dig_dynamic_min , dig_maxofmin;
302	bool bfirstconnect , bfirstdisconnect;
303	u8 dm_dig_max, dm_dig_min;
304	u8 current_igi = dm_dig->cur_igvalue;
305	u8 offset;
306
307	/* AP,BT */
308	if (mac->act_scanning)
309		return;
310
311	dig_dynamic_min = dm_dig->dig_dynamic_min;
312	bfirstconnect = (mac->link_state >= MAC80211_LINKED) &&
313			!dm_dig->media_connect_0;
314	bfirstdisconnect = (mac->link_state < MAC80211_LINKED) &&
315			   dm_dig->media_connect_0;
316
317	dm_dig_max = 0x5a;
318	dm_dig_min = DM_DIG_MIN;
319	dig_maxofmin = DM_DIG_MAX_AP;
320
321	if (mac->link_state >= MAC80211_LINKED) {
322		if ((dm_dig->rssi_val_min + 10) > dm_dig_max)
323			dm_dig->rx_gain_max = dm_dig_max;
324		else if ((dm_dig->rssi_val_min + 10) < dm_dig_min)
325			dm_dig->rx_gain_max = dm_dig_min;
326		else
327			dm_dig->rx_gain_max = dm_dig->rssi_val_min + 10;
328
329		if (rtlpriv->dm.one_entry_only) {
330			offset = 0;
331			if (dm_dig->rssi_val_min - offset < dm_dig_min)
332				dig_dynamic_min = dm_dig_min;
333			else if (dm_dig->rssi_val_min - offset >
334				 dig_maxofmin)
335				dig_dynamic_min = dig_maxofmin;
336			else
337				dig_dynamic_min = dm_dig->rssi_val_min - offset;
338		} else {
339			dig_dynamic_min = dm_dig_min;
340		}
341
342	} else {
343		dm_dig->rx_gain_max = dm_dig_max;
344		dig_dynamic_min = dm_dig_min;
345		RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "no link\n");
346	}
347
348	if (rtlpriv->falsealm_cnt.cnt_all > 10000) {
349		if (dm_dig->large_fa_hit != 3)
350			dm_dig->large_fa_hit++;
351		if (dm_dig->forbidden_igi < current_igi) {
352			dm_dig->forbidden_igi = current_igi;
353			dm_dig->large_fa_hit = 1;
354		}
355
356		if (dm_dig->large_fa_hit >= 3) {
357			if (dm_dig->forbidden_igi + 1 > dm_dig->rx_gain_max)
358				dm_dig->rx_gain_min =
359						dm_dig->rx_gain_max;
360			else
361				dm_dig->rx_gain_min =
362						dm_dig->forbidden_igi + 1;
363			dm_dig->recover_cnt = 3600;
364		}
365	} else {
366		if (dm_dig->recover_cnt != 0) {
367			dm_dig->recover_cnt--;
368		} else {
369			if (dm_dig->large_fa_hit < 3) {
370				if ((dm_dig->forbidden_igi - 1) <
371				    dig_dynamic_min) {
372					dm_dig->forbidden_igi = dig_dynamic_min;
373					dm_dig->rx_gain_min =
374								dig_dynamic_min;
375				} else {
376					dm_dig->forbidden_igi--;
377					dm_dig->rx_gain_min =
378						dm_dig->forbidden_igi + 1;
379				}
380			} else {
381				dm_dig->large_fa_hit = 0;
382			}
383		}
384	}
385
386	if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5)
387		dm_dig->rx_gain_min = dm_dig_min;
388
389	if (dm_dig->rx_gain_min > dm_dig->rx_gain_max)
390		dm_dig->rx_gain_min = dm_dig->rx_gain_max;
391
392	if (mac->link_state >= MAC80211_LINKED) {
393		if (bfirstconnect) {
394			if (dm_dig->rssi_val_min <= dig_maxofmin)
395				current_igi = dm_dig->rssi_val_min;
396			else
397				current_igi = dig_maxofmin;
398
399			dm_dig->large_fa_hit = 0;
400		} else {
401			if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH2)
402				current_igi += 4;
403			else if (rtlpriv->falsealm_cnt.cnt_all > DM_DIG_FA_TH1)
404				current_igi += 2;
405			else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
406				current_igi -= 2;
407
408			if (rtlpriv->dm.dbginfo.num_qry_beacon_pkt < 5 &&
409			    rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
410				current_igi = dm_dig->rx_gain_min;
411		}
412	} else {
413		if (bfirstdisconnect) {
414			current_igi = dm_dig->rx_gain_min;
415		} else {
416			if (rtlpriv->falsealm_cnt.cnt_all > 10000)
417				current_igi += 4;
418			else if (rtlpriv->falsealm_cnt.cnt_all > 8000)
419				current_igi += 2;
420			else if (rtlpriv->falsealm_cnt.cnt_all < 500)
421				current_igi -= 2;
422		}
423	}
424
425	if (current_igi > dm_dig->rx_gain_max)
426		current_igi = dm_dig->rx_gain_max;
427	if (current_igi < dm_dig->rx_gain_min)
428		current_igi = dm_dig->rx_gain_min;
429
430	rtl92ee_dm_write_dig(hw , current_igi);
431	dm_dig->media_connect_0 = ((mac->link_state >= MAC80211_LINKED) ?
432				   true : false);
433	dm_dig->dig_dynamic_min = dig_dynamic_min;
434}
435
436void rtl92ee_dm_write_cck_cca_thres(struct ieee80211_hw *hw, u8 cur_thres)
437{
438	struct rtl_priv *rtlpriv = rtl_priv(hw);
439	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
440
441	if (dm_dig->cur_cck_cca_thres != cur_thres)
442		rtl_write_byte(rtlpriv, DM_REG_CCK_CCA_11N, cur_thres);
443
444	dm_dig->pre_cck_cca_thres = dm_dig->cur_cck_cca_thres;
445	dm_dig->cur_cck_cca_thres = cur_thres;
446}
447
448void rtl92ee_dm_write_dig(struct ieee80211_hw *hw, u8 current_igi)
449{
450	struct rtl_priv *rtlpriv = rtl_priv(hw);
451	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
452
453	if (dm_dig->stop_dig)
454		return;
455
456	if (dm_dig->cur_igvalue != current_igi) {
457		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f, current_igi);
458		if (rtlpriv->phy.rf_type != RF_1T1R)
459			rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f, current_igi);
460	}
461	dm_dig->pre_igvalue = dm_dig->cur_igvalue;
462	dm_dig->cur_igvalue = current_igi;
463}
464
465static void rtl92ee_rssi_dump_to_register(struct ieee80211_hw *hw)
466{
467	struct rtl_priv *rtlpriv = rtl_priv(hw);
468
469	rtl_write_byte(rtlpriv, RA_RSSIDUMP,
470		       rtlpriv->stats.rx_rssi_percentage[0]);
471	rtl_write_byte(rtlpriv, RB_RSSIDUMP,
472		       rtlpriv->stats.rx_rssi_percentage[1]);
473	/*It seems the following values are not initialized.
474	  *According to Windows code,
475	  *these value will only be valid with JAGUAR chips
476	  */
477	/* Rx EVM */
478	rtl_write_byte(rtlpriv, RS1_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[0]);
479	rtl_write_byte(rtlpriv, RS2_RXEVMDUMP, rtlpriv->stats.rx_evm_dbm[1]);
480	/* Rx SNR */
481	rtl_write_byte(rtlpriv, RA_RXSNRDUMP,
482		       (u8)(rtlpriv->stats.rx_snr_db[0]));
483	rtl_write_byte(rtlpriv, RB_RXSNRDUMP,
484		       (u8)(rtlpriv->stats.rx_snr_db[1]));
485	/* Rx Cfo_Short */
486	rtl_write_word(rtlpriv, RA_CFOSHORTDUMP,
487		       rtlpriv->stats.rx_cfo_short[0]);
488	rtl_write_word(rtlpriv, RB_CFOSHORTDUMP,
489		       rtlpriv->stats.rx_cfo_short[1]);
490	/* Rx Cfo_Tail */
491	rtl_write_word(rtlpriv, RA_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[0]);
492	rtl_write_word(rtlpriv, RB_CFOLONGDUMP, rtlpriv->stats.rx_cfo_tail[1]);
493}
494
495static void rtl92ee_dm_find_minimum_rssi(struct ieee80211_hw *hw)
496{
497	struct rtl_priv *rtlpriv = rtl_priv(hw);
498	struct dig_t *rtl_dm_dig = &rtlpriv->dm_digtable;
499	struct rtl_mac *mac = rtl_mac(rtlpriv);
500
501	/* Determine the minimum RSSI  */
502	if ((mac->link_state < MAC80211_LINKED) &&
503	    (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) {
504		rtl_dm_dig->min_undec_pwdb_for_dm = 0;
505		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
506			 "Not connected to any\n");
507	}
508	if (mac->link_state >= MAC80211_LINKED) {
509		if (mac->opmode == NL80211_IFTYPE_AP ||
510		    mac->opmode == NL80211_IFTYPE_ADHOC) {
511			rtl_dm_dig->min_undec_pwdb_for_dm =
512				rtlpriv->dm.entry_min_undec_sm_pwdb;
513			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
514				 "AP Client PWDB = 0x%lx\n",
515				 rtlpriv->dm.entry_min_undec_sm_pwdb);
516		} else {
517			rtl_dm_dig->min_undec_pwdb_for_dm =
518			    rtlpriv->dm.undec_sm_pwdb;
519			RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
520				 "STA Default Port PWDB = 0x%x\n",
521				 rtl_dm_dig->min_undec_pwdb_for_dm);
522		}
523	} else {
524		rtl_dm_dig->min_undec_pwdb_for_dm =
525			rtlpriv->dm.entry_min_undec_sm_pwdb;
526		RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD,
527			 "AP Ext Port or disconnet PWDB = 0x%x\n",
528			 rtl_dm_dig->min_undec_pwdb_for_dm);
529	}
530	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
531		 "MinUndecoratedPWDBForDM =%d\n",
532		 rtl_dm_dig->min_undec_pwdb_for_dm);
533}
534
535static void rtl92ee_dm_check_rssi_monitor(struct ieee80211_hw *hw)
536{
537	struct rtl_priv *rtlpriv = rtl_priv(hw);
538	struct dig_t *dm_dig = &rtlpriv->dm_digtable;
539	struct rtl_mac *mac = rtl_mac(rtlpriv);
540	struct rtl_dm *dm = rtl_dm(rtlpriv);
541	struct rtl_sta_info *drv_priv;
542	u8 h2c[4] = { 0 };
543	long max = 0, min = 0xff;
544	u8 i = 0;
545
546	if (mac->opmode == NL80211_IFTYPE_AP ||
547	    mac->opmode == NL80211_IFTYPE_ADHOC ||
548	    mac->opmode == NL80211_IFTYPE_MESH_POINT) {
549		/* AP & ADHOC & MESH */
550		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
551		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
552			struct rssi_sta *stat = &drv_priv->rssi_stat;
553
554			if (stat->undec_sm_pwdb < min)
555				min = stat->undec_sm_pwdb;
556			if (stat->undec_sm_pwdb > max)
557				max = stat->undec_sm_pwdb;
558
559			h2c[3] = 0;
560			h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF);
561			h2c[1] = 0x20;
562			h2c[0] = ++i;
563			rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c);
564		}
565		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
566
567		/* If associated entry is found */
568		if (max != 0) {
569			dm->entry_max_undec_sm_pwdb = max;
570			RTPRINT(rtlpriv, FDM, DM_PWDB,
571				"EntryMaxPWDB = 0x%lx(%ld)\n", max, max);
572		} else {
573			dm->entry_max_undec_sm_pwdb = 0;
574		}
575		/* If associated entry is found */
576		if (min != 0xff) {
577			dm->entry_min_undec_sm_pwdb = min;
578			RTPRINT(rtlpriv, FDM, DM_PWDB,
579				"EntryMinPWDB = 0x%lx(%ld)\n", min, min);
580		} else {
581			dm->entry_min_undec_sm_pwdb = 0;
582		}
583	}
584
585	/* Indicate Rx signal strength to FW. */
586	if (dm->useramask) {
587		h2c[3] = 0;
588		h2c[2] = (u8)(dm->undec_sm_pwdb & 0xFF);
589		h2c[1] = 0x20;
590		h2c[0] = 0;
591		rtl92ee_fill_h2c_cmd(hw, H2C_92E_RSSI_REPORT, 4, h2c);
592	} else {
593		rtl_write_byte(rtlpriv, 0x4fe, dm->undec_sm_pwdb);
594	}
595	rtl92ee_rssi_dump_to_register(hw);
596	rtl92ee_dm_find_minimum_rssi(hw);
597	dm_dig->rssi_val_min = rtlpriv->dm_digtable.min_undec_pwdb_for_dm;
598}
599
600static void rtl92ee_dm_init_primary_cca_check(struct ieee80211_hw *hw)
601{
602	struct rtl_priv *rtlpriv = rtl_priv(hw);
603	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
604	struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca;
605
606	rtlhal->rts_en = 0;
607	primarycca->dup_rts_flag = 0;
608	primarycca->intf_flag = 0;
609	primarycca->intf_type = 0;
610	primarycca->monitor_flag = 0;
611	primarycca->ch_offset = 0;
612	primarycca->mf_state = 0;
613}
614
615static bool rtl92ee_dm_is_edca_turbo_disable(struct ieee80211_hw *hw)
616{
617	struct rtl_priv *rtlpriv = rtl_priv(hw);
618
619	if (rtlpriv->mac80211.mode == WIRELESS_MODE_B)
620		return true;
621
622	return false;
623}
624
625void rtl92ee_dm_init_edca_turbo(struct ieee80211_hw *hw)
626{
627	struct rtl_priv *rtlpriv = rtl_priv(hw);
628
629	rtlpriv->dm.current_turbo_edca = false;
630	rtlpriv->dm.is_cur_rdlstate = false;
631	rtlpriv->dm.is_any_nonbepkts = false;
632}
633
634static void rtl92ee_dm_check_edca_turbo(struct ieee80211_hw *hw)
635{
636	struct rtl_priv *rtlpriv = rtl_priv(hw);
637
638	static u64 last_txok_cnt;
639	static u64 last_rxok_cnt;
640	u64 cur_txok_cnt = 0;
641	u64 cur_rxok_cnt = 0;
642	u32 edca_be_ul = 0x5ea42b;
643	u32 edca_be_dl = 0x5ea42b; /*not sure*/
644	u32 edca_be = 0x5ea42b;
645	bool is_cur_rdlstate;
646	bool b_edca_turbo_on = false;
647
648	if (rtlpriv->dm.dbginfo.num_non_be_pkt > 0x100)
649		rtlpriv->dm.is_any_nonbepkts = true;
650	rtlpriv->dm.dbginfo.num_non_be_pkt = 0;
651
652	cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
653	cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
654
655	/*b_bias_on_rx = false;*/
656	b_edca_turbo_on = ((!rtlpriv->dm.is_any_nonbepkts) &&
657			   (!rtlpriv->dm.disable_framebursting)) ?
658			  true : false;
659
660	if (rtl92ee_dm_is_edca_turbo_disable(hw))
661		goto check_exit;
662
663	if (b_edca_turbo_on) {
664		is_cur_rdlstate = (cur_rxok_cnt > cur_txok_cnt * 4) ?
665				    true : false;
666
667		edca_be = is_cur_rdlstate ? edca_be_dl : edca_be_ul;
668		rtl_write_dword(rtlpriv , REG_EDCA_BE_PARAM , edca_be);
669		rtlpriv->dm.is_cur_rdlstate = is_cur_rdlstate;
670		rtlpriv->dm.current_turbo_edca = true;
671	} else {
672		if (rtlpriv->dm.current_turbo_edca) {
673			u8 tmp = AC0_BE;
674
675			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM,
676						      (u8 *)(&tmp));
677		}
678		rtlpriv->dm.current_turbo_edca = false;
679	}
680
681check_exit:
682	rtlpriv->dm.is_any_nonbepkts = false;
683	last_txok_cnt = rtlpriv->stats.txbytesunicast;
684	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
685}
686
687static void rtl92ee_dm_dynamic_edcca(struct ieee80211_hw *hw)
688{
689	struct rtl_priv *rtlpriv = rtl_priv(hw);
690	u8 reg_c50 , reg_c58;
691	bool fw_current_in_ps_mode = false;
692
693	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
694				      (u8 *)(&fw_current_in_ps_mode));
695	if (fw_current_in_ps_mode)
696		return;
697
698	reg_c50 = rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
699	reg_c58 = rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
700
701	if (reg_c50 > 0x28 && reg_c58 > 0x28) {
702		if (!rtlpriv->rtlhal.pre_edcca_enable) {
703			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x03);
704			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x00);
705			rtlpriv->rtlhal.pre_edcca_enable = true;
706		}
707	} else if (reg_c50 < 0x25 && reg_c58 < 0x25) {
708		if (rtlpriv->rtlhal.pre_edcca_enable) {
709			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD, 0x7f);
710			rtl_write_byte(rtlpriv, ROFDM0_ECCATHRESHOLD + 2, 0x7f);
711			rtlpriv->rtlhal.pre_edcca_enable = false;
712		}
713	}
714}
715
716static void rtl92ee_dm_adaptivity(struct ieee80211_hw *hw)
717{
718	rtl92ee_dm_dynamic_edcca(hw);
719}
720
721static void rtl92ee_dm_write_dynamic_cca(struct ieee80211_hw *hw,
722					 u8 cur_mf_state)
723{
724	struct dynamic_primary_cca *primarycca = &rtl_priv(hw)->primarycca;
725
726	if (primarycca->mf_state != cur_mf_state)
727		rtl_set_bbreg(hw, DM_REG_L1SBD_PD_CH_11N, BIT(8) | BIT(7),
728			      cur_mf_state);
729
730	primarycca->mf_state = cur_mf_state;
731}
732
733static void rtl92ee_dm_dynamic_primary_cca_ckeck(struct ieee80211_hw *hw)
734{
735	struct rtl_priv *rtlpriv = rtl_priv(hw);
736	struct false_alarm_statistics *falsealm_cnt = &rtlpriv->falsealm_cnt;
737	struct dynamic_primary_cca *primarycca = &rtlpriv->primarycca;
738	bool is40mhz = false;
739	u64 ofdm_cca, ofdm_fa, bw_usc_cnt, bw_lsc_cnt;
740	u8 sec_ch_offset;
741	u8 cur_mf_state;
742	static u8 count_down = MONITOR_TIME;
743
744	ofdm_cca = falsealm_cnt->cnt_ofdm_cca;
745	ofdm_fa = falsealm_cnt->cnt_ofdm_fail;
746	bw_usc_cnt = falsealm_cnt->cnt_bw_usc;
747	bw_lsc_cnt = falsealm_cnt->cnt_bw_lsc;
748	is40mhz = rtlpriv->mac80211.bw_40;
749	sec_ch_offset = rtlpriv->mac80211.cur_40_prime_sc;
750	/* NIC: 2: sec is below,  1: sec is above */
751
752	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP) {
753		cur_mf_state = MF_USC_LSC;
754		rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
755		return;
756	}
757
758	if (rtlpriv->mac80211.link_state < MAC80211_LINKED)
759		return;
760
761	if (is40mhz)
762		return;
763
764	if (primarycca->pricca_flag == 0) {
765		/* Primary channel is above
766		 * NOTE: duplicate CTS can remove this condition
767		 */
768		if (sec_ch_offset == 2) {
769			if ((ofdm_cca > OFDMCCA_TH) &&
770			    (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) &&
771			    (ofdm_fa > (ofdm_cca >> 1))) {
772				primarycca->intf_type = 1;
773				primarycca->intf_flag = 1;
774				cur_mf_state = MF_USC;
775				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
776				primarycca->pricca_flag = 1;
777			} else if ((ofdm_cca > OFDMCCA_TH) &&
778				   (bw_lsc_cnt > (bw_usc_cnt + BW_IND_BIAS)) &&
779				   (ofdm_fa < (ofdm_cca >> 1))) {
780				primarycca->intf_type = 2;
781				primarycca->intf_flag = 1;
782				cur_mf_state = MF_USC;
783				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
784				primarycca->pricca_flag = 1;
785				primarycca->dup_rts_flag = 1;
786				rtlpriv->rtlhal.rts_en = 1;
787			} else {
788				primarycca->intf_type = 0;
789				primarycca->intf_flag = 0;
790				cur_mf_state = MF_USC_LSC;
791				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
792				rtlpriv->rtlhal.rts_en = 0;
793				primarycca->dup_rts_flag = 0;
794			}
795		} else if (sec_ch_offset == 1) {
796			if ((ofdm_cca > OFDMCCA_TH) &&
797			    (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) &&
798			    (ofdm_fa > (ofdm_cca >> 1))) {
799				primarycca->intf_type = 1;
800				primarycca->intf_flag = 1;
801				cur_mf_state = MF_LSC;
802				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
803				primarycca->pricca_flag = 1;
804			} else if ((ofdm_cca > OFDMCCA_TH) &&
805				   (bw_usc_cnt > (bw_lsc_cnt + BW_IND_BIAS)) &&
806				   (ofdm_fa < (ofdm_cca >> 1))) {
807				primarycca->intf_type = 2;
808				primarycca->intf_flag = 1;
809				cur_mf_state = MF_LSC;
810				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
811				primarycca->pricca_flag = 1;
812				primarycca->dup_rts_flag = 1;
813				rtlpriv->rtlhal.rts_en = 1;
814			} else {
815				primarycca->intf_type = 0;
816				primarycca->intf_flag = 0;
817				cur_mf_state = MF_USC_LSC;
818				rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
819				rtlpriv->rtlhal.rts_en = 0;
820				primarycca->dup_rts_flag = 0;
821			}
822		}
823	} else {/* PrimaryCCA->PriCCA_flag==1 */
824		count_down--;
825		if (count_down == 0) {
826			count_down = MONITOR_TIME;
827			primarycca->pricca_flag = 0;
828			cur_mf_state = MF_USC_LSC;
829			/* default */
830			rtl92ee_dm_write_dynamic_cca(hw, cur_mf_state);
831			rtlpriv->rtlhal.rts_en = 0;
832			primarycca->dup_rts_flag = 0;
833			primarycca->intf_type = 0;
834			primarycca->intf_flag = 0;
835		}
836	}
837}
838
839static void rtl92ee_dm_dynamic_atc_switch(struct ieee80211_hw *hw)
840{
841	struct rtl_priv *rtlpriv = rtl_priv(hw);
842	struct rtl_dm *rtldm = rtl_dm(rtl_priv(hw));
843	u8 crystal_cap;
844	u32 packet_count;
845	int cfo_khz_a , cfo_khz_b , cfo_ave = 0, adjust_xtal = 0;
846	int cfo_ave_diff;
847
848	if (rtlpriv->mac80211.link_state < MAC80211_LINKED) {
849		if (rtldm->atc_status == ATC_STATUS_OFF) {
850			rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
851				      ATC_STATUS_ON);
852			rtldm->atc_status = ATC_STATUS_ON;
853		}
854		/* Disable CFO tracking for BT */
855		if (rtlpriv->cfg->ops->get_btc_status()) {
856			if (!rtlpriv->btcoexist.btc_ops->
857			    btc_is_bt_disabled(rtlpriv)) {
858				RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_LOUD,
859					 "odm_DynamicATCSwitch(): Disable CFO tracking for BT!!\n");
860				return;
861			}
862		}
863		/* Reset Crystal Cap */
864		if (rtldm->crystal_cap != rtlpriv->efuse.crystalcap) {
865			rtldm->crystal_cap = rtlpriv->efuse.crystalcap;
866			crystal_cap = rtldm->crystal_cap & 0x3f;
867			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
868				      (crystal_cap | (crystal_cap << 6)));
869		}
870	} else {
871		cfo_khz_a = (int)(rtldm->cfo_tail[0] * 3125) / 1280;
872		cfo_khz_b = (int)(rtldm->cfo_tail[1] * 3125) / 1280;
873		packet_count = rtldm->packet_count;
874
875		if (packet_count == rtldm->packet_count_pre)
876			return;
877
878		rtldm->packet_count_pre = packet_count;
879
880		if (rtlpriv->phy.rf_type == RF_1T1R)
881			cfo_ave = cfo_khz_a;
882		else
883			cfo_ave = (int)(cfo_khz_a + cfo_khz_b) >> 1;
884
885		cfo_ave_diff = (rtldm->cfo_ave_pre >= cfo_ave) ?
886			       (rtldm->cfo_ave_pre - cfo_ave) :
887			       (cfo_ave - rtldm->cfo_ave_pre);
888
889		if (cfo_ave_diff > 20 && rtldm->large_cfo_hit == 0) {
890			rtldm->large_cfo_hit = 1;
891			return;
892		}
893		rtldm->large_cfo_hit = 0;
894
895		rtldm->cfo_ave_pre = cfo_ave;
896
897		if (cfo_ave >= -rtldm->cfo_threshold &&
898		    cfo_ave <= rtldm->cfo_threshold && rtldm->is_freeze == 0) {
899			if (rtldm->cfo_threshold == CFO_THRESHOLD_XTAL) {
900				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL + 10;
901				rtldm->is_freeze = 1;
902			} else {
903				rtldm->cfo_threshold = CFO_THRESHOLD_XTAL;
904			}
905		}
906
907		if (cfo_ave > rtldm->cfo_threshold && rtldm->crystal_cap < 0x3f)
908			adjust_xtal = ((cfo_ave - CFO_THRESHOLD_XTAL) >> 2) + 1;
909		else if ((cfo_ave < -rtlpriv->dm.cfo_threshold) &&
910			 rtlpriv->dm.crystal_cap > 0)
911			adjust_xtal = ((cfo_ave + CFO_THRESHOLD_XTAL) >> 2) - 1;
912
913		if (adjust_xtal != 0) {
914			rtldm->is_freeze = 0;
915			rtldm->crystal_cap += adjust_xtal;
916
917			if (rtldm->crystal_cap > 0x3f)
918				rtldm->crystal_cap = 0x3f;
919			else if (rtldm->crystal_cap < 0)
920				rtldm->crystal_cap = 0;
921
922			crystal_cap = rtldm->crystal_cap & 0x3f;
923			rtl_set_bbreg(hw, REG_MAC_PHY_CTRL, 0xFFF000,
924				      (crystal_cap | (crystal_cap << 6)));
925		}
926
927		if (cfo_ave < CFO_THRESHOLD_ATC &&
928		    cfo_ave > -CFO_THRESHOLD_ATC) {
929			if (rtldm->atc_status == ATC_STATUS_ON) {
930				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
931					      ATC_STATUS_OFF);
932				rtldm->atc_status = ATC_STATUS_OFF;
933			}
934		} else {
935			if (rtldm->atc_status == ATC_STATUS_OFF) {
936				rtl_set_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11),
937					      ATC_STATUS_ON);
938				rtldm->atc_status = ATC_STATUS_ON;
939			}
940		}
941	}
942}
943
944static void rtl92ee_dm_init_txpower_tracking(struct ieee80211_hw *hw)
945{
946	struct rtl_priv *rtlpriv = rtl_priv(hw);
947	struct rtl_dm *dm = rtl_dm(rtlpriv);
948	u8 path;
949
950	dm->txpower_tracking = true;
951	dm->default_ofdm_index = 30;
952	dm->default_cck_index = 20;
953
954	dm->swing_idx_cck_base = dm->default_cck_index;
955	dm->cck_index = dm->default_cck_index;
956
957	for (path = RF90_PATH_A; path < MAX_RF_PATH; path++) {
958		dm->swing_idx_ofdm_base[path] = dm->default_ofdm_index;
959		dm->ofdm_index[path] = dm->default_ofdm_index;
960		dm->delta_power_index[path] = 0;
961		dm->delta_power_index_last[path] = 0;
962		dm->power_index_offset[path] = 0;
963	}
964}
965
966void rtl92ee_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
967{
968	struct rtl_priv *rtlpriv = rtl_priv(hw);
969	struct rate_adaptive *p_ra = &rtlpriv->ra;
970
971	p_ra->ratr_state = DM_RATR_STA_INIT;
972	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
973
974	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
975		rtlpriv->dm.useramask = true;
976	else
977		rtlpriv->dm.useramask = false;
978
979	p_ra->ldpc_thres = 35;
980	p_ra->use_ldpc = false;
981	p_ra->high_rssi_thresh_for_ra = 50;
982	p_ra->low_rssi_thresh_for_ra40m = 20;
983}
984
985static bool _rtl92ee_dm_ra_state_check(struct ieee80211_hw *hw,
986				       s32 rssi, u8 *ratr_state)
987{
988	struct rtl_priv *rtlpriv = rtl_priv(hw);
989	struct rate_adaptive *p_ra = &rtlpriv->ra;
990	const u8 go_up_gap = 5;
991	u32 high_rssithresh_for_ra = p_ra->high_rssi_thresh_for_ra;
992	u32 low_rssithresh_for_ra = p_ra->low_rssi_thresh_for_ra40m;
993	u8 state;
994
995	/* Threshold Adjustment:
996	 * when RSSI state trends to go up one or two levels,
997	 * make sure RSSI is high enough.
998	 * Here GoUpGap is added to solve
999	 * the boundary's level alternation issue.
1000	 */
1001	switch (*ratr_state) {
1002	case DM_RATR_STA_INIT:
1003	case DM_RATR_STA_HIGH:
1004		break;
1005	case DM_RATR_STA_MIDDLE:
1006		high_rssithresh_for_ra += go_up_gap;
1007		break;
1008	case DM_RATR_STA_LOW:
1009		high_rssithresh_for_ra += go_up_gap;
1010		low_rssithresh_for_ra += go_up_gap;
1011		break;
1012	default:
1013		RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
1014			 "wrong rssi level setting %d !", *ratr_state);
1015		break;
1016	}
1017
1018	/* Decide RATRState by RSSI. */
1019	if (rssi > high_rssithresh_for_ra)
1020		state = DM_RATR_STA_HIGH;
1021	else if (rssi > low_rssithresh_for_ra)
1022		state = DM_RATR_STA_MIDDLE;
1023	else
1024		state = DM_RATR_STA_LOW;
1025
1026	if (*ratr_state != state) {
1027		*ratr_state = state;
1028		return true;
1029	}
1030
1031	return false;
1032}
1033
1034static void rtl92ee_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
1035{
1036	struct rtl_priv *rtlpriv = rtl_priv(hw);
1037	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
1038	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
1039	struct rate_adaptive *p_ra = &rtlpriv->ra;
1040	struct ieee80211_sta *sta = NULL;
1041
1042	if (is_hal_stop(rtlhal)) {
1043		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1044			 "driver is going to unload\n");
1045		return;
1046	}
1047
1048	if (!rtlpriv->dm.useramask) {
1049		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
1050			 "driver does not control rate adaptive mask\n");
1051		return;
1052	}
1053
1054	if (mac->link_state == MAC80211_LINKED &&
1055	    mac->opmode == NL80211_IFTYPE_STATION) {
1056		if (rtlpriv->dm.undec_sm_pwdb < p_ra->ldpc_thres) {
1057			p_ra->use_ldpc = true;
1058			p_ra->lower_rts_rate = true;
1059		} else if (rtlpriv->dm.undec_sm_pwdb >
1060			   (p_ra->ldpc_thres - 5)) {
1061			p_ra->use_ldpc = false;
1062			p_ra->lower_rts_rate = false;
1063		}
1064		if (_rtl92ee_dm_ra_state_check(hw, rtlpriv->dm.undec_sm_pwdb,
1065					       &p_ra->ratr_state)) {
1066			rcu_read_lock();
1067			sta = rtl_find_sta(hw, mac->bssid);
1068			if (sta)
1069				rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
1070							      p_ra->ratr_state);
1071			rcu_read_unlock();
1072
1073			p_ra->pre_ratr_state = p_ra->ratr_state;
1074		}
1075	}
1076}
1077
1078static void rtl92ee_dm_init_dynamic_atc_switch(struct ieee80211_hw *hw)
1079{
1080	struct rtl_priv *rtlpriv = rtl_priv(hw);
1081
1082	rtlpriv->dm.crystal_cap = rtlpriv->efuse.crystalcap;
1083
1084	rtlpriv->dm.atc_status = rtl_get_bbreg(hw, ROFDM1_CFOTRACKING, BIT(11));
1085	rtlpriv->dm.cfo_threshold = CFO_THRESHOLD_XTAL;
1086}
1087
1088void rtl92ee_dm_init(struct ieee80211_hw *hw)
1089{
1090	struct rtl_priv *rtlpriv = rtl_priv(hw);
1091
1092	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
1093
1094	rtl92ee_dm_diginit(hw);
1095	rtl92ee_dm_init_rate_adaptive_mask(hw);
1096	rtl92ee_dm_init_primary_cca_check(hw);
1097	rtl92ee_dm_init_edca_turbo(hw);
1098	rtl92ee_dm_init_txpower_tracking(hw);
1099	rtl92ee_dm_init_dynamic_atc_switch(hw);
1100}
1101
1102static void rtl92ee_dm_common_info_self_update(struct ieee80211_hw *hw)
1103{
1104	struct rtl_priv *rtlpriv = rtl_priv(hw);
1105	struct rtl_sta_info *drv_priv;
1106	u8 cnt = 0;
1107
1108	rtlpriv->dm.one_entry_only = false;
1109
1110	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_STATION &&
1111	    rtlpriv->mac80211.link_state >= MAC80211_LINKED) {
1112		rtlpriv->dm.one_entry_only = true;
1113		return;
1114	}
1115
1116	if (rtlpriv->mac80211.opmode == NL80211_IFTYPE_AP ||
1117	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC ||
1118	    rtlpriv->mac80211.opmode == NL80211_IFTYPE_MESH_POINT) {
1119		spin_lock_bh(&rtlpriv->locks.entry_list_lock);
1120		list_for_each_entry(drv_priv, &rtlpriv->entry_list, list) {
1121			cnt++;
1122		}
1123		spin_unlock_bh(&rtlpriv->locks.entry_list_lock);
1124
1125		if (cnt == 1)
1126			rtlpriv->dm.one_entry_only = true;
1127	}
1128}
1129
1130void rtl92ee_dm_dynamic_arfb_select(struct ieee80211_hw *hw,
1131				    u8 rate, bool collision_state)
1132{
1133	struct rtl_priv *rtlpriv = rtl_priv(hw);
1134
1135	if (rate >= DESC92C_RATEMCS8  && rate <= DESC92C_RATEMCS12) {
1136		if (collision_state == 1) {
1137			if (rate == DESC92C_RATEMCS12) {
1138				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
1139				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1140						0x07060501);
1141			} else if (rate == DESC92C_RATEMCS11) {
1142				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
1143				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1144						0x07070605);
1145			} else if (rate == DESC92C_RATEMCS10) {
1146				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
1147				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1148						0x08080706);
1149			} else if (rate == DESC92C_RATEMCS9) {
1150				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
1151				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1152						0x08080707);
1153			} else {
1154				rtl_write_dword(rtlpriv, REG_DARFRC, 0x0);
1155				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1156						0x09090808);
1157			}
1158		} else {   /* collision_state == 0 */
1159			if (rate == DESC92C_RATEMCS12) {
1160				rtl_write_dword(rtlpriv, REG_DARFRC,
1161						0x05010000);
1162				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1163						0x09080706);
1164			} else if (rate == DESC92C_RATEMCS11) {
1165				rtl_write_dword(rtlpriv, REG_DARFRC,
1166						0x06050000);
1167				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1168						0x09080807);
1169			} else if (rate == DESC92C_RATEMCS10) {
1170				rtl_write_dword(rtlpriv, REG_DARFRC,
1171						0x07060000);
1172				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1173						0x0a090908);
1174			} else if (rate == DESC92C_RATEMCS9) {
1175				rtl_write_dword(rtlpriv, REG_DARFRC,
1176						0x07070000);
1177				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1178						0x0a090808);
1179			} else {
1180				rtl_write_dword(rtlpriv, REG_DARFRC,
1181						0x08080000);
1182				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1183						0x0b0a0909);
1184			}
1185		}
1186	} else {  /* MCS13~MCS15,  1SS, G-mode */
1187		if (collision_state == 1) {
1188			if (rate == DESC92C_RATEMCS15) {
1189				rtl_write_dword(rtlpriv, REG_DARFRC,
1190						0x00000000);
1191				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1192						0x05040302);
1193			} else if (rate == DESC92C_RATEMCS14) {
1194				rtl_write_dword(rtlpriv, REG_DARFRC,
1195						0x00000000);
1196				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1197						0x06050302);
1198			} else if (rate == DESC92C_RATEMCS13) {
1199				rtl_write_dword(rtlpriv, REG_DARFRC,
1200						0x00000000);
1201				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1202						0x07060502);
1203			} else {
1204				rtl_write_dword(rtlpriv, REG_DARFRC,
1205						0x00000000);
1206				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1207						0x06050402);
1208			}
1209		} else{   /* collision_state == 0 */
1210			if (rate == DESC92C_RATEMCS15) {
1211				rtl_write_dword(rtlpriv, REG_DARFRC,
1212						0x03020000);
1213				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1214						0x07060504);
1215			} else if (rate == DESC92C_RATEMCS14) {
1216				rtl_write_dword(rtlpriv, REG_DARFRC,
1217						0x03020000);
1218				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1219						0x08070605);
1220			} else if (rate == DESC92C_RATEMCS13) {
1221				rtl_write_dword(rtlpriv, REG_DARFRC,
1222						0x05020000);
1223				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1224						0x09080706);
1225			} else {
1226				rtl_write_dword(rtlpriv, REG_DARFRC,
1227						0x04020000);
1228				rtl_write_dword(rtlpriv, REG_DARFRC + 4,
1229						0x08070605);
1230			}
1231		}
1232	}
1233}
1234
1235void rtl92ee_dm_watchdog(struct ieee80211_hw *hw)
1236{
1237	struct rtl_priv *rtlpriv = rtl_priv(hw);
1238	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
1239	bool fw_current_inpsmode = false;
1240	bool fw_ps_awake = true;
1241
1242	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
1243				      (u8 *)(&fw_current_inpsmode));
1244	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
1245				      (u8 *)(&fw_ps_awake));
1246	if (ppsc->p2p_ps_info.p2p_ps_mode)
1247		fw_ps_awake = false;
1248
1249	if ((ppsc->rfpwr_state == ERFON) &&
1250	    ((!fw_current_inpsmode) && fw_ps_awake) &&
1251	    (!ppsc->rfchange_inprogress)) {
1252		rtl92ee_dm_common_info_self_update(hw);
1253		rtl92ee_dm_false_alarm_counter_statistics(hw);
1254		rtl92ee_dm_check_rssi_monitor(hw);
1255		rtl92ee_dm_dig(hw);
1256		rtl92ee_dm_adaptivity(hw);
1257		rtl92ee_dm_cck_packet_detection_thresh(hw);
1258		rtl92ee_dm_refresh_rate_adaptive_mask(hw);
1259		rtl92ee_dm_check_edca_turbo(hw);
1260		rtl92ee_dm_dynamic_atc_switch(hw);
1261		rtl92ee_dm_dynamic_primary_cca_ckeck(hw);
1262	}
1263}
1264