xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/phl_sound_fsm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 - 2020 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 #include "phl_headers.h"
16 
17 /*
18  * SND sub function
19  */
20 #ifdef CONFIG_FSM
snd_set_timer(struct phl_sound_obj * snd,int duration,u16 event)21 static void snd_set_timer(struct phl_sound_obj *snd, int duration, u16 event)
22 {
23 	FSM_INFO(snd->fsm, "%s, duration=%d\n", __func__, duration);
24 	phl_fsm_set_alarm(snd->fsm_obj, duration, event);
25 }
26 
27 
28 enum rtw_phl_status
phl_snd_upd_snd_para(struct phl_info_t * phl_info,void * param)29 phl_snd_upd_snd_para(struct phl_info_t *phl_info, void *param)
30 {
31 	struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
32 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
33 	struct phl_snd_start_req *req = (struct phl_snd_start_req *)param;
34 	struct phl_sound_param *snd_param = &snd->snd_param;
35 	struct rtw_wifi_role_t *wrole = NULL;
36 	FUNCIN_WSTS(pstatus);
37 
38 	snd_param->snd_func_grp_num = 0;
39 	snd_param->grp_used_map = 0;
40 	snd_param->snd_fail_counter = 0;
41 
42 	if (req != NULL) {
43 		snd_param->m_wrole = req->wrole;
44 		wrole = (struct rtw_wifi_role_t *)req->wrole;
45 		snd_param->snd_proc_timeout_ms = req->proc_timeout_ms;/* ms */
46 		snd_param->snd_dialog_token = req->dialog_token;
47 		snd_param->snd_proc_period = req->proc_period;
48 		snd_param->test_flag = req->test_flag;
49 		snd_param->bypass_snd_sts_chk = req->bypass_sts_chk;
50 	}
51 
52 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
53 		  "wrole->type = 0x%x \n",
54 		  wrole->type);
55 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
56 		  "timeout = %d ms\n", snd_param->snd_proc_timeout_ms);
57 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
58 		  "dialog tkn = %d\n", snd_param->snd_dialog_token);
59 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
60 		  "snd period = %d ms\n", snd_param->snd_proc_period);
61 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
62 		  "test flag = %d \n", snd_param->test_flag);
63 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
64 		  "by pass sts check = %d \n", snd_param->bypass_snd_sts_chk);
65 
66 	FUNCIN_WSTS(pstatus);
67 	return pstatus;
68 }
69 
70 
71 
72 /*
73  * SND state handler
74  */
75 
snd_fsm_func_init_st_hdl(void * obj,u16 event,void * param)76 static int snd_fsm_func_init_st_hdl(void *obj, u16 event, void *param)
77 {
78 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
79 	void *d = phl_to_drvpriv(snd->phl_info);
80 	int ret = 0;
81 
82 	switch (event) {
83 	case FSM_EV_STATE_IN:
84 		/* Pending and waiting sounding start event */
85 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
86 			  "snd_fsm_func_init_st_hdl : SND FUNC pending and wait SND START\n");
87 	break;
88 	case SND_FUNC_EV_SND_START:
89 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
90 			  "snd_fsm_func_init_st_hdl : Recv SND START Event at timestamp %d\n",
91 			  _os_get_cur_time_us());
92 		/* SND_FUNC_EV_SND_START Shall have input param */
93 		_os_spinlock(d, &snd->snd_lock, _bh, NULL);
94 		snd->snd_in_progress = 1; /*TODO: Check set flag timing*/
95 		_os_spinunlock(d, &snd->snd_lock, _bh, NULL);
96 
97 		phl_snd_upd_snd_para(snd->phl_info, param);
98 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_FUNC_READY);
99 	break;
100 	case FSM_EV_STATE_OUT:
101 		phl_fsm_cancel_alarm(snd->fsm_obj);
102 	break;
103 	case FSM_EV_CANCEL:
104 	case FSM_EV_TIMER_EXPIRE:
105 	break;
106 	default:
107 	break;
108 	}
109 	return ret;
110 
111 }
112 
snd_fsm_func_deinit_st_hdl(void * obj,u16 event,void * param)113 static int snd_fsm_func_deinit_st_hdl(void *obj, u16 event, void *param)
114 {
115 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
116 	int ret = 0;
117 
118 
119 	switch (event) {
120 	case FSM_EV_STATE_IN:
121 	break;
122 	case FSM_EV_STATE_OUT:
123 		phl_fsm_cancel_alarm(snd->fsm_obj);
124 	break;
125 	case FSM_EV_CANCEL:
126 	case FSM_EV_TIMER_EXPIRE:
127 	break;
128 	default:
129 	break;
130 	}
131 
132 	return ret;
133 
134 }
135 
snd_fsm_func_ready_st_hdl(void * obj,u16 event,void * param)136 static int snd_fsm_func_ready_st_hdl(void *obj, u16 event, void *param)
137 {
138 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
139 	int ret = 0;
140 	struct rtw_wifi_role_t *m_wrole =
141 			(struct rtw_wifi_role_t *)snd->snd_param.m_wrole;
142 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
143 
144 	switch (event) {
145 	case FSM_EV_STATE_IN:
146 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
147 			  "snd_fsm_func_ready_st_hdl : FSM_EV_STATE_IN\n");
148 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
149 			  "snd_fsm_func_ready_st_hdl : (Re)Start Sounding Timestamp %d\n",
150 				_os_get_cur_time_us());
151 		if(NULL == m_wrole) {
152 			snd_set_timer(snd, 0, SND_EV_TERMINATE);
153 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
154 				  "snd_fsm_func_ready_st_hdl : NULL == m_wrole\n");
155 			break;
156 		}
157 
158 		if ((PHL_RTYPE_STATION == m_wrole->type) &&
159 		    (MLME_LINKED != m_wrole->mstate)) {
160 				PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
161 					  "snd_fsm_func_ready_st_hdl : role STA in not in linked : 0x%x\n",
162 					   m_wrole->mstate);
163 				snd_set_timer(snd, 0, SND_EV_TERMINATE);
164 				break;
165 		}
166 		snd_set_timer(snd, 10, SND_FUNC_EV_PROC_GRP);
167 	break;
168 	case FSM_EV_STATE_OUT:
169 		phl_fsm_cancel_alarm(snd->fsm_obj);
170 	break;
171 	case FSM_EV_CANCEL:
172 	case FSM_EV_TIMER_EXPIRE:
173 		phl_fsm_cancel_alarm(snd->fsm_obj);
174 	break;
175 	case SND_FUNC_EV_PROC_GRP:
176 		phl_snd_func_remove_grp_all(snd->phl_info);
177 		/*TODO: loop for all of the wrole */
178 		if(NULL == m_wrole) {
179 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
180 				  "==> ROLE == NULL !!!\n STOP SND Function!!!\n");
181 			snd_set_timer(snd, 10, SND_EV_TERMINATE);
182 			break;
183 		}
184 		pstatus = phl_snd_func_grouping(snd->phl_info, m_wrole->id);
185 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
186 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
187 				  "==> SND_FUNC_EV_PROC_GRP FAIL !!!\n STOP SND Function!!!\n");
188 			snd_set_timer(snd, 10, SND_EV_TERMINATE);
189 			break;
190 		}
191 		if (0 == snd->snd_param.snd_func_grp_num) {
192 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
193 				  "==> Available SND GRP == 0 !!!\n STOP SND Function!!!\n");
194 			snd_set_timer(snd, 10, SND_EV_TERMINATE);
195 			break;
196 		}
197 		/* fall through */
198 	/*go through*/
199 	case SND_FUNC_EV_START_SND_PROC:
200 		pstatus = phl_snd_func_pre_config(snd->phl_info);
201 		if (pstatus != RTW_PHL_STATUS_SUCCESS) {
202 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
203 				  "==> SND_FUNC_EV_START_SND_PROC FAIL !!!\n STOP SND Function!!!\n");
204 			snd_set_timer(snd, 10, SND_EV_TERMINATE);
205 			break;
206 		}
207 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_IDLE);
208 	break;
209 	case SND_EV_TERMINATE:
210 		snd->is_terminated = true;
211 		phl_fsm_cancel_alarm(snd->fsm_obj);
212 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_TERMINATE);
213 	break;
214 	default:
215 	break;
216 	}
217 
218 	return ret;
219 }
220 
snd_fsm_func_leave_st_hdl(void * obj,u16 event,void * param)221 static int snd_fsm_func_leave_st_hdl(void *obj, u16 event, void *param)
222 {
223 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
224 	void *d = phl_to_drvpriv(snd->phl_info);
225 	int ret = 0;
226 
227 
228 	switch (event) {
229 	case FSM_EV_STATE_IN:
230 		_os_spinlock(d, &snd->snd_lock, _bh, NULL);
231 		snd->snd_in_progress = 0;
232 		_os_spinunlock(d, &snd->snd_lock, _bh, NULL);
233 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_FUNC_INIT);
234 	break;
235 	case FSM_EV_STATE_OUT:
236 		phl_fsm_cancel_alarm(snd->fsm_obj);
237 	break;
238 	case FSM_EV_CANCEL:
239 	case FSM_EV_TIMER_EXPIRE:
240 		phl_fsm_cancel_alarm(snd->fsm_obj);
241 	break;
242 	case SND_EV_TERMINATE:
243 		_os_spinlock(d, &snd->snd_lock, _bh, NULL);
244 		snd->is_terminated = 1;
245 		snd->snd_in_progress = 0;
246 		_os_spinunlock(d, &snd->snd_lock, _bh, NULL);
247 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_FUNC_INIT);
248 	break;
249 	default:
250 	break;
251 	}
252 	return ret;
253 }
254 
255 
256 
snd_fsm_proc_idle_st_hdl(void * obj,u16 event,void * param)257 static int snd_fsm_proc_idle_st_hdl(void *obj, u16 event, void *param)
258 {
259 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
260 	struct phl_sound_param *snd_param = &snd->snd_param;
261 	int ret = 0;
262 	struct phl_snd_grp *grp = NULL;
263 
264 	switch (event) {
265 	case FSM_EV_STATE_IN:
266 
267 	/* go through */
268 	case SND_PROC_EV_IDLE_FREE_PRE_RES :
269 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
270 		  "pre_proc_grp_idx : %d ; cur_proc_grp_idx : %d \n",
271 		  snd_param->pre_proc_grp_idx, snd_param->cur_proc_grp_idx);
272 
273 		if (snd_param->cur_proc_grp_idx !=
274 			snd_param->pre_proc_grp_idx) {
275 			grp = phl_snd_get_grp_byidx(snd->phl_info,
276 						snd_param->pre_proc_grp_idx);
277 			if (grp != NULL) {
278 				phl_snd_proc_chk_prev_grp(snd->phl_info, grp);
279 			}
280 		}
281 		/* fall through */
282 	/* go through */
283 	case SND_PROC_EV_IDLE_GET_SND_GRP :
284 		if(MAX_SND_GRP_NUM == snd_param->cur_proc_grp_idx) {
285 			snd_set_timer(snd, 10, SND_EV_TERMINATE);
286 			break;
287 		}
288 
289 		grp = phl_snd_get_grp_byidx(snd->phl_info,
290 					    snd_param->cur_proc_grp_idx);
291 		/* TODO: Check Grp STA is still available */
292 		/* phl_snd_check_condition() */
293 		if (NULL == grp) {
294 			snd_set_timer(snd, 0, SND_EV_TERMINATE);
295 			break;
296 		}
297 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_BUSY); /* For SND FSM LOOP Test */
298 	break;
299 	case FSM_EV_CANCEL:
300 	case FSM_EV_TIMER_EXPIRE:
301 		phl_fsm_cancel_alarm(snd->fsm_obj);
302 	break;
303 	case FSM_EV_STATE_OUT:
304 		phl_fsm_cancel_alarm(snd->fsm_obj);
305 	break;
306 	case SND_EV_TERMINATE:
307 		snd->is_terminated = true;
308 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_TERMINATE);
309 	break;
310 	default:
311 	break;
312 	}
313 	return ret;
314 }
snd_fsm_proc_busy_st_hdl(void * obj,u16 event,void * param)315 static int snd_fsm_proc_busy_st_hdl(void *obj, u16 event, void *param)
316 {
317 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
318 	struct phl_sound_param *snd_param = &snd->snd_param;
319 	int ret = 0;
320 	struct phl_snd_grp *grp = NULL;
321 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
322 	u8 sta_num = 0;
323 	struct rtw_wifi_role_t *wrole =
324 		(struct rtw_wifi_role_t *)snd->snd_param.m_wrole;
325 
326 	switch (event) {
327 	case FSM_EV_STATE_IN:
328 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
329 			  "SND PROC BUSY : Process Grp idx = %d\n",
330 			  snd_param->cur_proc_grp_idx);
331 		grp = phl_snd_get_grp_byidx(snd->phl_info,
332 					    snd_param->cur_proc_grp_idx);
333 		if (NULL == grp) {
334 			snd_set_timer(snd, 0, SND_PROC_EV_BUSY_SND_DOWN);
335 			break;
336 		}
337 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
338 			  "SND_PROC_BUSY : grp sta number = %d \n",
339 			  grp->num_sta);
340 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
341 			  "SND_PROC_BUSY : grp snd_fb_t = 0x%x \n",
342 			  grp->sta[0].snd_fb_t);
343 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
344 			  "SND_PROC_BUSY : grp primary sta macid = 0x%x \n",
345 			  grp->sta[0].macid);
346 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
347 			  "SND_PROC_BUSY : grp sta-1 macid = 0x%x \n",
348 			  grp->sta[1].macid);
349 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
350 			  "SND_PROC_BUSY : grp sta-2 macid = 0x%x \n",
351 			  grp->sta[2].macid);
352 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
353 			  "SND_PROC_BUSY : grp sta-3 macid = 0x%x \n",
354 			  grp->sta[3].macid);
355 		/* fall through */
356 	case SND_PROC_EV_BUSY_GET_BF_RES:
357 		pstatus = phl_snd_proc_get_res(snd->phl_info, grp, &sta_num);
358 		if ((sta_num == 0) || (RTW_PHL_STATUS_SUCCESS != pstatus)) {
359 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SND_PROC_BUSY : sta_num = 0 !!! \n");
360 			grp->snd_sts = PHL_SND_STS_FAILURE;
361 			snd_set_timer(snd, 0, SND_PROC_EV_BUSY_SND_DOWN);
362 			break;
363 		}
364 		/* fall through */
365 	/* go through */
366 	case SND_PROC_EV_BUSY_PRE_CFG:
367 		pstatus = phl_snd_proc_precfg(snd->phl_info, grp);
368 		/* fall through */
369 	/* go through */
370 	case SND_PROC_EV_BUSY_TRIG_SND:
371 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
372 			  "[SND] Dialog token = 0x%x\n",
373 			  snd->snd_param.snd_dialog_token);
374 		pstatus = phl_snd_proc_start_sounding_fw(snd->phl_info, grp);
375 		if (RTW_PHL_STATUS_SUCCESS != pstatus) {
376 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
377 				  "phl_snd_proc_start_sounding_fw FAIL\n");
378 			grp->snd_sts = PHL_SND_STS_FAILURE;
379 			if((grp->snd_type == PHL_SND_TYPE_HE_HW) ||
380 			   (grp->snd_type == PHL_SND_TYPE_VHT_HW)) {
381 				phl_snd_mac_ctrl(snd->phl_info, wrole, 1);
382 			}
383 			/* TODO : FW / halmac might crashed , stop sounding fsm module */
384 			snd_set_timer(snd, 0, SND_EV_TERMINATE);
385 		}
386 		snd->snd_param.snd_dialog_token++;
387 		snd_set_timer(snd, 10, SND_PROC_EV_BUSY_REL_SND_CTRL);
388 	break;
389 	case SND_PROC_EV_BUSY_REL_SND_CTRL :
390 		grp = phl_snd_get_grp_byidx(snd->phl_info,
391 					    snd_param->cur_proc_grp_idx);
392 		if (NULL == grp) {
393 			snd_set_timer(snd, 0, SND_PROC_EV_BUSY_SND_DOWN);
394 			break;
395 		}
396 		if((grp->snd_type == PHL_SND_TYPE_HE_HW) ||
397 		   (grp->snd_type == PHL_SND_TYPE_VHT_HW)) {
398 			phl_snd_mac_ctrl(snd->phl_info, wrole, 1);
399 		}
400 		snd_set_timer(snd, snd->snd_param.snd_proc_timeout_ms,
401 			      SND_PROC_EV_BUSY_SND_DOWN);
402 	break;
403 	case SND_PROC_EV_BUSY_SND_DOWN:
404 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
405 			  "SND_PROC_BUSY: Recv C2H or Timeout , Switch to PROC DOWN\n");
406 		grp = phl_snd_get_grp_byidx(snd->phl_info,
407 					    snd_param->cur_proc_grp_idx);
408 		if (NULL != grp)
409 			phl_snd_polling_pri_sta_sts(snd->phl_info, grp);
410 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_DOWN); /* For SND FSM Periodic LOOP Test */
411 	break;
412 	case FSM_EV_STATE_OUT:
413 		phl_fsm_cancel_alarm(snd->fsm_obj);
414 	break;
415 	case FSM_EV_CANCEL:
416 	case FSM_EV_TIMER_EXPIRE:
417 	break;
418 	case SND_EV_TERMINATE:
419 		snd->is_terminated = true;
420 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_TERMINATE);
421 	break;
422 	default:
423 	break;
424 	}
425 	return ret;
426 }
427 
snd_fsm_proc_down_st_hdl(void * obj,u16 event,void * param)428 static int snd_fsm_proc_down_st_hdl(void *obj, u16 event, void *param)
429 {
430 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
431 	int ret = 0;
432 	struct phl_sound_param *snd_param = &snd->snd_param;
433 	struct phl_snd_grp *grp = NULL;
434 	enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
435 
436 	switch (event) {
437 	case FSM_EV_STATE_IN:
438 		grp = phl_snd_get_grp_byidx(snd->phl_info,
439 					    snd_param->cur_proc_grp_idx);
440 		if (NULL == grp) {
441 			snd_set_timer(snd, snd_param->snd_proc_period,
442 						SND_PROC_EV_DOWN_SND_END);
443 			break;
444 		}
445 
446 		if (PHL_SND_STS_FAILURE == grp->snd_sts) {
447 			snd_set_timer(snd, snd_param->snd_proc_period,
448 				      SND_PROC_EV_DOWN_SND_END);
449 		}
450 		/* fall through */
451 	/* go through */
452 	case SND_PROC_EV_DOWN_POST_CFG:
453 		pstatus = phl_snd_proc_postcfg(snd->phl_info, grp);
454 		if (pstatus == RTW_PHL_STATUS_SUCCESS) {
455 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
456 				  "POST CONFIG SUCCESS!!!!\n");
457 		}
458 		/* fall through */
459 	/* go through */
460 	case SND_PROC_EV_DOWN_SND_END:
461 		/* Check Test Mode */
462 		if (snd_param->test_flag&PHL_SND_TEST_F_ONE_TIME) {
463 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
464 				  "TEST MODE : Set EV to TERMINATE by test_flag\n");
465 			snd_set_timer(snd, snd_param->snd_proc_period,
466 						SND_EV_TERMINATE);
467 			break;
468 		}
469 		/* TODO: check next sounding needed
470 			if any sta disassociate or new sta associate, need re-grouping? */
471 		grp = phl_snd_get_grp_byidx(snd->phl_info,
472 					    snd_param->cur_proc_grp_idx);
473 		if (grp == NULL) {
474 			snd_set_timer(snd, snd_param->snd_proc_period,
475 				      SND_EV_TERMINATE);
476 		}
477 		if (RTW_PHL_STATUS_SUCCESS ==
478 			phl_snd_proc_chk_condition(snd->phl_info, grp)) {
479 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
480 				  "Status : Linked ; Set Timer for Next Sounding \n");
481 			snd_set_timer(snd, snd_param->snd_proc_period,
482 						SND_PROC_EV_DOWN_NEXT_SND);
483 		} else {
484 			PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
485 				  "Status : ERROR ; Set Timer to Terminate \n");
486 			snd_set_timer(snd, snd_param->snd_proc_period,
487 						SND_EV_TERMINATE);
488 		}
489 	break;
490 	case FSM_EV_CANCEL:
491 	case FSM_EV_TIMER_EXPIRE:
492 	break;
493 	case FSM_EV_STATE_OUT:
494 		phl_fsm_cancel_alarm(snd->fsm_obj);
495 	break;
496 	case SND_PROC_EV_DOWN_NEXT_SND:
497 		snd_param->pre_proc_grp_idx = snd_param->cur_proc_grp_idx;
498 		snd_param->cur_proc_grp_idx++;
499 
500 		if (snd_param->cur_proc_grp_idx >=
501 			snd_param->snd_func_grp_num) {
502 			/* start sounding process from group list head or terminated */
503 			if (snd->is_terminated)
504 				snd_param->cur_proc_grp_idx = MAX_SND_GRP_NUM;
505 			else
506 				snd_param->cur_proc_grp_idx = 0;
507 		}
508 
509 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
510 			  "Next Sounding Group Idx = %d",
511 			  snd_param->cur_proc_grp_idx);
512 
513 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_IDLE);
514 	break;
515 	case SND_EV_TERMINATE:
516 		snd->is_terminated = true;
517 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_PROC_TERMINATE);
518 	break;
519 	default:
520 	break;
521 	}
522 	return ret;
523 }
524 
snd_fsm_proc_terminiate_st_hdl(void * obj,u16 event,void * param)525 static int snd_fsm_proc_terminiate_st_hdl(void *obj, u16 event, void *param)
526 {
527 	struct phl_sound_obj *snd = (struct phl_sound_obj *)obj;
528 	int ret = 0;
529 
530 	switch (event) {
531 	case FSM_EV_STATE_IN:
532 		/* Free all sounding resource and goto FUNC Leave */
533 		phl_snd_func_remove_grp_all(snd->phl_info);
534 
535 		phl_fsm_state_goto(snd->fsm_obj, SND_ST_FUNC_LEAVE);
536 	break;
537 	case FSM_EV_CANCEL:
538 	case FSM_EV_TIMER_EXPIRE:
539 		phl_fsm_cancel_alarm(snd->fsm_obj);
540 	break;
541 	case FSM_EV_STATE_OUT:
542 		phl_fsm_cancel_alarm(snd->fsm_obj);
543 	break;
544 	default:
545 	break;
546 	}
547 	return ret;
548 }
549 
snd_dump_obj(void * obj,char * s,int * sz)550 static void snd_dump_obj(void *obj, char *s, int *sz)
551 {
552 	/* nothing to do for now */
553 }
554 
snd_dump_fsm(void * fsm,char * s,int * sz)555 static void snd_dump_fsm(void *fsm, char *s, int *sz)
556 {
557 	/* nothing to do for now */
558 }
559 
560 /* STATE table */
561 static struct fsm_state_ent snd_state_tbl[] = {
562 	ST_ENT(SND_ST_FUNC_INIT, snd_fsm_func_init_st_hdl),
563 	ST_ENT(SND_ST_FUNC_DEINIT, snd_fsm_func_deinit_st_hdl),
564 	ST_ENT(SND_ST_FUNC_READY, snd_fsm_func_ready_st_hdl),
565 	ST_ENT(SND_ST_FUNC_LEAVE, snd_fsm_func_leave_st_hdl),
566 	ST_ENT(SND_ST_PROC_IDLE, snd_fsm_proc_idle_st_hdl),
567 	ST_ENT(SND_ST_PROC_BUSY, snd_fsm_proc_busy_st_hdl),
568 	ST_ENT(SND_ST_PROC_DOWN, snd_fsm_proc_down_st_hdl),
569 	ST_ENT(SND_ST_PROC_TERMINATE,snd_fsm_proc_terminiate_st_hdl)
570 };
571 
572 /* EVENT table */
573 static struct fsm_event_ent snd_event_tbl[] = {
574 	EV_ENT(SND_FUNC_EV_INIT),
575 	EV_ENT(SND_FUNC_EV_DEINIT),
576 	EV_ENT(SND_FUNC_EV_SND_START),
577 	EV_ENT(SND_FUNC_EV_NOTIFY_PENDING_REQ),
578 	EV_ENT(SND_FUNC_EV_CHK_SND_STS),
579 	EV_ENT(SND_FUNC_EV_PROC_GRP),
580 	EV_ENT(SND_FUNC_EV_START_SND_PROC),
581 	EV_ENT(SND_FUNC_EV_END_SND),
582 	/*PROC IDLE*/
583 	EV_ENT(SND_PROC_EV_IDLE_GET_SND_GRP),
584 	/*PROC BUSY*/
585 	EV_ENT(SND_PROC_EV_BUSY_GET_BF_RES),
586 	EV_ENT(SND_PROC_EV_IDLE_FREE_PRE_RES),
587 	EV_ENT(SND_PROC_EV_BUSY_PRE_CFG),
588 	EV_ENT(SND_PROC_EV_BUSY_TRIG_SND),
589 	EV_ENT(SND_PROC_EV_BUSY_REL_SND_CTRL),
590 	EV_ENT(SND_PROC_EV_BUSY_POLLING_STS),
591 	EV_ENT(SND_PROC_EV_BUSY_SND_DOWN),
592 	/*PROC DOWN*/
593 	EV_ENT(SND_PROC_EV_DOWN_POST_CFG),
594 	EV_ENT(SND_PROC_EV_DOWN_SND_END),
595 	EV_ENT(SND_PROC_EV_DOWN_NEXT_SND),
596 	/*COMMON*/
597 	EV_ENT(SND_EV_TERMINATE),
598 	EV_ENT(SND_EV_DONOTHING),
599 	EV_ENT(SND_EV_MAX),
600 };
601 
602 /* For EXTERNAL application to create a SND FSM */
603 /* @root: FSM root structure
604  * @phl_info: private data structure to invoke hal/phl function
605  *
606  * return
607  * fsm_main: FSM main structure (Do NOT expose)
608  */
phl_sound_new_fsm(struct fsm_root * root,struct phl_info_t * phl_info)609 struct fsm_main *phl_sound_new_fsm(struct fsm_root *root,
610 	struct phl_info_t *phl_info)
611 {
612 	void *d = phl_to_drvpriv(phl_info);
613 	struct fsm_main *fsm = NULL;
614 	struct rtw_phl_fsm_tb tb;
615 
616 	_os_mem_set(d, &tb, 0, sizeof(tb));
617 
618 
619 	tb.state_tbl = snd_state_tbl;
620 	tb.max_state = sizeof(snd_state_tbl)/sizeof(snd_state_tbl[0]);
621 	tb.max_event = sizeof(snd_event_tbl)/sizeof(snd_event_tbl[0]);
622 	tb.evt_tbl = snd_event_tbl;
623 	tb.dump_obj = snd_dump_obj;
624 	tb.dump_obj = snd_dump_fsm;
625 	tb.dbg_level = FSM_DBG_INFO;
626 	tb.evt_level = FSM_DBG_INFO;
627 
628 	fsm = phl_fsm_init_fsm(root, "sound", phl_info, &tb);
629 
630 	return fsm;
631 }
632 
633 /* For EXTERNAL application to destory SND FSM */
634 /* @fsm: see fsm_main
635  */
phl_snd_destory_fsm(struct fsm_main * fsm)636 void phl_snd_destory_fsm(struct fsm_main *fsm)
637 {
638 	if (fsm == NULL)
639 		return;
640 
641 	/* deinit fsm local variable if has */
642 
643 	/* call FSM Framewro to deinit fsm */
644 	phl_fsm_deinit_fsm(fsm);
645 }
646 
647 /* For EXTERNAL application to destory sound object */
648 /* @pcmd: local created command object
649  *
650  */
phl_snd_destory_obj(struct phl_sound_obj * snd)651 void phl_snd_destory_obj(struct phl_sound_obj *snd)
652 {
653 	void *d = phl_to_drvpriv(snd->phl_info);
654 	if (snd == NULL)
655 		return;
656 
657 	/* deinit obj local variable if has */
658 	_os_spinlock_free(d, &snd->snd_lock);
659 	_os_spinlock_free(d, &snd->cmd_lock);
660 
661 	/* inform FSM framewory to recycle fsm_obj */
662 	phl_fsm_destory_obj(snd->fsm_obj);
663 }
664 
665 /* For EXTERNAL interrupt handler to send event into snd fsm (expose) */
666 
phl_snd_fsm_ev_c2h_snd_down(void * phl)667 enum rtw_phl_status phl_snd_fsm_ev_c2h_snd_down(void *phl)
668 {
669 	enum RTW_PHL_SND_NOTIFY_EVENT notify = RTW_PHL_SND_C2H_SND_DOWN;
670 
671 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
672 			"phl_snd_event_c2h_snd_down notify 0x%x\n", notify);
673 	return phl_snd_fsm_send_msg(phl, notify, NULL, 0);
674 }
675 
676 
677 enum rtw_phl_status
phl_snd_fsm_ev_start_func(void * phl,void * req)678 phl_snd_fsm_ev_start_func(void *phl, void *req)
679 {
680 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
681 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
682 	void *d = phl_to_drvpriv(phl_info);
683 	struct phl_snd_start_req *snd_req = NULL;//(struct phl_snd_start_req *)req;
684 
685 	enum RTW_PHL_SND_NOTIFY_EVENT notify = RTW_PHL_SND_START;
686 
687 	do {
688 		snd_req = (struct phl_snd_start_req *)_os_kmem_alloc(d,
689 				sizeof(*snd_req));
690 
691 		if (snd_req == NULL)
692 			break;
693 
694 		_os_mem_cpy(d, snd_req, req, sizeof(*snd_req));
695 
696 		PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
697 			  "phl_snd_event_start_func notify 0x%x\n", notify);
698 
699 		status = phl_snd_fsm_send_msg(phl, notify, snd_req,
700 					      sizeof(*snd_req));
701 
702 		_os_kmem_free(d, snd_req, sizeof(*snd_req));
703 
704 	} while (0);
705 
706 	return status;
707 }
708 
709 
phl_snd_fsm_ev_abort(void * phl)710 enum rtw_phl_status phl_snd_fsm_ev_abort(void *phl)
711 {
712 	enum RTW_PHL_SND_NOTIFY_EVENT notify = RTW_PHL_SND_ABORT;
713 
714 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
715 			"phl_snd_event_abort notify 0x%x\n", notify);
716 	return phl_snd_fsm_send_msg(phl, notify, NULL, 0);
717 }
718 
719 /* @phl: phl_info_t
720  * @notify: event to snd fsm
721  */
722 enum rtw_phl_status
phl_snd_fsm_send_msg(void * phl,enum RTW_PHL_SND_NOTIFY_EVENT notify,void * buf,u32 buf_sz)723 phl_snd_fsm_send_msg(void *phl, enum RTW_PHL_SND_NOTIFY_EVENT notify,
724 				void *buf, u32 buf_sz)
725 {
726 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
727 	struct phl_sound_obj *snd = phl_info->snd_obj;
728 	u16 event;
729 
730 	switch (notify) {
731 	case RTW_PHL_SND_START: /* Start Sound Func */
732 		event = SND_FUNC_EV_SND_START;
733 		break;
734 	case RTW_PHL_SND_ABORT: /* Go Terminate*/
735 		event = SND_EV_TERMINATE;
736 		break;
737 	case RTW_PHL_SND_C2H_SND_DOWN: /* Sound Dwon Configuration */
738 		event = SND_PROC_EV_BUSY_SND_DOWN;
739 		break;
740 	default:
741 		return RTW_PHL_STATUS_FAILURE;
742 	}
743 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
744 		  "phl_snd_send_msg event %d\n",
745 		  event);
746 	return phl_fsm_gen_msg(phl, snd->fsm_obj, buf, buf_sz, event);
747 }
748 
749 
750 /* For EXTERNAL application notify from upper layer*/
phl_snd_notify_from_upper_watchdog_status(void * phl,bool inprogress)751 void phl_snd_notify_from_upper_watchdog_status(void *phl, bool inprogress)
752 {
753 	struct phl_info_t *phl_info = (struct phl_info_t *)phl;
754 	struct phl_sound_obj *snd = NULL;
755 
756 	snd = phl_info->snd_obj;
757 	PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "is snd in progress : %d \n",
758 		  snd->snd_in_progress);
759 	/*TODO:*/
760 }
761 #endif /*CONFIG_FSM*/
762 
763