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