xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8723bs/hal/phydm/phydm_dynamic_rx_path.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2017 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  *****************************************************************************/
15 
16 /* ************************************************************
17  * include files
18  * ************************************************************ */
19 #include "mp_precomp.h"
20 #include "phydm_precomp.h"
21 
22 #ifdef CONFIG_DYNAMIC_RX_PATH
23 
24 void
phydm_process_phy_status_for_dynamic_rx_path(void * p_dm_void,void * p_phy_info_void,void * p_pkt_info_void)25 phydm_process_phy_status_for_dynamic_rx_path(
26 	void			*p_dm_void,
27 	void			*p_phy_info_void,
28 	void			*p_pkt_info_void
29 )
30 {
31 	struct PHY_DM_STRUCT				*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
32 	struct phydm_phyinfo_struct		*p_phy_info = (struct phydm_phyinfo_struct *)p_phy_info_void;
33 	struct phydm_perpkt_info_struct		*p_pktinfo = (struct phydm_perpkt_info_struct *)p_pkt_info_void;
34 	struct _DYNAMIC_RX_PATH_					*p_dm_drp_table	= &(p_dm->dm_drp_table);
35 	/*u8					is_cck_rate=0;*/
36 
37 
38 
39 }
40 
41 void
phydm_drp_get_statistic(void * p_dm_void)42 phydm_drp_get_statistic(
43 	void			*p_dm_void
44 )
45 {
46 	struct PHY_DM_STRUCT					*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
47 	struct _DYNAMIC_RX_PATH_						*p_dm_drp_table = &(p_dm->dm_drp_table);
48 	struct phydm_fa_struct		*false_alm_cnt = (struct phydm_fa_struct *)phydm_get_structure(p_dm, PHYDM_FALSEALMCNT);
49 
50 	odm_false_alarm_counter_statistics(p_dm);
51 
52 	PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[CCA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n",
53 		false_alm_cnt->cnt_cck_cca, false_alm_cnt->cnt_ofdm_cca, false_alm_cnt->cnt_cca_all));
54 
55 	PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[FA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n",
56 		false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, false_alm_cnt->cnt_all));
57 }
58 
59 void
phydm_dynamic_rx_path(void * p_dm_void)60 phydm_dynamic_rx_path(
61 	void			*p_dm_void
62 )
63 {
64 	struct PHY_DM_STRUCT				*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
65 	struct _DYNAMIC_RX_PATH_					*p_dm_drp_table	= &(p_dm->dm_drp_table);
66 	u8		training_set_timmer_en;
67 	u8		curr_drp_state;
68 	u32		rx_ok_cal;
69 	u32		RSSI = 0;
70 	struct phydm_fa_struct		*false_alm_cnt = (struct phydm_fa_struct *)phydm_get_structure(p_dm, PHYDM_FALSEALMCNT);
71 
72 	if (!(p_dm->support_ability & ODM_BB_DYNAMIC_RX_PATH)) {
73 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[Return Init]   Not Support Dynamic RX PAth\n"));
74 		return;
75 	}
76 
77 	PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("Current drp_state = ((%d))\n", p_dm_drp_table->drp_state));
78 
79 	curr_drp_state = p_dm_drp_table->drp_state;
80 
81 	if (p_dm_drp_table->drp_state == DRP_INIT_STATE) {
82 
83 		phydm_drp_get_statistic(p_dm);
84 
85 		if (false_alm_cnt->cnt_crc32_ok_all > 20) {
86 			PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[Stop DRP Training] cnt_crc32_ok_all = ((%d))\n", false_alm_cnt->cnt_crc32_ok_all));
87 			p_dm_drp_table->drp_state  = DRP_INIT_STATE;
88 			training_set_timmer_en = false;
89 		} else {
90 			PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[Start DRP Training] cnt_crc32_ok_all = ((%d))\n", false_alm_cnt->cnt_crc32_ok_all));
91 			p_dm_drp_table->drp_state  = DRP_TRAINING_STATE_0;
92 			p_dm_drp_table->curr_rx_path = BB_PATH_AB;
93 			training_set_timmer_en = true;
94 		}
95 
96 	} else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_0) {
97 
98 		phydm_drp_get_statistic(p_dm);
99 
100 		p_dm_drp_table->curr_cca_all_cnt_0 = false_alm_cnt->cnt_cca_all;
101 		p_dm_drp_table->curr_fa_all_cnt_0 = false_alm_cnt->cnt_all;
102 
103 		p_dm_drp_table->drp_state  = DRP_TRAINING_STATE_1;
104 		p_dm_drp_table->curr_rx_path = BB_PATH_B;
105 		training_set_timmer_en = true;
106 
107 	} else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_1) {
108 
109 		phydm_drp_get_statistic(p_dm);
110 
111 		p_dm_drp_table->curr_cca_all_cnt_1 = false_alm_cnt->cnt_cca_all;
112 		p_dm_drp_table->curr_fa_all_cnt_1 = false_alm_cnt->cnt_all;
113 
114 #if 1
115 		p_dm_drp_table->drp_state  = DRP_DECISION_STATE;
116 #else
117 
118 		if (*(p_dm->p_mp_mode)) {
119 			rx_ok_cal = p_dm->phy_dbg_info.num_qry_phy_status_cck + p_dm->phy_dbg_info.num_qry_phy_status_ofdm;
120 			RSSI = (rx_ok_cal != 0) ? p_dm->rx_pwdb_ave / rx_ok_cal : 0;
121 			PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("MP RSSI = ((%d))\n", RSSI));
122 		}
123 
124 		if (RSSI > p_dm_drp_table->rssi_threshold)
125 
126 			p_dm_drp_table->drp_state  = DRP_DECISION_STATE;
127 
128 		else  {
129 
130 			p_dm_drp_table->drp_state  = DRP_TRAINING_STATE_2;
131 			p_dm_drp_table->curr_rx_path = BB_PATH_A;
132 			training_set_timmer_en = true;
133 		}
134 #endif
135 	} else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_2) {
136 
137 		phydm_drp_get_statistic(p_dm);
138 
139 		p_dm_drp_table->curr_cca_all_cnt_2 = false_alm_cnt->cnt_cca_all;
140 		p_dm_drp_table->curr_fa_all_cnt_2 = false_alm_cnt->cnt_all;
141 		p_dm_drp_table->drp_state  = DRP_DECISION_STATE;
142 	}
143 
144 	if (p_dm_drp_table->drp_state == DRP_DECISION_STATE) {
145 
146 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("Current drp_state = ((%d))\n", p_dm_drp_table->drp_state));
147 
148 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[0] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_0, p_dm_drp_table->curr_fa_all_cnt_0));
149 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[1] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_1, p_dm_drp_table->curr_fa_all_cnt_1));
150 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[2] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_2, p_dm_drp_table->curr_fa_all_cnt_2));
151 
152 		if (p_dm_drp_table->curr_fa_all_cnt_1 < p_dm_drp_table->curr_fa_all_cnt_0) {
153 
154 			if ((p_dm_drp_table->curr_fa_all_cnt_0 - p_dm_drp_table->curr_fa_all_cnt_1) > p_dm_drp_table->fa_diff_threshold)
155 				p_dm_drp_table->curr_rx_path = BB_PATH_B;
156 			else
157 				p_dm_drp_table->curr_rx_path = BB_PATH_AB;
158 		} else
159 			p_dm_drp_table->curr_rx_path = BB_PATH_AB;
160 
161 		phydm_config_ofdm_rx_path(p_dm, p_dm_drp_table->curr_rx_path);
162 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[Training Result]  curr_rx_path = ((%s%s)),\n",
163 			((p_dm_drp_table->curr_rx_path & BB_PATH_A)  ? "A"  : " "), ((p_dm_drp_table->curr_rx_path & BB_PATH_B)  ? "B"  : " ")));
164 
165 		p_dm_drp_table->drp_state = DRP_INIT_STATE;
166 		training_set_timmer_en = false;
167 	}
168 
169 	PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("DRP_state: ((%d)) -> ((%d))\n", curr_drp_state, p_dm_drp_table->drp_state));
170 
171 	if (training_set_timmer_en) {
172 
173 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[Training en]  curr_rx_path = ((%s%s)), training_time = ((%d ms))\n",
174 			((p_dm_drp_table->curr_rx_path & BB_PATH_A)  ? "A"  : " "), ((p_dm_drp_table->curr_rx_path & BB_PATH_B)  ? "B"  : " "), p_dm_drp_table->training_time));
175 
176 		phydm_config_ofdm_rx_path(p_dm, p_dm_drp_table->curr_rx_path);
177 		odm_set_timer(p_dm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer), p_dm_drp_table->training_time); /*ms*/
178 	} else
179 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("DRP period end\n\n", curr_drp_state, p_dm_drp_table->drp_state));
180 
181 }
182 
183 #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
184 void
phydm_dynamic_rx_path_callback(struct timer_list * p_timer)185 phydm_dynamic_rx_path_callback(
186 	struct timer_list		*p_timer
187 )
188 {
189 	struct _ADAPTER		*adapter = (struct _ADAPTER *)p_timer->adapter;
190 	HAL_DATA_TYPE	*p_hal_data = GET_HAL_DATA(adapter);
191 	struct PHY_DM_STRUCT		*p_dm = &(p_hal_data->DM_OutSrc);
192 	struct _DYNAMIC_RX_PATH_			*p_dm_drp_table = &(p_dm->dm_drp_table);
193 
194 #if DEV_BUS_TYPE == RT_PCI_INTERFACE
195 #if USE_WORKITEM
196 	odm_schedule_work_item(&(p_dm_drp_table->phydm_dynamic_rx_path_workitem));
197 #else
198 	{
199 		/* dbg_print("phydm_dynamic_rx_path\n"); */
200 		phydm_dynamic_rx_path(p_dm);
201 	}
202 #endif
203 #else
204 	odm_schedule_work_item(&(p_dm_drp_table->phydm_dynamic_rx_path_workitem));
205 #endif
206 }
207 
208 void
phydm_dynamic_rx_path_workitem_callback(void * p_context)209 phydm_dynamic_rx_path_workitem_callback(
210 	void		*p_context
211 )
212 {
213 	struct _ADAPTER		*p_adapter = (struct _ADAPTER *)p_context;
214 	HAL_DATA_TYPE	*p_hal_data = GET_HAL_DATA(p_adapter);
215 	struct PHY_DM_STRUCT		*p_dm = &(p_hal_data->DM_OutSrc);
216 
217 	/* dbg_print("phydm_dynamic_rx_path\n"); */
218 	phydm_dynamic_rx_path(p_dm);
219 }
220 #else if (DM_ODM_SUPPORT_TYPE == ODM_CE)
221 
222 void
phydm_dynamic_rx_path_callback(void * function_context)223 phydm_dynamic_rx_path_callback(
224 	void *function_context
225 )
226 {
227 	struct PHY_DM_STRUCT	*p_dm = (struct PHY_DM_STRUCT *)function_context;
228 	struct _ADAPTER	*padapter = p_dm->adapter;
229 
230 	if (padapter->net_closed == true)
231 		return;
232 
233 #if 0 /* Can't do I/O in timer callback*/
234 	odm_s0s1_sw_ant_div(p_dm, SWAW_STEP_DETERMINE);
235 #else
236 	/*rtw_run_in_thread_cmd(padapter, odm_sw_antdiv_workitem_callback, padapter);*/
237 #endif
238 }
239 
240 #endif
241 
242 void
phydm_dynamic_rx_path_timers(void * p_dm_void,u8 state)243 phydm_dynamic_rx_path_timers(
244 	void		*p_dm_void,
245 	u8		state
246 )
247 {
248 	struct PHY_DM_STRUCT		*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
249 	struct _DYNAMIC_RX_PATH_			*p_dm_drp_table	= &(p_dm->dm_drp_table);
250 
251 	if (state == INIT_DRP_TIMMER) {
252 
253 		odm_initialize_timer(p_dm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer),
254 			(void *)phydm_dynamic_rx_path_callback, NULL, "phydm_sw_antenna_switch_timer");
255 	} else if (state == CANCEL_DRP_TIMMER)
256 
257 		odm_cancel_timer(p_dm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer));
258 
259 	else if (state == RELEASE_DRP_TIMMER)
260 
261 		odm_release_timer(p_dm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer));
262 
263 }
264 
265 void
phydm_dynamic_rx_path_init(void * p_dm_void)266 phydm_dynamic_rx_path_init(
267 	void			*p_dm_void
268 )
269 {
270 	struct PHY_DM_STRUCT				*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
271 	struct _DYNAMIC_RX_PATH_					*p_dm_drp_table	= &(p_dm->dm_drp_table);
272 	boolean			ret_value;
273 
274 	if (!(p_dm->support_ability & ODM_BB_DYNAMIC_RX_PATH)) {
275 		PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("[Return]   Not Support Dynamic RX PAth\n"));
276 		return;
277 	}
278 	PHYDM_DBG(p_dm, DBG_DYN_RX_PATH, ("phydm_dynamic_rx_path_init\n"));
279 
280 	p_dm_drp_table->drp_state = DRP_INIT_STATE;
281 	p_dm_drp_table->rssi_threshold = DRP_RSSI_TH;
282 	p_dm_drp_table->fa_count_thresold = 50;
283 	p_dm_drp_table->fa_diff_threshold = 50;
284 	p_dm_drp_table->training_time = 100; /*ms*/
285 	p_dm_drp_table->drp_skip_counter = 0;
286 	p_dm_drp_table->drp_period  = 0;
287 	p_dm_drp_table->drp_init_finished = true;
288 
289 	ret_value = phydm_api_trx_mode(p_dm, (enum bb_path)BB_PATH_AB, (enum bb_path)BB_PATH_AB, true);
290 
291 }
292 
293 void
phydm_drp_debug(void * p_dm_void,u32 * const dm_value,u32 * _used,char * output,u32 * _out_len)294 phydm_drp_debug(
295 	void		*p_dm_void,
296 	u32		*const dm_value,
297 	u32		*_used,
298 	char		*output,
299 	u32		*_out_len
300 )
301 {
302 	struct PHY_DM_STRUCT		*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
303 	u32			used = *_used;
304 	u32			out_len = *_out_len;
305 	struct _DYNAMIC_RX_PATH_			*p_dm_drp_table = &(p_dm->dm_drp_table);
306 
307 	switch (dm_value[0])	{
308 
309 	case DRP_TRAINING_TIME:
310 		p_dm_drp_table->training_time = (u16)dm_value[1];
311 		break;
312 	case DRP_TRAINING_PERIOD:
313 		p_dm_drp_table->drp_period = (u8)dm_value[1];
314 		break;
315 	case DRP_RSSI_THRESHOLD:
316 		p_dm_drp_table->rssi_threshold = (u8)dm_value[1];
317 		break;
318 	case DRP_FA_THRESHOLD:
319 		p_dm_drp_table->fa_count_thresold = dm_value[1];
320 		break;
321 	case DRP_FA_DIFF_THRESHOLD:
322 		p_dm_drp_table->fa_diff_threshold = dm_value[1];
323 		break;
324 	default:
325 		PHYDM_SNPRINTF((output + used, out_len - used, "[DRP] unknown command\n"));
326 		break;
327 	}
328 
329 	*_used = used;
330 	*_out_len = out_len;
331 }
332 
333 void
phydm_dynamic_rx_path_caller(void * p_dm_void)334 phydm_dynamic_rx_path_caller(
335 	void			*p_dm_void
336 )
337 {
338 	struct PHY_DM_STRUCT		*p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
339 	struct _DYNAMIC_RX_PATH_			*p_dm_drp_table	= &(p_dm->dm_drp_table);
340 
341 	if (p_dm_drp_table->drp_skip_counter <  p_dm_drp_table->drp_period)
342 		p_dm_drp_table->drp_skip_counter++;
343 	else
344 		p_dm_drp_table->drp_skip_counter = 0;
345 
346 	if (p_dm_drp_table->drp_skip_counter != 0)
347 		return;
348 
349 	if (p_dm_drp_table->drp_init_finished != true)
350 		return;
351 
352 	phydm_dynamic_rx_path(p_dm);
353 
354 }
355 #endif
356