blob: 985e959ab879ad9cc5e52290aed1ec2fce067c9b [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/slab.h>
13#include <linux/kthread.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/uaccess.h>
17#include <linux/wait.h>
18#include <linux/mutex.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053019
20#include <soc/qcom/socinfo.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053021
Laxminath Kasam605b42f2017-08-01 22:02:15 +053022#include <dsp/msm_audio_ion.h>
23#include <dsp/q6audio-v2.h>
24#include <dsp/apr_audio-v2.h>
25#include <dsp/q6afe-v2.h>
26#include <dsp/audio_cal_utils.h>
Laxminath Kasam38070be2017-08-17 18:21:59 +053027#include <dsp/q6core.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053028#include <dsp/q6voice.h>
Laxminath Kasam38070be2017-08-17 18:21:59 +053029#include <ipc/apr_tal.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053030#include "adsp_err.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031
32#define TIMEOUT_MS 300
33
34
35#define CMD_STATUS_SUCCESS 0
36#define CMD_STATUS_FAIL 1
Laxminath Kasam38070be2017-08-17 18:21:59 +053037#define NUM_CHANNELS_MONO 1
38#define NUM_CHANNELS_STEREO 2
Aditya Bavanarif0cb90b2017-09-07 11:40:08 +053039#define NUM_CHANNELS_QUAD 4
Laxminath Kasam38070be2017-08-17 18:21:59 +053040#define CVP_VERSION_2 2
Aditya Bavanari245361d2017-09-07 12:11:30 +053041#define GAIN_Q14_FORMAT(a) (a << 14)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053042
43enum {
44 VOC_TOKEN_NONE,
45 VOIP_MEM_MAP_TOKEN,
46 VOC_CAL_MEM_MAP_TOKEN,
47 VOC_VOICE_HOST_PCM_MAP_TOKEN,
48 VOC_RTAC_MEM_MAP_TOKEN,
49 VOC_SOURCE_TRACKING_MEM_MAP_TOKEN
50};
51
52struct cvd_version_table cvd_version_table_mapping[CVD_INT_VERSION_MAX] = {
53 {CVD_VERSION_DEFAULT, CVD_INT_VERSION_DEFAULT},
54 {CVD_VERSION_0_0, CVD_INT_VERSION_0_0},
55 {CVD_VERSION_2_1, CVD_INT_VERSION_2_1},
56 {CVD_VERSION_2_2, CVD_INT_VERSION_2_2},
57 {CVD_VERSION_2_3, CVD_INT_VERSION_2_3},
58};
59
60static struct common_data common;
61static bool module_initialized;
62
63static int voice_send_enable_vocproc_cmd(struct voice_data *v);
64static int voice_send_netid_timing_cmd(struct voice_data *v);
65static int voice_send_attach_vocproc_cmd(struct voice_data *v);
66static int voice_send_set_device_cmd(struct voice_data *v);
67static int voice_send_vol_step_cmd(struct voice_data *v);
68static int voice_send_mvm_unmap_memory_physical_cmd(struct voice_data *v,
69 uint32_t mem_handle);
70static int voice_send_mvm_cal_network_cmd(struct voice_data *v);
71static int voice_send_mvm_media_type_cmd(struct voice_data *v);
72static int voice_send_mvm_cvd_version_cmd(struct voice_data *v);
73static int voice_send_cvs_data_exchange_mode_cmd(struct voice_data *v);
74static int voice_send_cvs_packet_exchange_config_cmd(struct voice_data *v);
75static int voice_set_packet_exchange_mode_and_config(uint32_t session_id,
76 uint32_t mode);
77
78static int voice_send_cvs_register_cal_cmd(struct voice_data *v);
79static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v);
80static int voice_send_cvp_create_cmd(struct voice_data *v);
81static int voice_send_cvp_register_dev_cfg_cmd(struct voice_data *v);
82static int voice_send_cvp_deregister_dev_cfg_cmd(struct voice_data *v);
83static int voice_send_cvp_register_cal_cmd(struct voice_data *v);
84static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v);
85static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v);
86static int voice_send_cvp_deregister_vol_cal_cmd(struct voice_data *v);
87static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v);
88static int voice_send_cvp_device_channels_cmd(struct voice_data *v);
89static int voice_send_cvp_media_format_cmd(struct voice_data *v,
90 uint32_t param_type);
91static int voice_send_cvp_topology_commit_cmd(struct voice_data *v);
Laxminath Kasam38070be2017-08-17 18:21:59 +053092static int voice_send_cvp_channel_info_cmd(struct voice_data *v);
93static int voice_send_cvp_channel_info_v2(struct voice_data *v,
94 uint32_t param_type);
95static int voice_get_avcs_version_per_service(uint32_t service_id);
96
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053097
98static int voice_cvs_stop_playback(struct voice_data *v);
99static int voice_cvs_start_playback(struct voice_data *v);
100static int voice_cvs_start_record(struct voice_data *v, uint32_t rec_mode);
101static int voice_cvs_stop_record(struct voice_data *v);
102
103static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv);
104static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv);
105static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv);
106
107static int voice_send_set_pp_enable_cmd(struct voice_data *v,
108 uint32_t module_id, int enable);
109static int is_cal_memory_allocated(void);
110static bool is_cvd_version_queried(void);
111static int is_voip_memory_allocated(void);
112static int voice_get_cvd_int_version(char *cvd_ver_string);
113static int voice_alloc_cal_mem_map_table(void);
114static int voice_alloc_rtac_mem_map_table(void);
115static int voice_alloc_oob_shared_mem(void);
116static int voice_free_oob_shared_mem(void);
117static int voice_alloc_oob_mem_table(void);
118static int voice_alloc_and_map_oob_mem(struct voice_data *v);
119
120static struct voice_data *voice_get_session_by_idx(int idx);
121
122static int remap_cal_data(struct cal_block_data *cal_block,
123 uint32_t session_id);
124static int voice_unmap_cal_memory(int32_t cal_type,
125 struct cal_block_data *cal_block);
126
127static int is_source_tracking_shared_memomry_allocated(void);
128static int voice_alloc_source_tracking_shared_memory(void);
129static int voice_alloc_and_map_source_tracking_shared_memory(
130 struct voice_data *v);
131static int voice_unmap_and_free_source_tracking_shared_memory(
132 struct voice_data *v);
133static int voice_send_set_sound_focus_cmd(struct voice_data *v,
134 struct sound_focus_param soundFocusData);
135static int voice_send_get_sound_focus_cmd(struct voice_data *v,
136 struct sound_focus_param *soundFocusData);
137static int voice_send_get_source_tracking_cmd(struct voice_data *v,
138 struct source_tracking_param *sourceTrackingData);
139
140static void voice_itr_init(struct voice_session_itr *itr,
141 u32 session_id)
142{
143 if (itr == NULL)
144 return;
145 itr->session_idx = voice_get_idx_for_session(session_id);
146 if (session_id == ALL_SESSION_VSID)
147 itr->cur_idx = 0;
148 else
149 itr->cur_idx = itr->session_idx;
150
151}
152
153static bool voice_itr_get_next_session(struct voice_session_itr *itr,
154 struct voice_data **voice)
155{
156 bool ret = false;
157
158 if (itr == NULL)
159 return false;
160 pr_debug("%s : cur idx = %d session idx = %d\n",
161 __func__, itr->cur_idx, itr->session_idx);
162
163 if (itr->cur_idx <= itr->session_idx) {
164 ret = true;
165 *voice = voice_get_session_by_idx(itr->cur_idx);
166 itr->cur_idx++;
167 } else {
168 *voice = NULL;
169 }
170
171 return ret;
172}
173
174static bool voice_is_valid_session_id(uint32_t session_id)
175{
176 bool ret = false;
177
178 switch (session_id) {
179 case VOICE_SESSION_VSID:
180 case VOICE2_SESSION_VSID:
181 case VOLTE_SESSION_VSID:
182 case VOIP_SESSION_VSID:
183 case QCHAT_SESSION_VSID:
184 case VOWLAN_SESSION_VSID:
185 case VOICEMMODE1_VSID:
186 case VOICEMMODE2_VSID:
187 case ALL_SESSION_VSID:
188 ret = true;
189 break;
190 default:
191 pr_err("%s: Invalid session_id : %x\n", __func__, session_id);
192
193 break;
194 }
195
196 return ret;
197}
198
199static u16 voice_get_mvm_handle(struct voice_data *v)
200{
201 if (v == NULL) {
202 pr_err("%s: v is NULL\n", __func__);
203 return 0;
204 }
205
206 pr_debug("%s: mvm_handle %d\n", __func__, v->mvm_handle);
207
208 return v->mvm_handle;
209}
210
211static void voice_set_mvm_handle(struct voice_data *v, u16 mvm_handle)
212{
213 pr_debug("%s: mvm_handle %d\n", __func__, mvm_handle);
214 if (v == NULL) {
215 pr_err("%s: v is NULL\n", __func__);
216 return;
217 }
218
219 v->mvm_handle = mvm_handle;
220}
221
222static u16 voice_get_cvs_handle(struct voice_data *v)
223{
224 if (v == NULL) {
225 pr_err("%s: v is NULL\n", __func__);
226 return 0;
227 }
228
229 pr_debug("%s: cvs_handle %d\n", __func__, v->cvs_handle);
230
231 return v->cvs_handle;
232}
233
234static void voice_set_cvs_handle(struct voice_data *v, u16 cvs_handle)
235{
236 pr_debug("%s: cvs_handle %d\n", __func__, cvs_handle);
237 if (v == NULL) {
238 pr_err("%s: v is NULL\n", __func__);
239 return;
240 }
241
242 v->cvs_handle = cvs_handle;
243}
244
245static u16 voice_get_cvp_handle(struct voice_data *v)
246{
247 if (v == NULL) {
248 pr_err("%s: v is NULL\n", __func__);
249 return 0;
250 }
251
252 pr_debug("%s: cvp_handle %d\n", __func__, v->cvp_handle);
253
254 return v->cvp_handle;
255}
256
257static void voice_set_cvp_handle(struct voice_data *v, u16 cvp_handle)
258{
259 pr_debug("%s: cvp_handle %d\n", __func__, cvp_handle);
260 if (v == NULL) {
261 pr_err("%s: v is NULL\n", __func__);
262 return;
263 }
264
265 v->cvp_handle = cvp_handle;
266}
267
268char *voc_get_session_name(u32 session_id)
269{
270 char *session_name = NULL;
271
272 if (session_id == common.voice[VOC_PATH_PASSIVE].session_id) {
273 session_name = VOICE_SESSION_NAME;
274 } else if (session_id ==
275 common.voice[VOC_PATH_VOLTE_PASSIVE].session_id) {
276 session_name = VOLTE_SESSION_NAME;
277 } else if (session_id ==
278 common.voice[VOC_PATH_QCHAT_PASSIVE].session_id) {
279 session_name = QCHAT_SESSION_NAME;
280 } else if (session_id ==
281 common.voice[VOC_PATH_VOWLAN_PASSIVE].session_id) {
282 session_name = VOWLAN_SESSION_NAME;
283 } else if (session_id ==
284 common.voice[VOC_PATH_VOICEMMODE1_PASSIVE].session_id) {
285 session_name = VOICEMMODE1_NAME;
286 } else if (session_id ==
287 common.voice[VOC_PATH_VOICEMMODE2_PASSIVE].session_id) {
288 session_name = VOICEMMODE2_NAME;
289 } else if (session_id == common.voice[VOC_PATH_FULL].session_id) {
290 session_name = VOIP_SESSION_NAME;
291 }
292 return session_name;
293}
294
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530295/**
296 * voc_get_session_id -
297 * Get session ID of given voice session name
298 *
299 * @name: voice session name
300 *
301 * Returns session id for valid session or 0 if invalid.
302 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530303uint32_t voc_get_session_id(char *name)
304{
305 u32 session_id = 0;
306
307 if (name != NULL) {
308 if (!strcmp(name, "Voice session"))
309 session_id = common.voice[VOC_PATH_PASSIVE].session_id;
310 else if (!strcmp(name, "Voice2 session"))
311 session_id =
312 common.voice[VOC_PATH_VOICE2_PASSIVE].session_id;
313 else if (!strcmp(name, "VoLTE session"))
314 session_id =
315 common.voice[VOC_PATH_VOLTE_PASSIVE].session_id;
316 else if (!strcmp(name, "QCHAT session"))
317 session_id =
318 common.voice[VOC_PATH_QCHAT_PASSIVE].session_id;
319 else if (!strcmp(name, "VoWLAN session"))
320 session_id =
321 common.voice[VOC_PATH_VOWLAN_PASSIVE].session_id;
322 else if (!strcmp(name, "VoiceMMode1"))
323 session_id =
324 common.voice[VOC_PATH_VOICEMMODE1_PASSIVE].session_id;
325 else if (!strcmp(name, "VoiceMMode2"))
326 session_id =
327 common.voice[VOC_PATH_VOICEMMODE2_PASSIVE].session_id;
328 else
329 session_id = common.voice[VOC_PATH_FULL].session_id;
330
331 pr_debug("%s: %s has session id 0x%x\n", __func__, name,
332 session_id);
333 }
334
335 return session_id;
336}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530337EXPORT_SYMBOL(voc_get_session_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530338
339static struct voice_data *voice_get_session(u32 session_id)
340{
341 struct voice_data *v = NULL;
342
343 switch (session_id) {
344 case VOICE_SESSION_VSID:
345 v = &common.voice[VOC_PATH_PASSIVE];
346 break;
347
348 case VOICE2_SESSION_VSID:
349 v = &common.voice[VOC_PATH_VOICE2_PASSIVE];
350 break;
351
352 case VOLTE_SESSION_VSID:
353 v = &common.voice[VOC_PATH_VOLTE_PASSIVE];
354 break;
355
356 case VOIP_SESSION_VSID:
357 v = &common.voice[VOC_PATH_FULL];
358 break;
359
360 case QCHAT_SESSION_VSID:
361 v = &common.voice[VOC_PATH_QCHAT_PASSIVE];
362 break;
363
364 case VOWLAN_SESSION_VSID:
365 v = &common.voice[VOC_PATH_VOWLAN_PASSIVE];
366 break;
367
368 case VOICEMMODE1_VSID:
369 v = &common.voice[VOC_PATH_VOICEMMODE1_PASSIVE];
370 break;
371
372 case VOICEMMODE2_VSID:
373 v = &common.voice[VOC_PATH_VOICEMMODE2_PASSIVE];
374 break;
375
376 case ALL_SESSION_VSID:
377 break;
378
379 default:
380 pr_err("%s: Invalid session_id : %x\n", __func__, session_id);
381
382 break;
383 }
384
385 pr_debug("%s:session_id 0x%x session handle %pK\n",
386 __func__, session_id, v);
387
388 return v;
389}
390
391int voice_get_idx_for_session(u32 session_id)
392{
393 int idx = 0;
394
395 switch (session_id) {
396 case VOICE_SESSION_VSID:
397 idx = VOC_PATH_PASSIVE;
398 break;
399
400 case VOICE2_SESSION_VSID:
401 idx = VOC_PATH_VOICE2_PASSIVE;
402 break;
403
404 case VOLTE_SESSION_VSID:
405 idx = VOC_PATH_VOLTE_PASSIVE;
406 break;
407
408 case VOIP_SESSION_VSID:
409 idx = VOC_PATH_FULL;
410 break;
411
412 case QCHAT_SESSION_VSID:
413 idx = VOC_PATH_QCHAT_PASSIVE;
414 break;
415
416 case VOWLAN_SESSION_VSID:
417 idx = VOC_PATH_VOWLAN_PASSIVE;
418 break;
419
420 case VOICEMMODE1_VSID:
421 idx = VOC_PATH_VOICEMMODE1_PASSIVE;
422 break;
423
424 case VOICEMMODE2_VSID:
425 idx = VOC_PATH_VOICEMMODE2_PASSIVE;
426 break;
427
428 case ALL_SESSION_VSID:
429 idx = MAX_VOC_SESSIONS - 1;
430 break;
431
432 default:
433 pr_err("%s: Invalid session_id : %x\n", __func__, session_id);
434
435 break;
436 }
437
438 return idx;
439}
440
441static struct voice_data *voice_get_session_by_idx(int idx)
442{
443 return ((idx < 0 || idx >= MAX_VOC_SESSIONS) ?
444 NULL : &common.voice[idx]);
445}
446
447static bool is_voip_session(u32 session_id)
448{
449 return (session_id == common.voice[VOC_PATH_FULL].session_id);
450}
451
452static bool is_volte_session(u32 session_id)
453{
454 return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id);
455}
456
457static bool is_voice2_session(u32 session_id)
458{
459 return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
460}
461
462static bool is_qchat_session(u32 session_id)
463{
464 return (session_id == common.voice[VOC_PATH_QCHAT_PASSIVE].session_id);
465}
466
467static bool is_vowlan_session(u32 session_id)
468{
469 return (session_id == common.voice[VOC_PATH_VOWLAN_PASSIVE].session_id);
470}
471
472static bool is_voicemmode1(u32 session_id)
473{
474 return session_id ==
475 common.voice[VOC_PATH_VOICEMMODE1_PASSIVE].session_id;
476}
477
478static bool is_voicemmode2(u32 session_id)
479{
480 return session_id ==
481 common.voice[VOC_PATH_VOICEMMODE2_PASSIVE].session_id;
482}
483
484static bool is_voc_state_active(int voc_state)
485{
486 if ((voc_state == VOC_RUN) ||
487 (voc_state == VOC_CHANGE) ||
488 (voc_state == VOC_STANDBY))
489 return true;
490
491 return false;
492}
493
494static void voc_set_error_state(uint16_t reset_proc)
495{
496 struct voice_data *v = NULL;
497 int i;
498
499 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
500 v = &common.voice[i];
501 if (v != NULL) {
502 v->voc_state = VOC_ERROR;
503 v->rec_info.recording = 0;
504 }
505 }
506}
507
508static bool is_other_session_active(u32 session_id)
509{
510 int i;
511 bool ret = false;
512
513 /* Check if there is other active session except the input one */
514 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
515 if (common.voice[i].session_id == session_id)
516 continue;
517
518 if (is_voc_state_active(common.voice[i].voc_state)) {
519 ret = true;
520 break;
521 }
522 }
523 pr_debug("%s: ret %d\n", __func__, ret);
524
525 return ret;
526}
527
528static bool is_sub1_vsid(u32 session_id)
529{
530 bool ret;
531
532 switch (session_id) {
533 case VOICE_SESSION_VSID:
534 case VOLTE_SESSION_VSID:
535 case VOWLAN_SESSION_VSID:
536 case VOICEMMODE1_VSID:
537 ret = true;
538 break;
539 default:
540 ret = false;
541 }
542
543 return ret;
544}
545
546static bool is_sub2_vsid(u32 session_id)
547{
548 bool ret;
549
550 switch (session_id) {
551 case VOICE2_SESSION_VSID:
552 case VOICEMMODE2_VSID:
553 ret = true;
554 break;
555 default:
556 ret = false;
557 }
558
559 return ret;
560}
561
562static bool is_voice_app_id(u32 session_id)
563{
564 return is_sub1_vsid(session_id) || is_sub2_vsid(session_id);
565}
566
567static void init_session_id(void)
568{
569 common.voice[VOC_PATH_PASSIVE].session_id = VOICE_SESSION_VSID;
570 common.voice[VOC_PATH_VOLTE_PASSIVE].session_id = VOLTE_SESSION_VSID;
571 common.voice[VOC_PATH_VOICE2_PASSIVE].session_id = VOICE2_SESSION_VSID;
572 common.voice[VOC_PATH_FULL].session_id = VOIP_SESSION_VSID;
573 common.voice[VOC_PATH_QCHAT_PASSIVE].session_id = QCHAT_SESSION_VSID;
574 common.voice[VOC_PATH_VOWLAN_PASSIVE].session_id = VOWLAN_SESSION_VSID;
575 common.voice[VOC_PATH_VOICEMMODE1_PASSIVE].session_id =
576 VOICEMMODE1_VSID;
577 common.voice[VOC_PATH_VOICEMMODE2_PASSIVE].session_id =
578 VOICEMMODE2_VSID;
579}
580
581static bool is_cvd_version_queried(void)
582{
583 bool ret = 0;
584
585 if (!strcmp(common.cvd_version, CVD_VERSION_DEFAULT))
586 ret = false;
587 else
588 ret = true;
589
590 return ret;
591}
592
593static int voice_get_cvd_int_version(char *cvd_ver_string)
594{
595 unsigned int idx;
596 int cvd_int_ver = CVD_INT_VERSION_DEFAULT;
597
598 for (idx = 0; idx < CVD_INT_VERSION_MAX; idx++) {
599 if (strcmp((char *)cvd_ver_string,
600 cvd_version_table_mapping[idx].cvd_ver) == 0) {
601 cvd_int_ver =
602 cvd_version_table_mapping[idx].cvd_ver_int;
603 break;
604 }
605 }
606 return cvd_int_ver;
607}
608
609static int voice_apr_register(uint32_t session_id)
610{
611
612 pr_debug("%s\n", __func__);
613
614 mutex_lock(&common.common_lock);
615
616 /* register callback to APR */
617 if (common.apr_q6_mvm == NULL) {
618 pr_debug("%s: Start to register MVM callback\n", __func__);
619
620 common.apr_q6_mvm = apr_register("ADSP", "MVM",
621 qdsp_mvm_callback,
622 0xFFFFFFFF, &common);
623
624 if (common.apr_q6_mvm == NULL) {
625 pr_err("%s: Unable to register MVM\n", __func__);
626 goto err;
627 }
628 }
629
630 if (common.apr_q6_cvs == NULL) {
631 pr_debug("%s: Start to register CVS callback\n", __func__);
632
633 common.apr_q6_cvs = apr_register("ADSP", "CVS",
634 qdsp_cvs_callback,
635 0xFFFFFFFF, &common);
636
637 if (common.apr_q6_cvs == NULL) {
638 pr_err("%s: Unable to register CVS\n", __func__);
639 goto err;
640 }
641 rtac_set_voice_handle(RTAC_CVS, common.apr_q6_cvs);
642 }
643
644 if (common.apr_q6_cvp == NULL) {
645 pr_debug("%s: Start to register CVP callback\n", __func__);
646
647 common.apr_q6_cvp = apr_register("ADSP", "CVP",
648 qdsp_cvp_callback,
649 0xFFFFFFFF, &common);
650
651 if (common.apr_q6_cvp == NULL) {
652 pr_err("%s: Unable to register CVP\n", __func__);
653 goto err;
654 }
655 rtac_set_voice_handle(RTAC_CVP, common.apr_q6_cvp);
656 }
657
658 mutex_unlock(&common.common_lock);
659
660 return 0;
661
662err:
663 if (common.apr_q6_cvs != NULL) {
664 apr_deregister(common.apr_q6_cvs);
665 common.apr_q6_cvs = NULL;
666 rtac_set_voice_handle(RTAC_CVS, NULL);
667 }
668 if (common.apr_q6_mvm != NULL) {
669 apr_deregister(common.apr_q6_mvm);
670 common.apr_q6_mvm = NULL;
671 }
672
673 mutex_unlock(&common.common_lock);
674
675 return -ENODEV;
676}
677
678static int voice_send_mvm_cvd_version_cmd(struct voice_data *v)
679{
680 int ret;
681 struct apr_hdr cvd_version_get_cmd;
682 void *apr_mvm;
683
684 if (v == NULL) {
685 pr_err("%s: v is NULL\n", __func__);
686
687 ret = -EINVAL;
688 goto done;
689 }
690
691 apr_mvm = common.apr_q6_mvm;
692 if (!apr_mvm) {
693 pr_err("%s: apr_mvm is NULL.\n", __func__);
694
695 ret = -EINVAL;
696 goto done;
697 }
698
699 /* Send command to CVD to retrieve Version */
700 cvd_version_get_cmd.hdr_field = APR_HDR_FIELD(
701 APR_MSG_TYPE_SEQ_CMD,
702 APR_HDR_LEN(APR_HDR_SIZE),
703 APR_PKT_VER);
704 cvd_version_get_cmd.pkt_size = APR_PKT_SIZE(
705 APR_HDR_SIZE,
706 sizeof(cvd_version_get_cmd) -
707 APR_HDR_SIZE);
708 cvd_version_get_cmd.src_port =
709 voice_get_idx_for_session(v->session_id);
710 cvd_version_get_cmd.dest_port = 0;
711 cvd_version_get_cmd.token = 0;
712 cvd_version_get_cmd.opcode = VSS_IVERSION_CMD_GET;
713
714 pr_debug("%s: send CVD version get cmd, pkt size = %d\n",
715 __func__, cvd_version_get_cmd.pkt_size);
716
717 v->mvm_state = CMD_STATUS_FAIL;
718 v->async_err = 0;
719 ret = apr_send_pkt(apr_mvm,
720 (uint32_t *) &cvd_version_get_cmd);
721 if (ret < 0) {
722 pr_err("%s: Error sending command\n", __func__);
723
724 ret = -EINVAL;
725 goto done;
726 }
727
728 ret = wait_event_timeout(v->mvm_wait,
729 (v->mvm_state == CMD_STATUS_SUCCESS),
730 msecs_to_jiffies(TIMEOUT_MS));
731 if (!ret) {
732 pr_err("%s: wait_event timeout, fall back to default\n",
733 __func__);
734
735 ret = -EINVAL;
736 goto done;
737 }
738 if (v->async_err > 0) {
739 pr_err("%s: DSP returned error[%s]\n",
740 __func__, adsp_err_get_err_str(
741 v->async_err));
742 ret = adsp_err_get_lnx_err_code(
743 v->async_err);
744 goto done;
745 }
746 ret = 0;
747
748done:
749 if (ret) {
750 strlcpy(common.cvd_version, CVD_VERSION_0_0,
751 sizeof(common.cvd_version));
752 }
753 pr_debug("%s: CVD Version retrieved=%s\n",
754 __func__, common.cvd_version);
755
756 return ret;
757}
758
759static int voice_send_dual_control_cmd(struct voice_data *v)
760{
761 int ret = 0;
762 struct mvm_modem_dual_control_session_cmd mvm_voice_ctl_cmd;
763 void *apr_mvm;
764 u16 mvm_handle;
765
766 if (v == NULL) {
767 pr_err("%s: v is NULL\n", __func__);
768 return -EINVAL;
769 }
770 apr_mvm = common.apr_q6_mvm;
771 if (!apr_mvm) {
772 pr_err("%s: apr_mvm is NULL.\n", __func__);
773 return -EINVAL;
774 }
775 pr_debug("%s: Send Dual Control command to MVM\n", __func__);
776 if (!is_voip_session(v->session_id)) {
777 mvm_handle = voice_get_mvm_handle(v);
778 mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
779 APR_MSG_TYPE_SEQ_CMD,
780 APR_HDR_LEN(APR_HDR_SIZE),
781 APR_PKT_VER);
782 mvm_voice_ctl_cmd.hdr.pkt_size = APR_PKT_SIZE(
783 APR_HDR_SIZE,
784 sizeof(mvm_voice_ctl_cmd) -
785 APR_HDR_SIZE);
786 pr_debug("%s: send mvm Voice Ctl pkt size = %d\n",
787 __func__, mvm_voice_ctl_cmd.hdr.pkt_size);
788 mvm_voice_ctl_cmd.hdr.src_port =
789 voice_get_idx_for_session(v->session_id);
790 mvm_voice_ctl_cmd.hdr.dest_port = mvm_handle;
791 mvm_voice_ctl_cmd.hdr.token = 0;
792 mvm_voice_ctl_cmd.hdr.opcode =
793 VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL;
794 mvm_voice_ctl_cmd.voice_ctl.enable_flag = true;
795 v->mvm_state = CMD_STATUS_FAIL;
796 v->async_err = 0;
797
798 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_voice_ctl_cmd);
799 if (ret < 0) {
800 pr_err("%s: Error sending MVM Voice CTL CMD\n",
801 __func__);
802 ret = -EINVAL;
803 goto fail;
804 }
805 ret = wait_event_timeout(v->mvm_wait,
806 (v->mvm_state == CMD_STATUS_SUCCESS),
807 msecs_to_jiffies(TIMEOUT_MS));
808 if (!ret) {
809 pr_err("%s: wait_event timeout\n", __func__);
810 ret = -EINVAL;
811 goto fail;
812 }
813 if (v->async_err > 0) {
814 pr_err("%s: DSP returned error[%s]\n",
815 __func__, adsp_err_get_err_str(
816 v->async_err));
817 ret = adsp_err_get_lnx_err_code(
818 v->async_err);
819 goto fail;
820 }
821 }
822 ret = 0;
823fail:
824 return ret;
825}
826
827
828static int voice_create_mvm_cvs_session(struct voice_data *v)
829{
830 int ret = 0;
831 struct mvm_create_ctl_session_cmd mvm_session_cmd;
832 struct cvs_create_passive_ctl_session_cmd cvs_session_cmd;
833 struct cvs_create_full_ctl_session_cmd cvs_full_ctl_cmd;
834 struct mvm_attach_stream_cmd attach_stream_cmd;
835 void *apr_mvm, *apr_cvs, *apr_cvp;
836 u16 mvm_handle, cvs_handle, cvp_handle;
837
838 if (v == NULL) {
839 pr_err("%s: v is NULL\n", __func__);
840 return -EINVAL;
841 }
842 apr_mvm = common.apr_q6_mvm;
843 apr_cvs = common.apr_q6_cvs;
844 apr_cvp = common.apr_q6_cvp;
845
846 if (!apr_mvm || !apr_cvs || !apr_cvp) {
847 pr_err("%s: apr_mvm or apr_cvs or apr_cvp is NULL\n", __func__);
848 return -EINVAL;
849 }
850 mvm_handle = voice_get_mvm_handle(v);
851 cvs_handle = voice_get_cvs_handle(v);
852 cvp_handle = voice_get_cvp_handle(v);
853
854 pr_debug("%s: mvm_hdl=%d, cvs_hdl=%d\n", __func__,
855 mvm_handle, cvs_handle);
856 /* send cmd to create mvm session and wait for response */
857
858 if (!mvm_handle) {
859 memset(mvm_session_cmd.mvm_session.name, 0,
860 sizeof(mvm_session_cmd.mvm_session.name));
861 if (!is_voip_session(v->session_id)) {
862 mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
863 APR_MSG_TYPE_SEQ_CMD,
864 APR_HDR_LEN(APR_HDR_SIZE),
865 APR_PKT_VER);
866 mvm_session_cmd.hdr.pkt_size = APR_PKT_SIZE(
867 APR_HDR_SIZE,
868 sizeof(mvm_session_cmd) -
869 APR_HDR_SIZE);
870 pr_debug("%s: send mvm create session pkt size = %d\n",
871 __func__, mvm_session_cmd.hdr.pkt_size);
872 mvm_session_cmd.hdr.src_port =
873 voice_get_idx_for_session(v->session_id);
874 mvm_session_cmd.hdr.dest_port = 0;
875 mvm_session_cmd.hdr.token = 0;
876 mvm_session_cmd.hdr.opcode =
877 VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
878 if (is_volte_session(v->session_id)) {
879 strlcpy(mvm_session_cmd.mvm_session.name,
880 "default volte voice",
881 strlen("default volte voice")+1);
882 } else if (is_voice2_session(v->session_id)) {
883 strlcpy(mvm_session_cmd.mvm_session.name,
884 VOICE2_SESSION_VSID_STR,
885 strlen(VOICE2_SESSION_VSID_STR)+1);
886 } else if (is_qchat_session(v->session_id)) {
887 strlcpy(mvm_session_cmd.mvm_session.name,
888 QCHAT_SESSION_VSID_STR,
889 strlen(QCHAT_SESSION_VSID_STR)+1);
890 } else if (is_vowlan_session(v->session_id)) {
891 strlcpy(mvm_session_cmd.mvm_session.name,
892 VOWLAN_SESSION_VSID_STR,
893 strlen(VOWLAN_SESSION_VSID_STR)+1);
894 } else if (is_voicemmode1(v->session_id)) {
895 strlcpy(mvm_session_cmd.mvm_session.name,
896 VOICEMMODE1_VSID_STR,
897 strlen(VOICEMMODE1_VSID_STR) + 1);
898 } else if (is_voicemmode2(v->session_id)) {
899 strlcpy(mvm_session_cmd.mvm_session.name,
900 VOICEMMODE2_VSID_STR,
901 strlen(VOICEMMODE2_VSID_STR) + 1);
902 } else {
903 strlcpy(mvm_session_cmd.mvm_session.name,
904 "default modem voice",
905 strlen("default modem voice")+1);
906 }
907
908 v->mvm_state = CMD_STATUS_FAIL;
909 v->async_err = 0;
910
911 ret = apr_send_pkt(apr_mvm,
912 (uint32_t *) &mvm_session_cmd);
913 if (ret < 0) {
914 pr_err("%s: Error sending MVM_CONTROL_SESSION\n",
915 __func__);
916 goto fail;
917 }
918 ret = wait_event_timeout(v->mvm_wait,
919 (v->mvm_state == CMD_STATUS_SUCCESS),
920 msecs_to_jiffies(TIMEOUT_MS));
921 if (!ret) {
922 pr_err("%s: wait_event timeout\n", __func__);
923 goto fail;
924 }
925 if (v->async_err > 0) {
926 pr_err("%s: DSP returned error[%s]\n",
927 __func__, adsp_err_get_err_str(
928 v->async_err));
929 ret = adsp_err_get_lnx_err_code(
930 v->async_err);
931 goto fail;
932 }
933 } else {
934 pr_debug("%s: creating MVM full ctrl\n", __func__);
935 mvm_session_cmd.hdr.hdr_field =
936 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
937 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
938 mvm_session_cmd.hdr.pkt_size =
939 APR_PKT_SIZE(APR_HDR_SIZE,
940 sizeof(mvm_session_cmd) -
941 APR_HDR_SIZE);
942 mvm_session_cmd.hdr.src_port =
943 voice_get_idx_for_session(v->session_id);
944 mvm_session_cmd.hdr.dest_port = 0;
945 mvm_session_cmd.hdr.token = 0;
946 mvm_session_cmd.hdr.opcode =
947 VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION;
948 strlcpy(mvm_session_cmd.mvm_session.name,
949 "default voip",
950 strlen("default voip")+1);
951
952 v->mvm_state = CMD_STATUS_FAIL;
953 v->async_err = 0;
954
955 ret = apr_send_pkt(apr_mvm,
956 (uint32_t *) &mvm_session_cmd);
957 if (ret < 0) {
958 pr_err("Fail in sending MVM_CONTROL_SESSION\n");
959 goto fail;
960 }
961 ret = wait_event_timeout(v->mvm_wait,
962 (v->mvm_state == CMD_STATUS_SUCCESS),
963 msecs_to_jiffies(TIMEOUT_MS));
964 if (!ret) {
965 pr_err("%s: wait_event timeout\n", __func__);
966 goto fail;
967 }
968 if (v->async_err > 0) {
969 pr_err("%s: DSP returned error[%s]\n",
970 __func__, adsp_err_get_err_str(
971 v->async_err));
972 ret = adsp_err_get_lnx_err_code(
973 v->async_err);
974 goto fail;
975 }
976 }
977 /* Get the created MVM handle. */
978 mvm_handle = voice_get_mvm_handle(v);
979 }
980 /* send cmd to create cvs session */
981 if (!cvs_handle) {
982 memset(cvs_session_cmd.cvs_session.name, 0,
983 sizeof(cvs_session_cmd.cvs_session.name));
984 if (!is_voip_session(v->session_id)) {
985 pr_debug("%s: creating CVS passive session\n",
986 __func__);
987
988 cvs_session_cmd.hdr.hdr_field = APR_HDR_FIELD(
989 APR_MSG_TYPE_SEQ_CMD,
990 APR_HDR_LEN(APR_HDR_SIZE),
991 APR_PKT_VER);
992 cvs_session_cmd.hdr.pkt_size =
993 APR_PKT_SIZE(APR_HDR_SIZE,
994 sizeof(cvs_session_cmd) -
995 APR_HDR_SIZE);
996 cvs_session_cmd.hdr.src_port =
997 voice_get_idx_for_session(v->session_id);
998 cvs_session_cmd.hdr.dest_port = 0;
999 cvs_session_cmd.hdr.token = 0;
1000 cvs_session_cmd.hdr.opcode =
1001 VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION;
1002 if (is_volte_session(v->session_id)) {
1003 strlcpy(cvs_session_cmd.cvs_session.name,
1004 "default volte voice",
1005 strlen("default volte voice")+1);
1006 } else if (is_voice2_session(v->session_id)) {
1007 strlcpy(cvs_session_cmd.cvs_session.name,
1008 VOICE2_SESSION_VSID_STR,
1009 strlen(VOICE2_SESSION_VSID_STR)+1);
1010 } else if (is_qchat_session(v->session_id)) {
1011 strlcpy(cvs_session_cmd.cvs_session.name,
1012 QCHAT_SESSION_VSID_STR,
1013 strlen(QCHAT_SESSION_VSID_STR)+1);
1014 } else if (is_vowlan_session(v->session_id)) {
1015 strlcpy(cvs_session_cmd.cvs_session.name,
1016 VOWLAN_SESSION_VSID_STR,
1017 strlen(VOWLAN_SESSION_VSID_STR)+1);
1018 } else if (is_voicemmode1(v->session_id)) {
1019 strlcpy(cvs_session_cmd.cvs_session.name,
1020 VOICEMMODE1_VSID_STR,
1021 strlen(VOICEMMODE1_VSID_STR) + 1);
1022 } else if (is_voicemmode2(v->session_id)) {
1023 strlcpy(cvs_session_cmd.cvs_session.name,
1024 VOICEMMODE2_VSID_STR,
1025 strlen(VOICEMMODE2_VSID_STR) + 1);
1026 } else {
1027 strlcpy(cvs_session_cmd.cvs_session.name,
1028 "default modem voice",
1029 strlen("default modem voice")+1);
1030 }
1031 v->cvs_state = CMD_STATUS_FAIL;
1032 v->async_err = 0;
1033
1034 ret = apr_send_pkt(apr_cvs,
1035 (uint32_t *) &cvs_session_cmd);
1036 if (ret < 0) {
1037 pr_err("Fail in sending STREAM_CONTROL_SESSION\n");
1038 goto fail;
1039 }
1040 ret = wait_event_timeout(v->cvs_wait,
1041 (v->cvs_state == CMD_STATUS_SUCCESS),
1042 msecs_to_jiffies(TIMEOUT_MS));
1043 if (!ret) {
1044 pr_err("%s: wait_event timeout\n", __func__);
1045 goto fail;
1046 }
1047 if (v->async_err > 0) {
1048 pr_err("%s: DSP returned error[%s]\n",
1049 __func__, adsp_err_get_err_str(
1050 v->async_err));
1051 ret = adsp_err_get_lnx_err_code(
1052 v->async_err);
1053 goto fail;
1054 }
1055 /* Get the created CVS handle. */
1056 cvs_handle = voice_get_cvs_handle(v);
1057
1058 } else {
1059 pr_debug("%s: creating CVS full session\n", __func__);
1060
1061 cvs_full_ctl_cmd.hdr.hdr_field =
1062 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1063 APR_HDR_LEN(APR_HDR_SIZE),
1064 APR_PKT_VER);
1065
1066 cvs_full_ctl_cmd.hdr.pkt_size =
1067 APR_PKT_SIZE(APR_HDR_SIZE,
1068 sizeof(cvs_full_ctl_cmd) -
1069 APR_HDR_SIZE);
1070
1071 cvs_full_ctl_cmd.hdr.src_port =
1072 voice_get_idx_for_session(v->session_id);
1073 cvs_full_ctl_cmd.hdr.dest_port = 0;
1074 cvs_full_ctl_cmd.hdr.token = 0;
1075 cvs_full_ctl_cmd.hdr.opcode =
1076 VSS_ISTREAM_CMD_CREATE_FULL_CONTROL_SESSION;
1077 cvs_full_ctl_cmd.cvs_session.direction = 2;
1078 cvs_full_ctl_cmd.cvs_session.enc_media_type =
1079 common.mvs_info.media_type;
1080 cvs_full_ctl_cmd.cvs_session.dec_media_type =
1081 common.mvs_info.media_type;
1082 cvs_full_ctl_cmd.cvs_session.network_id =
1083 common.mvs_info.network_type;
1084 strlcpy(cvs_full_ctl_cmd.cvs_session.name,
1085 "default q6 voice",
1086 strlen("default q6 voice")+1);
1087
1088 v->cvs_state = CMD_STATUS_FAIL;
1089 v->async_err = 0;
1090
1091 ret = apr_send_pkt(apr_cvs,
1092 (uint32_t *) &cvs_full_ctl_cmd);
1093
1094 if (ret < 0) {
1095 pr_err("%s: Err %d sending CREATE_FULL_CTRL\n",
1096 __func__, ret);
1097 goto fail;
1098 }
1099 ret = wait_event_timeout(v->cvs_wait,
1100 (v->cvs_state == CMD_STATUS_SUCCESS),
1101 msecs_to_jiffies(TIMEOUT_MS));
1102 if (!ret) {
1103 pr_err("%s: wait_event timeout\n", __func__);
1104 goto fail;
1105 }
1106 if (v->async_err > 0) {
1107 pr_err("%s: DSP returned error[%s]\n",
1108 __func__, adsp_err_get_err_str(
1109 v->async_err));
1110 ret = adsp_err_get_lnx_err_code(
1111 v->async_err);
1112 goto fail;
1113 }
1114 /* Get the created CVS handle. */
1115 cvs_handle = voice_get_cvs_handle(v);
1116
1117 /* Attach MVM to CVS. */
1118 pr_debug("%s: Attach MVM to stream\n", __func__);
1119
1120 attach_stream_cmd.hdr.hdr_field =
1121 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1122 APR_HDR_LEN(APR_HDR_SIZE),
1123 APR_PKT_VER);
1124 attach_stream_cmd.hdr.pkt_size =
1125 APR_PKT_SIZE(APR_HDR_SIZE,
1126 sizeof(attach_stream_cmd) -
1127 APR_HDR_SIZE);
1128 attach_stream_cmd.hdr.src_port =
1129 voice_get_idx_for_session(v->session_id);
1130 attach_stream_cmd.hdr.dest_port = mvm_handle;
1131 attach_stream_cmd.hdr.token = 0;
1132 attach_stream_cmd.hdr.opcode =
1133 VSS_IMVM_CMD_ATTACH_STREAM;
1134 attach_stream_cmd.attach_stream.handle = cvs_handle;
1135
1136 v->mvm_state = CMD_STATUS_FAIL;
1137 v->async_err = 0;
1138 ret = apr_send_pkt(apr_mvm,
1139 (uint32_t *) &attach_stream_cmd);
1140 if (ret < 0) {
1141 pr_err("%s: Error %d sending ATTACH_STREAM\n",
1142 __func__, ret);
1143 goto fail;
1144 }
1145 ret = wait_event_timeout(v->mvm_wait,
1146 (v->mvm_state == CMD_STATUS_SUCCESS),
1147 msecs_to_jiffies(TIMEOUT_MS));
1148 if (!ret) {
1149 pr_err("%s: wait_event timeout\n", __func__);
1150 goto fail;
1151 }
1152 if (v->async_err > 0) {
1153 pr_err("%s: DSP returned error[%s]\n",
1154 __func__, adsp_err_get_err_str(
1155 v->async_err));
1156 ret = adsp_err_get_lnx_err_code(
1157 v->async_err);
1158 goto fail;
1159 }
1160 }
1161 }
1162 return 0;
1163
1164fail:
1165 return ret;
1166}
1167
1168static int voice_unmap_cal_block(struct voice_data *v, int cal_index)
1169{
1170 int result = 0;
1171 struct cal_block_data *cal_block;
1172
1173 if (common.cal_data[cal_index] == NULL) {
1174 pr_err("%s: Cal type is NULL, index %d!\n",
1175 __func__, cal_index);
1176
1177 goto done;
1178 }
1179
1180 mutex_lock(&common.cal_data[cal_index]->lock);
1181 cal_block = cal_utils_get_only_cal_block(
1182 common.cal_data[cal_index]);
1183 if (cal_block == NULL) {
1184 pr_err("%s: Cal block is NULL, index %d!\n",
1185 __func__, cal_index);
1186
1187 result = -EINVAL;
1188 goto unlock;
1189 }
1190
1191 if (cal_block->map_data.q6map_handle == 0) {
1192 pr_debug("%s: Q6 handle is not set!\n", __func__);
1193
1194 result = -EINVAL;
1195 goto unlock;
1196 }
1197
1198 mutex_lock(&common.common_lock);
1199 result = voice_send_mvm_unmap_memory_physical_cmd(
1200 v, cal_block->map_data.q6map_handle);
1201 if (result)
1202 pr_err("%s: Voice_send_mvm_unmap_memory_physical_cmd failed for session 0x%x, err %d!\n",
1203 __func__, v->session_id, result);
1204
1205 cal_block->map_data.q6map_handle = 0;
1206 mutex_unlock(&common.common_lock);
1207unlock:
1208 mutex_unlock(&common.cal_data[cal_index]->lock);
1209done:
1210 return result;
1211}
1212
1213static int voice_destroy_mvm_cvs_session(struct voice_data *v)
1214{
1215 int ret = 0;
1216 struct mvm_detach_stream_cmd detach_stream;
1217 struct apr_hdr mvm_destroy;
1218 struct apr_hdr cvs_destroy;
1219 void *apr_mvm, *apr_cvs;
1220 u16 mvm_handle, cvs_handle;
1221
1222 if (v == NULL) {
1223 pr_err("%s: v is NULL\n", __func__);
1224 return -EINVAL;
1225 }
1226 apr_mvm = common.apr_q6_mvm;
1227 apr_cvs = common.apr_q6_cvs;
1228
1229 if (!apr_mvm || !apr_cvs) {
1230 pr_err("%s: apr_mvm or apr_cvs is NULL\n", __func__);
1231 return -EINVAL;
1232 }
1233 mvm_handle = voice_get_mvm_handle(v);
1234 cvs_handle = voice_get_cvs_handle(v);
1235
1236 /* MVM, CVS sessions are destroyed only for Full control sessions. */
1237 if (is_voip_session(v->session_id)) {
1238 pr_debug("%s: MVM detach stream, VOC_STATE: %d\n", __func__,
1239 v->voc_state);
1240
1241 /* Detach voice stream. */
1242 detach_stream.hdr.hdr_field =
1243 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1244 APR_HDR_LEN(APR_HDR_SIZE),
1245 APR_PKT_VER);
1246 detach_stream.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1247 sizeof(detach_stream) - APR_HDR_SIZE);
1248 detach_stream.hdr.src_port =
1249 voice_get_idx_for_session(v->session_id);
1250 detach_stream.hdr.dest_port = mvm_handle;
1251 detach_stream.hdr.token = 0;
1252 detach_stream.hdr.opcode = VSS_IMVM_CMD_DETACH_STREAM;
1253 detach_stream.detach_stream.handle = cvs_handle;
1254
1255 v->mvm_state = CMD_STATUS_FAIL;
1256 v->async_err = 0;
1257 ret = apr_send_pkt(apr_mvm, (uint32_t *) &detach_stream);
1258 if (ret < 0) {
1259 pr_err("%s: Error %d sending DETACH_STREAM\n",
1260 __func__, ret);
1261
1262 goto fail;
1263 }
1264 ret = wait_event_timeout(v->mvm_wait,
1265 (v->mvm_state == CMD_STATUS_SUCCESS),
1266 msecs_to_jiffies(TIMEOUT_MS));
1267 if (!ret) {
1268 pr_err("%s: wait event timeout\n", __func__);
1269
1270 goto fail;
1271 }
1272 if (v->async_err > 0) {
1273 pr_err("%s: DSP returned error[%s]\n",
1274 __func__, adsp_err_get_err_str(
1275 v->async_err));
1276 ret = adsp_err_get_lnx_err_code(
1277 v->async_err);
1278 goto fail;
1279 }
1280
1281 /* Unmap memory */
1282 if (v->shmem_info.mem_handle != 0) {
1283 ret = voice_send_mvm_unmap_memory_physical_cmd(v,
1284 v->shmem_info.mem_handle);
1285 if (ret < 0) {
1286 pr_err("%s Memory_unmap for voip failed %d\n",
1287 __func__, ret);
1288
1289 goto fail;
1290 }
1291 v->shmem_info.mem_handle = 0;
1292 }
1293 }
1294
1295 /* Unmap Source Tracking shared memory if mapped earlier */
1296 voice_unmap_and_free_source_tracking_shared_memory(v);
1297
1298 if (is_voip_session(v->session_id) ||
1299 is_qchat_session(v->session_id) ||
1300 is_volte_session(v->session_id) ||
1301 is_vowlan_session(v->session_id) ||
1302 v->voc_state == VOC_ERROR || common.is_destroy_cvd) {
1303 /* Destroy CVS. */
1304 pr_debug("%s: CVS destroy session\n", __func__);
1305
1306 cvs_destroy.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1307 APR_HDR_LEN(APR_HDR_SIZE),
1308 APR_PKT_VER);
1309 cvs_destroy.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1310 sizeof(cvs_destroy) - APR_HDR_SIZE);
1311 cvs_destroy.src_port =
1312 voice_get_idx_for_session(v->session_id);
1313 cvs_destroy.dest_port = cvs_handle;
1314 cvs_destroy.token = 0;
1315 cvs_destroy.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION;
1316
1317 v->cvs_state = CMD_STATUS_FAIL;
1318 v->async_err = 0;
1319 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_destroy);
1320 if (ret < 0) {
1321 pr_err("%s: Error %d sending CVS DESTROY\n",
1322 __func__, ret);
1323
1324 goto fail;
1325 }
1326 ret = wait_event_timeout(v->cvs_wait,
1327 (v->cvs_state == CMD_STATUS_SUCCESS),
1328 msecs_to_jiffies(TIMEOUT_MS));
1329 if (!ret) {
1330 pr_err("%s: wait event timeout\n", __func__);
1331
1332 goto fail;
1333 }
1334 if (v->async_err > 0) {
1335 pr_err("%s: DSP returned error[%s]\n",
1336 __func__, adsp_err_get_err_str(
1337 v->async_err));
1338 ret = adsp_err_get_lnx_err_code(
1339 v->async_err);
1340 goto fail;
1341 }
1342 cvs_handle = 0;
1343 voice_set_cvs_handle(v, cvs_handle);
1344
1345 /* Unmap physical memory for all calibration buffers */
1346 if (!is_other_session_active(v->session_id)) {
1347 if (voice_unmap_cal_block(v, CVP_VOCPROC_CAL))
1348 pr_err("%s: Unmap VOCPROC cal failed\n",
1349 __func__);
1350 if (voice_unmap_cal_block(v, CVP_VOCVOL_CAL))
1351 pr_err("%s: Unmap VOCVOL cal failed\n",
1352 __func__);
1353 if (voice_unmap_cal_block(v, CVP_VOCDEV_CFG_CAL))
1354 pr_err("%s: Unmap VOCDEV_CFG cal failed\n",
1355 __func__);
1356 if (voice_unmap_cal_block(v, CVS_VOCSTRM_CAL))
1357 pr_err("%s: Unmap VOCSTRM cal failed\n",
1358 __func__);
1359 }
1360
1361 /* Destroy MVM. */
1362 pr_debug("%s: MVM destroy session\n", __func__);
1363
1364 mvm_destroy.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1365 APR_HDR_LEN(APR_HDR_SIZE),
1366 APR_PKT_VER);
1367 mvm_destroy.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1368 sizeof(mvm_destroy) - APR_HDR_SIZE);
1369 mvm_destroy.src_port =
1370 voice_get_idx_for_session(v->session_id);
1371 mvm_destroy.dest_port = mvm_handle;
1372 mvm_destroy.token = 0;
1373 mvm_destroy.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION;
1374
1375 v->mvm_state = CMD_STATUS_FAIL;
1376 v->async_err = 0;
1377
1378 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_destroy);
1379 if (ret < 0) {
1380 pr_err("%s: Error %d sending MVM DESTROY\n",
1381 __func__, ret);
1382
1383 goto fail;
1384 }
1385 ret = wait_event_timeout(v->mvm_wait,
1386 (v->mvm_state == CMD_STATUS_SUCCESS),
1387 msecs_to_jiffies(TIMEOUT_MS));
1388 if (!ret) {
1389 pr_err("%s: wait event timeout\n", __func__);
1390 goto fail;
1391 }
1392 if (v->async_err > 0) {
1393 pr_err("%s: DSP returned error[%s]\n",
1394 __func__, adsp_err_get_err_str(
1395 v->async_err));
1396 ret = adsp_err_get_lnx_err_code(
1397 v->async_err);
1398 goto fail;
1399 }
1400 mvm_handle = 0;
1401 voice_set_mvm_handle(v, mvm_handle);
1402 }
1403 return 0;
1404fail:
1405 return ret;
1406}
1407
1408static int voice_send_tty_mode_cmd(struct voice_data *v)
1409{
1410 int ret = 0;
1411 struct mvm_set_tty_mode_cmd mvm_tty_mode_cmd;
1412 void *apr_mvm;
1413 u16 mvm_handle;
1414
1415 if (v == NULL) {
1416 pr_err("%s: v is NULL\n", __func__);
1417 return -EINVAL;
1418 }
1419 apr_mvm = common.apr_q6_mvm;
1420
1421 if (!apr_mvm) {
1422 pr_err("%s: apr_mvm is NULL.\n", __func__);
1423 return -EINVAL;
1424 }
1425 mvm_handle = voice_get_mvm_handle(v);
1426
1427 /* send tty mode cmd to mvm */
1428 mvm_tty_mode_cmd.hdr.hdr_field = APR_HDR_FIELD(
1429 APR_MSG_TYPE_SEQ_CMD,
1430 APR_HDR_LEN(APR_HDR_SIZE),
1431 APR_PKT_VER);
1432 mvm_tty_mode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1433 sizeof(mvm_tty_mode_cmd) -
1434 APR_HDR_SIZE);
1435 pr_debug("%s: pkt size = %d\n",
1436 __func__, mvm_tty_mode_cmd.hdr.pkt_size);
1437 mvm_tty_mode_cmd.hdr.src_port =
1438 voice_get_idx_for_session(v->session_id);
1439 mvm_tty_mode_cmd.hdr.dest_port = mvm_handle;
1440 mvm_tty_mode_cmd.hdr.token = 0;
1441 mvm_tty_mode_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_TTY_MODE;
1442 mvm_tty_mode_cmd.tty_mode.mode = v->tty_mode;
1443 pr_debug("tty mode =%d\n", mvm_tty_mode_cmd.tty_mode.mode);
1444
1445 v->mvm_state = CMD_STATUS_FAIL;
1446 v->async_err = 0;
1447 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_tty_mode_cmd);
1448 if (ret < 0) {
1449 pr_err("%s: Error %d sending SET_TTY_MODE\n",
1450 __func__, ret);
1451 goto fail;
1452 }
1453 ret = wait_event_timeout(v->mvm_wait,
1454 (v->mvm_state == CMD_STATUS_SUCCESS),
1455 msecs_to_jiffies(TIMEOUT_MS));
1456 if (!ret) {
1457 pr_err("%s: wait_event timeout\n", __func__);
1458 goto fail;
1459 }
1460 if (v->async_err > 0) {
1461 pr_err("%s: DSP returned error[%s]\n",
1462 __func__, adsp_err_get_err_str(
1463 v->async_err));
1464 ret = adsp_err_get_lnx_err_code(
1465 v->async_err);
1466 goto fail;
1467 }
1468 return 0;
1469fail:
1470 return ret;
1471}
1472
1473static int voice_send_set_pp_enable_cmd(struct voice_data *v,
1474 uint32_t module_id, int enable)
1475{
1476 struct cvs_set_pp_enable_cmd cvs_set_pp_cmd;
1477 int ret = 0;
1478 void *apr_cvs;
1479 u16 cvs_handle;
1480
1481 if (v == NULL) {
1482 pr_err("%s: v is NULL\n", __func__);
1483 return -EINVAL;
1484 }
1485 apr_cvs = common.apr_q6_cvs;
1486
1487 if (!apr_cvs) {
1488 pr_err("%s: apr_cvs is NULL.\n", __func__);
1489 return -EINVAL;
1490 }
1491 cvs_handle = voice_get_cvs_handle(v);
1492
1493 cvs_set_pp_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1494 APR_HDR_LEN(APR_HDR_SIZE),
1495 APR_PKT_VER);
1496 cvs_set_pp_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1497 sizeof(cvs_set_pp_cmd) -
1498 APR_HDR_SIZE);
1499 cvs_set_pp_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
1500 cvs_set_pp_cmd.hdr.dest_port = cvs_handle;
1501 cvs_set_pp_cmd.hdr.token = 0;
1502 cvs_set_pp_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_UI_PROPERTY;
1503
1504 cvs_set_pp_cmd.vss_set_pp.module_id = module_id;
1505 cvs_set_pp_cmd.vss_set_pp.param_id = VOICE_PARAM_MOD_ENABLE;
1506 cvs_set_pp_cmd.vss_set_pp.param_size = MOD_ENABLE_PARAM_LEN;
1507 cvs_set_pp_cmd.vss_set_pp.reserved = 0;
1508 cvs_set_pp_cmd.vss_set_pp.enable = enable;
1509 cvs_set_pp_cmd.vss_set_pp.reserved_field = 0;
1510 pr_debug("voice_send_set_pp_enable_cmd, module_id=%d, enable=%d\n",
1511 module_id, enable);
1512
1513 v->cvs_state = CMD_STATUS_FAIL;
1514 v->async_err = 0;
1515 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_pp_cmd);
1516 if (ret < 0) {
1517 pr_err("Fail: sending cvs set pp enable,\n");
1518 goto fail;
1519 }
1520 ret = wait_event_timeout(v->cvs_wait,
1521 (v->cvs_state == CMD_STATUS_SUCCESS),
1522 msecs_to_jiffies(TIMEOUT_MS));
1523 if (!ret) {
1524 pr_err("%s: wait_event timeout\n", __func__);
1525 goto fail;
1526 }
1527 if (v->async_err > 0) {
1528 pr_err("%s: DSP returned error[%s]\n",
1529 __func__, adsp_err_get_err_str(
1530 v->async_err));
1531 ret = adsp_err_get_lnx_err_code(
1532 v->async_err);
1533 goto fail;
1534 }
1535 return 0;
1536fail:
1537 return ret;
1538}
1539
1540static int voice_send_hd_cmd(struct voice_data *v, int enable)
1541{
1542 struct mvm_set_hd_enable_cmd mvm_set_hd_cmd;
1543 int ret = 0;
1544 void *apr_mvm;
1545 u16 mvm_handle;
1546
1547 if (v == NULL) {
1548 pr_err("%s: v is NULL\n", __func__);
1549
1550 ret = -EINVAL;
1551 goto done;
1552 }
1553
1554 apr_mvm = common.apr_q6_mvm;
1555 if (!apr_mvm) {
1556 pr_err("%s: apr_mvm is NULL.\n", __func__);
1557
1558 ret = -EINVAL;
1559 goto done;
1560 }
1561
1562 mvm_handle = voice_get_mvm_handle(v);
1563 if (!mvm_handle) {
1564 pr_err("%s: mvm_handle is NULL\n", __func__);
1565
1566 ret = -EINVAL;
1567 goto done;
1568 }
1569
1570 mvm_set_hd_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1571 APR_HDR_LEN(APR_HDR_SIZE),
1572 APR_PKT_VER);
1573 mvm_set_hd_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1574 sizeof(mvm_set_hd_cmd) -
1575 APR_HDR_SIZE);
1576 mvm_set_hd_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
1577 mvm_set_hd_cmd.hdr.dest_port = mvm_handle;
1578 mvm_set_hd_cmd.hdr.token = 0;
1579
1580 if (enable)
1581 mvm_set_hd_cmd.hdr.opcode = VSS_IHDVOICE_CMD_ENABLE;
1582 else
1583 mvm_set_hd_cmd.hdr.opcode = VSS_IHDVOICE_CMD_DISABLE;
1584
1585 pr_debug("%s: enable=%d\n", __func__, enable);
1586
1587 v->mvm_state = CMD_STATUS_FAIL;
1588 v->async_err = 0;
1589 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_hd_cmd);
1590 if (ret < 0) {
1591 pr_err("%s: Failed to sending mvm set HD Voice enable %d\n",
1592 __func__, ret);
1593
1594 ret = -EINVAL;
1595 goto done;
1596 }
1597
1598 ret = wait_event_timeout(v->mvm_wait,
1599 (v->mvm_state == CMD_STATUS_SUCCESS),
1600 msecs_to_jiffies(TIMEOUT_MS));
1601 if (!ret) {
1602 pr_err("%s: wait_event timeout\n", __func__);
1603
1604 ret = -EINVAL;
1605 goto done;
1606 }
1607 if (v->async_err > 0) {
1608 pr_err("%s: DSP returned error[%s]\n",
1609 __func__, adsp_err_get_err_str(
1610 v->async_err));
1611 ret = adsp_err_get_lnx_err_code(
1612 v->async_err);
1613 goto done;
1614 }
1615
1616done:
1617 return ret;
1618}
1619
1620static int voice_set_dtx(struct voice_data *v)
1621{
1622 int ret = 0;
1623 void *apr_cvs;
1624 u16 cvs_handle;
1625 struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx;
1626
1627 if (v == NULL) {
1628 pr_err("%s: v is NULL\n", __func__);
1629 return -EINVAL;
1630 }
1631 apr_cvs = common.apr_q6_cvs;
1632
1633 if (!apr_cvs) {
1634 pr_err("%s: apr_cvs is NULL.\n", __func__);
1635 return -EINVAL;
1636 }
1637
1638 cvs_handle = voice_get_cvs_handle(v);
1639
1640 /* Set DTX */
1641 cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1642 APR_HDR_LEN(APR_HDR_SIZE),
1643 APR_PKT_VER);
1644 cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1645 sizeof(cvs_set_dtx) - APR_HDR_SIZE);
1646 cvs_set_dtx.hdr.src_port =
1647 voice_get_idx_for_session(v->session_id);
1648 cvs_set_dtx.hdr.dest_port = cvs_handle;
1649 cvs_set_dtx.hdr.token = 0;
1650 cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE;
1651 cvs_set_dtx.dtx_mode.enable = common.mvs_info.dtx_mode;
1652
1653 pr_debug("%s: Setting DTX %d\n", __func__, common.mvs_info.dtx_mode);
1654
1655 v->cvs_state = CMD_STATUS_FAIL;
1656 v->async_err = 0;
1657
1658 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx);
1659 if (ret < 0) {
1660 pr_err("%s: Error %d sending SET_DTX\n", __func__, ret);
1661 return -EINVAL;
1662 }
1663
1664 ret = wait_event_timeout(v->cvs_wait,
1665 (v->cvs_state == CMD_STATUS_SUCCESS),
1666 msecs_to_jiffies(TIMEOUT_MS));
1667 if (!ret) {
1668 pr_err("%s: wait_event timeout\n", __func__);
1669 return -EINVAL;
1670 }
1671 if (v->async_err > 0) {
1672 pr_err("%s: DSP returned error[%s]\n",
1673 __func__, adsp_err_get_err_str(
1674 v->async_err));
1675 ret = adsp_err_get_lnx_err_code(
1676 v->async_err);
1677 return ret;
1678 }
1679
1680 return 0;
1681}
1682
1683static int voice_send_mvm_media_type_cmd(struct voice_data *v)
1684{
1685 struct vss_imvm_cmd_set_cal_media_type_t mvm_set_cal_media_type;
1686 int ret = 0;
1687 void *apr_mvm;
1688 u16 mvm_handle;
1689
1690 if (v == NULL) {
1691 pr_err("%s: v is NULL\n", __func__);
1692 return -EINVAL;
1693 }
1694 apr_mvm = common.apr_q6_mvm;
1695
1696 if (!apr_mvm) {
1697 pr_err("%s: apr_mvm is NULL.\n", __func__);
1698 return -EINVAL;
1699 }
1700 mvm_handle = voice_get_mvm_handle(v);
1701
1702 mvm_set_cal_media_type.hdr.hdr_field =
1703 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1704 APR_HDR_LEN(APR_HDR_SIZE),
1705 APR_PKT_VER);
1706 mvm_set_cal_media_type.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
1707 sizeof(mvm_set_cal_media_type) -
1708 APR_HDR_SIZE);
1709 mvm_set_cal_media_type.hdr.src_port =
1710 voice_get_idx_for_session(v->session_id);
1711 mvm_set_cal_media_type.hdr.dest_port = mvm_handle;
1712 mvm_set_cal_media_type.hdr.token = 0;
1713 mvm_set_cal_media_type.hdr.opcode = VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE;
1714 mvm_set_cal_media_type.media_id = common.mvs_info.media_type;
1715 pr_debug("%s: setting media_id as %x\n",
1716 __func__, mvm_set_cal_media_type.media_id);
1717
1718 v->mvm_state = CMD_STATUS_FAIL;
1719 v->async_err = 0;
1720 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_cal_media_type);
1721 if (ret < 0) {
1722 pr_err("%s: Error %d sending media type\n", __func__, ret);
1723 goto fail;
1724 }
1725
1726 ret = wait_event_timeout(v->mvm_wait,
1727 (v->mvm_state == CMD_STATUS_SUCCESS),
1728 msecs_to_jiffies(TIMEOUT_MS));
1729 if (!ret) {
1730 pr_err("%s: wait_event timeout %d\n", __func__, ret);
1731 goto fail;
1732 }
1733 if (v->async_err > 0) {
1734 pr_err("%s: DSP returned error[%s]\n",
1735 __func__, adsp_err_get_err_str(
1736 v->async_err));
1737 ret = adsp_err_get_lnx_err_code(
1738 v->async_err);
1739 goto fail;
1740 }
1741 return 0;
1742fail:
1743 return ret;
1744}
1745
1746static int voice_send_dtmf_rx_detection_cmd(struct voice_data *v,
1747 uint32_t enable)
1748{
1749 int ret = 0;
1750 void *apr_cvs;
1751 u16 cvs_handle;
1752 struct cvs_set_rx_dtmf_detection_cmd cvs_dtmf_rx_detection;
1753
1754 if (v == NULL) {
1755 pr_err("%s: v is NULL\n", __func__);
1756 return -EINVAL;
1757 }
1758 apr_cvs = common.apr_q6_cvs;
1759
1760 if (!apr_cvs) {
1761 pr_err("%s: apr_cvs is NULL.\n", __func__);
1762 return -EINVAL;
1763 }
1764
1765 cvs_handle = voice_get_cvs_handle(v);
1766
1767 /* Set SET_DTMF_RX_DETECTION */
1768 cvs_dtmf_rx_detection.hdr.hdr_field =
1769 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1770 APR_HDR_LEN(APR_HDR_SIZE),
1771 APR_PKT_VER);
1772 cvs_dtmf_rx_detection.hdr.pkt_size =
1773 APR_PKT_SIZE(APR_HDR_SIZE,
1774 sizeof(cvs_dtmf_rx_detection) - APR_HDR_SIZE);
1775 cvs_dtmf_rx_detection.hdr.src_port =
1776 voice_get_idx_for_session(v->session_id);
1777 cvs_dtmf_rx_detection.hdr.dest_port = cvs_handle;
1778 cvs_dtmf_rx_detection.hdr.token = 0;
1779 cvs_dtmf_rx_detection.hdr.opcode =
1780 VSS_ISTREAM_CMD_SET_RX_DTMF_DETECTION;
1781 cvs_dtmf_rx_detection.cvs_dtmf_det.enable = enable;
1782
1783 v->cvs_state = CMD_STATUS_FAIL;
1784 v->async_err = 0;
1785
1786 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_dtmf_rx_detection);
1787 if (ret < 0) {
1788 pr_err("%s: Error %d sending SET_DTMF_RX_DETECTION\n",
1789 __func__,
1790 ret);
1791 return -EINVAL;
1792 }
1793
1794 ret = wait_event_timeout(v->cvs_wait,
1795 (v->cvs_state == CMD_STATUS_SUCCESS),
1796 msecs_to_jiffies(TIMEOUT_MS));
1797
1798 if (!ret) {
1799 pr_err("%s: wait_event timeout\n", __func__);
1800 return -EINVAL;
1801 }
1802 if (v->async_err > 0) {
1803 pr_err("%s: DSP returned error[%s]\n",
1804 __func__, adsp_err_get_err_str(
1805 v->async_err));
1806 ret = adsp_err_get_lnx_err_code(
1807 v->async_err);
1808 return ret;
1809 }
1810
1811 return ret;
1812}
1813
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301814/**
1815 * voc_disable_dtmf_det_on_active_sessions -
1816 * command to disable DTMF detection for voice sessions
1817 *
1818 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301819void voc_disable_dtmf_det_on_active_sessions(void)
1820{
1821 struct voice_data *v = NULL;
1822 int i;
1823
1824 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
1825 v = &common.voice[i];
1826 if ((v->dtmf_rx_detect_en) &&
1827 is_voc_state_active(v->voc_state)) {
1828
1829 pr_debug("disable dtmf det on ses_id=%d\n",
1830 v->session_id);
1831 voice_send_dtmf_rx_detection_cmd(v, 0);
1832 }
1833 }
1834}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301835EXPORT_SYMBOL(voc_disable_dtmf_det_on_active_sessions);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301836
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301837/**
1838 * voc_enable_dtmf_rx_detection -
1839 * command to set DTMF RX detection
1840 *
1841 * @session_id: voice session ID to send this command
1842 * @enable: Enable or Disable detection
1843 *
1844 * Returns 0 on success or error on failure
1845 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301846int voc_enable_dtmf_rx_detection(uint32_t session_id, uint32_t enable)
1847{
1848 struct voice_data *v = voice_get_session(session_id);
1849 int ret = 0;
1850
1851 if (v == NULL) {
1852 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
1853 return -EINVAL;
1854 }
1855
1856 mutex_lock(&v->lock);
1857 v->dtmf_rx_detect_en = enable;
1858
1859 if (is_voc_state_active(v->voc_state))
1860 ret = voice_send_dtmf_rx_detection_cmd(v,
1861 v->dtmf_rx_detect_en);
1862
1863 mutex_unlock(&v->lock);
1864
1865 return ret;
1866}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301867EXPORT_SYMBOL(voc_enable_dtmf_rx_detection);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301868
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301869/**
1870 * voc_set_destroy_cvd_flag -
1871 * set flag for destroy CVD session
1872 *
1873 * @is_destroy_cvd: bool value used to indicate
1874 * destroy CVD session or not.
1875 *
1876 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301877void voc_set_destroy_cvd_flag(bool is_destroy_cvd)
1878{
1879 pr_debug("%s: %d\n", __func__, is_destroy_cvd);
1880 common.is_destroy_cvd = is_destroy_cvd;
1881}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301882EXPORT_SYMBOL(voc_set_destroy_cvd_flag);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301883
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301884/**
1885 * voc_alloc_cal_shared_memory -
1886 * Alloc mem map table for calibration
1887 *
1888 * Returns 0 on success or error on failure
1889 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301890int voc_alloc_cal_shared_memory(void)
1891{
1892 int rc = 0;
1893
1894 mutex_lock(&common.common_lock);
1895 if (is_cal_memory_allocated()) {
1896 pr_debug("%s: Calibration shared buffer already allocated",
1897 __func__);
1898 } else {
1899 /* Allocate memory for calibration memory map table. */
1900 rc = voice_alloc_cal_mem_map_table();
1901 if ((rc < 0) && (rc != -EPROBE_DEFER)) {
1902 pr_err("%s: Failed to allocate cal memory, err=%d",
1903 __func__, rc);
1904 }
1905 }
1906 mutex_unlock(&common.common_lock);
1907
1908 return rc;
1909}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301910EXPORT_SYMBOL(voc_alloc_cal_shared_memory);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301911
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301912/**
1913 * voc_alloc_voip_shared_memory -
1914 * Alloc mem map table for OOB
1915 *
1916 * Returns 0 on success or error on failure
1917 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301918int voc_alloc_voip_shared_memory(void)
1919{
1920 int rc = 0;
1921
1922 /* Allocate shared memory for OOB Voip */
1923 rc = voice_alloc_oob_shared_mem();
1924 if (rc < 0) {
1925 pr_err("%s: Failed to alloc shared memory for OOB rc:%d\n",
1926 __func__, rc);
1927 } else {
1928 /* Allocate mem map table for OOB */
1929 rc = voice_alloc_oob_mem_table();
1930 if (rc < 0) {
1931 pr_err("%s: Failed to alloc mem map talbe rc:%d\n",
1932 __func__, rc);
1933
1934 voice_free_oob_shared_mem();
1935 }
1936 }
1937
1938 return rc;
1939}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301940EXPORT_SYMBOL(voc_alloc_voip_shared_memory);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301941
1942static int is_cal_memory_allocated(void)
1943{
1944 bool ret;
1945
1946 if (common.cal_mem_map_table.client != NULL &&
1947 common.cal_mem_map_table.handle != NULL)
1948 ret = true;
1949 else
1950 ret = false;
1951
1952 return ret;
1953}
1954
1955
1956static int free_cal_map_table(void)
1957{
1958 int ret = 0;
1959
1960 if ((common.cal_mem_map_table.client == NULL) ||
1961 (common.cal_mem_map_table.handle == NULL))
1962 goto done;
1963
1964 ret = msm_audio_ion_free(common.cal_mem_map_table.client,
1965 common.cal_mem_map_table.handle);
1966 if (ret < 0)
1967 pr_err("%s: msm_audio_ion_free failed:\n", __func__);
1968
1969done:
1970 common.cal_mem_map_table.client = NULL;
1971 common.cal_mem_map_table.handle = NULL;
1972 return ret;
1973}
1974
1975static int is_rtac_memory_allocated(void)
1976{
1977 bool ret;
1978
1979 if (common.rtac_mem_map_table.client != NULL &&
1980 common.rtac_mem_map_table.handle != NULL)
1981 ret = true;
1982 else
1983 ret = false;
1984
1985 return ret;
1986}
1987
1988static int free_rtac_map_table(void)
1989{
1990 int ret = 0;
1991
1992 if ((common.rtac_mem_map_table.client == NULL) ||
1993 (common.rtac_mem_map_table.handle == NULL))
1994 goto done;
1995
1996 ret = msm_audio_ion_free(common.rtac_mem_map_table.client,
1997 common.rtac_mem_map_table.handle);
1998 if (ret < 0)
1999 pr_err("%s: msm_audio_ion_free failed:\n", __func__);
2000
2001done:
2002 common.rtac_mem_map_table.client = NULL;
2003 common.rtac_mem_map_table.handle = NULL;
2004 return ret;
2005}
2006
2007
2008static int is_voip_memory_allocated(void)
2009{
2010 bool ret;
2011 struct voice_data *v = voice_get_session(
2012 common.voice[VOC_PATH_FULL].session_id);
2013
2014 if (v == NULL) {
2015 pr_err("%s: v is NULL, session_id:%d\n", __func__,
2016 common.voice[VOC_PATH_FULL].session_id);
2017
2018 ret = false;
2019 goto done;
2020 }
2021
2022 mutex_lock(&common.common_lock);
2023 if (v->shmem_info.sh_buf.client != NULL &&
2024 v->shmem_info.sh_buf.handle != NULL)
2025 ret = true;
2026 else
2027 ret = false;
2028 mutex_unlock(&common.common_lock);
2029
2030done:
2031 return ret;
2032}
2033
2034static int voice_config_cvs_vocoder_amr_rate(struct voice_data *v)
2035{
2036 int ret = 0;
2037 void *apr_cvs;
2038 u16 cvs_handle;
2039 struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate;
2040
2041 if (v == NULL) {
2042 pr_err("%s: v is NULL\n", __func__);
2043
2044 ret = -EINVAL;
2045 goto done;
2046 }
2047 apr_cvs = common.apr_q6_cvs;
2048
2049 if (!apr_cvs) {
2050 pr_err("%s: apr_cvs is NULL.\n", __func__);
2051
2052 ret = -EINVAL;
2053 goto done;
2054 }
2055
2056 cvs_handle = voice_get_cvs_handle(v);
2057
2058 pr_debug("%s: Setting AMR rate. Media Type: %d\n", __func__,
2059 common.mvs_info.media_type);
2060
2061 cvs_set_amr_rate.hdr.hdr_field =
2062 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2063 APR_HDR_LEN(APR_HDR_SIZE),
2064 APR_PKT_VER);
2065 cvs_set_amr_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2066 sizeof(cvs_set_amr_rate) - APR_HDR_SIZE);
2067 cvs_set_amr_rate.hdr.src_port =
2068 voice_get_idx_for_session(v->session_id);
2069 cvs_set_amr_rate.hdr.dest_port = cvs_handle;
2070 cvs_set_amr_rate.hdr.token = 0;
2071
2072 if (common.mvs_info.media_type == VSS_MEDIA_ID_AMR_NB_MODEM)
2073 cvs_set_amr_rate.hdr.opcode =
2074 VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE;
2075 else if (common.mvs_info.media_type == VSS_MEDIA_ID_AMR_WB_MODEM)
2076 cvs_set_amr_rate.hdr.opcode =
2077 VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE;
2078
2079 cvs_set_amr_rate.amr_rate.mode = common.mvs_info.rate;
2080
2081 v->cvs_state = CMD_STATUS_FAIL;
2082 v->async_err = 0;
2083
2084 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_amr_rate);
2085 if (ret < 0) {
2086 pr_err("%s: Error %d sending SET_AMR_RATE\n",
2087 __func__, ret);
2088
2089 goto done;
2090 }
2091 ret = wait_event_timeout(v->cvs_wait,
2092 (v->cvs_state == CMD_STATUS_SUCCESS),
2093 msecs_to_jiffies(TIMEOUT_MS));
2094 if (!ret) {
2095 pr_err("%s: wait_event timeout\n", __func__);
2096
2097 ret = -EINVAL;
2098 goto done;
2099 }
2100 if (v->async_err > 0) {
2101 pr_err("%s: DSP returned error[%s]\n",
2102 __func__, adsp_err_get_err_str(
2103 v->async_err));
2104 ret = adsp_err_get_lnx_err_code(
2105 v->async_err);
2106 goto done;
2107 }
2108
2109 return 0;
2110done:
2111 return ret;
2112}
2113
2114static int voice_config_cvs_vocoder(struct voice_data *v)
2115{
2116 int ret = 0;
2117 void *apr_cvs;
2118 u16 cvs_handle;
2119 /* Set media type. */
2120 struct cvs_set_media_type_cmd cvs_set_media_cmd;
2121
2122 if (v == NULL) {
2123 pr_err("%s: v is NULL\n", __func__);
2124 return -EINVAL;
2125 }
2126 apr_cvs = common.apr_q6_cvs;
2127
2128 if (!apr_cvs) {
2129 pr_err("%s: apr_cvs is NULL.\n", __func__);
2130 return -EINVAL;
2131 }
2132
2133 cvs_handle = voice_get_cvs_handle(v);
2134
2135 cvs_set_media_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2136 APR_HDR_LEN(APR_HDR_SIZE),
2137 APR_PKT_VER);
2138 cvs_set_media_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2139 sizeof(cvs_set_media_cmd) -
2140 APR_HDR_SIZE);
2141 cvs_set_media_cmd.hdr.src_port =
2142 voice_get_idx_for_session(v->session_id);
2143 cvs_set_media_cmd.hdr.dest_port = cvs_handle;
2144 cvs_set_media_cmd.hdr.token = 0;
2145 cvs_set_media_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_MEDIA_TYPE;
2146 cvs_set_media_cmd.media_type.tx_media_id = common.mvs_info.media_type;
2147 cvs_set_media_cmd.media_type.rx_media_id = common.mvs_info.media_type;
2148
2149 v->cvs_state = CMD_STATUS_FAIL;
2150 v->async_err = 0;
2151
2152 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_media_cmd);
2153 if (ret < 0) {
2154 pr_err("%s: Error %d sending SET_MEDIA_TYPE\n",
2155 __func__, ret);
2156
2157 goto fail;
2158 }
2159 ret = wait_event_timeout(v->cvs_wait,
2160 (v->cvs_state == CMD_STATUS_SUCCESS),
2161 msecs_to_jiffies(TIMEOUT_MS));
2162 if (!ret) {
2163 pr_err("%s: wait_event timeout\n", __func__);
2164
2165 goto fail;
2166 }
2167 if (v->async_err > 0) {
2168 pr_err("%s: DSP returned error[%s]\n",
2169 __func__, adsp_err_get_err_str(
2170 v->async_err));
2171 ret = adsp_err_get_lnx_err_code(
2172 v->async_err);
2173 goto fail;
2174 }
2175 /* Set encoder properties. */
2176 switch (common.mvs_info.media_type) {
2177 case VSS_MEDIA_ID_EVRC_MODEM:
2178 case VSS_MEDIA_ID_4GV_NB_MODEM:
2179 case VSS_MEDIA_ID_4GV_WB_MODEM:
2180 case VSS_MEDIA_ID_4GV_NW_MODEM: {
2181 struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate;
2182
2183 pr_debug("Setting EVRC min-max rate\n");
2184
2185 cvs_set_cdma_rate.hdr.hdr_field =
2186 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2187 APR_HDR_LEN(APR_HDR_SIZE),
2188 APR_PKT_VER);
2189 cvs_set_cdma_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2190 sizeof(cvs_set_cdma_rate) - APR_HDR_SIZE);
2191 cvs_set_cdma_rate.hdr.src_port =
2192 voice_get_idx_for_session(v->session_id);
2193 cvs_set_cdma_rate.hdr.dest_port = cvs_handle;
2194 cvs_set_cdma_rate.hdr.token = 0;
2195 cvs_set_cdma_rate.hdr.opcode =
2196 VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE;
2197 cvs_set_cdma_rate.cdma_rate.min_rate =
2198 common.mvs_info.evrc_min_rate;
2199 cvs_set_cdma_rate.cdma_rate.max_rate =
2200 common.mvs_info.evrc_max_rate;
2201
2202 v->cvs_state = CMD_STATUS_FAIL;
2203 v->async_err = 0;
2204
2205 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_cdma_rate);
2206 if (ret < 0) {
2207 pr_err("%s: Error %d sending SET_EVRC_MINMAX_RATE\n",
2208 __func__, ret);
2209 goto fail;
2210 }
2211 ret = wait_event_timeout(v->cvs_wait,
2212 (v->cvs_state == CMD_STATUS_SUCCESS),
2213 msecs_to_jiffies(TIMEOUT_MS));
2214 if (!ret) {
2215 pr_err("%s: wait_event timeout\n", __func__);
2216
2217 goto fail;
2218 }
2219 if (v->async_err > 0) {
2220 pr_err("%s: DSP returned error[%s]\n",
2221 __func__, adsp_err_get_err_str(
2222 v->async_err));
2223 ret = adsp_err_get_lnx_err_code(
2224 v->async_err);
2225 goto fail;
2226 }
2227
2228 if (common.mvs_info.media_type != VSS_MEDIA_ID_EVRC_MODEM) {
2229 ret = voice_set_dtx(v);
2230 if (ret < 0)
2231 goto fail;
2232 }
2233
2234 break;
2235 }
2236 case VSS_MEDIA_ID_AMR_NB_MODEM:
2237 case VSS_MEDIA_ID_AMR_WB_MODEM: {
2238 ret = voice_config_cvs_vocoder_amr_rate(v);
2239 if (ret) {
2240 pr_err("%s: Failed to update vocoder rate. %d\n",
2241 __func__, ret);
2242
2243 goto fail;
2244 }
2245
2246 ret = voice_set_dtx(v);
2247 if (ret < 0)
2248 goto fail;
2249
2250 break;
2251 }
2252 case VSS_MEDIA_ID_G729:
2253 case VSS_MEDIA_ID_G711_ALAW:
2254 case VSS_MEDIA_ID_G711_MULAW: {
2255 ret = voice_set_dtx(v);
2256
2257 break;
2258 }
2259 default:
2260 /* Do nothing. */
2261 break;
2262 }
2263 return 0;
2264
2265fail:
2266 return ret;
2267}
2268
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302269/**
2270 * voc_update_amr_vocoder_rate -
2271 * command to update AMR rate for voice session
2272 *
2273 * @session_id: voice session ID to send this command
2274 *
2275 * Returns 0 on success or error on failure
2276 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302277int voc_update_amr_vocoder_rate(uint32_t session_id)
2278{
2279 int ret = 0;
2280 struct voice_data *v;
2281
2282 pr_debug("%s: session_id:%d", __func__, session_id);
2283
2284 v = voice_get_session(session_id);
2285
2286 if (v == NULL) {
2287 pr_err("%s: v is NULL, session_id:%d\n", __func__,
2288 session_id);
2289
2290 ret = -EINVAL;
2291 goto done;
2292 }
2293
2294 mutex_lock(&v->lock);
2295 ret = voice_config_cvs_vocoder_amr_rate(v);
2296 mutex_unlock(&v->lock);
2297
2298done:
2299 return ret;
2300}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302301EXPORT_SYMBOL(voc_update_amr_vocoder_rate);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302302
2303static int voice_send_start_voice_cmd(struct voice_data *v)
2304{
2305 struct apr_hdr mvm_start_voice_cmd;
2306 int ret = 0;
2307 void *apr_mvm;
2308 u16 mvm_handle;
2309
2310 if (v == NULL) {
2311 pr_err("%s: v is NULL\n", __func__);
2312 return -EINVAL;
2313 }
2314 apr_mvm = common.apr_q6_mvm;
2315
2316 if (!apr_mvm) {
2317 pr_err("%s: apr_mvm is NULL.\n", __func__);
2318 return -EINVAL;
2319 }
2320 mvm_handle = voice_get_mvm_handle(v);
2321
2322 mvm_start_voice_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2323 APR_HDR_LEN(APR_HDR_SIZE),
2324 APR_PKT_VER);
2325 mvm_start_voice_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2326 sizeof(mvm_start_voice_cmd) - APR_HDR_SIZE);
2327 pr_debug("send mvm_start_voice_cmd pkt size = %d\n",
2328 mvm_start_voice_cmd.pkt_size);
2329 mvm_start_voice_cmd.src_port =
2330 voice_get_idx_for_session(v->session_id);
2331 mvm_start_voice_cmd.dest_port = mvm_handle;
2332 mvm_start_voice_cmd.token = 0;
2333 mvm_start_voice_cmd.opcode = VSS_IMVM_CMD_START_VOICE;
2334
2335 v->mvm_state = CMD_STATUS_FAIL;
2336 v->async_err = 0;
2337 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_start_voice_cmd);
2338 if (ret < 0) {
2339 pr_err("Fail in sending VSS_IMVM_CMD_START_VOICE\n");
2340 goto fail;
2341 }
2342 ret = wait_event_timeout(v->mvm_wait,
2343 (v->mvm_state == CMD_STATUS_SUCCESS),
2344 msecs_to_jiffies(TIMEOUT_MS));
2345 if (!ret) {
2346 pr_err("%s: wait_event timeout\n", __func__);
2347 goto fail;
2348 }
2349 if (v->async_err > 0) {
2350 pr_err("%s: DSP returned error[%s]\n",
2351 __func__, adsp_err_get_err_str(
2352 v->async_err));
2353 ret = adsp_err_get_lnx_err_code(
2354 v->async_err);
2355 goto fail;
2356 }
2357 return 0;
2358fail:
2359 return ret;
2360}
2361
2362static void voc_get_tx_rx_topology(struct voice_data *v,
2363 uint32_t *tx_topology_id,
2364 uint32_t *rx_topology_id)
2365{
2366 uint32_t tx_id = 0;
2367 uint32_t rx_id = 0;
2368
2369 if (v->lch_mode == VOICE_LCH_START || v->disable_topology) {
2370 pr_debug("%s: Setting TX and RX topology to NONE for LCH\n",
2371 __func__);
2372
2373 tx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE;
2374 rx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE;
2375 } else {
2376 tx_id = voice_get_topology(CVP_VOC_TX_TOPOLOGY_CAL);
2377 rx_id = voice_get_topology(CVP_VOC_RX_TOPOLOGY_CAL);
2378 }
2379
2380 *tx_topology_id = tx_id;
2381 *rx_topology_id = rx_id;
2382}
2383
2384static int voice_send_set_device_cmd(struct voice_data *v)
2385{
2386 struct cvp_set_device_cmd cvp_setdev_cmd;
2387 int ret = 0;
2388 void *apr_cvp;
2389 u16 cvp_handle;
2390
2391 if (v == NULL) {
2392 pr_err("%s: v is NULL\n", __func__);
2393 return -EINVAL;
2394 }
2395 apr_cvp = common.apr_q6_cvp;
2396
2397 if (!apr_cvp) {
2398 pr_err("%s: apr_cvp is NULL.\n", __func__);
2399 return -EINVAL;
2400 }
2401 cvp_handle = voice_get_cvp_handle(v);
2402
2403 /* set device and wait for response */
2404 cvp_setdev_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2405 APR_HDR_LEN(APR_HDR_SIZE),
2406 APR_PKT_VER);
2407 cvp_setdev_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2408 sizeof(cvp_setdev_cmd) - APR_HDR_SIZE);
2409 pr_debug(" send create cvp setdev, pkt size = %d\n",
2410 cvp_setdev_cmd.hdr.pkt_size);
2411 cvp_setdev_cmd.hdr.src_port =
2412 voice_get_idx_for_session(v->session_id);
2413 cvp_setdev_cmd.hdr.dest_port = cvp_handle;
2414 cvp_setdev_cmd.hdr.token = 0;
2415
2416 if (voice_get_cvd_int_version(common.cvd_version) >=
2417 CVD_INT_VERSION_2_2)
2418 cvp_setdev_cmd.hdr.opcode =
2419 VSS_IVOCPROC_CMD_SET_DEVICE_V3;
2420 else
2421 cvp_setdev_cmd.hdr.opcode =
2422 VSS_IVOCPROC_CMD_SET_DEVICE_V2;
2423
2424 voc_get_tx_rx_topology(v,
2425 &cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
2426 &cvp_setdev_cmd.cvp_set_device_v2.rx_topology_id);
2427
Aditya Bavanari88513a32017-10-12 12:29:25 +05302428 voice_set_topology_specific_info(v, CVP_VOC_RX_TOPOLOGY_CAL);
2429 voice_set_topology_specific_info(v, CVP_VOC_TX_TOPOLOGY_CAL);
2430
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302431 cvp_setdev_cmd.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
2432 cvp_setdev_cmd.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
2433
2434 if (common.ec_ref_ext) {
2435 cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
2436 VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING;
2437 cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
2438 common.ec_media_fmt_info.port_id;
2439 } else {
2440 cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
2441 VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
2442 cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
2443 VSS_IVOCPROC_PORT_ID_NONE;
2444 }
2445 pr_debug("topology=%d , tx_port_id=%d, rx_port_id=%d\n",
2446 cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
2447 cvp_setdev_cmd.cvp_set_device_v2.tx_port_id,
2448 cvp_setdev_cmd.cvp_set_device_v2.rx_port_id);
2449
2450 v->cvp_state = CMD_STATUS_FAIL;
2451 v->async_err = 0;
2452 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd);
2453 if (ret < 0) {
2454 pr_err("Fail in sending VSS_IVOCPROC_CMD_SET_DEVICE\n");
2455 goto fail;
2456 }
2457
2458 ret = wait_event_timeout(v->cvp_wait,
2459 (v->cvp_state == CMD_STATUS_SUCCESS),
2460 msecs_to_jiffies(TIMEOUT_MS));
2461 if (!ret) {
2462 pr_err("%s: wait_event timeout\n", __func__);
2463 goto fail;
2464 }
2465 if (v->async_err > 0) {
2466 pr_err("%s: DSP returned error[%s]\n",
2467 __func__, adsp_err_get_err_str(
2468 v->async_err));
2469 ret = adsp_err_get_lnx_err_code(
2470 v->async_err);
2471 goto fail;
2472 }
2473
2474 return 0;
2475fail:
2476 return ret;
2477}
2478
2479static int voice_send_stop_voice_cmd(struct voice_data *v)
2480{
2481 struct apr_hdr mvm_stop_voice_cmd;
2482 int ret = 0;
2483 void *apr_mvm;
2484 u16 mvm_handle;
2485
2486 if (v == NULL) {
2487 pr_err("%s: v is NULL\n", __func__);
2488 return -EINVAL;
2489 }
2490 apr_mvm = common.apr_q6_mvm;
2491
2492 if (!apr_mvm) {
2493 pr_err("%s: apr_mvm is NULL.\n", __func__);
2494 return -EINVAL;
2495 }
2496 mvm_handle = voice_get_mvm_handle(v);
2497
2498 mvm_stop_voice_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2499 APR_HDR_LEN(APR_HDR_SIZE),
2500 APR_PKT_VER);
2501 mvm_stop_voice_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2502 sizeof(mvm_stop_voice_cmd) - APR_HDR_SIZE);
2503 pr_debug("send mvm_stop_voice_cmd pkt size = %d\n",
2504 mvm_stop_voice_cmd.pkt_size);
2505 mvm_stop_voice_cmd.src_port =
2506 voice_get_idx_for_session(v->session_id);
2507 mvm_stop_voice_cmd.dest_port = mvm_handle;
2508 mvm_stop_voice_cmd.token = 0;
2509 mvm_stop_voice_cmd.opcode = VSS_IMVM_CMD_STOP_VOICE;
2510
2511 v->mvm_state = CMD_STATUS_FAIL;
2512 v->async_err = 0;
2513 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_stop_voice_cmd);
2514 if (ret < 0) {
2515 pr_err("Fail in sending VSS_IMVM_CMD_STOP_VOICE\n");
2516 goto fail;
2517 }
2518 ret = wait_event_timeout(v->mvm_wait,
2519 (v->mvm_state == CMD_STATUS_SUCCESS),
2520 msecs_to_jiffies(TIMEOUT_MS));
2521 if (!ret) {
2522 pr_err("%s: wait_event timeout\n", __func__);
2523 goto fail;
2524 }
2525 if (v->async_err > 0) {
2526 pr_err("%s: DSP returned error[%s]\n",
2527 __func__, adsp_err_get_err_str(
2528 v->async_err));
2529 ret = adsp_err_get_lnx_err_code(
2530 v->async_err);
2531 goto fail;
2532 }
2533
2534 return 0;
2535fail:
2536 return ret;
2537}
2538static int voice_get_cal(struct cal_block_data **cal_block,
2539 int cal_block_idx,
2540 struct cal_block_data **col_data,
2541 int col_data_idx, int session_id)
2542{
2543 int ret = 0;
2544
2545 *cal_block = cal_utils_get_only_cal_block(
2546 common.cal_data[cal_block_idx]);
2547 if (*cal_block == NULL) {
2548 pr_err("%s: No cal data for cal %d!\n",
2549 __func__, cal_block_idx);
2550
2551 ret = -ENODEV;
2552 goto done;
2553 }
2554 ret = remap_cal_data(*cal_block, session_id);
2555 if (ret < 0) {
2556 pr_err("%s: Remap_cal_data failed for cal %d!\n",
2557 __func__, cal_block_idx);
2558
2559 ret = -ENODEV;
2560 goto done;
2561 }
2562
2563 if (col_data == NULL)
2564 goto done;
2565
2566 *col_data = cal_utils_get_only_cal_block(
2567 common.cal_data[col_data_idx]);
2568 if (*col_data == NULL) {
2569 pr_err("%s: No cal data for cal %d!\n",
2570 __func__, col_data_idx);
2571
2572 ret = -ENODEV;
2573 goto done;
2574 }
2575done:
2576 return ret;
2577}
2578
2579static int voice_send_cvs_register_cal_cmd(struct voice_data *v)
2580{
2581 struct cvs_register_cal_data_cmd cvs_reg_cal_cmd;
2582 struct cal_block_data *cal_block = NULL;
2583 struct cal_block_data *col_data = NULL;
2584 int ret = 0;
2585
2586 memset(&cvs_reg_cal_cmd, 0, sizeof(cvs_reg_cal_cmd));
2587
2588 if (v == NULL) {
2589 pr_err("%s: v is NULL\n", __func__);
2590
2591 ret = -EINVAL;
2592 goto done;
2593 }
2594
2595 if (!common.apr_q6_cvs) {
2596 pr_err("%s: apr_cvs is NULL\n", __func__);
2597
2598 ret = -EINVAL;
2599 goto done;
2600 }
2601
2602 mutex_lock(&common.cal_data[CVS_VOCSTRM_CAL]->lock);
2603 mutex_lock(&common.cal_data[CVS_VOCSTRM_COL_CAL]->lock);
2604
2605 ret = voice_get_cal(&cal_block, CVS_VOCSTRM_CAL, &col_data,
2606 CVS_VOCSTRM_COL_CAL, v->session_id);
2607 if (ret < 0) {
2608 pr_err("%s: Voice_get_cal failed for cal %d!\n",
2609 __func__, CVS_VOCSTRM_CAL);
2610
2611 goto unlock;
2612 }
2613
2614 memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0],
2615 (void *) &((struct audio_cal_info_voc_col *)
2616 col_data->cal_info)->data,
2617 col_data->cal_data.size);
2618
2619 cvs_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2620 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2621 cvs_reg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2622 sizeof(cvs_reg_cal_cmd) - APR_HDR_SIZE);
2623 cvs_reg_cal_cmd.hdr.src_port =
2624 voice_get_idx_for_session(v->session_id);
2625 cvs_reg_cal_cmd.hdr.dest_port = voice_get_cvs_handle(v);
2626 cvs_reg_cal_cmd.hdr.token = 0;
2627 if (common.is_per_vocoder_cal_enabled)
2628 cvs_reg_cal_cmd.hdr.opcode =
2629 VSS_ISTREAM_CMD_REGISTER_STATIC_CALIBRATION_DATA;
2630 else
2631 cvs_reg_cal_cmd.hdr.opcode =
2632 VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA_V2;
2633
2634 cvs_reg_cal_cmd.cvs_cal_data.cal_mem_handle =
2635 cal_block->map_data.q6map_handle;
2636 cvs_reg_cal_cmd.cvs_cal_data.cal_mem_address_lsw =
2637 lower_32_bits(cal_block->cal_data.paddr);
2638 cvs_reg_cal_cmd.cvs_cal_data.cal_mem_address_msw =
2639 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2640 cvs_reg_cal_cmd.cvs_cal_data.cal_mem_size =
2641 cal_block->cal_data.size;
2642
2643 v->cvs_state = CMD_STATUS_FAIL;
2644 v->async_err = 0;
2645 ret = apr_send_pkt(common.apr_q6_cvs, (uint32_t *) &cvs_reg_cal_cmd);
2646 if (ret < 0) {
2647 pr_err("%s: Error %d registering CVS cal\n", __func__, ret);
2648
2649 ret = -EINVAL;
2650 goto unlock;
2651 }
2652 ret = wait_event_timeout(v->cvs_wait,
2653 (v->cvs_state == CMD_STATUS_SUCCESS),
2654 msecs_to_jiffies(TIMEOUT_MS));
2655 if (!ret) {
2656 pr_err("%s: Command timeout\n", __func__);
2657
2658 ret = -EINVAL;
2659 goto unlock;
2660 }
2661 if (v->async_err > 0) {
2662 pr_err("%s: DSP returned error[%s]\n",
2663 __func__, adsp_err_get_err_str(
2664 v->async_err));
2665 ret = adsp_err_get_lnx_err_code(
2666 v->async_err);
2667 goto unlock;
2668 }
2669unlock:
2670 mutex_unlock(&common.cal_data[CVS_VOCSTRM_COL_CAL]->lock);
2671 mutex_unlock(&common.cal_data[CVS_VOCSTRM_CAL]->lock);
2672done:
2673 return ret;
2674}
2675
2676static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v)
2677{
2678 struct cvs_deregister_cal_data_cmd cvs_dereg_cal_cmd;
2679 int ret = 0;
2680
2681 memset(&cvs_dereg_cal_cmd, 0, sizeof(cvs_dereg_cal_cmd));
2682
2683 if (v == NULL) {
2684 pr_err("%s: v is NULL\n", __func__);
2685
2686 ret = -EINVAL;
2687 goto done;
2688 }
2689
2690 if (!common.apr_q6_cvs) {
2691 pr_err("%s: apr_cvs is NULL\n", __func__);
2692
2693 ret = -EPERM;
2694 goto done;
2695 }
2696
2697 cvs_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2698 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2699 cvs_dereg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2700 sizeof(cvs_dereg_cal_cmd) - APR_HDR_SIZE);
2701 cvs_dereg_cal_cmd.hdr.src_port =
2702 voice_get_idx_for_session(v->session_id);
2703 cvs_dereg_cal_cmd.hdr.dest_port = voice_get_cvs_handle(v);
2704 cvs_dereg_cal_cmd.hdr.token = 0;
2705 if (common.is_per_vocoder_cal_enabled)
2706 cvs_dereg_cal_cmd.hdr.opcode =
2707 VSS_ISTREAM_CMD_DEREGISTER_STATIC_CALIBRATION_DATA;
2708 else
2709 cvs_dereg_cal_cmd.hdr.opcode =
2710 VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA;
2711
2712 v->cvs_state = CMD_STATUS_FAIL;
2713 v->async_err = 0;
2714 ret = apr_send_pkt(common.apr_q6_cvs, (uint32_t *) &cvs_dereg_cal_cmd);
2715 if (ret < 0) {
2716 pr_err("%s: Error %d de-registering CVS cal\n", __func__, ret);
2717 goto done;
2718 }
2719 ret = wait_event_timeout(v->cvs_wait,
2720 (v->cvs_state == CMD_STATUS_SUCCESS),
2721 msecs_to_jiffies(TIMEOUT_MS));
2722 if (!ret) {
2723 pr_err("%s: Command timeout\n", __func__);
2724 goto done;
2725 }
2726 if (v->async_err > 0) {
2727 pr_err("%s: DSP returned error[%s]\n",
2728 __func__, adsp_err_get_err_str(
2729 v->async_err));
2730 ret = adsp_err_get_lnx_err_code(
2731 v->async_err);
2732 goto done;
2733 }
2734
2735done:
2736 return ret;
2737
2738}
2739
2740static int voice_send_cvp_create_cmd(struct voice_data *v)
2741{
2742 struct cvp_create_full_ctl_session_cmd cvp_session_cmd;
2743 void *apr_cvp;
2744 int ret = 0;
2745
2746 if (v == NULL) {
2747 pr_err("%s: v is NULL\n", __func__);
2748 ret = -EINVAL;
2749 goto done;
2750 }
2751
2752 apr_cvp = common.apr_q6_cvp;
2753 if (!apr_cvp) {
2754 pr_err("%s: apr_cvp is NULL.\n", __func__);
2755
2756 ret = -EINVAL;
2757 goto done;
2758 }
2759
2760 /* create cvp session and wait for response */
2761 cvp_session_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2762 APR_HDR_LEN(APR_HDR_SIZE),
2763 APR_PKT_VER);
2764 cvp_session_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2765 sizeof(cvp_session_cmd) - APR_HDR_SIZE);
2766 pr_debug("%s: send create cvp session, pkt size = %d\n",
2767 __func__, cvp_session_cmd.hdr.pkt_size);
2768 cvp_session_cmd.hdr.src_port =
2769 voice_get_idx_for_session(v->session_id);
2770 cvp_session_cmd.hdr.dest_port = 0;
2771 cvp_session_cmd.hdr.token = 0;
2772
2773 if (voice_get_cvd_int_version(common.cvd_version) >=
2774 CVD_INT_VERSION_2_2)
2775 cvp_session_cmd.hdr.opcode =
2776 VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V3;
2777 else
2778 cvp_session_cmd.hdr.opcode =
2779 VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2;
2780
2781 voc_get_tx_rx_topology(v,
2782 &cvp_session_cmd.cvp_session.tx_topology_id,
2783 &cvp_session_cmd.cvp_session.rx_topology_id);
2784
Aditya Bavanari88513a32017-10-12 12:29:25 +05302785 voice_set_topology_specific_info(v, CVP_VOC_RX_TOPOLOGY_CAL);
2786 voice_set_topology_specific_info(v, CVP_VOC_TX_TOPOLOGY_CAL);
2787
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302788 cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/
2789 cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id;
2790 cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.port_id;
2791 cvp_session_cmd.cvp_session.profile_id =
2792 VSS_ICOMMON_CAL_NETWORK_ID_NONE;
2793 if (common.ec_ref_ext) {
2794 cvp_session_cmd.cvp_session.vocproc_mode =
2795 VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING;
2796 cvp_session_cmd.cvp_session.ec_ref_port_id =
2797 common.ec_media_fmt_info.port_id;
2798 } else {
2799 cvp_session_cmd.cvp_session.vocproc_mode =
2800 VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
2801 cvp_session_cmd.cvp_session.ec_ref_port_id =
2802 VSS_IVOCPROC_PORT_ID_NONE;
2803 }
2804
2805 pr_debug("tx_topology: %d tx_port_id=%d, rx_port_id=%d, mode: 0x%x\n",
2806 cvp_session_cmd.cvp_session.tx_topology_id,
2807 cvp_session_cmd.cvp_session.tx_port_id,
2808 cvp_session_cmd.cvp_session.rx_port_id,
2809 cvp_session_cmd.cvp_session.vocproc_mode);
2810 pr_debug("rx_topology: %d, profile_id: 0x%x, pkt_size: %d\n",
2811 cvp_session_cmd.cvp_session.rx_topology_id,
2812 cvp_session_cmd.cvp_session.profile_id,
2813 cvp_session_cmd.hdr.pkt_size);
2814
2815 v->cvp_state = CMD_STATUS_FAIL;
2816 v->async_err = 0;
2817 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_session_cmd);
2818 if (ret < 0) {
2819 pr_err("Fail in sending VOCPROC_FULL_CONTROL_SESSION\n");
2820
2821 ret = -EINVAL;
2822 goto done;
2823 }
2824
2825 ret = wait_event_timeout(v->cvp_wait,
2826 (v->cvp_state == CMD_STATUS_SUCCESS),
2827 msecs_to_jiffies(TIMEOUT_MS));
2828 if (!ret) {
2829 pr_err("%s: wait_event timeout\n", __func__);
2830
2831 ret = -EINVAL;
2832 goto done;
2833 }
2834 if (v->async_err > 0) {
2835 pr_err("%s: DSP returned error[%s]\n",
2836 __func__, adsp_err_get_err_str(
2837 v->async_err));
2838 ret = adsp_err_get_lnx_err_code(
2839 v->async_err);
2840 goto done;
2841 }
2842
2843done:
2844 return ret;
2845}
2846
2847static int voice_send_cvp_register_dev_cfg_cmd(struct voice_data *v)
2848{
2849 struct cvp_register_dev_cfg_cmd cvp_reg_dev_cfg_cmd;
2850 struct cal_block_data *cal_block = NULL;
2851 int ret = 0;
2852
2853 memset(&cvp_reg_dev_cfg_cmd, 0, sizeof(cvp_reg_dev_cfg_cmd));
2854
2855 if (v == NULL) {
2856 pr_err("%s: v is NULL\n", __func__);
2857
2858 ret = -EINVAL;
2859 goto done;
2860 }
2861
2862 if (!common.apr_q6_cvp) {
2863 pr_err("%s: apr_cvp is NULL\n", __func__);
2864
2865 ret = -EPERM;
2866 goto done;
2867 }
2868
2869 mutex_lock(&common.cal_data[CVP_VOCDEV_CFG_CAL]->lock);
2870
2871 ret = voice_get_cal(&cal_block, CVP_VOCDEV_CFG_CAL, NULL,
2872 0, v->session_id);
2873 if (ret < 0) {
2874 pr_err("%s: Voice_get_cal failed for cal %d!\n",
2875 __func__, CVP_VOCDEV_CFG_CAL);
2876
2877 goto unlock;
2878 }
2879
2880 cvp_reg_dev_cfg_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2881 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2882 cvp_reg_dev_cfg_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2883 sizeof(cvp_reg_dev_cfg_cmd) - APR_HDR_SIZE);
2884 cvp_reg_dev_cfg_cmd.hdr.src_port =
2885 voice_get_idx_for_session(v->session_id);
2886 cvp_reg_dev_cfg_cmd.hdr.dest_port = voice_get_cvp_handle(v);
2887 cvp_reg_dev_cfg_cmd.hdr.token = 0;
2888 cvp_reg_dev_cfg_cmd.hdr.opcode =
2889 VSS_IVOCPROC_CMD_REGISTER_DEVICE_CONFIG;
2890
2891 cvp_reg_dev_cfg_cmd.cvp_dev_cfg_data.mem_handle =
2892 cal_block->map_data.q6map_handle;
2893 cvp_reg_dev_cfg_cmd.cvp_dev_cfg_data.mem_address_lsw =
2894 lower_32_bits(cal_block->cal_data.paddr);
2895 cvp_reg_dev_cfg_cmd.cvp_dev_cfg_data.mem_address_msw =
2896 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
2897 cvp_reg_dev_cfg_cmd.cvp_dev_cfg_data.mem_size =
2898 cal_block->cal_data.size;
2899
2900 v->cvp_state = CMD_STATUS_FAIL;
2901 v->async_err = 0;
2902 ret = apr_send_pkt(common.apr_q6_cvp,
2903 (uint32_t *) &cvp_reg_dev_cfg_cmd);
2904 if (ret < 0) {
2905 pr_err("%s: Error %d registering CVP dev cfg cal\n",
2906 __func__, ret);
2907
2908 ret = -EINVAL;
2909 goto unlock;
2910 }
2911 ret = wait_event_timeout(v->cvp_wait,
2912 (v->cvp_state == CMD_STATUS_SUCCESS),
2913 msecs_to_jiffies(TIMEOUT_MS));
2914 if (!ret) {
2915 pr_err("%s: Command timeout\n", __func__);
2916
2917 ret = -EINVAL;
2918 goto unlock;
2919 }
2920 if (v->async_err > 0) {
2921 pr_err("%s: DSP returned error[%s]\n",
2922 __func__, adsp_err_get_err_str(
2923 v->async_err));
2924 ret = adsp_err_get_lnx_err_code(
2925 v->async_err);
2926 goto unlock;
2927 }
2928unlock:
2929 mutex_unlock(&common.cal_data[CVP_VOCDEV_CFG_CAL]->lock);
2930done:
2931 return ret;
2932}
2933
2934static int voice_send_cvp_deregister_dev_cfg_cmd(struct voice_data *v)
2935{
2936 struct cvp_deregister_dev_cfg_cmd cvp_dereg_dev_cfg_cmd;
2937 int ret = 0;
2938
2939 memset(&cvp_dereg_dev_cfg_cmd, 0, sizeof(cvp_dereg_dev_cfg_cmd));
2940
2941 if (v == NULL) {
2942 pr_err("%s: v is NULL\n", __func__);
2943
2944 ret = -EINVAL;
2945 goto done;
2946 }
2947
2948 if (!common.apr_q6_cvp) {
2949 pr_err("%s: apr_cvp is NULL\n", __func__);
2950
2951 ret = -EPERM;
2952 goto done;
2953 }
2954
2955 cvp_dereg_dev_cfg_cmd.hdr.hdr_field =
2956 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
2957 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
2958 cvp_dereg_dev_cfg_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
2959 sizeof(cvp_dereg_dev_cfg_cmd) - APR_HDR_SIZE);
2960 cvp_dereg_dev_cfg_cmd.hdr.src_port =
2961 voice_get_idx_for_session(v->session_id);
2962 cvp_dereg_dev_cfg_cmd.hdr.dest_port = voice_get_cvp_handle(v);
2963 cvp_dereg_dev_cfg_cmd.hdr.token = 0;
2964 cvp_dereg_dev_cfg_cmd.hdr.opcode =
2965 VSS_IVOCPROC_CMD_DEREGISTER_DEVICE_CONFIG;
2966
2967 v->cvp_state = CMD_STATUS_FAIL;
2968 v->async_err = 0;
2969 ret = apr_send_pkt(common.apr_q6_cvp,
2970 (uint32_t *) &cvp_dereg_dev_cfg_cmd);
2971 if (ret < 0) {
2972 pr_err("%s: Error %d de-registering CVP dev cfg cal\n",
2973 __func__, ret);
2974 goto done;
2975 }
2976 ret = wait_event_timeout(v->cvp_wait,
2977 (v->cvp_state == CMD_STATUS_SUCCESS),
2978 msecs_to_jiffies(TIMEOUT_MS));
2979 if (!ret) {
2980 pr_err("%s: Command timeout\n", __func__);
2981 goto done;
2982 }
2983 if (v->async_err > 0) {
2984 pr_err("%s: DSP returned error[%s]\n",
2985 __func__, adsp_err_get_err_str(
2986 v->async_err));
2987 ret = adsp_err_get_lnx_err_code(
2988 v->async_err);
2989 goto done;
2990 }
2991
2992done:
2993 return ret;
2994}
2995
2996static int voice_send_cvp_register_cal_cmd(struct voice_data *v)
2997{
2998 struct cvp_register_cal_data_cmd cvp_reg_cal_cmd;
2999 struct cal_block_data *cal_block = NULL;
3000 struct cal_block_data *col_data = NULL;
3001 int ret = 0;
3002
3003 memset(&cvp_reg_cal_cmd, 0, sizeof(cvp_reg_cal_cmd));
3004
3005 if (v == NULL) {
3006 pr_err("%s: v is NULL\n", __func__);
3007
3008 ret = -EINVAL;
3009 goto done;
3010 }
3011
3012 if (!common.apr_q6_cvp) {
3013 pr_err("%s: apr_cvp is NULL\n", __func__);
3014
3015 ret = -EINVAL;
3016 goto done;
3017 }
3018
3019 mutex_lock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
3020 mutex_lock(&common.cal_data[CVP_VOCPROC_COL_CAL]->lock);
3021
3022 ret = voice_get_cal(&cal_block, CVP_VOCPROC_CAL, &col_data,
3023 CVP_VOCPROC_COL_CAL, v->session_id);
3024 if (ret < 0) {
3025 pr_err("%s: Voice_get_cal failed for cal %d!\n",
3026 __func__, CVP_VOCPROC_CAL);
3027
3028 goto unlock;
3029 }
3030
3031 v->dev_tx.dev_id = ((struct audio_cal_info_vocproc *)
3032 cal_block->cal_info)->tx_acdb_id;
3033 v->dev_rx.dev_id = ((struct audio_cal_info_vocproc *)
3034 cal_block->cal_info)->rx_acdb_id;
3035 pr_debug("%s: %s: Tx acdb id = %d and Rx acdb id = %d", __func__,
3036 voc_get_session_name(v->session_id), v->dev_tx.dev_id,
3037 v->dev_rx.dev_id);
3038
3039 memcpy(&cvp_reg_cal_cmd.cvp_cal_data.column_info[0],
3040 (void *) &((struct audio_cal_info_voc_col *)
3041 col_data->cal_info)->data,
3042 col_data->cal_data.size);
3043
3044 cvp_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3045 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3046 cvp_reg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
3047 sizeof(cvp_reg_cal_cmd) - APR_HDR_SIZE);
3048 cvp_reg_cal_cmd.hdr.src_port =
3049 voice_get_idx_for_session(v->session_id);
3050 cvp_reg_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
3051 cvp_reg_cal_cmd.hdr.token = 0;
3052 if (common.is_per_vocoder_cal_enabled)
3053 cvp_reg_cal_cmd.hdr.opcode =
3054 VSS_IVOCPROC_CMD_REGISTER_STATIC_CALIBRATION_DATA;
3055 else
3056 cvp_reg_cal_cmd.hdr.opcode =
3057 VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA_V2;
3058
3059 cvp_reg_cal_cmd.cvp_cal_data.cal_mem_handle =
3060 cal_block->map_data.q6map_handle;
3061 cvp_reg_cal_cmd.cvp_cal_data.cal_mem_address_lsw =
3062 lower_32_bits(cal_block->cal_data.paddr);
3063 cvp_reg_cal_cmd.cvp_cal_data.cal_mem_address_msw =
3064 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
3065 cvp_reg_cal_cmd.cvp_cal_data.cal_mem_size =
3066 cal_block->cal_data.size;
3067
3068 v->cvp_state = CMD_STATUS_FAIL;
3069 v->async_err = 0;
3070 ret = apr_send_pkt(common.apr_q6_cvp, (uint32_t *) &cvp_reg_cal_cmd);
3071 if (ret < 0) {
3072 pr_err("%s: Error %d registering CVP cal\n", __func__, ret);
3073
3074 ret = -EINVAL;
3075 goto unlock;
3076 }
3077 ret = wait_event_timeout(v->cvp_wait,
3078 (v->cvp_state == CMD_STATUS_SUCCESS),
3079 msecs_to_jiffies(TIMEOUT_MS));
3080 if (!ret) {
3081 pr_err("%s: Command timeout\n", __func__);
3082
3083 ret = -EINVAL;
3084 goto unlock;
3085 }
3086 if (v->async_err > 0) {
3087 pr_err("%s: DSP returned error[%s]\n",
3088 __func__, adsp_err_get_err_str(
3089 v->async_err));
3090 ret = adsp_err_get_lnx_err_code(
3091 v->async_err);
3092 goto unlock;
3093 }
3094unlock:
3095 mutex_unlock(&common.cal_data[CVP_VOCPROC_COL_CAL]->lock);
3096 mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
3097done:
3098 return ret;
3099}
3100
3101static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v)
3102{
3103 struct cvp_deregister_cal_data_cmd cvp_dereg_cal_cmd;
3104 int ret = 0;
3105
3106 memset(&cvp_dereg_cal_cmd, 0, sizeof(cvp_dereg_cal_cmd));
3107
3108 if (v == NULL) {
3109 pr_err("%s: v is NULL\n", __func__);
3110
3111 ret = -EINVAL;
3112 goto done;
3113 }
3114
3115 if (!common.apr_q6_cvp) {
3116 pr_err("%s: apr_cvp is NULL.\n", __func__);
3117
3118 ret = -EPERM;
3119 goto done;
3120 }
3121
3122 cvp_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3123 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3124 cvp_dereg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
3125 sizeof(cvp_dereg_cal_cmd) - APR_HDR_SIZE);
3126 cvp_dereg_cal_cmd.hdr.src_port =
3127 voice_get_idx_for_session(v->session_id);
3128 cvp_dereg_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
3129 cvp_dereg_cal_cmd.hdr.token = 0;
3130 if (common.is_per_vocoder_cal_enabled)
3131 cvp_dereg_cal_cmd.hdr.opcode =
3132 VSS_IVOCPROC_CMD_DEREGISTER_STATIC_CALIBRATION_DATA;
3133 else
3134 cvp_dereg_cal_cmd.hdr.opcode =
3135 VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA;
3136
3137 v->cvp_state = CMD_STATUS_FAIL;
3138 v->async_err = 0;
3139 ret = apr_send_pkt(common.apr_q6_cvp, (uint32_t *) &cvp_dereg_cal_cmd);
3140 if (ret < 0) {
3141 pr_err("%s: Error %d de-registering CVP cal\n", __func__, ret);
3142 goto done;
3143 }
3144 ret = wait_event_timeout(v->cvp_wait,
3145 (v->cvp_state == CMD_STATUS_SUCCESS),
3146 msecs_to_jiffies(TIMEOUT_MS));
3147 if (!ret) {
3148 pr_err("%s: Command timeout\n", __func__);
3149 goto done;
3150 }
3151 if (v->async_err > 0) {
3152 pr_err("%s: DSP returned error[%s]\n",
3153 __func__, adsp_err_get_err_str(
3154 v->async_err));
3155 ret = adsp_err_get_lnx_err_code(
3156 v->async_err);
3157 goto done;
3158 }
3159
3160done:
3161 return ret;
3162}
3163
3164static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v)
3165{
3166 struct cvp_register_vol_cal_data_cmd cvp_reg_vol_cal_cmd;
3167 struct cal_block_data *cal_block = NULL;
3168 struct cal_block_data *col_data = NULL;
3169 int ret = 0;
3170
3171 memset(&cvp_reg_vol_cal_cmd, 0, sizeof(cvp_reg_vol_cal_cmd));
3172
3173 if (v == NULL) {
3174 pr_err("%s: v is NULL\n", __func__);
3175
3176 ret = -EINVAL;
3177 goto done;
3178 }
3179
3180 if (!common.apr_q6_cvp) {
3181 pr_err("%s: apr_cvp is NULL\n", __func__);
3182
3183 ret = -EINVAL;
3184 goto done;
3185 }
3186
3187 mutex_lock(&common.cal_data[CVP_VOCVOL_CAL]->lock);
3188 mutex_lock(&common.cal_data[CVP_VOCVOL_COL_CAL]->lock);
3189
3190 ret = voice_get_cal(&cal_block, CVP_VOCVOL_CAL, &col_data,
3191 CVP_VOCVOL_COL_CAL, v->session_id);
3192 if (ret < 0) {
3193 pr_err("%s: Voice_get_cal failed for cal %d!\n",
3194 __func__, CVP_VOCVOL_CAL);
3195
3196 goto unlock;
3197 }
3198
3199 memcpy(&cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info[0],
3200 (void *) &((struct audio_cal_info_voc_col *)
3201 col_data->cal_info)->data,
3202 col_data->cal_data.size);
3203
3204 cvp_reg_vol_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3205 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3206 cvp_reg_vol_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
3207 sizeof(cvp_reg_vol_cal_cmd) - APR_HDR_SIZE);
3208 cvp_reg_vol_cal_cmd.hdr.src_port =
3209 voice_get_idx_for_session(v->session_id);
3210 cvp_reg_vol_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
3211 cvp_reg_vol_cal_cmd.hdr.token = 0;
3212 if (common.is_per_vocoder_cal_enabled)
3213 cvp_reg_vol_cal_cmd.hdr.opcode =
3214 VSS_IVOCPROC_CMD_REGISTER_DYNAMIC_CALIBRATION_DATA;
3215 else
3216 cvp_reg_vol_cal_cmd.hdr.opcode =
3217 VSS_IVOCPROC_CMD_REGISTER_VOL_CALIBRATION_DATA;
3218
3219 cvp_reg_vol_cal_cmd.cvp_vol_cal_data.cal_mem_handle =
3220 cal_block->map_data.q6map_handle;
3221 cvp_reg_vol_cal_cmd.cvp_vol_cal_data.cal_mem_address_lsw =
3222 lower_32_bits(cal_block->cal_data.paddr);
3223 cvp_reg_vol_cal_cmd.cvp_vol_cal_data.cal_mem_address_msw =
3224 msm_audio_populate_upper_32_bits(cal_block->cal_data.paddr);
3225 cvp_reg_vol_cal_cmd.cvp_vol_cal_data.cal_mem_size =
3226 cal_block->cal_data.size;
3227
3228 v->cvp_state = CMD_STATUS_FAIL;
3229 v->async_err = 0;
3230 ret = apr_send_pkt(common.apr_q6_cvp,
3231 (uint32_t *) &cvp_reg_vol_cal_cmd);
3232 if (ret < 0) {
3233 pr_err("%s: Error %d registering CVP vol cal\n", __func__, ret);
3234
3235 ret = -EINVAL;
3236 goto unlock;
3237 }
3238 ret = wait_event_timeout(v->cvp_wait,
3239 (v->cvp_state == CMD_STATUS_SUCCESS),
3240 msecs_to_jiffies(TIMEOUT_MS));
3241 if (!ret) {
3242 pr_err("%s: Command timeout\n", __func__);
3243
3244 ret = -EINVAL;
3245 goto unlock;
3246 }
3247 if (v->async_err > 0) {
3248 pr_err("%s: DSP returned error[%s]\n",
3249 __func__, adsp_err_get_err_str(
3250 v->async_err));
3251 ret = adsp_err_get_lnx_err_code(
3252 v->async_err);
3253 goto unlock;
3254 }
3255unlock:
3256 mutex_unlock(&common.cal_data[CVP_VOCVOL_COL_CAL]->lock);
3257 mutex_unlock(&common.cal_data[CVP_VOCVOL_CAL]->lock);
3258done:
3259 return ret;
3260}
3261
3262static int voice_send_cvp_deregister_vol_cal_cmd(struct voice_data *v)
3263{
3264 struct cvp_deregister_vol_cal_data_cmd cvp_dereg_vol_cal_cmd;
3265 int ret = 0;
3266
3267 memset(&cvp_dereg_vol_cal_cmd, 0, sizeof(cvp_dereg_vol_cal_cmd));
3268
3269 if (v == NULL) {
3270 pr_err("%s: v is NULL\n", __func__);
3271
3272 ret = -EINVAL;
3273 goto done;
3274 }
3275
3276 if (!common.apr_q6_cvp) {
3277 pr_err("%s: apr_cvp is NULL\n", __func__);
3278
3279 ret = -EPERM;
3280 goto done;
3281 }
3282
3283 cvp_dereg_vol_cal_cmd.hdr.hdr_field =
3284 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3285 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3286 cvp_dereg_vol_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
3287 sizeof(cvp_dereg_vol_cal_cmd) - APR_HDR_SIZE);
3288 cvp_dereg_vol_cal_cmd.hdr.src_port =
3289 voice_get_idx_for_session(v->session_id);
3290 cvp_dereg_vol_cal_cmd.hdr.dest_port = voice_get_cvp_handle(v);
3291 cvp_dereg_vol_cal_cmd.hdr.token = 0;
3292 if (common.is_per_vocoder_cal_enabled)
3293 cvp_dereg_vol_cal_cmd.hdr.opcode =
3294 VSS_IVOCPROC_CMD_DEREGISTER_DYNAMIC_CALIBRATION_DATA;
3295 else
3296 cvp_dereg_vol_cal_cmd.hdr.opcode =
3297 VSS_IVOCPROC_CMD_DEREGISTER_VOL_CALIBRATION_DATA;
3298
3299 v->cvp_state = CMD_STATUS_FAIL;
3300 v->async_err = 0;
3301 ret = apr_send_pkt(common.apr_q6_cvp,
3302 (uint32_t *) &cvp_dereg_vol_cal_cmd);
3303 if (ret < 0) {
3304 pr_err("%s: Error %d de-registering CVP vol cal\n",
3305 __func__, ret);
3306 goto done;
3307 }
3308 ret = wait_event_timeout(v->cvp_wait,
3309 (v->cvp_state == CMD_STATUS_SUCCESS),
3310 msecs_to_jiffies(TIMEOUT_MS));
3311 if (!ret) {
3312 pr_err("%s: Command timeout\n", __func__);
3313 goto done;
3314 }
3315 if (v->async_err > 0) {
3316 pr_err("%s: DSP returned error[%s]\n",
3317 __func__, adsp_err_get_err_str(
3318 v->async_err));
3319 ret = adsp_err_get_lnx_err_code(
3320 v->async_err);
3321 goto done;
3322 }
3323
3324done:
3325 return ret;
3326}
3327
3328static int voice_map_memory_physical_cmd(struct voice_data *v,
3329 struct mem_map_table *table_info,
3330 dma_addr_t phys,
3331 uint32_t size,
3332 uint32_t token)
3333{
3334 struct vss_imemory_cmd_map_physical_t mvm_map_phys_cmd;
3335 uint32_t *memtable;
3336 int ret = 0;
3337
3338 if (v == NULL) {
3339 pr_err("%s: v is NULL\n", __func__);
3340 ret = -EINVAL;
3341 goto fail;
3342 }
3343
3344 if (!common.apr_q6_mvm) {
3345 pr_err("%s: apr_mvm is NULL.\n", __func__);
3346 ret = -EINVAL;
3347 goto fail;
3348 }
3349
3350 if (!table_info->data) {
3351 pr_err("%s: memory table is NULL.\n", __func__);
3352 ret = -EINVAL;
3353 goto fail;
3354 }
3355
3356 memtable = (uint32_t *) table_info->data;
3357
3358 /*
3359 * Store next table descriptor's address(64 bit) as NULL as there
3360 * is only one memory block
3361 */
3362 memtable[0] = 0;
3363 memtable[1] = 0;
3364
3365 /* Store next table descriptor's size */
3366 memtable[2] = 0;
3367
3368 /* Store shared mem adddress (64 bit) */
3369 memtable[3] = lower_32_bits(phys);
3370 memtable[4] = msm_audio_populate_upper_32_bits(phys);
3371
3372 /* Store shared memory size */
3373 memtable[5] = size;
3374
3375 mvm_map_phys_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3376 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3377 mvm_map_phys_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
3378 sizeof(mvm_map_phys_cmd) - APR_HDR_SIZE);
3379 mvm_map_phys_cmd.hdr.src_port =
3380 voice_get_idx_for_session(v->session_id);
3381 mvm_map_phys_cmd.hdr.dest_port = voice_get_mvm_handle(v);
3382 mvm_map_phys_cmd.hdr.token = token;
3383 mvm_map_phys_cmd.hdr.opcode = VSS_IMEMORY_CMD_MAP_PHYSICAL;
3384
3385 mvm_map_phys_cmd.table_descriptor.mem_address_lsw =
3386 lower_32_bits(table_info->phys);
3387 mvm_map_phys_cmd.table_descriptor.mem_address_msw =
3388 msm_audio_populate_upper_32_bits(table_info->phys);
3389 mvm_map_phys_cmd.table_descriptor.mem_size =
3390 sizeof(struct vss_imemory_block_t) +
3391 sizeof(struct vss_imemory_table_descriptor_t);
3392 mvm_map_phys_cmd.is_cached = true;
3393 mvm_map_phys_cmd.cache_line_size = 128;
3394 mvm_map_phys_cmd.access_mask = 3;
3395 mvm_map_phys_cmd.page_align = 4096;
3396 mvm_map_phys_cmd.min_data_width = 8;
3397 mvm_map_phys_cmd.max_data_width = 64;
3398
3399 pr_debug("%s: next table desc: add: %lld, size: %d\n",
3400 __func__, *((uint64_t *) memtable),
3401 *(((uint32_t *) memtable) + 2));
3402 pr_debug("%s: phy add of of mem being mapped LSW:0x%x, MSW:0x%x size: %d\n",
3403 __func__, *(((uint32_t *) memtable) + 3),
3404 *(((uint32_t *) memtable) + 4), *(((uint32_t *) memtable) + 5));
3405
3406 v->mvm_state = CMD_STATUS_FAIL;
3407 v->async_err = 0;
3408 ret = apr_send_pkt(common.apr_q6_mvm, (uint32_t *) &mvm_map_phys_cmd);
3409 if (ret < 0) {
3410 pr_err("%s: Error %d sending mvm map phy cmd\n", __func__, ret);
3411
3412 goto fail;
3413 }
3414
3415 ret = wait_event_timeout(v->mvm_wait,
3416 (v->mvm_state == CMD_STATUS_SUCCESS),
3417 msecs_to_jiffies(TIMEOUT_MS));
3418 if (!ret) {
3419 pr_err("%s: Command timeout\n", __func__);
3420
3421 goto fail;
3422 }
3423 if (v->async_err > 0) {
3424 pr_err("%s: DSP returned error[%s]\n",
3425 __func__, adsp_err_get_err_str(
3426 v->async_err));
3427 ret = adsp_err_get_lnx_err_code(
3428 v->async_err);
3429 goto fail;
3430 }
3431
3432 return 0;
3433
3434fail:
3435 return ret;
3436}
3437
3438static int voice_pause_voice_call(struct voice_data *v)
3439{
3440 struct apr_hdr mvm_pause_voice_cmd;
3441 void *apr_mvm;
3442 int ret = 0;
3443
3444 pr_debug("%s\n", __func__);
3445
3446 if (v == NULL) {
3447 pr_err("%s: Voice data is NULL\n", __func__);
3448
3449 ret = -EINVAL;
3450 goto done;
3451 }
3452
3453 apr_mvm = common.apr_q6_mvm;
3454 if (!apr_mvm) {
3455 pr_err("%s: apr_mvm is NULL.\n", __func__);
3456
3457 ret = -EINVAL;
3458 goto done;
3459 }
3460
3461 mvm_pause_voice_cmd.hdr_field =
3462 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
3463 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
3464 mvm_pause_voice_cmd.pkt_size =
3465 APR_PKT_SIZE(APR_HDR_SIZE,
3466 sizeof(mvm_pause_voice_cmd) - APR_HDR_SIZE);
3467 mvm_pause_voice_cmd.src_port =
3468 voice_get_idx_for_session(v->session_id);
3469 mvm_pause_voice_cmd.dest_port = voice_get_mvm_handle(v);
3470 mvm_pause_voice_cmd.token = 0;
3471 mvm_pause_voice_cmd.opcode = VSS_IMVM_CMD_PAUSE_VOICE;
3472 v->mvm_state = CMD_STATUS_FAIL;
3473 v->async_err = 0;
3474
3475 pr_debug("%s: send mvm_pause_voice_cmd pkt size = %d\n",
3476 __func__, mvm_pause_voice_cmd.pkt_size);
3477
3478 ret = apr_send_pkt(apr_mvm,
3479 (uint32_t *)&mvm_pause_voice_cmd);
3480 if (ret < 0) {
3481 pr_err("Fail in sending VSS_IMVM_CMD_PAUSE_VOICE\n");
3482
3483 ret = -EINVAL;
3484 goto done;
3485 }
3486
3487 ret = wait_event_timeout(v->mvm_wait,
3488 (v->mvm_state == CMD_STATUS_SUCCESS),
3489 msecs_to_jiffies(TIMEOUT_MS));
3490 if (!ret) {
3491 pr_err("%s: Command timeout\n", __func__);
3492
3493 ret = -EINVAL;
3494 goto done;
3495 }
3496 if (v->async_err > 0) {
3497 pr_err("%s: DSP returned error[%s]\n",
3498 __func__, adsp_err_get_err_str(
3499 v->async_err));
3500 ret = adsp_err_get_lnx_err_code(
3501 v->async_err);
3502 goto done;
3503 }
3504
3505done:
3506 return ret;
3507}
3508
3509static int voice_map_cal_memory(struct cal_block_data *cal_block,
3510 uint32_t session_id)
3511{
3512 int result = 0;
3513 int voc_index;
3514 struct voice_data *v = NULL;
3515
3516 pr_debug("%s\n", __func__);
3517
3518 if (cal_block == NULL) {
3519 pr_err("%s: Cal block is NULL!\n", __func__);
3520
3521 result = -EINVAL;
3522 goto done;
3523 }
3524
3525 if (cal_block->cal_data.paddr == 0) {
3526 pr_debug("%s: No address to map!\n", __func__);
3527
3528 result = -EINVAL;
3529 goto done;
3530 }
3531
3532 if (cal_block->map_data.map_size == 0) {
3533 pr_debug("%s: Map size is 0!\n", __func__);
3534
3535 result = -EINVAL;
3536 goto done;
3537 }
3538
3539 voc_index = voice_get_idx_for_session(session_id);
3540 if (voc_index < 0) {
3541 pr_err("%s: Invalid session ID %d\n", __func__, session_id);
3542
3543 goto done;
3544 }
3545
3546 mutex_lock(&common.common_lock);
3547 v = &common.voice[voc_index];
3548
3549 result = voice_map_memory_physical_cmd(v,
3550 &common.cal_mem_map_table,
3551 (dma_addr_t)cal_block->cal_data.paddr,
3552 cal_block->map_data.map_size,
3553 VOC_CAL_MEM_MAP_TOKEN);
3554 if (result < 0) {
3555 pr_err("%s: Mmap did not work! addr = 0x%pK, size = %zd\n",
3556 __func__,
3557 &cal_block->cal_data.paddr,
3558 cal_block->map_data.map_size);
3559
3560 goto done_unlock;
3561 }
3562
3563 cal_block->map_data.q6map_handle = common.cal_mem_handle;
3564done_unlock:
3565 mutex_unlock(&common.common_lock);
3566done:
3567 return result;
3568}
3569
3570static int remap_cal_data(struct cal_block_data *cal_block,
3571 uint32_t session_id)
3572{
3573 int ret = 0;
3574
3575 pr_debug("%s\n", __func__);
3576
3577 if (cal_block->map_data.ion_client == NULL) {
3578 pr_err("%s: No ION allocation for session_id %d!\n",
3579 __func__, session_id);
3580 ret = -EINVAL;
3581 goto done;
3582 }
3583
3584 if ((cal_block->map_data.map_size > 0) &&
3585 (cal_block->map_data.q6map_handle == 0)) {
3586
3587 /* cal type not used */
3588 ret = voice_map_cal_memory(cal_block, session_id);
3589 if (ret < 0) {
3590 pr_err("%s: Mmap did not work! size = %zd\n",
3591 __func__, cal_block->map_data.map_size);
3592
3593 goto done;
3594 }
3595 } else {
3596 pr_debug("%s: Cal block 0x%pK, size %zd already mapped. Q6 map handle = %d\n",
3597 __func__, &cal_block->cal_data.paddr,
3598 cal_block->map_data.map_size,
3599 cal_block->map_data.q6map_handle);
3600 }
3601done:
3602 return ret;
3603}
3604
3605static int voice_unmap_cal_memory(int32_t cal_type,
3606 struct cal_block_data *cal_block)
3607{
3608 int result = 0;
3609 int result2 = 0;
3610 int i;
3611 struct voice_data *v = NULL;
3612
3613 pr_debug("%s\n", __func__);
3614
3615 if (cal_block == NULL) {
3616 pr_err("%s: Cal block is NULL!\n", __func__);
3617
3618 result = -EINVAL;
3619 goto done;
3620 }
3621
3622 if (cal_block->map_data.q6map_handle == 0) {
3623 pr_debug("%s: Q6 handle is not set!\n", __func__);
3624
3625 result = -EINVAL;
3626 goto done;
3627 }
3628
3629 mutex_lock(&common.common_lock);
3630
3631 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
3632 v = &common.voice[i];
3633
3634 mutex_lock(&v->lock);
3635 if (is_voc_state_active(v->voc_state)) {
3636 result2 = voice_pause_voice_call(v);
3637 if (result2 < 0) {
3638 pr_err("%s: Voice_pause_voice_call failed for session 0x%x, err %d!\n",
3639 __func__, v->session_id, result2);
3640
3641 result = result2;
3642 }
3643
3644 if (cal_type == CVP_VOCPROC_DYNAMIC_CAL_TYPE)
3645 voice_send_cvp_deregister_vol_cal_cmd(v);
3646 else if (cal_type == CVP_VOCPROC_STATIC_CAL_TYPE)
3647 voice_send_cvp_deregister_cal_cmd(v);
3648 else if (cal_type == CVP_VOCDEV_CFG_CAL_TYPE)
3649 voice_send_cvp_deregister_dev_cfg_cmd(v);
3650 else if (cal_type == CVS_VOCSTRM_STATIC_CAL_TYPE)
3651 voice_send_cvs_deregister_cal_cmd(v);
3652 else
3653 pr_err("%s: Invalid cal type %d!\n",
3654 __func__, cal_type);
3655
3656 result2 = voice_send_start_voice_cmd(v);
3657 if (result2) {
3658 pr_err("%s: Voice_send_start_voice_cmd failed for session 0x%x, err %d!\n",
3659 __func__, v->session_id, result2);
3660
3661 result = result2;
3662 }
3663 }
3664
3665 if ((cal_block->map_data.q6map_handle != 0) &&
3666 (!is_other_session_active(v->session_id))) {
3667
3668 result2 = voice_send_mvm_unmap_memory_physical_cmd(
3669 v, cal_block->map_data.q6map_handle);
3670 if (result2) {
3671 pr_err("%s: Voice_send_mvm_unmap_memory_physical_cmd failed for session 0x%x, err %d!\n",
3672 __func__, v->session_id, result2);
3673
3674 result = result2;
3675 }
3676 cal_block->map_data.q6map_handle = 0;
3677 }
3678 mutex_unlock(&v->lock);
3679 }
3680 mutex_unlock(&common.common_lock);
3681done:
3682 return result;
3683}
3684
3685int voc_register_vocproc_vol_table(void)
3686{
3687 int result = 0;
3688 int result2 = 0;
3689 int i;
3690 struct voice_data *v = NULL;
3691
3692 pr_debug("%s\n", __func__);
3693
3694 mutex_lock(&common.common_lock);
3695 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
3696 v = &common.voice[i];
3697
3698 mutex_lock(&v->lock);
3699 if (is_voc_state_active(v->voc_state)) {
3700 result2 = voice_send_cvp_register_vol_cal_cmd(v);
3701 if (result2 < 0) {
3702 pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
3703 __func__, v->session_id);
3704
3705 result = result2;
3706 /* Still try to register other sessions */
3707 }
3708 }
3709 mutex_unlock(&v->lock);
3710 }
3711
3712 mutex_unlock(&common.common_lock);
3713 return result;
3714}
3715
3716int voc_deregister_vocproc_vol_table(void)
3717{
3718 int result = 0;
3719 int success = 0;
3720 int i;
3721 struct voice_data *v = NULL;
3722
3723 pr_debug("%s\n", __func__);
3724
3725 mutex_lock(&common.common_lock);
3726 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
3727 v = &common.voice[i];
3728
3729 mutex_lock(&v->lock);
3730 if (is_voc_state_active(v->voc_state)) {
3731 result = voice_send_cvp_deregister_vol_cal_cmd(v);
3732 if (result < 0) {
3733 pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
3734 __func__, v->session_id);
3735
3736 mutex_unlock(&v->lock);
3737 mutex_unlock(&common.common_lock);
3738 if (success) {
3739 pr_err("%s: Try to re-register all deregistered sessions!\n",
3740 __func__);
3741
3742 voc_register_vocproc_vol_table();
3743 }
3744 goto done;
3745 } else {
3746 success = 1;
3747 }
3748 }
3749 mutex_unlock(&v->lock);
3750 }
3751 mutex_unlock(&common.common_lock);
3752done:
3753 return result;
3754}
3755
3756int voc_map_rtac_block(struct rtac_cal_block_data *cal_block)
3757{
3758 int result = 0;
3759 struct voice_data *v = NULL;
3760
3761 pr_debug("%s\n", __func__);
3762
3763 if (cal_block == NULL) {
3764 pr_err("%s: cal_block is NULL!\n",
3765 __func__);
3766
3767 result = -EINVAL;
3768 goto done;
3769 }
3770
3771 if (cal_block->cal_data.paddr == 0) {
3772 pr_debug("%s: No address to map!\n",
3773 __func__);
3774
3775 result = -EINVAL;
3776 goto done;
3777 }
3778
3779 if (cal_block->map_data.map_size == 0) {
3780 pr_debug("%s: map size is 0!\n",
3781 __func__);
3782
3783 result = -EINVAL;
3784 goto done;
3785 }
3786
3787 mutex_lock(&common.common_lock);
3788 /* use first session */
3789 v = &common.voice[0];
3790 mutex_lock(&v->lock);
3791
3792 if (!is_rtac_memory_allocated()) {
3793 result = voice_alloc_rtac_mem_map_table();
3794 if (result < 0) {
3795 pr_err("%s: RTAC alloc mem map table did not work! addr = 0x%pK, size = %d\n",
3796 __func__,
3797 &cal_block->cal_data.paddr,
3798 cal_block->map_data.map_size);
3799
3800 goto done_unlock;
3801 }
3802 }
3803
3804 result = voice_map_memory_physical_cmd(v,
3805 &common.rtac_mem_map_table,
3806 (dma_addr_t)cal_block->cal_data.paddr,
3807 cal_block->map_data.map_size,
3808 VOC_RTAC_MEM_MAP_TOKEN);
3809 if (result < 0) {
3810 pr_err("%s: RTAC mmap did not work! addr = 0x%pK, size = %d\n",
3811 __func__,
3812 &cal_block->cal_data.paddr,
3813 cal_block->map_data.map_size);
3814
3815 free_rtac_map_table();
3816 goto done_unlock;
3817 }
3818
3819 cal_block->map_data.map_handle = common.rtac_mem_handle;
3820done_unlock:
3821 mutex_unlock(&v->lock);
3822 mutex_unlock(&common.common_lock);
3823done:
3824 return result;
3825}
3826
3827int voc_unmap_rtac_block(uint32_t *mem_map_handle)
3828{
3829 int result = 0;
3830 struct voice_data *v = NULL;
3831
3832 pr_debug("%s\n", __func__);
3833
3834 if (mem_map_handle == NULL) {
3835 pr_debug("%s: Map handle is NULL, nothing to unmap\n",
3836 __func__);
3837
3838 goto done;
3839 }
3840
3841 if (*mem_map_handle == 0) {
3842 pr_debug("%s: Map handle is 0, nothing to unmap\n",
3843 __func__);
3844
3845 goto done;
3846 }
3847
3848 mutex_lock(&common.common_lock);
3849 /* Use first session */
3850 /* Only used for apr wait lock */
3851 v = &common.voice[0];
3852 mutex_lock(&v->lock);
3853
3854 result = voice_send_mvm_unmap_memory_physical_cmd(
3855 v, *mem_map_handle);
3856 if (result) {
3857 pr_err("%s: voice_send_mvm_unmap_memory_physical_cmd Failed for session 0x%x!\n",
3858 __func__, v->session_id);
3859 } else {
3860 *mem_map_handle = 0;
3861 common.rtac_mem_handle = 0;
3862 free_rtac_map_table();
3863 }
3864 mutex_unlock(&v->lock);
3865 mutex_unlock(&common.common_lock);
3866done:
3867 return result;
3868}
3869
Laxminath Kasam38070be2017-08-17 18:21:59 +05303870static int voice_send_cvp_channel_info_v2(struct voice_data *v,
3871 uint32_t param_type)
3872{
3873 int ret;
3874 struct cvp_set_channel_info_cmd_v2 cvp_set_channel_info_cmd;
3875 void *apr_cvp;
3876 u16 cvp_handle;
3877 struct vss_icommon_param_data_channel_info_v2_t
3878 *channel_info_param_data =
3879 &cvp_set_channel_info_cmd.
3880 cvp_set_ch_info_param_v2.param_data;
3881 struct vss_param_vocproc_dev_channel_info_t *channel_info =
3882 &channel_info_param_data->channel_info;
3883
3884 if (v == NULL) {
3885 pr_err("%s: v is NULL\n", __func__);
3886 ret = -EINVAL;
3887 goto done;
3888 }
3889
3890 apr_cvp = common.apr_q6_cvp;
3891 if (!apr_cvp) {
3892 pr_err("%s: apr_cvp is NULL\n", __func__);
3893 ret = -EINVAL;
3894 goto done;
3895 }
3896
3897 cvp_handle = voice_get_cvp_handle(v);
3898 memset(&cvp_set_channel_info_cmd, 0, sizeof(cvp_set_channel_info_cmd));
3899
3900 cvp_set_channel_info_cmd.hdr.hdr_field =
3901 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
3902 APR_PKT_VER);
3903 cvp_set_channel_info_cmd.hdr.pkt_size =
3904 APR_PKT_SIZE(APR_HDR_SIZE,
3905 sizeof(cvp_set_channel_info_cmd) - APR_HDR_SIZE);
3906 cvp_set_channel_info_cmd.hdr.src_svc = 0;
3907 cvp_set_channel_info_cmd.hdr.src_domain = APR_DOMAIN_APPS;
3908 cvp_set_channel_info_cmd.hdr.src_port =
3909 voice_get_idx_for_session(v->session_id);
3910 cvp_set_channel_info_cmd.hdr.dest_svc = 0;
3911 cvp_set_channel_info_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
3912 cvp_set_channel_info_cmd.hdr.dest_port = cvp_handle;
3913 cvp_set_channel_info_cmd.hdr.token = 0;
3914 cvp_set_channel_info_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
3915
3916 cvp_set_channel_info_cmd.cvp_set_ch_info_param_v2.mem_size =
3917 sizeof(struct vss_icommon_param_data_channel_info_v2_t);
3918
3919 channel_info_param_data->module_id = VSS_MODULE_CVD_GENERIC;
3920 channel_info_param_data->param_size =
3921 sizeof(struct vss_param_vocproc_dev_channel_info_t);
3922
3923 /* Device specific data */
3924 switch (param_type) {
3925 case RX_PATH:
3926 channel_info_param_data->param_id =
3927 VSS_PARAM_VOCPROC_RX_CHANNEL_INFO;
3928 channel_info->num_channels = v->dev_rx.no_of_channels;
3929 channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
Aditya Bavanari88513a32017-10-12 12:29:25 +05303930 memcpy(&channel_info->channel_mapping,
3931 v->dev_rx.channel_mapping,
3932 VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
Laxminath Kasam38070be2017-08-17 18:21:59 +05303933 break;
3934
3935 case TX_PATH:
3936 channel_info_param_data->param_id =
3937 VSS_PARAM_VOCPROC_TX_CHANNEL_INFO;
3938 channel_info->num_channels = v->dev_tx.no_of_channels;
3939 channel_info->bits_per_sample = v->dev_tx.bits_per_sample;
Aditya Bavanari88513a32017-10-12 12:29:25 +05303940 memcpy(&channel_info->channel_mapping,
3941 v->dev_tx.channel_mapping,
3942 VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
Laxminath Kasam38070be2017-08-17 18:21:59 +05303943 break;
3944
3945 case EC_REF_PATH:
3946 channel_info_param_data->param_id =
3947 VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO;
3948 channel_info->num_channels = v->dev_rx.no_of_channels;
3949 channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
Aditya Bavanari88513a32017-10-12 12:29:25 +05303950 memcpy(&channel_info->channel_mapping,
3951 v->dev_rx.channel_mapping,
3952 VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
Laxminath Kasam38070be2017-08-17 18:21:59 +05303953 break;
3954 default:
3955 pr_err("%s: Invalid param type\n",
3956 __func__);
3957 ret = -EINVAL;
3958 goto done;
3959 }
3960
Laxminath Kasam38070be2017-08-17 18:21:59 +05303961
3962 v->cvp_state = CMD_STATUS_FAIL;
3963 v->async_err = 0;
3964 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_channel_info_cmd);
3965 if (ret < 0) {
3966 pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2\n",
3967 __func__);
3968 goto done;
3969 }
3970
3971 ret = wait_event_timeout(v->cvp_wait,
3972 (v->cvp_state == CMD_STATUS_SUCCESS),
3973 msecs_to_jiffies(TIMEOUT_MS));
3974 if (!ret) {
3975 pr_err("%s: wait_event timeout\n", __func__);
3976 ret = -ETIMEDOUT;
3977 goto done;
3978 }
3979
3980 if (v->async_err > 0) {
3981 pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
3982 adsp_err_get_err_str(v->async_err), cvp_handle);
3983 ret = adsp_err_get_lnx_err_code(v->async_err);
3984 goto done;
3985 }
3986 ret = 0;
3987done:
3988 return ret;
3989}
3990
3991static int voice_send_cvp_channel_info_cmd(struct voice_data *v)
3992{
3993 int ret = 0;
3994
3995 ret = voice_send_cvp_channel_info_v2(v, RX_PATH);
3996 if (ret < 0) {
3997 pr_err("%s: Error in sending cvp_channel_info RX: %d\n",
3998 __func__, ret);
3999 goto done;
4000 }
4001
4002 ret = voice_send_cvp_channel_info_v2(v, TX_PATH);
4003 if (ret < 0) {
4004 pr_err("%s: Error in sending cvp_channel_info TX: %d\n",
4005 __func__, ret);
4006 goto done;
4007 }
4008
4009 ret = voice_send_cvp_channel_info_v2(v, EC_REF_PATH);
4010 if (ret < 0) {
4011 pr_err("%s: Error in sending cvp_channel_info EC Ref: %d\n",
4012 __func__, ret);
4013 goto done;
4014 }
4015done:
4016 return ret;
4017}
4018
Aditya Bavanari245361d2017-09-07 12:11:30 +05304019static int voice_send_cvp_ch_mixer_info_v2(struct voice_data *v)
4020{
4021 int ret;
4022 struct cvp_set_channel_mixer_info_cmd_v2 cvp_set_ch_mixer_info_cmd;
4023 void *apr_cvp;
4024 u16 cvp_handle;
4025 struct vss_icommon_param_data_ch_mixer_v2_t *cvp_config_param_data =
4026 &cvp_set_ch_mixer_info_cmd.
4027 cvp_set_ch_mixer_param_v2.param_data;
4028 struct vss_param_channel_mixer_info_t *ch_mixer_info =
4029 &cvp_config_param_data->ch_mixer_info;
4030
4031 if (v == NULL) {
4032 pr_err("%s: v is NULL\n", __func__);
4033 ret = -EINVAL;
4034 goto done;
4035 }
4036
4037 apr_cvp = common.apr_q6_cvp;
4038 if (!apr_cvp) {
4039 pr_err("%s: apr_cvp is NULL\n", __func__);
4040 ret = -EINVAL;
4041 goto done;
4042 }
4043
4044 cvp_handle = voice_get_cvp_handle(v);
4045 memset(&cvp_set_ch_mixer_info_cmd, 0,
4046 sizeof(cvp_set_ch_mixer_info_cmd));
4047
4048 cvp_set_ch_mixer_info_cmd.hdr.hdr_field =
4049 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4050 APR_HDR_LEN(APR_HDR_SIZE),
4051 APR_PKT_VER);
4052 cvp_set_ch_mixer_info_cmd.hdr.pkt_size =
4053 APR_PKT_SIZE(APR_HDR_SIZE,
4054 sizeof(cvp_set_ch_mixer_info_cmd) - APR_HDR_SIZE);
4055 cvp_set_ch_mixer_info_cmd.hdr.src_svc = 0;
4056 cvp_set_ch_mixer_info_cmd.hdr.src_domain = APR_DOMAIN_APPS;
4057 cvp_set_ch_mixer_info_cmd.hdr.src_port =
4058 voice_get_idx_for_session(v->session_id);
4059 cvp_set_ch_mixer_info_cmd.hdr.dest_svc = 0;
4060 cvp_set_ch_mixer_info_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
4061 cvp_set_ch_mixer_info_cmd.hdr.dest_port = cvp_handle;
4062 cvp_set_ch_mixer_info_cmd.hdr.token = VOC_GENERIC_SET_PARAM_TOKEN;
4063 cvp_set_ch_mixer_info_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
4064 cvp_set_ch_mixer_info_cmd.cvp_set_ch_mixer_param_v2.mem_size =
4065 sizeof(struct vss_icommon_param_data_ch_mixer_v2_t);
4066
4067 cvp_config_param_data->module_id = AUDPROC_MODULE_ID_MFC;
4068 cvp_config_param_data->param_id =
4069 AUDPROC_CHMIXER_PARAM_ID_COEFF;
4070 cvp_config_param_data->param_size =
4071 sizeof(struct vss_param_channel_mixer_info_t);
4072
4073 ch_mixer_info->index = 0;
4074 ch_mixer_info->num_output_channels = v->dev_rx.no_of_channels;
4075 /*
4076 * Configure Rx input to be mono for channel mixer as the DSP
4077 * configures vocproc input as mono.
4078 */
4079 ch_mixer_info->num_input_channels = NUM_CHANNELS_MONO;
4080 ch_mixer_info->out_channel_map[0] = PCM_CHANNEL_L;
4081 ch_mixer_info->out_channel_map[1] = PCM_CHANNEL_R;
4082 ch_mixer_info->in_channel_map[0] = PCM_CHANNEL_L;
4083 ch_mixer_info->channel_weight_coeff[0][0] = GAIN_Q14_FORMAT(1);
4084 ch_mixer_info->channel_weight_coeff[1][0] = GAIN_Q14_FORMAT(1);
4085 ch_mixer_info->reserved = 0;
4086
4087 v->cvp_state = CMD_STATUS_FAIL;
4088 v->async_err = 0;
4089 ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_ch_mixer_info_cmd);
4090 if (ret < 0) {
4091 pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
4092 __func__, ret);
4093 goto done;
4094 }
4095 ret = wait_event_timeout(v->cvp_wait,
4096 (v->cvp_state == CMD_STATUS_SUCCESS),
4097 msecs_to_jiffies(TIMEOUT_MS));
4098
4099 if (!ret) {
4100 pr_err("%s: wait_event timeout\n", __func__);
4101 ret = -ETIMEDOUT;
4102 goto done;
4103 }
4104
4105 if (v->async_err > 0) {
4106 pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
4107 adsp_err_get_err_str(v->async_err), cvp_handle);
4108 ret = adsp_err_get_lnx_err_code(v->async_err);
4109 goto done;
4110 }
4111 ret = 0;
4112done:
4113 return ret;
4114}
4115
Laxminath Kasam38070be2017-08-17 18:21:59 +05304116static int voice_send_cvp_mfc_config_v2(struct voice_data *v)
4117{
4118 int ret;
4119 struct cvp_set_mfc_config_cmd_v2 cvp_set_mfc_config_cmd;
4120 void *apr_cvp;
4121 u16 cvp_handle;
4122 struct vss_icommon_param_data_mfc_config_v2_t *cvp_config_param_data =
4123 &cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.param_data;
4124 struct vss_param_mfc_config_info_t *mfc_config_info =
4125 &cvp_config_param_data->mfc_config_info;
4126
4127 if (v == NULL) {
4128 pr_err("%s: v is NULL\n", __func__);
4129 ret = -EINVAL;
4130 goto done;
4131 }
4132
4133 apr_cvp = common.apr_q6_cvp;
4134 if (!apr_cvp) {
4135 pr_err("%s: apr_cvp is NULL\n", __func__);
4136 ret = -EINVAL;
4137 goto done;
4138 }
4139
4140 cvp_handle = voice_get_cvp_handle(v);
4141 memset(&cvp_set_mfc_config_cmd, 0, sizeof(cvp_set_mfc_config_cmd));
4142
4143 cvp_set_mfc_config_cmd.hdr.hdr_field =
4144 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
4145 APR_PKT_VER);
4146 cvp_set_mfc_config_cmd.hdr.pkt_size =
4147 APR_PKT_SIZE(APR_HDR_SIZE,
4148 sizeof(cvp_set_mfc_config_cmd) - APR_HDR_SIZE);
4149 cvp_set_mfc_config_cmd.hdr.src_svc = 0;
4150 cvp_set_mfc_config_cmd.hdr.src_domain = APR_DOMAIN_APPS;
4151 cvp_set_mfc_config_cmd.hdr.src_port =
4152 voice_get_idx_for_session(v->session_id);
4153 cvp_set_mfc_config_cmd.hdr.dest_svc = 0;
4154 cvp_set_mfc_config_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
4155 cvp_set_mfc_config_cmd.hdr.dest_port = cvp_handle;
4156 cvp_set_mfc_config_cmd.hdr.token = 0;
4157 cvp_set_mfc_config_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
4158 cvp_set_mfc_config_cmd.cvp_set_mfc_param_v2.mem_size =
4159 sizeof(struct vss_icommon_param_data_mfc_config_v2_t);
4160
4161 cvp_config_param_data->module_id = AUDPROC_MODULE_ID_MFC;
4162 cvp_config_param_data->param_id =
4163 AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT;
4164 cvp_config_param_data->param_size =
4165 sizeof(struct vss_param_mfc_config_info_t);
4166
4167 mfc_config_info->num_channels = v->dev_rx.no_of_channels;
4168 mfc_config_info->bits_per_sample = 16;
4169 mfc_config_info->sample_rate = v->dev_rx.sample_rate;
Aditya Bavanari88513a32017-10-12 12:29:25 +05304170 memcpy(&mfc_config_info->channel_type,
4171 v->dev_rx.channel_mapping,
4172 VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
Laxminath Kasam38070be2017-08-17 18:21:59 +05304173
4174 v->cvp_state = CMD_STATUS_FAIL;
4175 v->async_err = 0;
4176 ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_mfc_config_cmd);
4177 if (ret < 0) {
4178 pr_err("%s: Failed to send VSS_ICOMMON_CMD_SET_PARAM_V2 %d\n",
4179 __func__, ret);
4180 goto done;
4181 }
4182 ret = wait_event_timeout(v->cvp_wait,
4183 (v->cvp_state == CMD_STATUS_SUCCESS),
4184 msecs_to_jiffies(TIMEOUT_MS));
4185
4186 if (!ret) {
4187 pr_err("%s: wait_event timeout\n", __func__);
4188 ret = -ETIMEDOUT;
4189 goto done;
4190 }
4191
4192 if (v->async_err > 0) {
4193 pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
4194 adsp_err_get_err_str(v->async_err), cvp_handle);
4195 ret = adsp_err_get_lnx_err_code(v->async_err);
4196 goto done;
4197 }
4198 ret = 0;
4199done:
4200 return ret;
4201}
4202
4203static int voice_send_cvp_mfc_config_cmd(struct voice_data *v)
4204{
4205 int ret = 0;
4206
4207 if (common.cvp_version >= CVP_VERSION_2) {
Aditya Bavanari245361d2017-09-07 12:11:30 +05304208 ret = voice_send_cvp_ch_mixer_info_v2(v);
4209 if (ret < 0)
4210 pr_warn("%s: Set channel mixer config failed err:%d",
4211 __func__, ret);
4212
Laxminath Kasam38070be2017-08-17 18:21:59 +05304213 ret = voice_send_cvp_mfc_config_v2(v);
Aditya Bavanari245361d2017-09-07 12:11:30 +05304214 if (ret < 0)
4215 pr_warn("%s: Set MFC config failed err:%d",
4216 __func__, ret);
Laxminath Kasam38070be2017-08-17 18:21:59 +05304217 } else {
4218 pr_warn("%s: CVP Version not supported\n", __func__);
4219 ret = -EINVAL;
4220 }
4221
4222 return ret;
4223}
4224
4225static int voice_get_avcs_version_per_service(uint32_t service_id)
4226{
4227 int ret = 0;
Siena Richard2d0102d2017-09-05 11:15:45 -07004228 size_t ver_size;
4229 struct avcs_fwk_ver_info *ver_info = NULL;
Laxminath Kasam38070be2017-08-17 18:21:59 +05304230
4231 if (service_id == AVCS_SERVICE_ID_ALL) {
4232 pr_err("%s: Invalid service id: %d", __func__,
4233 AVCS_SERVICE_ID_ALL);
4234 return -EINVAL;
4235 }
4236
Siena Richard2d0102d2017-09-05 11:15:45 -07004237 ver_size = sizeof(struct avcs_get_fwk_version) +
4238 sizeof(struct avs_svc_api_info);
4239 ver_info = kzalloc(ver_size, GFP_KERNEL);
4240 if (ver_info == NULL)
Laxminath Kasam38070be2017-08-17 18:21:59 +05304241 return -ENOMEM;
4242
Siena Richard2d0102d2017-09-05 11:15:45 -07004243 ret = q6core_get_service_version(service_id, ver_info, ver_size);
Laxminath Kasam38070be2017-08-17 18:21:59 +05304244 if (ret < 0)
4245 goto done;
4246
Siena Richard2d0102d2017-09-05 11:15:45 -07004247 ret = ver_info->services[0].api_version;
Laxminath Kasam38070be2017-08-17 18:21:59 +05304248 common.is_avcs_version_queried = true;
4249done:
Siena Richard2d0102d2017-09-05 11:15:45 -07004250 kfree(ver_info);
Laxminath Kasam38070be2017-08-17 18:21:59 +05304251 return ret;
4252}
4253
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304254static int voice_setup_vocproc(struct voice_data *v)
4255{
4256 int ret = 0;
4257
4258 ret = voice_send_cvp_create_cmd(v);
4259 if (ret < 0) {
4260 pr_err("%s: CVP create failed err:%d\n", __func__, ret);
4261 goto fail;
4262 }
4263
Laxminath Kasam38070be2017-08-17 18:21:59 +05304264 if (common.is_avcs_version_queried == false)
4265 common.cvp_version = voice_get_avcs_version_per_service(
4266 APRV2_IDS_SERVICE_ID_ADSP_CVP_V);
4267
4268 if (common.cvp_version < 0) {
4269 pr_err("%s: Invalid CVP version %d\n",
4270 __func__, common.cvp_version);
4271 ret = -EINVAL;
4272 goto fail;
4273 }
4274 pr_debug("%s: CVP Version %d\n", __func__, common.cvp_version);
4275
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304276 ret = voice_send_cvp_media_fmt_info_cmd(v);
4277 if (ret < 0) {
4278 pr_err("%s: Set media format info failed err:%d\n", __func__,
4279 ret);
4280 goto fail;
4281 }
4282
4283 ret = voice_send_cvp_topology_commit_cmd(v);
4284 if (ret < 0) {
4285 pr_err("%s: Set topology commit failed err:%d\n",
4286 __func__, ret);
4287 goto fail;
4288 }
4289
Laxminath Kasam38070be2017-08-17 18:21:59 +05304290 /* Send MFC config only when the no of channels are more than 1 */
4291 if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
4292 ret = voice_send_cvp_mfc_config_cmd(v);
4293 if (ret < 0) {
4294 pr_warn("%s: Set mfc config failed err:%d\n",
4295 __func__, ret);
4296 }
4297 }
4298
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304299 voice_send_cvs_register_cal_cmd(v);
4300 voice_send_cvp_register_dev_cfg_cmd(v);
4301 voice_send_cvp_register_cal_cmd(v);
4302 voice_send_cvp_register_vol_cal_cmd(v);
4303
4304 /* enable vocproc */
4305 ret = voice_send_enable_vocproc_cmd(v);
4306 if (ret < 0)
4307 goto fail;
4308
4309 /* attach vocproc */
4310 ret = voice_send_attach_vocproc_cmd(v);
4311 if (ret < 0)
4312 goto fail;
4313
4314 /* send tty mode if tty device is used */
4315 voice_send_tty_mode_cmd(v);
4316
4317 if (is_voip_session(v->session_id)) {
4318 ret = voice_send_mvm_cal_network_cmd(v);
4319 if (ret < 0)
4320 pr_err("%s: voice_send_mvm_cal_network_cmd: %d\n",
4321 __func__, ret);
4322
4323 ret = voice_send_mvm_media_type_cmd(v);
4324 if (ret < 0)
4325 pr_err("%s: voice_send_mvm_media_type_cmd: %d\n",
4326 __func__, ret);
4327
4328 voice_send_netid_timing_cmd(v);
4329 }
4330
4331 if (v->st_enable && !v->tty_mode)
4332 voice_send_set_pp_enable_cmd(v,
4333 MODULE_ID_VOICE_MODULE_ST,
4334 v->st_enable);
4335 /* Start in-call music delivery if this feature is enabled */
4336 if (v->music_info.play_enable)
4337 voice_cvs_start_playback(v);
4338
4339 /* Start in-call recording if this feature is enabled */
4340 if (v->rec_info.rec_enable)
4341 voice_cvs_start_record(v, v->rec_info.rec_mode);
4342
4343 if (v->dtmf_rx_detect_en)
4344 voice_send_dtmf_rx_detection_cmd(v, v->dtmf_rx_detect_en);
4345
4346 if (v->hd_enable)
4347 voice_send_hd_cmd(v, v->hd_enable);
4348
4349 rtac_add_voice(voice_get_cvs_handle(v),
4350 voice_get_cvp_handle(v),
4351 v->dev_rx.port_id, v->dev_tx.port_id,
4352 v->dev_rx.dev_id, v->dev_tx.dev_id,
4353 v->session_id);
4354
4355 return 0;
4356
4357fail:
4358 return ret;
4359}
4360
4361static int voice_send_cvp_device_channels_cmd(struct voice_data *v)
4362{
4363 int ret = 0;
4364 struct cvp_set_dev_channels_cmd cvp_set_dev_channels_cmd;
4365 void *apr_cvp;
4366 u16 cvp_handle;
4367
4368 if (!(voice_get_cvd_int_version(common.cvd_version) >=
4369 CVD_INT_VERSION_2_2)) {
4370 pr_debug("%s CVD ver %s doesn't support send_device_channels cmd\n",
4371 __func__, common.cvd_version);
4372
4373 goto done;
4374 }
4375
4376 if (v == NULL) {
4377 pr_err("%s: v is NULL\n", __func__);
4378
4379 ret = -EINVAL;
4380 goto done;
4381 }
4382
4383 apr_cvp = common.apr_q6_cvp;
4384 if (!apr_cvp) {
4385 pr_err("%s: apr_cvp is NULL.\n", __func__);
4386
4387 ret = -EINVAL;
4388 goto done;
4389 }
4390
4391 cvp_handle = voice_get_cvp_handle(v);
4392 cvp_set_dev_channels_cmd.hdr.hdr_field =
4393 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4394 APR_HDR_LEN(APR_HDR_SIZE),
4395 APR_PKT_VER);
4396 cvp_set_dev_channels_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4397 sizeof(cvp_set_dev_channels_cmd) - APR_HDR_SIZE);
4398 cvp_set_dev_channels_cmd.hdr.src_port =
4399 voice_get_idx_for_session(v->session_id);
4400 cvp_set_dev_channels_cmd.hdr.dest_port = cvp_handle;
4401 cvp_set_dev_channels_cmd.hdr.token = 0;
4402 cvp_set_dev_channels_cmd.hdr.opcode =
4403 VSS_IVOCPROC_CMD_TOPOLOGY_SET_DEV_CHANNELS;
4404 cvp_set_dev_channels_cmd.cvp_set_channels.rx_num_channels =
4405 VSS_NUM_DEV_CHANNELS_1;
4406 cvp_set_dev_channels_cmd.cvp_set_channels.tx_num_channels =
4407 v->dev_tx.no_of_channels;
4408
4409 v->cvp_state = CMD_STATUS_FAIL;
4410 v->async_err = 0;
4411 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_dev_channels_cmd);
4412 if (ret < 0) {
4413 pr_err("%s: Fail in sending VSS_IVOCPROC_CMD_TOPOLOGY_SET_DEV_CHANNELS\n",
4414 __func__);
4415
4416 ret = -EINVAL;
4417 goto done;
4418 }
4419
4420 ret = wait_event_timeout(v->cvp_wait,
4421 (v->cvp_state == CMD_STATUS_SUCCESS),
4422 msecs_to_jiffies(TIMEOUT_MS));
4423 if (!ret) {
4424 pr_err("%s: wait_event timeout\n", __func__);
4425
4426 ret = -EINVAL;
4427 goto done;
4428 }
4429 if (v->async_err > 0) {
4430 pr_err("%s: DSP returned error[%s]\n",
4431 __func__, adsp_err_get_err_str(
4432 v->async_err));
4433 ret = adsp_err_get_lnx_err_code(
4434 v->async_err);
4435 goto done;
4436 }
4437
4438done:
4439 return ret;
4440}
4441
4442static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v)
4443{
Laxminath Kasam38070be2017-08-17 18:21:59 +05304444 int ret = 0;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304445
Laxminath Kasam38070be2017-08-17 18:21:59 +05304446 if (common.cvp_version < CVP_VERSION_2)
4447 ret = voice_send_cvp_device_channels_cmd(v);
4448 else
4449 ret = voice_send_cvp_channel_info_cmd(v);
4450
4451 if (ret < 0) {
4452 pr_err("%s: Set channel info failed err: %d\n", __func__,
4453 ret);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304454 goto done;
Laxminath Kasam38070be2017-08-17 18:21:59 +05304455 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304456
4457 if (voice_get_cvd_int_version(common.cvd_version) >=
4458 CVD_INT_VERSION_2_3) {
4459 ret = voice_send_cvp_media_format_cmd(v, RX_PATH);
4460 if (ret < 0)
4461 goto done;
4462
4463 ret = voice_send_cvp_media_format_cmd(v, TX_PATH);
4464 if (ret < 0)
4465 goto done;
4466
4467 if (common.ec_ref_ext)
4468 ret = voice_send_cvp_media_format_cmd(v, EC_REF_PATH);
4469 }
4470
4471done:
4472 return ret;
4473}
4474
4475static int voice_send_cvp_media_format_cmd(struct voice_data *v,
4476 uint32_t param_type)
4477{
4478 int ret = 0;
4479 struct cvp_set_media_format_cmd cvp_set_media_format_cmd;
4480 void *apr_cvp;
4481 u16 cvp_handle;
4482 struct vss_icommon_param_data_t *media_fmt_param_data =
Laxminath Kasam38070be2017-08-17 18:21:59 +05304483 &cvp_set_media_format_cmd.cvp_set_media_param_v2.param_data;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304484 struct vss_param_endpoint_media_format_info_t *media_fmt_info =
4485 &media_fmt_param_data->media_format_info;
4486
4487 if (v == NULL) {
4488 pr_err("%s: v is NULL\n", __func__);
4489 ret = -EINVAL;
4490 goto done;
4491 }
4492
4493 apr_cvp = common.apr_q6_cvp;
4494 if (!apr_cvp) {
4495 pr_err("%s: apr_cvp is NULL.\n", __func__);
4496 ret = -EINVAL;
4497 goto done;
4498 }
4499
4500 cvp_handle = voice_get_cvp_handle(v);
4501 memset(&cvp_set_media_format_cmd, 0, sizeof(cvp_set_media_format_cmd));
4502
4503 /* Fill header data */
4504 cvp_set_media_format_cmd.hdr.hdr_field =
4505 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE),
4506 APR_PKT_VER);
4507 cvp_set_media_format_cmd.hdr.pkt_size =
4508 APR_PKT_SIZE(APR_HDR_SIZE,
4509 sizeof(cvp_set_media_format_cmd) - APR_HDR_SIZE);
4510 cvp_set_media_format_cmd.hdr.src_svc = 0;
4511 cvp_set_media_format_cmd.hdr.src_domain = APR_DOMAIN_APPS;
4512 cvp_set_media_format_cmd.hdr.src_port =
4513 voice_get_idx_for_session(v->session_id);
4514 cvp_set_media_format_cmd.hdr.dest_svc = 0;
4515 cvp_set_media_format_cmd.hdr.dest_domain = APR_DOMAIN_ADSP;
4516 cvp_set_media_format_cmd.hdr.dest_port = cvp_handle;
4517 cvp_set_media_format_cmd.hdr.token = VOC_SET_MEDIA_FORMAT_PARAM_TOKEN;
4518 cvp_set_media_format_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2;
4519
4520 /* Fill param data */
Laxminath Kasam38070be2017-08-17 18:21:59 +05304521 cvp_set_media_format_cmd.cvp_set_media_param_v2.mem_size =
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05304522 sizeof(struct vss_icommon_param_data_t);
4523 media_fmt_param_data->module_id = VSS_MODULE_CVD_GENERIC;
4524 media_fmt_param_data->param_size =
4525 sizeof(struct vss_param_endpoint_media_format_info_t);
4526
4527 /* Fill device specific data */
4528 switch (param_type) {
4529 case RX_PATH:
4530 media_fmt_param_data->param_id =
4531 VSS_PARAM_RX_PORT_ENDPOINT_MEDIA_INFO;
4532 media_fmt_info->port_id = v->dev_rx.port_id;
4533 media_fmt_info->num_channels = v->dev_rx.no_of_channels;
4534 media_fmt_info->bits_per_sample = v->dev_rx.bits_per_sample;
4535 media_fmt_info->sample_rate = v->dev_rx.sample_rate;
4536 memcpy(&media_fmt_info->channel_mapping,
4537 &v->dev_rx.channel_mapping, VSS_CHANNEL_MAPPING_SIZE);
4538 break;
4539
4540 case TX_PATH:
4541 media_fmt_param_data->param_id =
4542 VSS_PARAM_TX_PORT_ENDPOINT_MEDIA_INFO;
4543 media_fmt_info->port_id = v->dev_tx.port_id;
4544 media_fmt_info->num_channels = v->dev_tx.no_of_channels;
4545 media_fmt_info->bits_per_sample = v->dev_tx.bits_per_sample;
4546 media_fmt_info->sample_rate = v->dev_tx.sample_rate;
4547 memcpy(&media_fmt_info->channel_mapping,
4548 &v->dev_tx.channel_mapping, VSS_CHANNEL_MAPPING_SIZE);
4549 break;
4550
4551 case EC_REF_PATH:
4552 media_fmt_param_data->param_id =
4553 VSS_PARAM_EC_REF_PORT_ENDPOINT_MEDIA_INFO;
4554 media_fmt_info->port_id = common.ec_media_fmt_info.port_id;
4555 media_fmt_info->num_channels =
4556 common.ec_media_fmt_info.num_channels;
4557 media_fmt_info->bits_per_sample =
4558 common.ec_media_fmt_info.bits_per_sample;
4559 media_fmt_info->sample_rate =
4560 common.ec_media_fmt_info.sample_rate;
4561 memcpy(&media_fmt_info->channel_mapping,
4562 &common.ec_media_fmt_info.channel_mapping,
4563 VSS_CHANNEL_MAPPING_SIZE);
4564 break;
4565
4566 default:
4567 pr_err("%s: Invalid param type %d\n", __func__, param_type);
4568 ret = -EINVAL;
4569 goto done;
4570 }
4571
4572 /* Send command */
4573 v->cvp_state = CMD_STATUS_FAIL;
4574 v->async_err = 0;
4575 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_media_format_cmd);
4576 if (ret < 0) {
4577 pr_err("%s: Fail in sending VSS_ICOMMON_CMD_SET_PARAM_V2\n",
4578 __func__);
4579 ret = -EINVAL;
4580 goto done;
4581 }
4582
4583 ret = wait_event_timeout(v->cvp_wait,
4584 (v->cvp_state == CMD_STATUS_SUCCESS),
4585 msecs_to_jiffies(TIMEOUT_MS));
4586 if (!ret) {
4587 pr_err("%s: wait_event timeout\n", __func__);
4588 ret = -EINVAL;
4589 goto done;
4590 }
4591
4592 if (v->async_err > 0) {
4593 pr_err("%s: DSP returned error[%s] handle = %d\n", __func__,
4594 adsp_err_get_err_str(v->async_err), cvp_handle);
4595 ret = adsp_err_get_lnx_err_code(v->async_err);
4596 goto done;
4597 }
4598
4599done:
4600 return ret;
4601}
4602
4603static int voice_send_cvp_topology_commit_cmd(struct voice_data *v)
4604{
4605 int ret = 0;
4606 struct apr_hdr cvp_topology_commit_cmd;
4607 void *apr_cvp;
4608 u16 cvp_handle;
4609
4610 if (!(voice_get_cvd_int_version(common.cvd_version) >=
4611 CVD_INT_VERSION_2_2)) {
4612 pr_debug("%s CVD version string %s doesn't support this command\n",
4613 __func__, common.cvd_version);
4614
4615 goto done;
4616 }
4617
4618 if (v == NULL) {
4619 pr_err("%s: v is NULL\n", __func__);
4620
4621 ret = -EINVAL;
4622 goto done;
4623 }
4624
4625 apr_cvp = common.apr_q6_cvp;
4626 if (!apr_cvp) {
4627 pr_err("%s: apr_cvp is NULL.\n", __func__);
4628
4629 ret = -EINVAL;
4630 goto done;
4631 }
4632
4633 cvp_handle = voice_get_cvp_handle(v);
4634 cvp_topology_commit_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4635 APR_HDR_LEN(APR_HDR_SIZE),
4636 APR_PKT_VER);
4637 cvp_topology_commit_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4638 sizeof(cvp_topology_commit_cmd) - APR_HDR_SIZE);
4639 cvp_topology_commit_cmd.src_port =
4640 voice_get_idx_for_session(v->session_id);
4641 cvp_topology_commit_cmd.dest_port = cvp_handle;
4642 cvp_topology_commit_cmd.token = 0;
4643 cvp_topology_commit_cmd.opcode = VSS_IVOCPROC_CMD_TOPOLOGY_COMMIT;
4644
4645 v->cvp_state = CMD_STATUS_FAIL;
4646 v->async_err = 0;
4647 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_topology_commit_cmd);
4648 if (ret < 0) {
4649 pr_err("%s: Fail in sending VSS_IVOCPROC_CMD_TOPOLOGY_COMMIT\n",
4650 __func__);
4651
4652 ret = -EINVAL;
4653 goto done;
4654 }
4655
4656 ret = wait_event_timeout(v->cvp_wait,
4657 (v->cvp_state == CMD_STATUS_SUCCESS),
4658 msecs_to_jiffies(TIMEOUT_MS));
4659 if (!ret) {
4660 pr_err("%s: wait_event timeout\n", __func__);
4661 ret = -EINVAL;
4662 goto done;
4663 }
4664 if (v->async_err > 0) {
4665 pr_err("%s: DSP returned error[%s]\n",
4666 __func__, adsp_err_get_err_str(
4667 v->async_err));
4668 ret = adsp_err_get_lnx_err_code(
4669 v->async_err);
4670 goto done;
4671 }
4672
4673done:
4674 return ret;
4675}
4676
4677static int voice_send_enable_vocproc_cmd(struct voice_data *v)
4678{
4679 int ret = 0;
4680 struct apr_hdr cvp_enable_cmd;
4681 void *apr_cvp;
4682 u16 cvp_handle;
4683
4684 if (v == NULL) {
4685 pr_err("%s: v is NULL\n", __func__);
4686 return -EINVAL;
4687 }
4688 apr_cvp = common.apr_q6_cvp;
4689
4690 if (!apr_cvp) {
4691 pr_err("%s: apr_cvp is NULL.\n", __func__);
4692 return -EINVAL;
4693 }
4694 cvp_handle = voice_get_cvp_handle(v);
4695
4696 /* enable vocproc and wait for respose */
4697 cvp_enable_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4698 APR_HDR_LEN(APR_HDR_SIZE),
4699 APR_PKT_VER);
4700 cvp_enable_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4701 sizeof(cvp_enable_cmd) - APR_HDR_SIZE);
4702 pr_debug("cvp_enable_cmd pkt size = %d, cvp_handle=%d\n",
4703 cvp_enable_cmd.pkt_size, cvp_handle);
4704 cvp_enable_cmd.src_port =
4705 voice_get_idx_for_session(v->session_id);
4706 cvp_enable_cmd.dest_port = cvp_handle;
4707 cvp_enable_cmd.token = 0;
4708 cvp_enable_cmd.opcode = VSS_IVOCPROC_CMD_ENABLE;
4709
4710 v->cvp_state = CMD_STATUS_FAIL;
4711 v->async_err = 0;
4712 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_enable_cmd);
4713 if (ret < 0) {
4714 pr_err("Fail in sending VSS_IVOCPROC_CMD_ENABLE\n");
4715 goto fail;
4716 }
4717 ret = wait_event_timeout(v->cvp_wait,
4718 (v->cvp_state == CMD_STATUS_SUCCESS),
4719 msecs_to_jiffies(TIMEOUT_MS));
4720 if (!ret) {
4721 pr_err("%s: wait_event timeout\n", __func__);
4722 goto fail;
4723 }
4724 if (v->async_err > 0) {
4725 pr_err("%s: DSP returned error[%s]\n",
4726 __func__, adsp_err_get_err_str(
4727 v->async_err));
4728 ret = adsp_err_get_lnx_err_code(
4729 v->async_err);
4730 goto fail;
4731 }
4732
4733 return 0;
4734fail:
4735 return ret;
4736}
4737
4738static int voice_send_mvm_cal_network_cmd(struct voice_data *v)
4739{
4740 struct vss_imvm_cmd_set_cal_network_t mvm_set_cal_network;
4741 int ret = 0;
4742 void *apr_mvm;
4743 u16 mvm_handle;
4744
4745 if (v == NULL) {
4746 pr_err("%s: v is NULL\n", __func__);
4747 return -EINVAL;
4748 }
4749 apr_mvm = common.apr_q6_mvm;
4750
4751 if (!apr_mvm) {
4752 pr_err("%s: apr_mvm is NULL.\n", __func__);
4753 return -EINVAL;
4754 }
4755 mvm_handle = voice_get_mvm_handle(v);
4756
4757 mvm_set_cal_network.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4758 APR_HDR_LEN(APR_HDR_SIZE),
4759 APR_PKT_VER);
4760 mvm_set_cal_network.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4761 sizeof(mvm_set_cal_network) - APR_HDR_SIZE);
4762 mvm_set_cal_network.hdr.src_port =
4763 voice_get_idx_for_session(v->session_id);
4764 mvm_set_cal_network.hdr.dest_port = mvm_handle;
4765 mvm_set_cal_network.hdr.token = 0;
4766 mvm_set_cal_network.hdr.opcode = VSS_IMVM_CMD_SET_CAL_NETWORK;
4767 mvm_set_cal_network.network_id = VSS_ICOMMON_CAL_NETWORK_ID_NONE;
4768
4769 v->mvm_state = CMD_STATUS_FAIL;
4770 v->async_err = 0;
4771 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_cal_network);
4772 if (ret < 0) {
4773 pr_err("%s: Error %d sending SET_NETWORK\n", __func__, ret);
4774 goto fail;
4775 }
4776
4777 ret = wait_event_timeout(v->mvm_wait,
4778 (v->mvm_state == CMD_STATUS_SUCCESS),
4779 msecs_to_jiffies(TIMEOUT_MS));
4780 if (!ret) {
4781 pr_err("%s: wait_event timeout %d\n", __func__, ret);
4782 goto fail;
4783 }
4784 if (v->async_err > 0) {
4785 pr_err("%s: DSP returned error[%s]\n",
4786 __func__, adsp_err_get_err_str(
4787 v->async_err));
4788 ret = adsp_err_get_lnx_err_code(
4789 v->async_err);
4790 goto fail;
4791 }
4792 return 0;
4793fail:
4794 return ret;
4795}
4796
4797static int voice_send_netid_timing_cmd(struct voice_data *v)
4798{
4799 int ret = 0;
4800 void *apr_mvm;
4801 u16 mvm_handle;
4802 struct mvm_set_network_cmd mvm_set_network;
4803 struct mvm_set_voice_timing_cmd mvm_set_voice_timing;
4804
4805 if (v == NULL) {
4806 pr_err("%s: v is NULL\n", __func__);
4807 return -EINVAL;
4808 }
4809 apr_mvm = common.apr_q6_mvm;
4810
4811 if (!apr_mvm) {
4812 pr_err("%s: apr_mvm is NULL.\n", __func__);
4813 return -EINVAL;
4814 }
4815 mvm_handle = voice_get_mvm_handle(v);
4816
4817 ret = voice_config_cvs_vocoder(v);
4818 if (ret < 0) {
4819 pr_err("%s: Error %d configuring CVS voc",
4820 __func__, ret);
4821 goto fail;
4822 }
4823 /* Set network ID. */
4824 pr_debug("Setting network ID %x\n", common.mvs_info.network_type);
4825
4826 mvm_set_network.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4827 APR_HDR_LEN(APR_HDR_SIZE),
4828 APR_PKT_VER);
4829 mvm_set_network.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4830 sizeof(mvm_set_network) - APR_HDR_SIZE);
4831 mvm_set_network.hdr.src_port =
4832 voice_get_idx_for_session(v->session_id);
4833 mvm_set_network.hdr.dest_port = mvm_handle;
4834 mvm_set_network.hdr.token = 0;
4835 mvm_set_network.hdr.opcode = VSS_IMVM_CMD_SET_CAL_NETWORK;
4836 mvm_set_network.network.network_id = common.mvs_info.network_type;
4837
4838 v->mvm_state = CMD_STATUS_FAIL;
4839 v->async_err = 0;
4840 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_network);
4841 if (ret < 0) {
4842 pr_err("%s: Error %d sending SET_NETWORK\n", __func__, ret);
4843 goto fail;
4844 }
4845
4846 ret = wait_event_timeout(v->mvm_wait,
4847 (v->mvm_state == CMD_STATUS_SUCCESS),
4848 msecs_to_jiffies(TIMEOUT_MS));
4849 if (!ret) {
4850 pr_err("%s: wait_event timeout\n", __func__);
4851 goto fail;
4852 }
4853 if (v->async_err > 0) {
4854 pr_err("%s: DSP returned error[%s]\n",
4855 __func__, adsp_err_get_err_str(
4856 v->async_err));
4857 ret = adsp_err_get_lnx_err_code(
4858 v->async_err);
4859 goto fail;
4860 }
4861
4862 /* Set voice timing. */
4863 pr_debug("Setting voice timing\n");
4864
4865 mvm_set_voice_timing.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4866 APR_HDR_LEN(APR_HDR_SIZE),
4867 APR_PKT_VER);
4868 mvm_set_voice_timing.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4869 sizeof(mvm_set_voice_timing) -
4870 APR_HDR_SIZE);
4871 mvm_set_voice_timing.hdr.src_port =
4872 voice_get_idx_for_session(v->session_id);
4873 mvm_set_voice_timing.hdr.dest_port = mvm_handle;
4874 mvm_set_voice_timing.hdr.token = 0;
4875 mvm_set_voice_timing.hdr.opcode = VSS_ICOMMON_CMD_SET_VOICE_TIMING;
4876 mvm_set_voice_timing.timing.mode = 0;
4877 mvm_set_voice_timing.timing.enc_offset = 8000;
4878 mvm_set_voice_timing.timing.dec_req_offset = 3300;
4879 mvm_set_voice_timing.timing.dec_offset = 8300;
4880
4881 v->mvm_state = CMD_STATUS_FAIL;
4882 v->async_err = 0;
4883
4884 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_voice_timing);
4885 if (ret < 0) {
4886 pr_err("%s: Error %d sending SET_TIMING\n", __func__, ret);
4887 goto fail;
4888 }
4889
4890 ret = wait_event_timeout(v->mvm_wait,
4891 (v->mvm_state == CMD_STATUS_SUCCESS),
4892 msecs_to_jiffies(TIMEOUT_MS));
4893 if (!ret) {
4894 pr_err("%s: wait_event timeout\n", __func__);
4895 goto fail;
4896 }
4897 if (v->async_err > 0) {
4898 pr_err("%s: DSP returned error[%s]\n",
4899 __func__, adsp_err_get_err_str(
4900 v->async_err));
4901 ret = adsp_err_get_lnx_err_code(
4902 v->async_err);
4903 goto fail;
4904 }
4905
4906 return 0;
4907fail:
4908 return ret;
4909}
4910
4911static int voice_send_attach_vocproc_cmd(struct voice_data *v)
4912{
4913 int ret = 0;
4914 struct mvm_attach_vocproc_cmd mvm_a_vocproc_cmd;
4915 void *apr_mvm;
4916 u16 mvm_handle, cvp_handle;
4917
4918 if (v == NULL) {
4919 pr_err("%s: v is NULL\n", __func__);
4920 return -EINVAL;
4921 }
4922 apr_mvm = common.apr_q6_mvm;
4923
4924 if (!apr_mvm) {
4925 pr_err("%s: apr_mvm is NULL.\n", __func__);
4926 return -EINVAL;
4927 }
4928 mvm_handle = voice_get_mvm_handle(v);
4929 cvp_handle = voice_get_cvp_handle(v);
4930
4931 /* attach vocproc and wait for response */
4932 mvm_a_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
4933 APR_HDR_LEN(APR_HDR_SIZE),
4934 APR_PKT_VER);
4935 mvm_a_vocproc_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
4936 sizeof(mvm_a_vocproc_cmd) - APR_HDR_SIZE);
4937 pr_debug("send mvm_a_vocproc_cmd pkt size = %d\n",
4938 mvm_a_vocproc_cmd.hdr.pkt_size);
4939 mvm_a_vocproc_cmd.hdr.src_port =
4940 voice_get_idx_for_session(v->session_id);
4941 mvm_a_vocproc_cmd.hdr.dest_port = mvm_handle;
4942 mvm_a_vocproc_cmd.hdr.token = 0;
4943 mvm_a_vocproc_cmd.hdr.opcode = VSS_IMVM_CMD_ATTACH_VOCPROC;
4944 mvm_a_vocproc_cmd.mvm_attach_cvp_handle.handle = cvp_handle;
4945
4946 v->mvm_state = CMD_STATUS_FAIL;
4947 v->async_err = 0;
4948 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_a_vocproc_cmd);
4949 if (ret < 0) {
4950 pr_err("Fail in sending VSS_IMVM_CMD_ATTACH_VOCPROC\n");
4951 goto fail;
4952 }
4953 ret = wait_event_timeout(v->mvm_wait,
4954 (v->mvm_state == CMD_STATUS_SUCCESS),
4955 msecs_to_jiffies(TIMEOUT_MS));
4956 if (!ret) {
4957 pr_err("%s: wait_event timeout\n", __func__);
4958 goto fail;
4959 }
4960 if (v->async_err > 0) {
4961 pr_err("%s: DSP returned error[%s]\n",
4962 __func__, adsp_err_get_err_str(
4963 v->async_err));
4964 ret = adsp_err_get_lnx_err_code(
4965 v->async_err);
4966 goto fail;
4967 }
4968
4969 return 0;
4970fail:
4971 return ret;
4972}
4973
4974static void voc_update_session_params(struct voice_data *v)
4975{
4976 /* reset LCH mode */
4977 v->lch_mode = 0;
4978
4979 /* clear disable topology setting */
4980 v->disable_topology = false;
4981
4982 /* clear mute setting */
4983 v->dev_rx.dev_mute = common.default_mute_val;
4984 v->dev_tx.dev_mute = common.default_mute_val;
4985 v->stream_rx.stream_mute = common.default_mute_val;
4986 v->stream_tx.stream_mute = common.default_mute_val;
4987}
4988
4989static int voice_destroy_vocproc(struct voice_data *v)
4990{
4991 struct mvm_detach_vocproc_cmd mvm_d_vocproc_cmd;
4992 struct apr_hdr cvp_destroy_session_cmd;
4993 int ret = 0;
4994 void *apr_mvm, *apr_cvp;
4995 u16 mvm_handle, cvp_handle;
4996
4997 if (v == NULL) {
4998 pr_err("%s: v is NULL\n", __func__);
4999 return -EINVAL;
5000 }
5001 apr_mvm = common.apr_q6_mvm;
5002 apr_cvp = common.apr_q6_cvp;
5003
5004 if (!apr_mvm || !apr_cvp) {
5005 pr_err("%s: apr_mvm or apr_cvp is NULL.\n", __func__);
5006 return -EINVAL;
5007 }
5008 mvm_handle = voice_get_mvm_handle(v);
5009 cvp_handle = voice_get_cvp_handle(v);
5010
5011 /* disable slowtalk if st_enable is set */
5012 if (v->st_enable)
5013 voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_ST, 0);
5014
5015 /* Disable HD Voice if hd_enable is set */
5016 if (v->hd_enable)
5017 voice_send_hd_cmd(v, 0);
5018
5019 /* stop playback or recording */
5020 v->music_info.force = 1;
5021 voice_cvs_stop_playback(v);
5022 voice_cvs_stop_record(v);
5023 /* If voice call is active during VoLTE, SRVCC happens.
5024 * Start recording on voice session if recording started during VoLTE.
5025 */
5026 if (is_volte_session(v->session_id) &&
5027 ((common.voice[VOC_PATH_PASSIVE].voc_state == VOC_RUN) ||
5028 (common.voice[VOC_PATH_PASSIVE].voc_state == VOC_CHANGE))) {
5029 if (v->rec_info.rec_enable) {
5030 voice_cvs_start_record(
5031 &common.voice[VOC_PATH_PASSIVE],
5032 v->rec_info.rec_mode);
5033 common.srvcc_rec_flag = true;
5034
5035 pr_debug("%s: switch recording, srvcc_rec_flag %d\n",
5036 __func__, common.srvcc_rec_flag);
5037 }
5038 }
5039
5040 /* send stop voice cmd */
5041 voice_send_stop_voice_cmd(v);
5042
5043 /* send stop dtmf detecton cmd */
5044 if (v->dtmf_rx_detect_en)
5045 voice_send_dtmf_rx_detection_cmd(v, 0);
5046
5047 /* detach VOCPROC and wait for response from mvm */
5048 mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5049 APR_HDR_LEN(APR_HDR_SIZE),
5050 APR_PKT_VER);
5051 mvm_d_vocproc_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5052 sizeof(mvm_d_vocproc_cmd) - APR_HDR_SIZE);
5053 pr_debug("mvm_d_vocproc_cmd pkt size = %d\n",
5054 mvm_d_vocproc_cmd.hdr.pkt_size);
5055 mvm_d_vocproc_cmd.hdr.src_port =
5056 voice_get_idx_for_session(v->session_id);
5057 mvm_d_vocproc_cmd.hdr.dest_port = mvm_handle;
5058 mvm_d_vocproc_cmd.hdr.token = 0;
5059 mvm_d_vocproc_cmd.hdr.opcode = VSS_IMVM_CMD_DETACH_VOCPROC;
5060 mvm_d_vocproc_cmd.mvm_detach_cvp_handle.handle = cvp_handle;
5061
5062 v->mvm_state = CMD_STATUS_FAIL;
5063 v->async_err = 0;
5064 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_d_vocproc_cmd);
5065 if (ret < 0) {
5066 pr_err("Fail in sending VSS_IMVM_CMD_DETACH_VOCPROC\n");
5067 goto fail;
5068 }
5069 ret = wait_event_timeout(v->mvm_wait,
5070 (v->mvm_state == CMD_STATUS_SUCCESS),
5071 msecs_to_jiffies(TIMEOUT_MS));
5072 if (!ret) {
5073 pr_err("%s: wait_event timeout\n", __func__);
5074 goto fail;
5075 }
5076 if (v->async_err > 0) {
5077 pr_err("%s: DSP returned error[%s]\n",
5078 __func__, adsp_err_get_err_str(
5079 v->async_err));
5080 ret = adsp_err_get_lnx_err_code(
5081 v->async_err);
5082 goto fail;
5083 }
5084
5085 voice_send_cvp_deregister_vol_cal_cmd(v);
5086 voice_send_cvp_deregister_cal_cmd(v);
5087 voice_send_cvp_deregister_dev_cfg_cmd(v);
5088 voice_send_cvs_deregister_cal_cmd(v);
5089
5090 /* destrop cvp session */
5091 cvp_destroy_session_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5092 APR_HDR_LEN(APR_HDR_SIZE),
5093 APR_PKT_VER);
5094 cvp_destroy_session_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5095 sizeof(cvp_destroy_session_cmd) - APR_HDR_SIZE);
5096 pr_debug("cvp_destroy_session_cmd pkt size = %d\n",
5097 cvp_destroy_session_cmd.pkt_size);
5098 cvp_destroy_session_cmd.src_port =
5099 voice_get_idx_for_session(v->session_id);
5100 cvp_destroy_session_cmd.dest_port = cvp_handle;
5101 cvp_destroy_session_cmd.token = 0;
5102 cvp_destroy_session_cmd.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION;
5103
5104 v->cvp_state = CMD_STATUS_FAIL;
5105 v->async_err = 0;
5106 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_destroy_session_cmd);
5107 if (ret < 0) {
5108 pr_err("Fail in sending APRV2_IBASIC_CMD_DESTROY_SESSION\n");
5109 goto fail;
5110 }
5111 ret = wait_event_timeout(v->cvp_wait,
5112 (v->cvp_state == CMD_STATUS_SUCCESS),
5113 msecs_to_jiffies(TIMEOUT_MS));
5114 if (!ret) {
5115 pr_err("%s: wait_event timeout\n", __func__);
5116 goto fail;
5117 }
5118 if (v->async_err > 0) {
5119 pr_err("%s: DSP returned error[%s]\n",
5120 __func__, adsp_err_get_err_str(
5121 v->async_err));
5122 ret = adsp_err_get_lnx_err_code(
5123 v->async_err);
5124 goto fail;
5125 }
5126
5127 rtac_remove_voice(voice_get_cvs_handle(v));
5128 cvp_handle = 0;
5129 voice_set_cvp_handle(v, cvp_handle);
5130 return 0;
5131fail:
5132 return ret;
5133}
5134
5135static int voice_send_mvm_unmap_memory_physical_cmd(struct voice_data *v,
5136 uint32_t mem_handle)
5137{
5138 struct vss_imemory_cmd_unmap_t mem_unmap;
5139 int ret = 0;
5140 void *apr_mvm;
5141 u16 mvm_handle;
5142
5143 if (v == NULL) {
5144 pr_err("%s: v is NULL\n", __func__);
5145 return -EINVAL;
5146 }
5147 apr_mvm = common.apr_q6_mvm;
5148
5149 if (!apr_mvm) {
5150 pr_err("%s: apr_mvm is NULL.\n", __func__);
5151 return -EINVAL;
5152 }
5153 mvm_handle = voice_get_mvm_handle(v);
5154
5155 mem_unmap.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5156 APR_HDR_LEN(APR_HDR_SIZE),
5157 APR_PKT_VER);
5158 mem_unmap.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5159 sizeof(mem_unmap) - APR_HDR_SIZE);
5160 mem_unmap.hdr.src_port =
5161 voice_get_idx_for_session(v->session_id);
5162 mem_unmap.hdr.dest_port = mvm_handle;
5163 mem_unmap.hdr.token = 0;
5164 mem_unmap.hdr.opcode = VSS_IMEMORY_CMD_UNMAP;
5165 mem_unmap.mem_handle = mem_handle;
5166
5167 pr_debug("%s: mem_handle: 0x%x\n", __func__, mem_unmap.mem_handle);
5168
5169 v->mvm_state = CMD_STATUS_FAIL;
5170 v->async_err = 0;
5171 ret = apr_send_pkt(apr_mvm, (uint32_t *) &mem_unmap);
5172 if (ret < 0) {
5173 pr_err("mem_unmap op[0x%x]ret[%d]\n",
5174 mem_unmap.hdr.opcode, ret);
5175 goto fail;
5176 }
5177
5178 ret = wait_event_timeout(v->mvm_wait,
5179 (v->mvm_state == CMD_STATUS_SUCCESS),
5180 msecs_to_jiffies(TIMEOUT_MS));
5181 if (!ret) {
5182 pr_err("%s: wait_event timeout %d\n", __func__, ret);
5183 goto fail;
5184 }
5185 if (v->async_err > 0) {
5186 pr_err("%s: DSP returned error[%s]\n",
5187 __func__, adsp_err_get_err_str(
5188 v->async_err));
5189 ret = adsp_err_get_lnx_err_code(
5190 v->async_err);
5191 goto fail;
5192 }
5193 return 0;
5194
5195fail:
5196 return ret;
5197}
5198
5199static int voice_send_cvs_packet_exchange_config_cmd(struct voice_data *v)
5200{
5201 struct vss_istream_cmd_set_oob_packet_exchange_config_t
5202 packet_exchange_config_pkt;
5203 int ret = 0;
5204 void *apr_cvs;
5205 u16 cvs_handle;
5206
5207 if (v == NULL) {
5208 pr_err("%s: v is NULL\n", __func__);
5209 return -EINVAL;
5210 }
5211
5212 apr_cvs = common.apr_q6_cvs;
5213
5214 if (!apr_cvs) {
5215 pr_err("%s: apr_cvs is NULL.\n", __func__);
5216 return -EINVAL;
5217 }
5218 cvs_handle = voice_get_cvs_handle(v);
5219
5220 packet_exchange_config_pkt.hdr.hdr_field = APR_HDR_FIELD(
5221 APR_MSG_TYPE_SEQ_CMD,
5222 APR_HDR_LEN(APR_HDR_SIZE),
5223 APR_PKT_VER);
5224 packet_exchange_config_pkt.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5225 sizeof(packet_exchange_config_pkt) -
5226 APR_HDR_SIZE);
5227 packet_exchange_config_pkt.hdr.src_port =
5228 voice_get_idx_for_session(v->session_id);
5229 packet_exchange_config_pkt.hdr.dest_port = cvs_handle;
5230 packet_exchange_config_pkt.hdr.token = 0;
5231 packet_exchange_config_pkt.hdr.opcode =
5232 VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG;
5233 packet_exchange_config_pkt.mem_handle = v->shmem_info.mem_handle;
5234 /* dec buffer address */
5235 packet_exchange_config_pkt.dec_buf_addr_lsw =
5236 lower_32_bits(v->shmem_info.sh_buf.buf[0].phys);
5237 packet_exchange_config_pkt.dec_buf_addr_msw =
5238 msm_audio_populate_upper_32_bits(
5239 v->shmem_info.sh_buf.buf[0].phys);
5240 packet_exchange_config_pkt.dec_buf_size = 4096;
5241 /* enc buffer address */
5242 packet_exchange_config_pkt.enc_buf_addr_lsw =
5243 lower_32_bits(v->shmem_info.sh_buf.buf[1].phys);
5244 packet_exchange_config_pkt.enc_buf_addr_msw =
5245 msm_audio_populate_upper_32_bits(
5246 v->shmem_info.sh_buf.buf[1].phys);
5247 packet_exchange_config_pkt.enc_buf_size = 4096;
5248
5249 pr_debug("%s: dec buf add: lsw %0x msw %0x, size %d, enc buf add: lsw %0x msw %0x, size %d\n",
5250 __func__,
5251 packet_exchange_config_pkt.dec_buf_addr_lsw,
5252 packet_exchange_config_pkt.dec_buf_addr_msw,
5253 packet_exchange_config_pkt.dec_buf_size,
5254 packet_exchange_config_pkt.enc_buf_addr_lsw,
5255 packet_exchange_config_pkt.enc_buf_addr_msw,
5256 packet_exchange_config_pkt.enc_buf_size);
5257
5258 v->cvs_state = CMD_STATUS_FAIL;
5259 v->async_err = 0;
5260 ret = apr_send_pkt(apr_cvs, (uint32_t *) &packet_exchange_config_pkt);
5261 if (ret < 0) {
5262 pr_err("Failed to send packet exchange config cmd %d\n", ret);
5263 goto fail;
5264 }
5265
5266 ret = wait_event_timeout(v->cvs_wait,
5267 (v->cvs_state == CMD_STATUS_SUCCESS),
5268 msecs_to_jiffies(TIMEOUT_MS));
5269 if (!ret)
5270 pr_err("%s: wait_event timeout %d\n", __func__, ret);
5271
5272 if (v->async_err > 0) {
5273 pr_err("%s: DSP returned error[%s]\n",
5274 __func__, adsp_err_get_err_str(
5275 v->async_err));
5276 ret = adsp_err_get_lnx_err_code(
5277 v->async_err);
5278 goto fail;
5279 }
5280
5281 return 0;
5282fail:
5283 return ret;
5284}
5285
5286static int voice_send_cvs_data_exchange_mode_cmd(struct voice_data *v)
5287{
5288 struct vss_istream_cmd_set_packet_exchange_mode_t data_exchange_pkt;
5289 int ret = 0;
5290 void *apr_cvs;
5291 u16 cvs_handle;
5292
5293 if (v == NULL) {
5294 pr_err("%s: v is NULL\n", __func__);
5295 return -EINVAL;
5296 }
5297 apr_cvs = common.apr_q6_cvs;
5298
5299 if (!apr_cvs) {
5300 pr_err("%s: apr_cvs is NULL.\n", __func__);
5301 return -EINVAL;
5302 }
5303 cvs_handle = voice_get_cvs_handle(v);
5304
5305 data_exchange_pkt.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5306 APR_HDR_LEN(APR_HDR_SIZE),
5307 APR_PKT_VER);
5308 data_exchange_pkt.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5309 sizeof(data_exchange_pkt) - APR_HDR_SIZE);
5310 data_exchange_pkt.hdr.src_port =
5311 voice_get_idx_for_session(v->session_id);
5312 data_exchange_pkt.hdr.dest_port = cvs_handle;
5313 data_exchange_pkt.hdr.token = 0;
5314 data_exchange_pkt.hdr.opcode = VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE;
5315 data_exchange_pkt.mode = VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND;
5316
5317 v->cvs_state = CMD_STATUS_FAIL;
5318 v->async_err = 0;
5319 ret = apr_send_pkt(apr_cvs, (uint32_t *) &data_exchange_pkt);
5320 if (ret < 0) {
5321 pr_err("Failed to send data exchange mode %d\n", ret);
5322 goto fail;
5323 }
5324
5325 ret = wait_event_timeout(v->cvs_wait,
5326 (v->cvs_state == CMD_STATUS_SUCCESS),
5327 msecs_to_jiffies(TIMEOUT_MS));
5328 if (!ret)
5329 pr_err("%s: wait_event timeout %d\n", __func__, ret);
5330
5331 if (v->async_err > 0) {
5332 pr_err("%s: DSP returned error[%s]\n",
5333 __func__, adsp_err_get_err_str(
5334 v->async_err));
5335 ret = adsp_err_get_lnx_err_code(
5336 v->async_err);
5337 goto fail;
5338 }
5339 return 0;
5340fail:
5341 return ret;
5342}
5343
5344static int voice_send_stream_mute_cmd(struct voice_data *v, uint16_t direction,
5345 uint16_t mute_flag, uint32_t ramp_duration)
5346{
5347 struct cvs_set_mute_cmd cvs_mute_cmd;
5348 int ret = 0;
5349
5350 if (v == NULL) {
5351 pr_err("%s: v is NULL\n", __func__);
5352 ret = -EINVAL;
5353 goto fail;
5354 }
5355
5356 if (!common.apr_q6_cvs) {
5357 pr_err("%s: apr_cvs is NULL.\n", __func__);
5358 ret = -EINVAL;
5359 goto fail;
5360 }
5361
5362 /* send mute/unmute to cvs */
5363 cvs_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5364 APR_HDR_LEN(APR_HDR_SIZE),
5365 APR_PKT_VER);
5366 cvs_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5367 sizeof(cvs_mute_cmd) - APR_HDR_SIZE);
5368 cvs_mute_cmd.hdr.src_port =
5369 voice_get_idx_for_session(v->session_id);
5370 cvs_mute_cmd.hdr.dest_port = voice_get_cvs_handle(v);
5371 cvs_mute_cmd.hdr.token = 0;
5372 cvs_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
5373 cvs_mute_cmd.cvs_set_mute.direction = direction;
5374 cvs_mute_cmd.cvs_set_mute.mute_flag = mute_flag;
5375 cvs_mute_cmd.cvs_set_mute.ramp_duration_ms = ramp_duration;
5376
5377 v->cvs_state = CMD_STATUS_FAIL;
5378 v->async_err = 0;
5379 ret = apr_send_pkt(common.apr_q6_cvs, (uint32_t *) &cvs_mute_cmd);
5380 if (ret < 0) {
5381 pr_err("%s: Error %d sending stream mute\n", __func__, ret);
5382
5383 goto fail;
5384 }
5385 ret = wait_event_timeout(v->cvs_wait,
5386 (v->cvs_state == CMD_STATUS_SUCCESS),
5387 msecs_to_jiffies(TIMEOUT_MS));
5388 if (!ret) {
5389 pr_err("%s: Command timeout\n", __func__);
5390 goto fail;
5391 }
5392 if (v->async_err > 0) {
5393 pr_err("%s: DSP returned error[%s]\n",
5394 __func__, adsp_err_get_err_str(
5395 v->async_err));
5396 ret = adsp_err_get_lnx_err_code(
5397 v->async_err);
5398 goto fail;
5399 }
5400
5401 return 0;
5402
5403fail:
5404 return ret;
5405}
5406
5407static int voice_send_device_mute_cmd(struct voice_data *v, uint16_t direction,
5408 uint16_t mute_flag, uint32_t ramp_duration)
5409{
5410 struct cvp_set_mute_cmd cvp_mute_cmd;
5411 int ret = 0;
5412
5413 if (v == NULL) {
5414 pr_err("%s: v is NULL\n", __func__);
5415 ret = -EINVAL;
5416 goto fail;
5417 }
5418
5419 if (!common.apr_q6_cvp) {
5420 pr_err("%s: apr_cvp is NULL.\n", __func__);
5421 ret = -EINVAL;
5422 goto fail;
5423 }
5424
5425 cvp_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5426 APR_HDR_LEN(APR_HDR_SIZE),
5427 APR_PKT_VER);
5428 cvp_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5429 sizeof(cvp_mute_cmd) - APR_HDR_SIZE);
5430 cvp_mute_cmd.hdr.src_port =
5431 voice_get_idx_for_session(v->session_id);
5432 cvp_mute_cmd.hdr.dest_port = voice_get_cvp_handle(v);
5433 cvp_mute_cmd.hdr.token = 0;
5434 cvp_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
5435 cvp_mute_cmd.cvp_set_mute.direction = direction;
5436 cvp_mute_cmd.cvp_set_mute.mute_flag = mute_flag;
5437 cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = ramp_duration;
5438
5439 v->cvp_state = CMD_STATUS_FAIL;
5440 v->async_err = 0;
5441 ret = apr_send_pkt(common.apr_q6_cvp, (uint32_t *) &cvp_mute_cmd);
5442 if (ret < 0) {
5443 pr_err("%s: Error %d sending rx device cmd\n", __func__, ret);
5444
5445 goto fail;
5446 }
5447 ret = wait_event_timeout(v->cvp_wait,
5448 (v->cvp_state == CMD_STATUS_SUCCESS),
5449 msecs_to_jiffies(TIMEOUT_MS));
5450 if (!ret) {
5451 pr_err("%s: Command timeout\n", __func__);
5452 goto fail;
5453 }
5454 if (v->async_err > 0) {
5455 pr_err("%s: DSP returned error[%s]\n",
5456 __func__, adsp_err_get_err_str(
5457 v->async_err));
5458 ret = adsp_err_get_lnx_err_code(
5459 v->async_err);
5460 goto fail;
5461 }
5462
5463 return 0;
5464
5465fail:
5466 return ret;
5467}
5468
5469static int voice_send_vol_step_cmd(struct voice_data *v)
5470{
5471 struct cvp_set_rx_volume_step_cmd cvp_vol_step_cmd;
5472 int ret = 0;
5473 void *apr_cvp;
5474 u16 cvp_handle;
5475
5476 if (v == NULL) {
5477 pr_err("%s: v is NULL\n", __func__);
5478 return -EINVAL;
5479 }
5480 apr_cvp = common.apr_q6_cvp;
5481
5482 if (!apr_cvp) {
5483 pr_err("%s: apr_cvp is NULL.\n", __func__);
5484 return -EINVAL;
5485 }
5486 cvp_handle = voice_get_cvp_handle(v);
5487
5488 /* send volume index to cvp */
5489 cvp_vol_step_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5490 APR_HDR_LEN(APR_HDR_SIZE),
5491 APR_PKT_VER);
5492 cvp_vol_step_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5493 sizeof(cvp_vol_step_cmd) - APR_HDR_SIZE);
5494 cvp_vol_step_cmd.hdr.src_port =
5495 voice_get_idx_for_session(v->session_id);
5496 cvp_vol_step_cmd.hdr.dest_port = cvp_handle;
5497 cvp_vol_step_cmd.hdr.token = 0;
5498 cvp_vol_step_cmd.hdr.opcode = VSS_IVOLUME_CMD_SET_STEP;
5499 cvp_vol_step_cmd.cvp_set_vol_step.direction = VSS_IVOLUME_DIRECTION_RX;
5500 cvp_vol_step_cmd.cvp_set_vol_step.value = v->dev_rx.volume_step_value;
5501 cvp_vol_step_cmd.cvp_set_vol_step.ramp_duration_ms =
5502 v->dev_rx.volume_ramp_duration_ms;
5503 pr_debug("%s step_value:%d, ramp_duration_ms:%d",
5504 __func__,
5505 cvp_vol_step_cmd.cvp_set_vol_step.value,
5506 cvp_vol_step_cmd.cvp_set_vol_step.ramp_duration_ms);
5507
5508 v->cvp_state = CMD_STATUS_FAIL;
5509 v->async_err = 0;
5510 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_vol_step_cmd);
5511 if (ret < 0) {
5512 pr_err("Fail in sending RX VOL step\n");
5513 return -EINVAL;
5514 }
5515 ret = wait_event_timeout(v->cvp_wait,
5516 (v->cvp_state == CMD_STATUS_SUCCESS),
5517 msecs_to_jiffies(TIMEOUT_MS));
5518 if (!ret) {
5519 pr_err("%s: wait_event timeout\n", __func__);
5520 return -EINVAL;
5521 }
5522 if (v->async_err > 0) {
5523 pr_err("%s: DSP returned error[%s]\n",
5524 __func__, adsp_err_get_err_str(
5525 v->async_err));
5526 ret = adsp_err_get_lnx_err_code(
5527 v->async_err);
5528 return ret;
5529 }
5530 return 0;
5531}
5532
5533static int voice_cvs_start_record(struct voice_data *v, uint32_t rec_mode)
5534{
5535 int ret = 0;
5536 void *apr_cvs;
5537 u16 cvs_handle;
5538
5539 struct cvs_start_record_cmd cvs_start_record;
5540
5541 if (v == NULL) {
5542 pr_err("%s: v is NULL\n", __func__);
5543 return -EINVAL;
5544 }
5545 apr_cvs = common.apr_q6_cvs;
5546
5547 if (!apr_cvs) {
5548 pr_err("%s: apr_cvs is NULL.\n", __func__);
5549 return -EINVAL;
5550 }
5551
5552 cvs_handle = voice_get_cvs_handle(v);
5553
5554 if (!v->rec_info.recording) {
5555 cvs_start_record.hdr.hdr_field = APR_HDR_FIELD(
5556 APR_MSG_TYPE_SEQ_CMD,
5557 APR_HDR_LEN(APR_HDR_SIZE),
5558 APR_PKT_VER);
5559 cvs_start_record.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5560 sizeof(cvs_start_record) - APR_HDR_SIZE);
5561 cvs_start_record.hdr.src_port =
5562 voice_get_idx_for_session(v->session_id);
5563 cvs_start_record.hdr.dest_port = cvs_handle;
5564 cvs_start_record.hdr.token = 0;
5565 cvs_start_record.hdr.opcode = VSS_IRECORD_CMD_START;
5566
5567 cvs_start_record.rec_mode.port_id =
5568 VSS_IRECORD_PORT_ID_DEFAULT;
5569 if (rec_mode == VOC_REC_UPLINK) {
5570 cvs_start_record.rec_mode.rx_tap_point =
5571 VSS_IRECORD_TAP_POINT_NONE;
5572 cvs_start_record.rec_mode.tx_tap_point =
5573 VSS_IRECORD_TAP_POINT_STREAM_END;
5574 } else if (rec_mode == VOC_REC_DOWNLINK) {
5575 cvs_start_record.rec_mode.rx_tap_point =
5576 VSS_IRECORD_TAP_POINT_STREAM_END;
5577 cvs_start_record.rec_mode.tx_tap_point =
5578 VSS_IRECORD_TAP_POINT_NONE;
5579 } else if (rec_mode == VOC_REC_BOTH) {
5580 cvs_start_record.rec_mode.rx_tap_point =
5581 VSS_IRECORD_TAP_POINT_STREAM_END;
5582 cvs_start_record.rec_mode.tx_tap_point =
5583 VSS_IRECORD_TAP_POINT_STREAM_END;
5584 } else {
5585 pr_err("%s: Invalid in-call rec_mode %d\n", __func__,
5586 rec_mode);
5587
5588 ret = -EINVAL;
5589 goto fail;
5590 }
5591
5592 v->cvs_state = CMD_STATUS_FAIL;
5593 v->async_err = 0;
5594
5595 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_record);
5596 if (ret < 0) {
5597 pr_err("%s: Error %d sending START_RECORD\n", __func__,
5598 ret);
5599
5600 goto fail;
5601 }
5602
5603 ret = wait_event_timeout(v->cvs_wait,
5604 (v->cvs_state == CMD_STATUS_SUCCESS),
5605 msecs_to_jiffies(TIMEOUT_MS));
5606
5607 if (!ret) {
5608 pr_err("%s: wait_event timeout\n", __func__);
5609
5610 goto fail;
5611 }
5612 if (v->async_err > 0) {
5613 pr_err("%s: DSP returned error[%s]\n",
5614 __func__, adsp_err_get_err_str(
5615 v->async_err));
5616 ret = adsp_err_get_lnx_err_code(
5617 v->async_err);
5618 goto fail;
5619 }
5620 v->rec_info.recording = 1;
5621 } else {
5622 pr_debug("%s: Start record already sent\n", __func__);
5623 }
5624
5625 return 0;
5626
5627fail:
5628 return ret;
5629}
5630
5631static int voice_cvs_stop_record(struct voice_data *v)
5632{
5633 int ret = 0;
5634 void *apr_cvs;
5635 u16 cvs_handle;
5636 struct apr_hdr cvs_stop_record;
5637
5638 if (v == NULL) {
5639 pr_err("%s: v is NULL\n", __func__);
5640 return -EINVAL;
5641 }
5642 apr_cvs = common.apr_q6_cvs;
5643
5644 if (!apr_cvs) {
5645 pr_err("%s: apr_cvs is NULL.\n", __func__);
5646 return -EINVAL;
5647 }
5648
5649 cvs_handle = voice_get_cvs_handle(v);
5650
5651 if (v->rec_info.recording) {
5652 cvs_stop_record.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5653 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5654 cvs_stop_record.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5655 sizeof(cvs_stop_record) - APR_HDR_SIZE);
5656 cvs_stop_record.src_port =
5657 voice_get_idx_for_session(v->session_id);
5658 cvs_stop_record.dest_port = cvs_handle;
5659 cvs_stop_record.token = 0;
5660 cvs_stop_record.opcode = VSS_IRECORD_CMD_STOP;
5661
5662 v->cvs_state = CMD_STATUS_FAIL;
5663 v->async_err = 0;
5664
5665 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_stop_record);
5666 if (ret < 0) {
5667 pr_err("%s: Error %d sending STOP_RECORD\n",
5668 __func__, ret);
5669
5670 goto fail;
5671 }
5672
5673 ret = wait_event_timeout(v->cvs_wait,
5674 (v->cvs_state == CMD_STATUS_SUCCESS),
5675 msecs_to_jiffies(TIMEOUT_MS));
5676 if (!ret) {
5677 pr_err("%s: wait_event timeout\n", __func__);
5678
5679 goto fail;
5680 }
5681 if (v->async_err > 0) {
5682 pr_err("%s: DSP returned error[%s]\n",
5683 __func__, adsp_err_get_err_str(
5684 v->async_err));
5685 ret = adsp_err_get_lnx_err_code(
5686 v->async_err);
5687 goto fail;
5688 }
5689 v->rec_info.recording = 0;
5690 } else {
5691 pr_debug("%s: Stop record already sent\n", __func__);
5692 }
5693
5694 return 0;
5695
5696fail:
5697 return ret;
5698}
5699
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305700/**
5701 * voc_start_record -
5702 * command to set record for voice session
5703 *
5704 * @port_id: Pseudo Port ID for record data
5705 * @set: Enable or Disable for record start/stop
5706 * @session_id: voice session ID to send this command
5707 *
5708 * Returns 0 on success or error on failure
5709 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305710int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id)
5711{
5712 int ret = 0;
5713 int rec_mode = 0;
5714 u16 cvs_handle;
5715 int rec_set = 0;
5716 struct voice_session_itr itr;
5717 struct voice_data *v = NULL;
5718
5719 /* check if session_id is valid */
5720 if (!voice_is_valid_session_id(session_id)) {
5721 pr_err("%s: Invalid session id:%u\n", __func__,
5722 session_id);
5723
5724 return -EINVAL;
5725 }
5726
5727 voice_itr_init(&itr, session_id);
5728 pr_debug("%s: session_id:%u\n", __func__, session_id);
5729
5730 while (voice_itr_get_next_session(&itr, &v)) {
5731 if (v == NULL) {
5732 pr_err("%s: v is NULL, sessionid:%u\n", __func__,
5733 session_id);
5734
5735 break;
5736 }
5737 pr_debug("%s: port_id: %d, set: %d, v: %pK\n",
5738 __func__, port_id, set, v);
5739
5740 mutex_lock(&v->lock);
5741 rec_mode = v->rec_info.rec_mode;
5742 rec_set = set;
5743 if (set) {
5744 if ((v->rec_route_state.ul_flag != 0) &&
5745 (v->rec_route_state.dl_flag != 0)) {
5746 pr_debug("%s: rec mode already set.\n",
5747 __func__);
5748
5749 mutex_unlock(&v->lock);
5750 continue;
5751 }
5752
5753 if (port_id == VOICE_RECORD_TX) {
5754 if ((v->rec_route_state.ul_flag == 0)
5755 && (v->rec_route_state.dl_flag == 0)) {
5756 rec_mode = VOC_REC_UPLINK;
5757 v->rec_route_state.ul_flag = 1;
5758 } else if ((v->rec_route_state.ul_flag == 0)
5759 && (v->rec_route_state.dl_flag != 0)) {
5760 voice_cvs_stop_record(v);
5761 rec_mode = VOC_REC_BOTH;
5762 v->rec_route_state.ul_flag = 1;
5763 }
5764 } else if (port_id == VOICE_RECORD_RX) {
5765 if ((v->rec_route_state.ul_flag == 0)
5766 && (v->rec_route_state.dl_flag == 0)) {
5767 rec_mode = VOC_REC_DOWNLINK;
5768 v->rec_route_state.dl_flag = 1;
5769 } else if ((v->rec_route_state.ul_flag != 0)
5770 && (v->rec_route_state.dl_flag == 0)) {
5771 voice_cvs_stop_record(v);
5772 rec_mode = VOC_REC_BOTH;
5773 v->rec_route_state.dl_flag = 1;
5774 }
5775 }
5776 rec_set = 1;
5777 } else {
5778 if ((v->rec_route_state.ul_flag == 0) &&
5779 (v->rec_route_state.dl_flag == 0)) {
5780 pr_debug("%s: rec already stops.\n",
5781 __func__);
5782 mutex_unlock(&v->lock);
5783 continue;
5784 }
5785
5786 if (port_id == VOICE_RECORD_TX) {
5787 if ((v->rec_route_state.ul_flag != 0)
5788 && (v->rec_route_state.dl_flag == 0)) {
5789 v->rec_route_state.ul_flag = 0;
5790 rec_set = 0;
5791 } else if ((v->rec_route_state.ul_flag != 0)
5792 && (v->rec_route_state.dl_flag != 0)) {
5793 voice_cvs_stop_record(v);
5794 v->rec_route_state.ul_flag = 0;
5795 rec_mode = VOC_REC_DOWNLINK;
5796 rec_set = 1;
5797 }
5798 } else if (port_id == VOICE_RECORD_RX) {
5799 if ((v->rec_route_state.ul_flag == 0)
5800 && (v->rec_route_state.dl_flag != 0)) {
5801 v->rec_route_state.dl_flag = 0;
5802 rec_set = 0;
5803 } else if ((v->rec_route_state.ul_flag != 0)
5804 && (v->rec_route_state.dl_flag != 0)) {
5805 voice_cvs_stop_record(v);
5806 v->rec_route_state.dl_flag = 0;
5807 rec_mode = VOC_REC_UPLINK;
5808 rec_set = 1;
5809 }
5810 }
5811 }
5812 pr_debug("%s: mode =%d, set =%d\n", __func__,
5813 rec_mode, rec_set);
5814 cvs_handle = voice_get_cvs_handle(v);
5815
5816 if (cvs_handle != 0) {
5817 if (rec_set)
5818 ret = voice_cvs_start_record(v, rec_mode);
5819 else
5820 ret = voice_cvs_stop_record(v);
5821 }
5822
5823 /* During SRVCC, recording will switch from VoLTE session to
5824 * voice session.
5825 * Then stop recording, need to stop recording on voice session.
5826 */
5827 if ((!rec_set) && common.srvcc_rec_flag) {
5828 pr_debug("%s, srvcc_rec_flag:%d\n", __func__,
5829 common.srvcc_rec_flag);
5830
5831 voice_cvs_stop_record(&common.voice[VOC_PATH_PASSIVE]);
5832 common.srvcc_rec_flag = false;
5833 }
5834
5835 /* Cache the value */
5836 v->rec_info.rec_enable = rec_set;
5837 v->rec_info.rec_mode = rec_mode;
5838
5839 mutex_unlock(&v->lock);
5840 }
5841
5842 return ret;
5843}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05305844EXPORT_SYMBOL(voc_start_record);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05305845
5846static int voice_cvs_start_playback(struct voice_data *v)
5847{
5848 int ret = 0;
5849 struct cvs_start_playback_cmd cvs_start_playback;
5850 void *apr_cvs;
5851 u16 cvs_handle;
5852
5853 if (v == NULL) {
5854 pr_err("%s: v is NULL\n", __func__);
5855 return -EINVAL;
5856 }
5857 apr_cvs = common.apr_q6_cvs;
5858
5859 if (!apr_cvs) {
5860 pr_err("%s: apr_cvs is NULL.\n", __func__);
5861 return -EINVAL;
5862 }
5863
5864 cvs_handle = voice_get_cvs_handle(v);
5865
5866 if (!v->music_info.playing && v->music_info.count) {
5867 cvs_start_playback.hdr.hdr_field = APR_HDR_FIELD(
5868 APR_MSG_TYPE_SEQ_CMD,
5869 APR_HDR_LEN(APR_HDR_SIZE),
5870 APR_PKT_VER);
5871 cvs_start_playback.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5872 sizeof(cvs_start_playback) - APR_HDR_SIZE);
5873 cvs_start_playback.hdr.src_port =
5874 voice_get_idx_for_session(v->session_id);
5875 cvs_start_playback.hdr.dest_port = cvs_handle;
5876 cvs_start_playback.hdr.token = 0;
5877 cvs_start_playback.hdr.opcode = VSS_IPLAYBACK_CMD_START;
5878 cvs_start_playback.playback_mode.port_id =
5879 v->music_info.port_id;
5880
5881 v->cvs_state = CMD_STATUS_FAIL;
5882 v->async_err = 0;
5883
5884 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_playback);
5885
5886 if (ret < 0) {
5887 pr_err("%s: Error %d sending START_PLAYBACK\n",
5888 __func__, ret);
5889
5890 goto fail;
5891 }
5892
5893 ret = wait_event_timeout(v->cvs_wait,
5894 (v->cvs_state == CMD_STATUS_SUCCESS),
5895 msecs_to_jiffies(TIMEOUT_MS));
5896 if (!ret) {
5897 pr_err("%s: wait_event timeout\n", __func__);
5898
5899 goto fail;
5900 }
5901 if (v->async_err > 0) {
5902 pr_err("%s: DSP returned error[%s]\n",
5903 __func__, adsp_err_get_err_str(
5904 v->async_err));
5905 ret = adsp_err_get_lnx_err_code(
5906 v->async_err);
5907 goto fail;
5908 }
5909
5910 v->music_info.playing = 1;
5911 } else {
5912 pr_debug("%s: Start playback already sent\n", __func__);
5913 }
5914
5915 return 0;
5916
5917fail:
5918 return ret;
5919}
5920
5921static int voice_cvs_stop_playback(struct voice_data *v)
5922{
5923 int ret = 0;
5924 struct apr_hdr cvs_stop_playback;
5925 void *apr_cvs;
5926 u16 cvs_handle;
5927
5928 if (v == NULL) {
5929 pr_err("%s: v is NULL\n", __func__);
5930 return -EINVAL;
5931 }
5932 apr_cvs = common.apr_q6_cvs;
5933
5934 if (!apr_cvs) {
5935 pr_err("%s: apr_cvs is NULL.\n", __func__);
5936 return -EINVAL;
5937 }
5938
5939 cvs_handle = voice_get_cvs_handle(v);
5940
5941 if (v->music_info.playing && ((!v->music_info.count) ||
5942 (v->music_info.force))) {
5943 cvs_stop_playback.hdr_field =
5944 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
5945 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
5946 cvs_stop_playback.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
5947 sizeof(cvs_stop_playback) - APR_HDR_SIZE);
5948 cvs_stop_playback.src_port =
5949 voice_get_idx_for_session(v->session_id);
5950 cvs_stop_playback.dest_port = cvs_handle;
5951 cvs_stop_playback.token = 0;
5952
5953 cvs_stop_playback.opcode = VSS_IPLAYBACK_CMD_STOP;
5954
5955 v->cvs_state = CMD_STATUS_FAIL;
5956 v->async_err = 0;
5957
5958 ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_stop_playback);
5959 if (ret < 0) {
5960 pr_err("%s: Error %d sending STOP_PLAYBACK\n",
5961 __func__, ret);
5962
5963
5964 goto fail;
5965 }
5966
5967 ret = wait_event_timeout(v->cvs_wait,
5968 (v->cvs_state == CMD_STATUS_SUCCESS),
5969 msecs_to_jiffies(TIMEOUT_MS));
5970 if (!ret) {
5971 pr_err("%s: wait_event timeout\n", __func__);
5972
5973 goto fail;
5974 }
5975 if (v->async_err > 0) {
5976 pr_err("%s: DSP returned error[%s]\n",
5977 __func__, adsp_err_get_err_str(
5978 v->async_err));
5979 ret = adsp_err_get_lnx_err_code(
5980 v->async_err);
5981 goto fail;
5982 }
5983
5984 v->music_info.playing = 0;
5985 v->music_info.force = 0;
5986 } else {
5987 pr_debug("%s: Stop playback already sent\n", __func__);
5988 }
5989
5990 return 0;
5991
5992fail:
5993 return ret;
5994}
5995
5996static int voc_lch_ops(struct voice_data *v, enum voice_lch_mode lch_mode)
5997{
5998 int ret = 0;
5999
6000 if (v == NULL) {
6001 pr_err("%s: v is NULL\n", __func__);
6002
6003 ret = -EINVAL;
6004 goto done;
6005 }
6006
6007 switch (lch_mode) {
6008 case VOICE_LCH_START:
6009
6010 ret = voc_end_voice_call(v->session_id);
6011 if (ret < 0)
6012 pr_err("%s: voice call end failed %d\n",
6013 __func__, ret);
6014 break;
6015 case VOICE_LCH_STOP:
6016
6017 ret = voc_start_voice_call(v->session_id);
6018 if (ret < 0) {
6019 pr_err("%s: voice call start failed %d\n",
6020 __func__, ret);
6021 goto done;
6022 }
6023 break;
6024 default:
6025 pr_err("%s: Invalid LCH mode: %d\n",
6026 __func__, v->lch_mode);
6027 break;
6028 }
6029done:
6030 return ret;
6031}
6032
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306033/**
6034 * voc_start_playback -
6035 * command to set playback for voice session
6036 *
6037 * @set: Enable or Disable for playback start/stop
6038 * @port_id: Pseudo Port ID for playback data
6039 *
6040 * Returns 0 on success or error on failure
6041 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306042int voc_start_playback(uint32_t set, uint16_t port_id)
6043{
6044 struct voice_data *v = NULL;
6045 int ret = 0;
6046 struct voice_session_itr itr;
6047 u16 cvs_handle;
6048
6049 pr_debug("%s port_id = %#x set = %d", __func__, port_id, set);
6050
6051 voice_itr_init(&itr, ALL_SESSION_VSID);
6052 while (voice_itr_get_next_session(&itr, &v)) {
6053 if ((v != NULL) &&
6054 (((port_id == VOICE_PLAYBACK_TX) &&
6055 is_sub1_vsid(v->session_id)) ||
6056 ((port_id == VOICE2_PLAYBACK_TX) &&
6057 is_sub2_vsid(v->session_id)))) {
6058
6059 mutex_lock(&v->lock);
6060 v->music_info.port_id = port_id;
6061 v->music_info.play_enable = set;
6062 if (set)
6063 v->music_info.count++;
6064 else
6065 v->music_info.count--;
6066 pr_debug("%s: music_info count=%d\n", __func__,
6067 v->music_info.count);
6068
6069 cvs_handle = voice_get_cvs_handle(v);
6070 if (cvs_handle != 0) {
6071 if (set)
6072 ret = voice_cvs_start_playback(v);
6073 else
6074 ret = voice_cvs_stop_playback(v);
6075 }
6076 mutex_unlock(&v->lock);
6077 } else {
6078 pr_err("%s: Invalid session\n", __func__);
6079 }
6080 }
6081
6082 return ret;
6083}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306084EXPORT_SYMBOL(voc_start_playback);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306085
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306086/**
6087 * voc_disable_topology -
6088 * disable topology for voice session
6089 *
6090 * @session_id: voice session ID to send this command
6091 * @disable: disable value
6092 *
6093 * Returns 0 on success or error on failure
6094 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306095int voc_disable_topology(uint32_t session_id, uint32_t disable)
6096{
6097 struct voice_data *v = voice_get_session(session_id);
6098 int ret = 0;
6099
6100 if (v == NULL) {
6101 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6102
6103 return -EINVAL;
6104 }
6105
6106 mutex_lock(&v->lock);
6107
6108 v->disable_topology = disable;
6109
6110 mutex_unlock(&v->lock);
6111
6112 return ret;
6113}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306114EXPORT_SYMBOL(voc_disable_topology);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306115
6116static int voice_set_packet_exchange_mode_and_config(uint32_t session_id,
6117 uint32_t mode)
6118{
6119 struct voice_data *v = voice_get_session(session_id);
6120 int ret = 0;
6121
6122 if (v == NULL) {
6123 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6124 return -EINVAL;
6125 }
6126
6127 if (v->voc_state != VOC_RUN)
6128 ret = voice_send_cvs_data_exchange_mode_cmd(v);
6129
6130 if (ret) {
6131 pr_err("%s: Error voice_send_data_exchange_mode_cmd %d\n",
6132 __func__, ret);
6133 goto fail;
6134 }
6135
6136 ret = voice_send_cvs_packet_exchange_config_cmd(v);
6137 if (ret) {
6138 pr_err("%s: Error: voice_send_packet_exchange_config_cmd %d\n",
6139 __func__, ret);
6140 goto fail;
6141 }
6142
6143 return ret;
6144fail:
6145 return -EINVAL;
6146}
6147
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306148/**
6149 * voc_set_tx_mute -
6150 * command to send TX mute for voice session
6151 *
6152 * @session_id: voice session ID to send this command
6153 * @dir: RX or TX
6154 * @mute: TX mute value
6155 * @ramp_duration: Ramp duration in ms
6156 *
6157 * Returns 0 on success or error on failure
6158 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306159int voc_set_tx_mute(uint32_t session_id, uint32_t dir, uint32_t mute,
6160 uint32_t ramp_duration)
6161{
6162 struct voice_data *v = NULL;
6163 int ret = 0;
6164 struct voice_session_itr itr;
6165
6166 voice_itr_init(&itr, session_id);
6167 while (voice_itr_get_next_session(&itr, &v)) {
6168 if (v != NULL) {
6169 mutex_lock(&v->lock);
6170 v->stream_tx.stream_mute = mute;
6171 v->stream_tx.stream_mute_ramp_duration_ms =
6172 ramp_duration;
6173 if (is_voc_state_active(v->voc_state) &&
6174 (v->lch_mode == 0))
6175 ret = voice_send_stream_mute_cmd(v,
6176 VSS_IVOLUME_DIRECTION_TX,
6177 v->stream_tx.stream_mute,
6178 v->stream_tx.stream_mute_ramp_duration_ms);
6179 mutex_unlock(&v->lock);
6180 } else {
6181 pr_err("%s: invalid session_id 0x%x\n", __func__,
6182 session_id);
6183
6184 ret = -EINVAL;
6185 break;
6186 }
6187 }
6188
6189 return ret;
6190}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306191EXPORT_SYMBOL(voc_set_tx_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306192
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306193/**
6194 * voc_set_device_mute -
6195 * command to set device mute for voice session
6196 *
6197 * @session_id: voice session ID to send this command
6198 * @dir: RX or TX
6199 * @mute: mute value
6200 * @ramp_duration: Ramp duration in ms
6201 *
6202 * Returns 0 on success or error on failure
6203 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306204int voc_set_device_mute(uint32_t session_id, uint32_t dir, uint32_t mute,
6205 uint32_t ramp_duration)
6206{
6207 struct voice_data *v = NULL;
6208 int ret = 0;
6209 struct voice_session_itr itr;
6210
6211 voice_itr_init(&itr, session_id);
6212 while (voice_itr_get_next_session(&itr, &v)) {
6213 if (v != NULL) {
6214 mutex_lock(&v->lock);
6215 if (dir == VSS_IVOLUME_DIRECTION_TX) {
6216 v->dev_tx.dev_mute = mute;
6217 v->dev_tx.dev_mute_ramp_duration_ms =
6218 ramp_duration;
6219 } else {
6220 v->dev_rx.dev_mute = mute;
6221 v->dev_rx.dev_mute_ramp_duration_ms =
6222 ramp_duration;
6223 }
6224
6225 if (((v->voc_state == VOC_RUN) ||
6226 (v->voc_state == VOC_STANDBY)) &&
6227 (v->lch_mode == 0))
6228 ret = voice_send_device_mute_cmd(v,
6229 dir,
6230 mute,
6231 ramp_duration);
6232 mutex_unlock(&v->lock);
6233 } else {
6234 pr_err("%s: invalid session_id 0x%x\n", __func__,
6235 session_id);
6236
6237 ret = -EINVAL;
6238 break;
6239 }
6240 }
6241
6242 return ret;
6243}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306244EXPORT_SYMBOL(voc_set_device_mute);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306245
6246int voc_get_rx_device_mute(uint32_t session_id)
6247{
6248 struct voice_data *v = voice_get_session(session_id);
6249 int ret = 0;
6250
6251 if (v == NULL) {
6252 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6253
6254 return -EINVAL;
6255 }
6256
6257 mutex_lock(&v->lock);
6258
6259 ret = v->dev_rx.dev_mute;
6260
6261 mutex_unlock(&v->lock);
6262
6263 return ret;
6264}
6265
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306266/**
6267 * voc_set_tty_mode -
6268 * Update tty mode for voice session
6269 *
6270 * @session_id: voice session ID
6271 * @tty_mode: TTY mode value
6272 *
6273 * Returns 0 on success or error on failure
6274 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306275int voc_set_tty_mode(uint32_t session_id, uint8_t tty_mode)
6276{
6277 struct voice_data *v = voice_get_session(session_id);
6278 int ret = 0;
6279
6280 if (v == NULL) {
6281 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6282
6283 return -EINVAL;
6284 }
6285
6286 mutex_lock(&v->lock);
6287
6288 v->tty_mode = tty_mode;
6289
6290 mutex_unlock(&v->lock);
6291
6292 return ret;
6293}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306294EXPORT_SYMBOL(voc_set_tty_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306295
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306296/**
6297 * voc_get_tty_mode -
6298 * Retrieve tty mode for voice session
6299 *
6300 * @session_id: voice session ID
6301 *
6302 * Returns 0 on success or error on failure
6303 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306304uint8_t voc_get_tty_mode(uint32_t session_id)
6305{
6306 struct voice_data *v = voice_get_session(session_id);
6307 int ret = 0;
6308
6309 if (v == NULL) {
6310 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6311
6312 return -EINVAL;
6313 }
6314
6315 mutex_lock(&v->lock);
6316
6317 ret = v->tty_mode;
6318
6319 mutex_unlock(&v->lock);
6320
6321 return ret;
6322}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306323EXPORT_SYMBOL(voc_get_tty_mode);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306324
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306325/**
6326 * voc_set_pp_enable -
6327 * Command to set PP for voice module
6328 *
6329 * @session_id: voice session ID to send this command
6330 * @module_id: voice module id
6331 * @enable: enable/disable flag
6332 *
6333 * Returns 0 on success or error on failure
6334 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306335int voc_set_pp_enable(uint32_t session_id, uint32_t module_id, uint32_t enable)
6336{
6337 struct voice_data *v = NULL;
6338 int ret = 0;
6339 struct voice_session_itr itr;
6340
6341 voice_itr_init(&itr, session_id);
6342 while (voice_itr_get_next_session(&itr, &v)) {
6343 if (v != NULL) {
6344 if (!(is_voice_app_id(v->session_id)))
6345 continue;
6346
6347 mutex_lock(&v->lock);
6348 if (module_id == MODULE_ID_VOICE_MODULE_ST)
6349 v->st_enable = enable;
6350
6351 if (v->voc_state == VOC_RUN) {
6352 if ((module_id == MODULE_ID_VOICE_MODULE_ST) &&
6353 (!v->tty_mode))
6354 ret = voice_send_set_pp_enable_cmd(v,
6355 MODULE_ID_VOICE_MODULE_ST,
6356 enable);
6357 }
6358 mutex_unlock(&v->lock);
6359 } else {
6360 pr_err("%s: invalid session_id 0x%x\n", __func__,
6361 session_id);
6362 ret = -EINVAL;
6363 break;
6364 }
6365 }
6366
6367 return ret;
6368}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306369EXPORT_SYMBOL(voc_set_pp_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306370
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306371/**
6372 * voc_set_hd_enable -
6373 * Command to set HD for voice session
6374 *
6375 * @session_id: voice session ID to send this command
6376 * @enable: enable/disable flag
6377 *
6378 * Returns 0 on success or error on failure
6379 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306380int voc_set_hd_enable(uint32_t session_id, uint32_t enable)
6381{
6382 struct voice_data *v = NULL;
6383 int ret = 0;
6384 struct voice_session_itr itr;
6385
6386 voice_itr_init(&itr, session_id);
6387 while (voice_itr_get_next_session(&itr, &v)) {
6388 if (v != NULL) {
6389 mutex_lock(&v->lock);
6390 v->hd_enable = enable;
6391
6392 if (v->voc_state == VOC_RUN)
6393 ret = voice_send_hd_cmd(v, enable);
6394
6395 mutex_unlock(&v->lock);
6396 } else {
6397 pr_err("%s: invalid session_id 0x%x\n", __func__,
6398 session_id);
6399 ret = -EINVAL;
6400 break;
6401 }
6402 }
6403
6404 return ret;
6405}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306406EXPORT_SYMBOL(voc_set_hd_enable);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306407
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306408/**
6409 * voc_set_afe_sidetone -
6410 * Command to set sidetone at AFE
6411 *
6412 * @session_id: voice session ID to send this command
6413 * @sidetone_enable: enable/disable flag for sidetone
6414 *
6415 * Returns 0 on success or error on failure
6416 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306417int voc_set_afe_sidetone(uint32_t session_id, bool sidetone_enable)
6418{
6419 struct voice_data *v = NULL;
6420 int ret = -EINVAL;
6421 struct voice_session_itr itr;
6422 u16 rx_port, tx_port;
6423
6424 common.sidetone_enable = sidetone_enable;
6425 voice_itr_init(&itr, session_id);
6426 while (voice_itr_get_next_session(&itr, &v)) {
6427 if (v == NULL) {
6428 pr_err("%s: invalid session_id 0x%x\n", __func__,
6429 session_id);
6430 ret = -EINVAL;
6431 break;
6432 }
6433 mutex_lock(&v->lock);
6434 if (v->voc_state != VOC_RUN) {
6435 mutex_unlock(&v->lock);
6436 continue;
6437 }
6438 rx_port = v->dev_rx.port_id;
6439 tx_port = v->dev_tx.port_id;
6440 ret = afe_sidetone_enable(tx_port, rx_port,
6441 sidetone_enable);
6442 if (!ret) {
6443 mutex_unlock(&v->lock);
6444 break;
6445 }
6446 mutex_unlock(&v->lock);
6447 }
6448 return ret;
6449}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306450EXPORT_SYMBOL(voc_set_afe_sidetone);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306451
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306452/**
6453 * voc_get_afe_sidetone -
6454 * Retrieve sidetone status at AFE
6455 *
6456 * Returns sidetone enable status
6457 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306458bool voc_get_afe_sidetone(void)
6459{
6460 bool ret;
6461
6462 ret = common.sidetone_enable;
6463 return ret;
6464}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306465EXPORT_SYMBOL(voc_get_afe_sidetone);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306466
6467int voc_get_pp_enable(uint32_t session_id, uint32_t module_id)
6468{
6469 struct voice_data *v = voice_get_session(session_id);
6470 int ret = 0;
6471
6472 if (v == NULL) {
6473 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6474
6475 return -EINVAL;
6476 }
6477
6478 mutex_lock(&v->lock);
6479 if (module_id == MODULE_ID_VOICE_MODULE_ST)
6480 ret = v->st_enable;
6481 mutex_unlock(&v->lock);
6482
6483 return ret;
6484}
6485
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306486/**
6487 * voc_set_rx_vol_step -
6488 * command to send voice RX volume in step value
6489 *
6490 * @session_id: voice session ID
6491 * @dir: direction RX or TX
6492 * @vol_step: Volume step value
6493 * @ramp_duration: Ramp duration in ms
6494 *
6495 * Returns 0 on success or -EINVAL on failure
6496 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306497int voc_set_rx_vol_step(uint32_t session_id, uint32_t dir, uint32_t vol_step,
6498 uint32_t ramp_duration)
6499{
6500 struct voice_data *v = NULL;
6501 int ret = 0;
6502 struct voice_session_itr itr;
6503
6504 pr_debug("%s session id = %#x vol = %u", __func__, session_id,
6505 vol_step);
6506
6507 voice_itr_init(&itr, session_id);
6508 while (voice_itr_get_next_session(&itr, &v)) {
6509 if (v != NULL) {
6510 mutex_lock(&v->lock);
6511 v->dev_rx.volume_step_value = vol_step;
6512 v->dev_rx.volume_ramp_duration_ms = ramp_duration;
6513 if (is_voc_state_active(v->voc_state))
6514 ret = voice_send_vol_step_cmd(v);
6515 mutex_unlock(&v->lock);
6516 } else {
6517 pr_err("%s: invalid session_id 0x%x\n", __func__,
6518 session_id);
6519
6520 ret = -EINVAL;
6521 break;
6522 }
6523 }
6524
6525 return ret;
6526}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306527EXPORT_SYMBOL(voc_set_rx_vol_step);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306528
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306529/**
6530 * voc_set_device_config -
6531 * Set voice path config for RX or TX
6532 *
6533 * @session_id: voice session ID
6534 * @path_dir: direction RX or TX
6535 * @finfo: format config info
6536 *
6537 * Returns 0 on success or -EINVAL on failure
6538 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306539int voc_set_device_config(uint32_t session_id, uint8_t path_dir,
6540 struct media_format_info *finfo)
6541{
6542 struct voice_data *v = voice_get_session(session_id);
6543
6544 if (v == NULL) {
6545 pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
6546
6547 return -EINVAL;
6548 }
6549
6550 pr_debug("%s: path_dir=%d port_id=%x, channels=%d, sample_rate=%d, bits_per_sample=%d\n",
6551 __func__, path_dir, finfo->port_id, finfo->num_channels,
6552 finfo->sample_rate, finfo->bits_per_sample);
6553
6554 mutex_lock(&v->lock);
6555 switch (path_dir) {
6556 case RX_PATH:
6557 v->dev_rx.port_id = q6audio_get_port_id(finfo->port_id);
6558 v->dev_rx.no_of_channels = finfo->num_channels;
6559 v->dev_rx.sample_rate = finfo->sample_rate;
6560 v->dev_rx.bits_per_sample = finfo->bits_per_sample;
6561 memcpy(&v->dev_rx.channel_mapping, &finfo->channel_mapping,
6562 VSS_CHANNEL_MAPPING_SIZE);
6563 break;
6564 case TX_PATH:
6565 v->dev_tx.port_id = q6audio_get_port_id(finfo->port_id);
6566 v->dev_tx.no_of_channels = finfo->num_channels;
6567 v->dev_tx.sample_rate = finfo->sample_rate;
6568 v->dev_tx.bits_per_sample = finfo->bits_per_sample;
6569 memcpy(&v->dev_tx.channel_mapping, &finfo->channel_mapping,
6570 VSS_CHANNEL_MAPPING_SIZE);
6571 break;
6572 default:
6573 pr_err("%s: Invalid path_dir %d\n", __func__, path_dir);
6574 return -EINVAL;
6575 }
6576
6577 mutex_unlock(&v->lock);
6578
6579 return 0;
6580}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306581EXPORT_SYMBOL(voc_set_device_config);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306582
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306583/**
6584 * voc_set_ext_ec_ref_media_fmt_info -
6585 * Update voice EC media format info
6586 *
6587 * @finfo: media format info
6588 *
6589 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306590int voc_set_ext_ec_ref_media_fmt_info(struct media_format_info *finfo)
6591{
6592 mutex_lock(&common.common_lock);
6593 if (common.ec_ref_ext) {
6594 common.ec_media_fmt_info.num_channels = finfo->num_channels;
6595 common.ec_media_fmt_info.bits_per_sample =
6596 finfo->bits_per_sample;
6597 common.ec_media_fmt_info.sample_rate = finfo->sample_rate;
6598 memcpy(&common.ec_media_fmt_info.channel_mapping,
6599 &finfo->channel_mapping, VSS_CHANNEL_MAPPING_SIZE);
6600 } else {
6601 pr_debug("%s: Ext Ec Ref not active, returning", __func__);
6602 }
6603 mutex_unlock(&common.common_lock);
6604 return 0;
6605}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306606EXPORT_SYMBOL(voc_set_ext_ec_ref_media_fmt_info);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306607
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306608/**
6609 * voc_set_route_flag -
6610 * Set voice route state for RX or TX
6611 *
6612 * @session_id: voice session ID
6613 * @path_dir: direction RX or TX
6614 * @set: Value of route state to set
6615 *
6616 * Returns 0 on success or -EINVAL on failure
6617 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306618int voc_set_route_flag(uint32_t session_id, uint8_t path_dir, uint8_t set)
6619{
6620 struct voice_data *v = voice_get_session(session_id);
6621
6622 if (v == NULL) {
6623 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6624
6625 return -EINVAL;
6626 }
6627
6628 pr_debug("%s: path_dir=%d, set=%d\n", __func__, path_dir, set);
6629
6630 mutex_lock(&v->lock);
6631
6632 if (path_dir == RX_PATH)
6633 v->voc_route_state.rx_route_flag = set;
6634 else
6635 v->voc_route_state.tx_route_flag = set;
6636
6637 mutex_unlock(&v->lock);
6638
6639 return 0;
6640}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306641EXPORT_SYMBOL(voc_set_route_flag);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306642
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306643/**
6644 * voc_get_route_flag -
6645 * Retrieve voice route state for RX or TX
6646 *
6647 * @session_id: voice session ID
6648 * @path_dir: direction RX or TX
6649 *
6650 * Returns route state on success or 0 on failure
6651 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306652uint8_t voc_get_route_flag(uint32_t session_id, uint8_t path_dir)
6653{
6654 struct voice_data *v = voice_get_session(session_id);
6655 int ret = 0;
6656
6657 if (v == NULL) {
6658 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6659
6660 return 0;
6661 }
6662
6663 mutex_lock(&v->lock);
6664
6665 if (path_dir == RX_PATH)
6666 ret = v->voc_route_state.rx_route_flag;
6667 else
6668 ret = v->voc_route_state.tx_route_flag;
6669
6670 mutex_unlock(&v->lock);
6671
6672 return ret;
6673}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306674EXPORT_SYMBOL(voc_get_route_flag);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306675
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306676/**
6677 * voc_end_voice_call -
6678 * command to end voice call
6679 *
6680 * @session_id: voice session ID to send this command
6681 *
6682 * Returns 0 on success or error on failure
6683 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306684int voc_end_voice_call(uint32_t session_id)
6685{
6686 struct voice_data *v = voice_get_session(session_id);
6687 int ret = 0;
6688
6689 if (v == NULL) {
6690 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
6691
6692 return -EINVAL;
6693 }
6694
6695 mutex_lock(&v->lock);
6696
6697 if (v->voc_state == VOC_RUN || v->voc_state == VOC_ERROR ||
6698 v->voc_state == VOC_CHANGE || v->voc_state == VOC_STANDBY) {
6699
6700 pr_debug("%s: VOC_STATE: %d\n", __func__, v->voc_state);
6701
6702 ret = voice_destroy_vocproc(v);
6703 if (ret < 0)
6704 pr_err("%s: destroy voice failed\n", __func__);
6705
6706 voc_update_session_params(v);
6707
6708 voice_destroy_mvm_cvs_session(v);
6709 v->voc_state = VOC_RELEASE;
6710 } else {
6711 pr_err("%s: Error: End voice called in state %d\n",
6712 __func__, v->voc_state);
6713
6714 ret = -EINVAL;
6715 }
6716
6717 mutex_unlock(&v->lock);
6718 return ret;
6719}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306720EXPORT_SYMBOL(voc_end_voice_call);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306721
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306722/**
6723 * voc_standby_voice_call -
6724 * command to standy voice call
6725 *
6726 * @session_id: voice session ID to send this command
6727 *
6728 * Returns 0 on success or error on failure
6729 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306730int voc_standby_voice_call(uint32_t session_id)
6731{
6732 struct voice_data *v = voice_get_session(session_id);
6733 struct apr_hdr mvm_standby_voice_cmd;
6734 void *apr_mvm;
6735 u16 mvm_handle;
6736 int ret = 0;
6737
6738 if (v == NULL) {
6739 pr_err("%s: v is NULL\n", __func__);
6740 return -EINVAL;
6741 }
6742 pr_debug("%s: voc state=%d", __func__, v->voc_state);
6743
6744 if (v->voc_state == VOC_RUN) {
6745 apr_mvm = common.apr_q6_mvm;
6746 if (!apr_mvm) {
6747 pr_err("%s: apr_mvm is NULL.\n", __func__);
6748 ret = -EINVAL;
6749 goto fail;
6750 }
6751 mvm_handle = voice_get_mvm_handle(v);
6752 mvm_standby_voice_cmd.hdr_field =
6753 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
6754 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
6755 mvm_standby_voice_cmd.pkt_size =
6756 APR_PKT_SIZE(APR_HDR_SIZE,
6757 sizeof(mvm_standby_voice_cmd) - APR_HDR_SIZE);
6758 pr_debug("send mvm_standby_voice_cmd pkt size = %d\n",
6759 mvm_standby_voice_cmd.pkt_size);
6760 mvm_standby_voice_cmd.src_port =
6761 voice_get_idx_for_session(v->session_id);
6762 mvm_standby_voice_cmd.dest_port = mvm_handle;
6763 mvm_standby_voice_cmd.token = 0;
6764 mvm_standby_voice_cmd.opcode = VSS_IMVM_CMD_STANDBY_VOICE;
6765 v->mvm_state = CMD_STATUS_FAIL;
6766 ret = apr_send_pkt(apr_mvm,
6767 (uint32_t *)&mvm_standby_voice_cmd);
6768 if (ret < 0) {
6769 pr_err("Fail in sending VSS_IMVM_CMD_STANDBY_VOICE\n");
6770 ret = -EINVAL;
6771 goto fail;
6772 }
6773 v->voc_state = VOC_STANDBY;
6774 }
6775fail:
6776 return ret;
6777}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306778EXPORT_SYMBOL(voc_standby_voice_call);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306779
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306780/**
6781 * voc_disable_device -
6782 * command to pause call and disable voice path
6783 *
6784 * @session_id: voice session ID to send this command
6785 *
6786 * Returns 0 on success or error on failure
6787 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306788int voc_disable_device(uint32_t session_id)
6789{
6790 struct voice_data *v = voice_get_session(session_id);
6791 int ret = 0;
6792
6793 if (v == NULL) {
6794 pr_err("%s: v is NULL\n", __func__);
6795 return -EINVAL;
6796 }
6797
6798 pr_debug("%s: voc state=%d\n", __func__, v->voc_state);
6799
6800 mutex_lock(&v->lock);
6801 if (v->voc_state == VOC_RUN) {
6802 ret = voice_pause_voice_call(v);
6803 if (ret < 0) {
6804 pr_err("%s: Pause Voice Call failed for session 0x%x, err %d!\n",
6805 __func__, v->session_id, ret);
6806 goto done;
6807 }
6808 rtac_remove_voice(voice_get_cvs_handle(v));
6809 voice_send_cvp_deregister_vol_cal_cmd(v);
6810 voice_send_cvp_deregister_cal_cmd(v);
6811 voice_send_cvp_deregister_dev_cfg_cmd(v);
6812
6813 v->voc_state = VOC_CHANGE;
6814 } else {
6815 pr_debug("%s: called in voc state=%d, No_OP\n",
6816 __func__, v->voc_state);
6817 }
6818
6819done:
6820 mutex_unlock(&v->lock);
6821
6822 return ret;
6823}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306824EXPORT_SYMBOL(voc_disable_device);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306825
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306826/**
6827 * voc_enable_device -
6828 * command to enable voice path and start call
6829 *
6830 * @session_id: voice session ID to send this command
6831 *
6832 * Returns 0 on success or error on failure
6833 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306834int voc_enable_device(uint32_t session_id)
6835{
6836 struct voice_data *v = voice_get_session(session_id);
6837 int ret = 0;
6838
6839 if (v == NULL) {
6840 pr_err("%s: v is NULL\n", __func__);
6841 return -EINVAL;
6842 }
6843
6844 pr_debug("%s: voc state=%d\n", __func__, v->voc_state);
6845 mutex_lock(&v->lock);
6846 if (v->voc_state == VOC_CHANGE) {
6847 ret = voice_send_tty_mode_cmd(v);
6848 if (ret < 0) {
6849 pr_err("%s: Sending TTY mode failed, ret=%d\n",
6850 __func__, ret);
6851 /* Not a critical error, allow voice call to continue */
6852 }
6853
6854 if (v->tty_mode) {
6855 /* disable slowtalk */
6856 voice_send_set_pp_enable_cmd(v,
6857 MODULE_ID_VOICE_MODULE_ST,
6858 0);
6859 } else {
6860 /* restore slowtalk */
6861 voice_send_set_pp_enable_cmd(v,
6862 MODULE_ID_VOICE_MODULE_ST,
6863 v->st_enable);
6864 }
6865
6866 ret = voice_send_set_device_cmd(v);
6867 if (ret < 0) {
6868 pr_err("%s: Set device failed, ret=%d\n",
6869 __func__, ret);
6870 goto done;
6871 }
6872
6873 ret = voice_send_cvp_media_fmt_info_cmd(v);
6874 if (ret < 0) {
6875 pr_err("%s: Set format failed err:%d\n", __func__, ret);
6876 goto done;
6877 }
6878
6879 ret = voice_send_cvp_topology_commit_cmd(v);
6880 if (ret < 0) {
6881 pr_err("%s: Set topology commit failed\n", __func__);
6882 goto done;
6883 }
6884
Laxminath Kasam38070be2017-08-17 18:21:59 +05306885 /* Send MFC config only when the no of channels are > 1 */
6886 if (v->dev_rx.no_of_channels > NUM_CHANNELS_MONO) {
6887 ret = voice_send_cvp_mfc_config_cmd(v);
6888 if (ret < 0) {
6889 pr_warn("%s: Set mfc config failed err: %d\n",
6890 __func__, ret);
6891 }
6892 }
6893
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306894 voice_send_cvp_register_dev_cfg_cmd(v);
6895 voice_send_cvp_register_cal_cmd(v);
6896 voice_send_cvp_register_vol_cal_cmd(v);
6897
6898 rtac_add_voice(voice_get_cvs_handle(v),
6899 voice_get_cvp_handle(v),
6900 v->dev_rx.port_id, v->dev_tx.port_id,
6901 v->dev_rx.dev_id, v->dev_tx.dev_id,
6902 v->session_id);
6903
6904 ret = voice_send_start_voice_cmd(v);
6905 if (ret < 0) {
6906 pr_err("%s: Fail in sending START_VOICE, ret=%d\n",
6907 __func__, ret);
6908 goto done;
6909 }
6910 v->voc_state = VOC_RUN;
6911 } else {
6912 pr_debug("%s: called in voc state=%d, No_OP\n",
6913 __func__, v->voc_state);
6914 }
6915
6916done:
6917 mutex_unlock(&v->lock);
6918
6919 return ret;
6920}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306921EXPORT_SYMBOL(voc_enable_device);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306922
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306923/**
6924 * voc_set_lch -
6925 * command to set hold/unhold call state
6926 *
6927 * @session_id: voice session ID to send this command
6928 * @lch_mode: LCH mode to set
6929 *
6930 * Returns 0 on success or error on failure
6931 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306932int voc_set_lch(uint32_t session_id, enum voice_lch_mode lch_mode)
6933{
6934 struct voice_data *v = voice_get_session(session_id);
6935 int ret = 0;
6936
6937 if (v == NULL) {
6938 pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id);
6939
6940 ret = -EINVAL;
6941 goto done;
6942 }
6943
6944 mutex_lock(&v->lock);
6945 if (v->lch_mode == lch_mode) {
6946 pr_debug("%s: Session %d already in LCH mode %d\n",
6947 __func__, session_id, lch_mode);
6948
6949 mutex_unlock(&v->lock);
6950 goto done;
6951 }
6952
6953 v->lch_mode = lch_mode;
6954 mutex_unlock(&v->lock);
6955
6956 ret = voc_lch_ops(v, v->lch_mode);
6957 if (ret < 0) {
6958 pr_err("%s: lch ops failed %d\n", __func__, ret);
6959 goto done;
6960 }
6961
6962done:
6963 return ret;
6964}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306965EXPORT_SYMBOL(voc_set_lch);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306966
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306967/**
6968 * voc_resume_voice_call -
6969 * command to resume voice call
6970 *
6971 * @session_id: voice session ID to send this command
6972 *
6973 * Returns 0 on success or error on failure
6974 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306975int voc_resume_voice_call(uint32_t session_id)
6976{
6977 struct voice_data *v = voice_get_session(session_id);
6978 int ret = 0;
6979
6980 ret = voice_send_start_voice_cmd(v);
6981 if (ret < 0) {
6982 pr_err("Fail in sending START_VOICE\n");
6983 goto fail;
6984 }
6985 v->voc_state = VOC_RUN;
6986 return 0;
6987fail:
6988 return -EINVAL;
6989}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306990EXPORT_SYMBOL(voc_resume_voice_call);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05306991
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05306992/**
6993 * voc_start_voice_call -
6994 * command to start voice call
6995 *
6996 * @session_id: voice session ID to send this command
6997 *
6998 * Returns 0 on success or error on failure
6999 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307000int voc_start_voice_call(uint32_t session_id)
7001{
7002 struct voice_data *v = voice_get_session(session_id);
7003 int ret = 0;
7004
7005 if (v == NULL) {
7006 pr_err("%s: invalid session_id 0x%x\n", __func__, session_id);
7007
7008 return -EINVAL;
7009 }
7010
7011 mutex_lock(&v->lock);
7012
7013 if (v->voc_state == VOC_ERROR) {
7014 pr_debug("%s: VOC in ERR state\n", __func__);
7015
7016 voice_destroy_mvm_cvs_session(v);
7017 v->voc_state = VOC_INIT;
7018 }
7019
7020 if ((v->voc_state == VOC_INIT) ||
7021 (v->voc_state == VOC_RELEASE)) {
7022 ret = voice_apr_register(session_id);
7023 if (ret < 0) {
7024 pr_err("%s: apr register failed\n", __func__);
7025 goto fail;
7026 }
7027
7028 if (is_cvd_version_queried()) {
7029 pr_debug("%s: Returning the cached value %s\n",
7030 __func__, common.cvd_version);
7031 } else {
7032 ret = voice_send_mvm_cvd_version_cmd(v);
7033 if (ret < 0)
7034 pr_debug("%s: Error retrieving CVD version %d\n",
7035 __func__, ret);
7036 }
7037
7038 ret = voice_create_mvm_cvs_session(v);
7039 if (ret < 0) {
7040 pr_err("create mvm and cvs failed\n");
7041 goto fail;
7042 }
7043
7044 if (is_voip_session(session_id)) {
7045 /* Allocate oob mem if not already allocated and
7046 * memory map the oob memory block.
7047 */
7048 ret = voice_alloc_and_map_oob_mem(v);
7049 if (ret < 0) {
7050 pr_err("%s: voice_alloc_and_map_oob_mem() failed, ret:%d\n",
7051 __func__, ret);
7052
7053 goto fail;
7054 }
7055
7056 ret = voice_set_packet_exchange_mode_and_config(
7057 session_id,
7058 VSS_ISTREAM_PACKET_EXCHANGE_MODE_OUT_OF_BAND);
7059 if (ret) {
7060 pr_err("%s: Err: exchange_mode_and_config %d\n",
7061 __func__, ret);
7062
7063 goto fail;
7064 }
7065 }
7066 ret = voice_send_dual_control_cmd(v);
7067 if (ret < 0) {
7068 pr_err("Err Dual command failed\n");
7069 goto fail;
7070 }
7071 ret = voice_setup_vocproc(v);
7072 if (ret < 0) {
7073 pr_err("setup voice failed\n");
7074 goto fail;
7075 }
7076
7077 ret = voice_send_vol_step_cmd(v);
7078 if (ret < 0)
7079 pr_err("voice volume failed\n");
7080
7081 ret = voice_send_stream_mute_cmd(v,
7082 VSS_IVOLUME_DIRECTION_TX,
7083 v->stream_tx.stream_mute,
7084 v->stream_tx.stream_mute_ramp_duration_ms);
7085 if (ret < 0)
7086 pr_err("voice mute failed\n");
7087
7088 ret = voice_send_start_voice_cmd(v);
7089 if (ret < 0) {
7090 pr_err("start voice failed\n");
7091 goto fail;
7092 }
7093
7094 v->voc_state = VOC_RUN;
7095 } else {
7096 pr_err("%s: Error: Start voice called in state %d\n",
7097 __func__, v->voc_state);
7098
7099 ret = -EINVAL;
7100 goto fail;
7101 }
7102fail:
7103 mutex_unlock(&v->lock);
7104 return ret;
7105}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307106EXPORT_SYMBOL(voc_start_voice_call);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307107
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307108/**
7109 * voc_set_ext_ec_ref_port_id -
7110 * Set EC ref port id
7111 *
7112 * Returns 0 on success or -EINVAL on failure
7113 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307114int voc_set_ext_ec_ref_port_id(uint16_t port_id, bool state)
7115{
7116 int ret = 0;
7117
7118 mutex_lock(&common.common_lock);
7119 if (state == true) {
7120 if (port_id == AFE_PORT_INVALID) {
7121 pr_err("%s: Invalid port id", __func__);
7122 ret = -EINVAL;
7123 goto exit;
7124 }
7125 common.ec_ref_ext = true;
7126 } else {
7127 common.ec_ref_ext = false;
7128 }
7129 /* Cache EC Fromat Info in common */
7130 common.ec_media_fmt_info.port_id = port_id;
7131exit:
7132 mutex_unlock(&common.common_lock);
7133 return ret;
7134}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307135EXPORT_SYMBOL(voc_set_ext_ec_ref_port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307136
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307137/**
7138 * voc_get_ext_ec_ref_port_id -
7139 * Retrieve EC ref port id
7140 *
7141 * Returns EC Ref port id if present
7142 * otherwise AFE_PORT_INVALID
7143 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307144int voc_get_ext_ec_ref_port_id(void)
7145{
7146 if (common.ec_ref_ext)
7147 return common.ec_media_fmt_info.port_id;
7148 else
7149 return AFE_PORT_INVALID;
7150}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307151EXPORT_SYMBOL(voc_get_ext_ec_ref_port_id);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307152
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307153/**
7154 * voc_register_mvs_cb -
7155 * Update callback info for mvs
7156 *
7157 * @ul_cb: Uplink callback fn
7158 * @dl_cb: downlink callback fn
7159 * ssr_cb: SSR callback fn
7160 * @private_data: private data of mvs
7161 *
7162 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307163void voc_register_mvs_cb(ul_cb_fn ul_cb,
7164 dl_cb_fn dl_cb,
7165 voip_ssr_cb ssr_cb,
7166 void *private_data)
7167{
7168 common.mvs_info.ul_cb = ul_cb;
7169 common.mvs_info.dl_cb = dl_cb;
7170 common.mvs_info.ssr_cb = ssr_cb;
7171 common.mvs_info.private_data = private_data;
7172}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307173EXPORT_SYMBOL(voc_register_mvs_cb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307174
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307175/**
7176 * voc_register_dtmf_rx_detection_cb -
7177 * Update callback info for dtmf
7178 *
7179 * @dtmf_rx_ul_cb: DTMF uplink RX callback fn
7180 * @private_data: private data of dtmf info
7181 *
7182 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307183void voc_register_dtmf_rx_detection_cb(dtmf_rx_det_cb_fn dtmf_rx_ul_cb,
7184 void *private_data)
7185{
7186 common.dtmf_info.dtmf_rx_ul_cb = dtmf_rx_ul_cb;
7187 common.dtmf_info.private_data = private_data;
7188}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307189EXPORT_SYMBOL(voc_register_dtmf_rx_detection_cb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307190
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307191/**
7192 * voc_config_vocoder -
7193 * Update config for mvs params.
7194 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307195void voc_config_vocoder(uint32_t media_type,
7196 uint32_t rate,
7197 uint32_t network_type,
7198 uint32_t dtx_mode,
7199 uint32_t evrc_min_rate,
7200 uint32_t evrc_max_rate)
7201{
7202 common.mvs_info.media_type = media_type;
7203 common.mvs_info.rate = rate;
7204 common.mvs_info.network_type = network_type;
7205 common.mvs_info.dtx_mode = dtx_mode;
7206 common.mvs_info.evrc_min_rate = evrc_min_rate;
7207 common.mvs_info.evrc_max_rate = evrc_max_rate;
7208}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05307209EXPORT_SYMBOL(voc_config_vocoder);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307210
7211static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv)
7212{
7213 uint32_t *ptr = NULL;
7214 struct common_data *c = NULL;
7215 struct voice_data *v = NULL;
7216 int i = 0;
7217 struct vss_iversion_rsp_get_t *version_rsp = NULL;
7218
7219 if ((data == NULL) || (priv == NULL)) {
7220 pr_err("%s: data or priv is NULL\n", __func__);
7221 return -EINVAL;
7222 }
7223
7224 c = priv;
7225
7226 pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
7227 data->payload_size, data->opcode);
7228
7229 if (data->opcode == RESET_EVENTS) {
7230 pr_debug("%s: Reset event received in Voice service\n",
7231 __func__);
7232
7233 if (common.mvs_info.ssr_cb) {
7234 pr_debug("%s: Informing reset event to VoIP\n",
7235 __func__);
7236 common.mvs_info.ssr_cb(data->opcode,
7237 common.mvs_info.private_data);
7238 }
7239
7240 apr_reset(c->apr_q6_mvm);
7241 c->apr_q6_mvm = NULL;
7242
7243 /* clean up memory handle */
7244 c->cal_mem_handle = 0;
7245 c->rtac_mem_handle = 0;
7246 cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
7247 common.cal_data);
7248 rtac_clear_mapping(VOICE_RTAC_CAL);
7249
7250 /* Sub-system restart is applicable to all sessions. */
7251 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
7252 c->voice[i].mvm_handle = 0;
7253 c->voice[i].shmem_info.mem_handle = 0;
7254 }
7255
7256 /* Free the ION memory and clear handles for Source Tracking */
7257 if (is_source_tracking_shared_memomry_allocated()) {
7258 msm_audio_ion_free(
7259 common.source_tracking_sh_mem.sh_mem_block.client,
7260 common.source_tracking_sh_mem.sh_mem_block.handle);
7261 common.source_tracking_sh_mem.mem_handle = 0;
7262 common.source_tracking_sh_mem.sh_mem_block.client =
7263 NULL;
7264 common.source_tracking_sh_mem.sh_mem_block.handle =
7265 NULL;
7266 }
7267 /* clean up srvcc rec flag */
7268 c->srvcc_rec_flag = false;
7269 voc_set_error_state(data->reset_proc);
7270 return 0;
7271 }
7272
7273 pr_debug("%s: session_idx 0x%x\n", __func__, data->dest_port);
7274
7275 v = voice_get_session_by_idx(data->dest_port);
7276 if (v == NULL) {
7277 pr_err("%s: v is NULL\n", __func__);
7278
7279 return -EINVAL;
7280 }
7281
7282 if (data->opcode == APR_BASIC_RSP_RESULT) {
7283 if (data->payload_size) {
7284 ptr = data->payload;
7285
7286 pr_debug("%x %x\n", ptr[0], ptr[1]);
7287 /* ping mvm service ACK */
7288 switch (ptr[0]) {
7289 case VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION:
7290 case VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION:
7291 /* Passive session is used for CS call
7292 * Full session is used for VoIP call.
7293 */
7294 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7295 if (!ptr[1]) {
7296 pr_debug("%s: MVM handle is %d\n",
7297 __func__, data->src_port);
7298 voice_set_mvm_handle(v, data->src_port);
7299 } else
7300 pr_err("got NACK for sending MVM create session\n");
7301 v->mvm_state = CMD_STATUS_SUCCESS;
7302 v->async_err = ptr[1];
7303 wake_up(&v->mvm_wait);
7304 break;
7305 case VSS_IMVM_CMD_START_VOICE:
7306 case VSS_IMVM_CMD_ATTACH_VOCPROC:
7307 case VSS_IMVM_CMD_STOP_VOICE:
7308 case VSS_IMVM_CMD_DETACH_VOCPROC:
7309 case VSS_ISTREAM_CMD_SET_TTY_MODE:
7310 case APRV2_IBASIC_CMD_DESTROY_SESSION:
7311 case VSS_IMVM_CMD_ATTACH_STREAM:
7312 case VSS_IMVM_CMD_DETACH_STREAM:
7313 case VSS_ICOMMON_CMD_SET_NETWORK:
7314 case VSS_ICOMMON_CMD_SET_VOICE_TIMING:
7315 case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL:
7316 case VSS_IMVM_CMD_SET_CAL_NETWORK:
7317 case VSS_IMVM_CMD_SET_CAL_MEDIA_TYPE:
7318 case VSS_IMEMORY_CMD_MAP_PHYSICAL:
7319 case VSS_IMEMORY_CMD_UNMAP:
7320 case VSS_IMVM_CMD_PAUSE_VOICE:
7321 case VSS_IMVM_CMD_STANDBY_VOICE:
7322 case VSS_IHDVOICE_CMD_ENABLE:
7323 case VSS_IHDVOICE_CMD_DISABLE:
7324 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7325 v->mvm_state = CMD_STATUS_SUCCESS;
7326 v->async_err = ptr[1];
7327 wake_up(&v->mvm_wait);
7328 break;
7329 case VSS_IVERSION_CMD_GET:
7330 pr_debug("%s: Error retrieving CVD Version, error:%d\n",
7331 __func__, ptr[1]);
7332
7333 strlcpy(common.cvd_version, CVD_VERSION_0_0,
7334 sizeof(common.cvd_version));
7335 pr_debug("%s: Fall back to default value, CVD Version = %s\n",
7336 __func__, common.cvd_version);
7337
7338 v->mvm_state = CMD_STATUS_SUCCESS;
7339 v->async_err = ptr[1];
7340 wake_up(&v->mvm_wait);
7341 break;
7342 default:
7343 pr_debug("%s: not match cmd = 0x%x\n",
7344 __func__, ptr[0]);
7345 break;
7346 }
7347 }
7348 } else if (data->opcode == VSS_IMEMORY_RSP_MAP) {
7349 pr_debug("%s, Revd VSS_IMEMORY_RSP_MAP response\n", __func__);
7350
7351 if (data->payload_size && data->token == VOIP_MEM_MAP_TOKEN) {
7352 ptr = data->payload;
7353 if (ptr[0]) {
7354 v->shmem_info.mem_handle = ptr[0];
7355 pr_debug("%s: shared mem_handle: 0x[%x]\n",
7356 __func__, v->shmem_info.mem_handle);
7357 v->mvm_state = CMD_STATUS_SUCCESS;
7358 wake_up(&v->mvm_wait);
7359 }
7360 } else if (data->payload_size &&
7361 data->token == VOC_CAL_MEM_MAP_TOKEN) {
7362 ptr = data->payload;
7363 if (ptr[0]) {
7364 c->cal_mem_handle = ptr[0];
7365
7366 pr_debug("%s: cal mem handle 0x%x\n",
7367 __func__, c->cal_mem_handle);
7368
7369 v->mvm_state = CMD_STATUS_SUCCESS;
7370 wake_up(&v->mvm_wait);
7371 }
7372 } else if (data->payload_size &&
7373 data->token == VOC_VOICE_HOST_PCM_MAP_TOKEN) {
7374 ptr = data->payload;
7375 if (ptr[0]) {
7376 common.voice_host_pcm_mem_handle = ptr[0];
7377
7378 pr_debug("%s: vhpcm mem handle 0x%x\n",
7379 __func__,
7380 common.voice_host_pcm_mem_handle);
7381 v->mvm_state = CMD_STATUS_SUCCESS;
7382 wake_up(&v->mvm_wait);
7383 }
7384 } else if (data->payload_size &&
7385 data->token == VOC_RTAC_MEM_MAP_TOKEN) {
7386 ptr = data->payload;
7387 if (ptr[0]) {
7388 c->rtac_mem_handle = ptr[0];
7389
7390 pr_debug("%s: cal mem handle 0x%x\n",
7391 __func__, c->rtac_mem_handle);
7392
7393 v->mvm_state = CMD_STATUS_SUCCESS;
7394 wake_up(&v->mvm_wait);
7395 }
7396 } else if (data->payload_size &&
7397 data->token == VOC_SOURCE_TRACKING_MEM_MAP_TOKEN) {
7398 ptr = data->payload;
7399 if (ptr[0]) {
7400 common.source_tracking_sh_mem.mem_handle =
7401 ptr[0];
7402
7403 pr_debug("%s: Source Tracking shared mem handle 0x%x\n",
7404 __func__,
7405 common.source_tracking_sh_mem.mem_handle);
7406
7407 v->mvm_state = CMD_STATUS_SUCCESS;
7408 wake_up(&v->mvm_wait);
7409 }
7410 } else {
7411 pr_err("%s: Unknown mem map token %d\n",
7412 __func__, data->token);
7413 }
7414 } else if (data->opcode == VSS_IVERSION_RSP_GET) {
7415 pr_debug("%s: Received VSS_IVERSION_RSP_GET\n", __func__);
7416
7417 if (data->payload_size) {
7418 version_rsp =
7419 (struct vss_iversion_rsp_get_t *)data->payload;
7420 memcpy(common.cvd_version, version_rsp->version,
7421 CVD_VERSION_STRING_MAX_SIZE);
7422 pr_debug("%s: CVD Version = %s\n",
7423 __func__, common.cvd_version);
7424
7425 v->mvm_state = CMD_STATUS_SUCCESS;
7426 wake_up(&v->mvm_wait);
7427 }
7428 }
7429 return 0;
7430}
7431
7432static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv)
7433{
7434 uint32_t *ptr = NULL;
7435 struct common_data *c = NULL;
7436 struct voice_data *v = NULL;
7437 int i = 0;
7438
7439 if ((data == NULL) || (priv == NULL)) {
7440 pr_err("%s: data or priv is NULL\n", __func__);
7441 return -EINVAL;
7442 }
7443
7444 c = priv;
7445
7446 pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port);
7447 pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
7448 data->payload_size, data->opcode);
7449
7450 if (data->opcode == RESET_EVENTS) {
7451 pr_debug("%s: Reset event received in Voice service\n",
7452 __func__);
7453
7454 apr_reset(c->apr_q6_cvs);
7455 c->apr_q6_cvs = NULL;
7456
7457 /* Sub-system restart is applicable to all sessions. */
7458 for (i = 0; i < MAX_VOC_SESSIONS; i++)
7459 c->voice[i].cvs_handle = 0;
7460
7461 cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
7462 common.cal_data);
7463
7464 /* Free the ION memory and clear handles for Source Tracking */
7465 if (is_source_tracking_shared_memomry_allocated()) {
7466 msm_audio_ion_free(
7467 common.source_tracking_sh_mem.sh_mem_block.client,
7468 common.source_tracking_sh_mem.sh_mem_block.handle);
7469 common.source_tracking_sh_mem.mem_handle = 0;
7470 common.source_tracking_sh_mem.sh_mem_block.client =
7471 NULL;
7472 common.source_tracking_sh_mem.sh_mem_block.handle =
7473 NULL;
7474 }
7475 voc_set_error_state(data->reset_proc);
7476 return 0;
7477 }
7478
7479 v = voice_get_session_by_idx(data->dest_port);
7480 if (v == NULL) {
7481 pr_err("%s: v is NULL\n", __func__);
7482
7483 return -EINVAL;
7484 }
7485
7486 if (data->opcode == APR_BASIC_RSP_RESULT) {
7487 if (data->payload_size) {
7488 ptr = data->payload;
7489
7490 pr_debug("%x %x\n", ptr[0], ptr[1]);
7491 if (ptr[1] != 0) {
7492 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
7493 __func__, ptr[0], ptr[1]);
7494 }
7495 /*response from CVS */
7496 switch (ptr[0]) {
7497 case VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION:
7498 case VSS_ISTREAM_CMD_CREATE_FULL_CONTROL_SESSION:
7499 if (!ptr[1]) {
7500 pr_debug("%s: CVS handle is %d\n",
7501 __func__, data->src_port);
7502 voice_set_cvs_handle(v, data->src_port);
7503 } else
7504 pr_err("got NACK for sending CVS create session\n");
7505 v->cvs_state = CMD_STATUS_SUCCESS;
7506 v->async_err = ptr[1];
7507 wake_up(&v->cvs_wait);
7508 break;
7509 case VSS_IVOLUME_CMD_MUTE_V2:
7510 case VSS_ISTREAM_CMD_SET_MEDIA_TYPE:
7511 case VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE:
7512 case VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE:
7513 case VSS_ISTREAM_CMD_SET_ENC_DTX_MODE:
7514 case VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE:
7515 case APRV2_IBASIC_CMD_DESTROY_SESSION:
7516 case VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA_V2:
7517 case VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA:
7518 case VSS_ISTREAM_CMD_REGISTER_STATIC_CALIBRATION_DATA:
7519 case VSS_ISTREAM_CMD_DEREGISTER_STATIC_CALIBRATION_DATA:
7520 case VSS_ICOMMON_CMD_MAP_MEMORY:
7521 case VSS_ICOMMON_CMD_UNMAP_MEMORY:
7522 case VSS_ICOMMON_CMD_SET_UI_PROPERTY:
7523 case VSS_IPLAYBACK_CMD_START:
7524 case VSS_IPLAYBACK_CMD_STOP:
7525 case VSS_IRECORD_CMD_START:
7526 case VSS_IRECORD_CMD_STOP:
7527 case VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE:
7528 case VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG:
7529 case VSS_ISTREAM_CMD_SET_RX_DTMF_DETECTION:
7530 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7531 v->cvs_state = CMD_STATUS_SUCCESS;
7532 v->async_err = ptr[1];
7533 wake_up(&v->cvs_wait);
7534 break;
7535 case VSS_ICOMMON_CMD_SET_PARAM_V2:
7536 pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2\n",
7537 __func__);
7538 rtac_make_voice_callback(RTAC_CVS, ptr,
7539 data->payload_size);
7540 break;
7541 case VSS_ICOMMON_CMD_GET_PARAM_V2:
7542 pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n",
7543 __func__);
7544 /* Should only come here if there is an APR */
7545 /* error or malformed APR packet. Otherwise */
7546 /* response will be returned as */
7547 /* VSS_ICOMMON_RSP_GET_PARAM */
7548 if (ptr[1] != 0) {
7549 pr_err("%s: CVP get param error = %d, resuming\n",
7550 __func__, ptr[1]);
7551 rtac_make_voice_callback(RTAC_CVP,
7552 data->payload,
7553 data->payload_size);
7554 }
7555 break;
7556 default:
7557 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7558 break;
7559 }
7560 }
7561 } else if (data->opcode ==
7562 VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_READY) {
7563 int ret = 0;
7564 u16 cvs_handle;
7565 uint32_t *cvs_voc_pkt;
7566 struct cvs_enc_buffer_consumed_cmd send_enc_buf_consumed_cmd;
7567 void *apr_cvs;
7568
7569 pr_debug("Encoder buffer is ready\n");
7570
7571 apr_cvs = common.apr_q6_cvs;
7572 if (!apr_cvs) {
7573 pr_err("%s: apr_cvs is NULL\n", __func__);
7574 return -EINVAL;
7575 }
7576 cvs_handle = voice_get_cvs_handle(v);
7577
7578 send_enc_buf_consumed_cmd.hdr.hdr_field =
7579 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7580 APR_HDR_LEN(APR_HDR_SIZE),
7581 APR_PKT_VER);
7582 send_enc_buf_consumed_cmd.hdr.pkt_size =
7583 APR_PKT_SIZE(APR_HDR_SIZE,
7584 sizeof(send_enc_buf_consumed_cmd) - APR_HDR_SIZE);
7585
7586 send_enc_buf_consumed_cmd.hdr.src_port =
7587 voice_get_idx_for_session(v->session_id);
7588 send_enc_buf_consumed_cmd.hdr.dest_port = cvs_handle;
7589 send_enc_buf_consumed_cmd.hdr.token = 0;
7590 send_enc_buf_consumed_cmd.hdr.opcode =
7591 VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_CONSUMED;
7592
7593 cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
7594 if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) {
7595 /* cvs_voc_pkt[0] contains tx timestamp */
7596 common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
7597 cvs_voc_pkt[2],
7598 cvs_voc_pkt[0],
7599 common.mvs_info.private_data);
7600 } else
7601 pr_err("%s: cvs_voc_pkt or ul_cb is NULL\n", __func__);
7602
7603 ret = apr_send_pkt(apr_cvs,
7604 (uint32_t *) &send_enc_buf_consumed_cmd);
7605 if (ret < 0) {
7606 pr_err("%s: Err send ENC_BUF_CONSUMED_NOTIFY %d\n",
7607 __func__, ret);
7608 goto fail;
7609 }
7610 } else if (data->opcode == VSS_ISTREAM_EVT_SEND_ENC_BUFFER) {
7611 pr_debug("Recd VSS_ISTREAM_EVT_SEND_ENC_BUFFER\n");
7612 } else if (data->opcode ==
7613 VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_REQUEST) {
7614 int ret = 0;
7615 u16 cvs_handle;
7616 uint32_t *cvs_voc_pkt;
7617 struct cvs_dec_buffer_ready_cmd send_dec_buf;
7618 void *apr_cvs;
7619
7620 apr_cvs = common.apr_q6_cvs;
7621
7622 if (!apr_cvs) {
7623 pr_err("%s: apr_cvs is NULL\n", __func__);
7624 return -EINVAL;
7625 }
7626 cvs_handle = voice_get_cvs_handle(v);
7627
7628 send_dec_buf.hdr.hdr_field =
7629 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7630 APR_HDR_LEN(APR_HDR_SIZE),
7631 APR_PKT_VER);
7632
7633 send_dec_buf.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
7634 sizeof(send_dec_buf) - APR_HDR_SIZE);
7635
7636 send_dec_buf.hdr.src_port =
7637 voice_get_idx_for_session(v->session_id);
7638 send_dec_buf.hdr.dest_port = cvs_handle;
7639 send_dec_buf.hdr.token = 0;
7640 send_dec_buf.hdr.opcode =
7641 VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_READY;
7642
7643 cvs_voc_pkt = (uint32_t *)(v->shmem_info.sh_buf.buf[0].data);
7644 if (cvs_voc_pkt != NULL && common.mvs_info.dl_cb != NULL) {
7645 /* Set timestamp to 0 and advance the pointer */
7646 cvs_voc_pkt[0] = 0;
7647 /* Set media_type and advance the pointer */
7648 cvs_voc_pkt[1] = common.mvs_info.media_type;
7649 common.mvs_info.dl_cb(
7650 (uint8_t *)&cvs_voc_pkt[2],
7651 common.mvs_info.private_data);
7652 ret = apr_send_pkt(apr_cvs, (uint32_t *) &send_dec_buf);
7653 if (ret < 0) {
7654 pr_err("%s: Err send DEC_BUF_READY_NOTIFI %d\n",
7655 __func__, ret);
7656 goto fail;
7657 }
7658 } else {
7659 pr_debug("%s: voc_pkt or dl_cb is NULL\n", __func__);
7660 goto fail;
7661 }
7662 } else if (data->opcode == VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER) {
7663 pr_debug("Recd VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER\n");
7664 } else if (data->opcode == VSS_ISTREAM_EVT_SEND_DEC_BUFFER) {
7665 pr_debug("Send dec buf resp\n");
7666 } else if (data->opcode == APR_RSP_ACCEPTED) {
7667 ptr = data->payload;
7668 if (ptr[0])
7669 pr_debug("%s: APR_RSP_ACCEPTED for 0x%x:\n",
7670 __func__, ptr[0]);
7671 } else if (data->opcode == VSS_ISTREAM_EVT_NOT_READY) {
7672 pr_debug("Recd VSS_ISTREAM_EVT_NOT_READY\n");
7673 } else if (data->opcode == VSS_ISTREAM_EVT_READY) {
7674 pr_debug("Recd VSS_ISTREAM_EVT_READY\n");
7675 } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) {
7676 pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__);
7677 ptr = data->payload;
7678 if (ptr[0] != 0) {
7679 pr_err("%s: VSS_ICOMMON_RSP_GET_PARAM returned error = 0x%x\n",
7680 __func__, ptr[0]);
7681 }
7682 rtac_make_voice_callback(RTAC_CVS, data->payload,
7683 data->payload_size);
7684 } else if (data->opcode == VSS_ISTREAM_EVT_RX_DTMF_DETECTED) {
7685 struct vss_istream_evt_rx_dtmf_detected *dtmf_rx_detected;
7686 uint32_t *voc_pkt = data->payload;
7687 uint32_t pkt_len = data->payload_size;
7688
7689 if ((voc_pkt != NULL) &&
7690 (pkt_len ==
7691 sizeof(struct vss_istream_evt_rx_dtmf_detected))) {
7692
7693 dtmf_rx_detected =
7694 (struct vss_istream_evt_rx_dtmf_detected *) voc_pkt;
7695 pr_debug("RX_DTMF_DETECTED low_freq=%d high_freq=%d\n",
7696 dtmf_rx_detected->low_freq,
7697 dtmf_rx_detected->high_freq);
7698 if (c->dtmf_info.dtmf_rx_ul_cb)
7699 c->dtmf_info.dtmf_rx_ul_cb((uint8_t *)voc_pkt,
7700 voc_get_session_name(v->session_id),
7701 c->dtmf_info.private_data);
7702 } else {
7703 pr_err("Invalid packet\n");
7704 }
7705 } else
7706 pr_debug("Unknown opcode 0x%x\n", data->opcode);
7707
7708fail:
7709 return 0;
7710}
7711
7712static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv)
7713{
7714 uint32_t *ptr = NULL;
7715 struct common_data *c = NULL;
7716 struct voice_data *v = NULL;
7717 int i = 0;
7718
7719 if ((data == NULL) || (priv == NULL)) {
7720 pr_err("%s: data or priv is NULL\n", __func__);
7721 return -EINVAL;
7722 }
7723
7724 c = priv;
7725
7726 if (data->opcode == RESET_EVENTS) {
7727 pr_debug("%s: Reset event received in Voice service\n",
7728 __func__);
7729
7730 apr_reset(c->apr_q6_cvp);
7731 c->apr_q6_cvp = NULL;
7732 cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
7733 common.cal_data);
7734
7735 /* Sub-system restart is applicable to all sessions. */
7736 for (i = 0; i < MAX_VOC_SESSIONS; i++)
7737 c->voice[i].cvp_handle = 0;
7738
7739 /*
7740 * Free the ION memory and clear handles for
7741 * Source Tracking
7742 */
7743 if (is_source_tracking_shared_memomry_allocated()) {
7744 msm_audio_ion_free(
7745 common.source_tracking_sh_mem.sh_mem_block.client,
7746 common.source_tracking_sh_mem.sh_mem_block.handle);
7747 common.source_tracking_sh_mem.mem_handle = 0;
7748 common.source_tracking_sh_mem.sh_mem_block.client =
7749 NULL;
7750 common.source_tracking_sh_mem.sh_mem_block.handle =
7751 NULL;
7752 }
7753 voc_set_error_state(data->reset_proc);
7754 return 0;
7755 }
7756
7757 v = voice_get_session_by_idx(data->dest_port);
7758 if (v == NULL) {
7759 pr_err("%s: v is NULL\n", __func__);
7760
7761 return -EINVAL;
7762 }
7763
7764 if (data->opcode == APR_BASIC_RSP_RESULT) {
7765 if (data->payload_size) {
7766 ptr = data->payload;
7767
7768 pr_debug("%x %x\n", ptr[0], ptr[1]);
7769 if (ptr[1] != 0) {
7770 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
7771 __func__, ptr[0], ptr[1]);
7772 }
7773 switch (ptr[0]) {
7774 case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2:
7775 case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V3:
7776 /*response from CVP */
7777 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7778 if (!ptr[1]) {
7779 voice_set_cvp_handle(v, data->src_port);
7780 pr_debug("status: %d, cvphdl=%d\n",
7781 ptr[1], data->src_port);
7782 } else
7783 pr_err("got NACK from CVP create session response\n");
7784 v->cvp_state = CMD_STATUS_SUCCESS;
7785 v->async_err = ptr[1];
7786 wake_up(&v->cvp_wait);
7787 break;
7788 case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
7789 case VSS_IVOCPROC_CMD_SET_DEVICE_V3:
7790 case VSS_IVOLUME_CMD_SET_STEP:
7791 case VSS_IVOCPROC_CMD_ENABLE:
7792 case VSS_IVOCPROC_CMD_DISABLE:
7793 case APRV2_IBASIC_CMD_DESTROY_SESSION:
7794 case VSS_IVOCPROC_CMD_REGISTER_VOL_CALIBRATION_DATA:
7795 case VSS_IVOCPROC_CMD_DEREGISTER_VOL_CALIBRATION_DATA:
7796 case VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA_V2:
7797 case VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA:
7798 case VSS_IVOCPROC_CMD_REGISTER_DYNAMIC_CALIBRATION_DATA:
7799 case VSS_IVOCPROC_CMD_DEREGISTER_DYNAMIC_CALIBRATION_DATA:
7800 case VSS_IVOCPROC_CMD_REGISTER_STATIC_CALIBRATION_DATA:
7801 case VSS_IVOCPROC_CMD_DEREGISTER_STATIC_CALIBRATION_DATA:
7802 case VSS_IVOCPROC_CMD_REGISTER_DEVICE_CONFIG:
7803 case VSS_IVOCPROC_CMD_DEREGISTER_DEVICE_CONFIG:
7804 case VSS_ICOMMON_CMD_MAP_MEMORY:
7805 case VSS_ICOMMON_CMD_UNMAP_MEMORY:
7806 case VSS_IVOLUME_CMD_MUTE_V2:
7807 case VSS_IVPCM_CMD_START_V2:
7808 case VSS_IVPCM_CMD_STOP:
7809 case VSS_IVOCPROC_CMD_TOPOLOGY_SET_DEV_CHANNELS:
7810 case VSS_IVOCPROC_CMD_TOPOLOGY_COMMIT:
7811 v->cvp_state = CMD_STATUS_SUCCESS;
7812 v->async_err = ptr[1];
7813 wake_up(&v->cvp_wait);
7814 break;
7815 case VSS_IVPCM_EVT_PUSH_BUFFER_V2:
7816 break;
7817 case VSS_ICOMMON_CMD_SET_PARAM_V2:
7818 switch (data->token) {
7819 case VOC_SET_MEDIA_FORMAT_PARAM_TOKEN:
Laxminath Kasam38070be2017-08-17 18:21:59 +05307820 case VOC_GENERIC_SET_PARAM_TOKEN:
7821 pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307822 __func__);
7823 v->cvp_state = CMD_STATUS_SUCCESS;
7824 v->async_err = ptr[1];
7825 wake_up(&v->cvp_wait);
7826 break;
7827 case VOC_RTAC_SET_PARAM_TOKEN:
7828 pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by rtac\n",
7829 __func__);
7830 rtac_make_voice_callback(
7831 RTAC_CVP, ptr,
7832 data->payload_size);
7833 break;
7834 default:
7835 pr_debug("%s: invalid token for command VSS_ICOMMON_CMD_SET_PARAM_V2: %d\n",
7836 __func__, data->token);
7837 break;
7838 }
7839 break;
7840 case VSS_ICOMMON_CMD_GET_PARAM_V2:
7841 pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n",
7842 __func__);
7843 /* Should only come here if there is an APR */
7844 /* error or malformed APR packet. Otherwise */
7845 /* response will be returned as */
7846 /* VSS_ICOMMON_RSP_GET_PARAM */
7847 if (ptr[1] != 0) {
7848 pr_err("%s: CVP get param error = %d, resuming\n",
7849 __func__, ptr[1]);
7850 rtac_make_voice_callback(RTAC_CVP,
7851 data->payload,
7852 data->payload_size);
7853 }
7854 break;
7855 case VSS_ISOUNDFOCUS_CMD_SET_SECTORS:
7856 if (!ptr[1])
7857 common.is_sound_focus_resp_success =
7858 true;
7859 else
7860 common.is_sound_focus_resp_success =
7861 false;
7862 v->cvp_state = CMD_STATUS_SUCCESS;
7863 v->async_err = ptr[1];
7864 wake_up(&v->cvp_wait);
7865 break;
7866 case VSS_ISOUNDFOCUS_CMD_GET_SECTORS:
7867 /*
7868 * Should only come here if there is an error
7869 * response received from ADSP. Otherwise
7870 * response will be returned as
7871 * VSS_ISOUNDFOCUS_RSP_GET_SECTORS
7872 */
7873 pr_err("%s: VSS_ISOUNDFOCUS_CMD_GET_SECTORS failed\n",
7874 __func__);
7875
7876 common.is_sound_focus_resp_success = false;
7877 v->cvp_state = CMD_STATUS_SUCCESS;
7878 v->async_err = ptr[1];
7879 wake_up(&v->cvp_wait);
7880 break;
7881 case VSS_ISOURCETRACK_CMD_GET_ACTIVITY:
7882 if (!ptr[1]) {
7883 /* Read data from shared memory */
7884 memcpy(&common.sourceTrackingResponse,
7885 common.source_tracking_sh_mem.
7886 sh_mem_block.data,
7887 sizeof(struct
7888 vss_isourcetrack_activity_data_t));
7889 common.is_source_tracking_resp_success =
7890 true;
7891 } else {
7892 common.is_source_tracking_resp_success =
7893 false;
7894 pr_err("%s: Error received for source tracking params\n",
7895 __func__);
7896 }
7897 v->cvp_state = CMD_STATUS_SUCCESS;
7898 v->async_err = ptr[1];
7899 wake_up(&v->cvp_wait);
7900 break;
7901 default:
7902 pr_debug("%s: not match cmd = 0x%x\n",
7903 __func__, ptr[0]);
7904 break;
7905 }
7906 }
7907 } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) {
7908 pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__);
7909 ptr = data->payload;
7910 if (ptr[0] != 0) {
7911 pr_err("%s: VSS_ICOMMON_RSP_GET_PARAM returned error = 0x%x\n",
7912 __func__, ptr[0]);
7913 }
7914 rtac_make_voice_callback(RTAC_CVP, data->payload,
7915 data->payload_size);
7916 } else if (data->opcode == VSS_IVPCM_EVT_NOTIFY_V2) {
7917 if ((data->payload != NULL) && data->payload_size ==
7918 sizeof(struct vss_ivpcm_evt_notify_v2_t) &&
7919 common.hostpcm_info.hostpcm_evt_cb != NULL) {
7920 common.hostpcm_info.hostpcm_evt_cb(data->payload,
7921 voc_get_session_name(v->session_id),
7922 common.hostpcm_info.private_data);
7923 }
7924 } else if (data->opcode == VSS_ISOUNDFOCUS_RSP_GET_SECTORS) {
7925 if (data->payload && (data->payload_size ==
7926 sizeof(struct vss_isoundfocus_rsp_get_sectors_t))) {
7927 common.is_sound_focus_resp_success = true;
7928 memcpy(&common.soundFocusResponse,
7929 (struct vss_isoundfocus_rsp_get_sectors_t *)
7930 data->payload,
7931 sizeof(struct
7932 vss_isoundfocus_rsp_get_sectors_t));
7933 } else {
7934 common.is_sound_focus_resp_success = false;
7935 pr_debug("%s: Invalid payload received from CVD\n",
7936 __func__);
7937 }
7938 v->cvp_state = CMD_STATUS_SUCCESS;
7939 wake_up(&v->cvp_wait);
7940 }
7941 return 0;
7942}
7943
7944static int voice_free_oob_shared_mem(void)
7945{
7946 int rc = 0;
7947 int cnt = 0;
7948 int bufcnt = NUM_OF_BUFFERS;
7949 struct voice_data *v = voice_get_session(
7950 common.voice[VOC_PATH_FULL].session_id);
7951
7952 mutex_lock(&common.common_lock);
7953 if (v == NULL) {
7954 pr_err("%s: v is NULL\n", __func__);
7955
7956 rc = -EINVAL;
7957 goto done;
7958 }
7959
7960 rc = msm_audio_ion_free(v->shmem_info.sh_buf.client,
7961 v->shmem_info.sh_buf.handle);
7962 v->shmem_info.sh_buf.client = NULL;
7963 v->shmem_info.sh_buf.handle = NULL;
7964 if (rc < 0) {
7965 pr_err("%s: Error:%d freeing memory\n", __func__, rc);
7966
7967 goto done;
7968 }
7969
7970
7971 while (cnt < bufcnt) {
7972 v->shmem_info.sh_buf.buf[cnt].data = NULL;
7973 v->shmem_info.sh_buf.buf[cnt].phys = 0;
7974 cnt++;
7975 }
7976
7977 v->shmem_info.sh_buf.client = NULL;
7978 v->shmem_info.sh_buf.handle = NULL;
7979
7980done:
7981 mutex_unlock(&common.common_lock);
7982 return rc;
7983}
7984
7985static int voice_alloc_oob_shared_mem(void)
7986{
7987 int cnt = 0;
7988 int rc = 0;
7989 size_t len;
7990 void *mem_addr;
7991 dma_addr_t phys;
7992 int bufsz = BUFFER_BLOCK_SIZE;
7993 int bufcnt = NUM_OF_BUFFERS;
7994 struct voice_data *v = voice_get_session(
7995 common.voice[VOC_PATH_FULL].session_id);
7996
7997 mutex_lock(&common.common_lock);
7998 if (v == NULL) {
7999 pr_err("%s: v is NULL\n", __func__);
8000
8001 rc = -EINVAL;
8002 goto done;
8003 }
8004
8005 rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
8006 &(v->shmem_info.sh_buf.handle),
8007 bufsz*bufcnt,
8008 &phys, &len,
8009 &mem_addr);
8010 if (rc < 0) {
8011 pr_err("%s: audio ION alloc failed, rc = %d\n",
8012 __func__, rc);
8013
8014 goto done;
8015 }
8016
8017 while (cnt < bufcnt) {
8018 v->shmem_info.sh_buf.buf[cnt].data = mem_addr + (cnt * bufsz);
8019 v->shmem_info.sh_buf.buf[cnt].phys = phys + (cnt * bufsz);
8020 v->shmem_info.sh_buf.buf[cnt].size = bufsz;
8021 cnt++;
8022 }
8023
8024 pr_debug("%s buf[0].data:[%pK], buf[0].phys:[%pK], &buf[0].phys:[%pK],\n",
8025 __func__,
8026 (void *)v->shmem_info.sh_buf.buf[0].data,
8027 &v->shmem_info.sh_buf.buf[0].phys,
8028 (void *)&v->shmem_info.sh_buf.buf[0].phys);
8029 pr_debug("%s: buf[1].data:[%pK], buf[1].phys[%pK], &buf[1].phys[%pK]\n",
8030 __func__,
8031 (void *)v->shmem_info.sh_buf.buf[1].data,
8032 &v->shmem_info.sh_buf.buf[1].phys,
8033 (void *)&v->shmem_info.sh_buf.buf[1].phys);
8034
8035 memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
8036
8037done:
8038 mutex_unlock(&common.common_lock);
8039 return rc;
8040}
8041
8042static int voice_alloc_oob_mem_table(void)
8043{
8044 int rc = 0;
8045 size_t len;
8046 struct voice_data *v = voice_get_session(
8047 common.voice[VOC_PATH_FULL].session_id);
8048
8049 mutex_lock(&common.common_lock);
8050 if (v == NULL) {
8051 pr_err("%s: v is NULL\n", __func__);
8052
8053 rc = -EINVAL;
8054 goto done;
8055 }
8056
8057 rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
8058 &(v->shmem_info.memtbl.handle),
8059 sizeof(struct vss_imemory_table_t),
8060 &v->shmem_info.memtbl.phys,
8061 &len,
8062 &(v->shmem_info.memtbl.data));
8063 if (rc < 0) {
8064 pr_err("%s: audio ION alloc failed, rc = %d\n",
8065 __func__, rc);
8066
8067 goto done;
8068 }
8069
8070 v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
8071 pr_debug("%s data[%pK]phys[%pK][%pK]\n", __func__,
8072 (void *)v->shmem_info.memtbl.data,
8073 &v->shmem_info.memtbl.phys,
8074 (void *)&v->shmem_info.memtbl.phys);
8075
8076done:
8077 mutex_unlock(&common.common_lock);
8078 return rc;
8079}
8080
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308081/**
8082 * voc_send_cvp_start_vocpcm -
8083 * command to start voice hpcm
8084 *
8085 * @session_id: voice session ID to send this command
8086 *
8087 * Returns 0 on success or error on failure
8088 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308089int voc_send_cvp_start_vocpcm(uint32_t session_id,
8090 struct vss_ivpcm_tap_point *vpcm_tp,
8091 uint32_t no_of_tp)
8092{
8093 struct cvp_start_cmd cvp_start_cmd;
8094 int ret = 0;
8095 void *apr_cvp;
8096 u16 cvp_handle;
8097 struct voice_data *v = voice_get_session(session_id);
8098 int i = 0;
8099
8100 if (v == NULL) {
8101 pr_err("%s: v is NULL\n", __func__);
8102 ret = -EINVAL;
8103 goto done;
8104 }
8105 apr_cvp = common.apr_q6_cvp;
8106
8107 if (!apr_cvp) {
8108 pr_err("%s: apr_cvp is NULL.\n", __func__);
8109 ret = -EINVAL;
8110 goto done;
8111 }
8112
8113 cvp_handle = voice_get_cvp_handle(v);
8114
8115 /* Fill the header */
8116 cvp_start_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8117 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
8118 cvp_start_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8119 sizeof(struct vss_ivpcm_tap_point) * no_of_tp) +
8120 sizeof(cvp_start_cmd.vpcm_start_cmd.num_tap_points) +
8121 sizeof(cvp_start_cmd.vpcm_start_cmd.mem_handle);
8122 cvp_start_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
8123 cvp_start_cmd.hdr.dest_port = cvp_handle;
8124 cvp_start_cmd.hdr.token = 0;
8125 cvp_start_cmd.hdr.opcode = VSS_IVPCM_CMD_START_V2;
8126
8127 for (i = 0; i < no_of_tp; i++) {
8128 cvp_start_cmd.vpcm_start_cmd.tap_points[i].tap_point =
8129 vpcm_tp[i].tap_point;
8130 cvp_start_cmd.vpcm_start_cmd.tap_points[i].direction =
8131 vpcm_tp[i].direction;
8132 cvp_start_cmd.vpcm_start_cmd.tap_points[i].sampling_rate =
8133 vpcm_tp[i].sampling_rate;
8134 cvp_start_cmd.vpcm_start_cmd.tap_points[i].duration = 0;
8135 }
8136
8137 cvp_start_cmd.vpcm_start_cmd.mem_handle =
8138 common.voice_host_pcm_mem_handle;
8139 cvp_start_cmd.vpcm_start_cmd.num_tap_points = no_of_tp;
8140
8141 v->cvp_state = CMD_STATUS_FAIL;
8142 v->async_err = 0;
8143 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_start_cmd);
8144 if (ret < 0) {
8145 pr_err("%s: Fail: sending vocpcm map memory,\n", __func__);
8146 goto done;
8147 }
8148 ret = wait_event_timeout(v->cvp_wait,
8149 (v->cvp_state == CMD_STATUS_SUCCESS),
8150 msecs_to_jiffies(TIMEOUT_MS));
8151 if (!ret) {
8152 pr_err("%s: wait_event timeout\n", __func__);
8153 goto done;
8154 }
8155 if (v->async_err > 0) {
8156 pr_err("%s: DSP returned error[%s]\n",
8157 __func__, adsp_err_get_err_str(
8158 v->async_err));
8159 ret = adsp_err_get_lnx_err_code(
8160 v->async_err);
8161 goto done;
8162 }
8163
8164done:
8165 return ret;
8166}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308167EXPORT_SYMBOL(voc_send_cvp_start_vocpcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308168
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308169/**
8170 * voc_send_cvp_stop_vocpcm -
8171 * command to stop voice hpcm
8172 *
8173 * @session_id: voice session ID to send this command
8174 *
8175 * Returns 0 on success or error on failure
8176 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308177int voc_send_cvp_stop_vocpcm(uint32_t session_id)
8178{
8179 struct cvp_command vpcm_stop_cmd;
8180 int ret = 0;
8181 void *apr_cvp;
8182 u16 cvp_handle;
8183 struct voice_data *v = voice_get_session(session_id);
8184
8185 if (v == NULL) {
8186 pr_err("%s: v is NULL\n", __func__);
8187 ret = -EINVAL;
8188 goto done;
8189 }
8190 apr_cvp = common.apr_q6_cvp;
8191
8192 if (!apr_cvp) {
8193 pr_err("%s: apr_cvp is NULL.\n", __func__);
8194 ret = -EINVAL;
8195 goto done;
8196 }
8197
8198 cvp_handle = voice_get_cvp_handle(v);
8199
8200 /* fill in the header */
8201 vpcm_stop_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8202 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
8203 vpcm_stop_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8204 sizeof(vpcm_stop_cmd) - APR_HDR_SIZE);
8205 vpcm_stop_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
8206 vpcm_stop_cmd.hdr.dest_port = cvp_handle;
8207 vpcm_stop_cmd.hdr.token = 0;
8208 vpcm_stop_cmd.hdr.opcode = VSS_IVPCM_CMD_STOP;
8209
8210 v->cvp_state = CMD_STATUS_FAIL;
8211 v->async_err = 0;
8212 ret = apr_send_pkt(apr_cvp, (uint32_t *) &vpcm_stop_cmd);
8213 if (ret < 0) {
8214 pr_err("Fail: sending vocpcm stop,\n");
8215 goto done;
8216 }
8217 ret = wait_event_timeout(v->cvp_wait,
8218 (v->cvp_state == CMD_STATUS_SUCCESS),
8219 msecs_to_jiffies(TIMEOUT_MS));
8220 if (!ret) {
8221 pr_err("%s: wait_event timeout\n", __func__);
8222 goto done;
8223 }
8224
8225 if (v->async_err > 0) {
8226 pr_err("%s: DSP returned error[%s]\n",
8227 __func__, adsp_err_get_err_str(
8228 v->async_err));
8229 ret = adsp_err_get_lnx_err_code(
8230 v->async_err);
8231 goto done;
8232 }
8233
8234done:
8235 return ret;
8236}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308237EXPORT_SYMBOL(voc_send_cvp_stop_vocpcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308238
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308239/**
8240 * voc_send_cvp_map_vocpcm_memory -
8241 * command to map memory for voice hpcm
8242 *
8243 * @session_id: voice session ID to send this command
8244 * @tp_mem_table: tap point memory table of hpcm
8245 * paddr: Physical address of hpcm memory mapped area.
8246 * bufsize: Buffer size of memory mapped area
8247 *
8248 * Returns 0 on success or error on failure
8249 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308250int voc_send_cvp_map_vocpcm_memory(uint32_t session_id,
8251 struct mem_map_table *tp_mem_table,
8252 phys_addr_t paddr, uint32_t bufsize)
8253{
8254 return voice_map_memory_physical_cmd(voice_get_session(session_id),
8255 tp_mem_table,
8256 (dma_addr_t) paddr, bufsize,
8257 VOC_VOICE_HOST_PCM_MAP_TOKEN);
8258}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308259EXPORT_SYMBOL(voc_send_cvp_map_vocpcm_memory);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308260
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308261/**
8262 * voc_send_cvp_unmap_vocpcm_memory -
8263 * command to unmap memory for voice hpcm
8264 *
8265 * @session_id: voice session ID to send this command
8266 *
8267 * Returns 0 on success or error on failure
8268 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308269int voc_send_cvp_unmap_vocpcm_memory(uint32_t session_id)
8270{
8271 int ret = 0;
8272
8273 ret = voice_send_mvm_unmap_memory_physical_cmd(
8274 voice_get_session(session_id),
8275 common.voice_host_pcm_mem_handle);
8276
8277 if (ret == 0)
8278 common.voice_host_pcm_mem_handle = 0;
8279
8280 return ret;
8281}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308282EXPORT_SYMBOL(voc_send_cvp_unmap_vocpcm_memory);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308283
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308284/**
8285 * voc_send_cvp_vocpcm_push_buf_evt - Send buf event command
8286 *
8287 * @session_id: voice session ID to send this command
8288 * @push_buff_evt: pointer with buffer event details
8289 *
8290 * Returns 0 on success or error on failure
8291 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308292int voc_send_cvp_vocpcm_push_buf_evt(uint32_t session_id,
8293 struct vss_ivpcm_evt_push_buffer_v2_t *push_buff_evt)
8294{
8295 struct cvp_push_buf_cmd vpcm_push_buf_cmd;
8296 int ret = 0;
8297 void *apr_cvp;
8298 u16 cvp_handle;
8299 struct voice_data *v = voice_get_session(session_id);
8300
8301 if (v == NULL) {
8302 pr_err("%s: v is NULL\n", __func__);
8303 ret = -EINVAL;
8304 goto done;
8305 }
8306 apr_cvp = common.apr_q6_cvp;
8307
8308 if (!apr_cvp) {
8309 pr_err("%s: apr_cvp is NULL.\n", __func__);
8310 ret = -EINVAL;
8311 goto done;
8312 }
8313
8314 memset(&vpcm_push_buf_cmd, 0, sizeof(vpcm_push_buf_cmd));
8315 cvp_handle = voice_get_cvp_handle(v);
8316
8317 /* fill in the header */
8318 vpcm_push_buf_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8319 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
8320 vpcm_push_buf_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8321 sizeof(vpcm_push_buf_cmd) - APR_HDR_SIZE);
8322 vpcm_push_buf_cmd.hdr.src_port =
8323 voice_get_idx_for_session(v->session_id);
8324 vpcm_push_buf_cmd.hdr.dest_port = cvp_handle;
8325 vpcm_push_buf_cmd.hdr.token = 0;
8326 vpcm_push_buf_cmd.hdr.opcode = VSS_IVPCM_EVT_PUSH_BUFFER_V2;
8327
8328 vpcm_push_buf_cmd.vpcm_evt_push_buffer.tap_point =
8329 push_buff_evt->tap_point;
8330 vpcm_push_buf_cmd.vpcm_evt_push_buffer.push_buf_mask =
8331 push_buff_evt->push_buf_mask;
8332 vpcm_push_buf_cmd.vpcm_evt_push_buffer.out_buf_mem_address =
8333 push_buff_evt->out_buf_mem_address;
8334 vpcm_push_buf_cmd.vpcm_evt_push_buffer.in_buf_mem_address =
8335 push_buff_evt->in_buf_mem_address;
8336 vpcm_push_buf_cmd.vpcm_evt_push_buffer.out_buf_mem_size =
8337 push_buff_evt->out_buf_mem_size;
8338 vpcm_push_buf_cmd.vpcm_evt_push_buffer.in_buf_mem_size =
8339 push_buff_evt->in_buf_mem_size;
8340 vpcm_push_buf_cmd.vpcm_evt_push_buffer.sampling_rate =
8341 push_buff_evt->sampling_rate;
8342 vpcm_push_buf_cmd.vpcm_evt_push_buffer.num_in_channels =
8343 push_buff_evt->num_in_channels;
8344
8345 ret = apr_send_pkt(apr_cvp, (uint32_t *) &vpcm_push_buf_cmd);
8346 if (ret < 0) {
8347 pr_err("Fail: sending vocpcm map memory,\n");
8348 goto done;
8349 }
8350
8351done:
8352 return ret;
8353}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308354EXPORT_SYMBOL(voc_send_cvp_vocpcm_push_buf_evt);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308355
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308356/**
8357 * voc_register_hpcm_evt_cb - Updates hostpcm info.
8358 *
8359 * @hostpcm_cb: callback function for hostpcm event
8360 * @private_data: private data for hostpcm
8361 *
8362 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308363void voc_register_hpcm_evt_cb(hostpcm_cb_fn hostpcm_cb,
8364 void *private_data)
8365{
8366 common.hostpcm_info.hostpcm_evt_cb = hostpcm_cb;
8367 common.hostpcm_info.private_data = private_data;
8368}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308369EXPORT_SYMBOL(voc_register_hpcm_evt_cb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308370
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308371/**
8372 * voc_deregister_hpcm_evt_cb - resets hostpcm info.
8373 *
8374 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308375void voc_deregister_hpcm_evt_cb(void)
8376{
8377 common.hostpcm_info.hostpcm_evt_cb = NULL;
8378 common.hostpcm_info.private_data = NULL;
8379}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308380EXPORT_SYMBOL(voc_deregister_hpcm_evt_cb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308381
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308382/**
8383 * voc_get_cvd_version - retrieve CVD version.
8384 *
8385 * @cvd_version: pointer to be updated with CVD version info.
8386 *
8387 * Returns 0 on success or error on failure
8388 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308389int voc_get_cvd_version(char *cvd_version)
8390{
8391 int ret = 0;
8392 struct voice_data *v = voice_get_session(VOICE_SESSION_VSID);
8393
8394
8395 if (v == NULL) {
8396 pr_err("%s: invalid session_id 0x%x\n",
8397 __func__, VOICE_SESSION_VSID);
8398
8399 ret = -EINVAL;
8400 goto done;
8401 }
8402
8403 if (is_cvd_version_queried()) {
8404 pr_debug("%s: Returning the cached value %s\n",
8405 __func__, common.cvd_version);
8406
8407 goto done;
8408 }
8409
8410 /* Register callback to APR */
8411 ret = voice_apr_register(VOICE_SESSION_VSID);
8412 if (ret < 0) {
8413 pr_err("%s: apr register failed\n", __func__);
8414 goto done;
8415 }
8416
8417 mutex_lock(&common.common_lock);
8418 mutex_lock(&v->lock);
8419 ret = voice_send_mvm_cvd_version_cmd(v);
8420 if (ret < 0) {
8421 pr_err("%s: voice_send_mvm_cvd_version_cmd failed\n", __func__);
8422 goto unlock;
8423 }
8424 ret = 0;
8425
8426unlock:
8427 mutex_unlock(&v->lock);
8428 mutex_unlock(&common.common_lock);
8429
8430done:
8431 if (cvd_version)
8432 memcpy(cvd_version, common.cvd_version,
8433 CVD_VERSION_STRING_MAX_SIZE);
8434
8435 return ret;
8436}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308437EXPORT_SYMBOL(voc_get_cvd_version);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308438
8439static int voice_alloc_cal_mem_map_table(void)
8440{
8441 int ret = 0;
8442 size_t len;
8443
8444 ret = msm_audio_ion_alloc("voc_cal",
8445 &(common.cal_mem_map_table.client),
8446 &(common.cal_mem_map_table.handle),
8447 sizeof(struct vss_imemory_table_t),
8448 &common.cal_mem_map_table.phys,
8449 &len,
8450 &(common.cal_mem_map_table.data));
8451 if ((ret < 0) && (ret != -EPROBE_DEFER)) {
8452 pr_err("%s: audio ION alloc failed, rc = %d\n",
8453 __func__, ret);
8454 goto done;
8455 }
8456
8457 common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
8458 pr_debug("%s: data %pK phys %pK\n", __func__,
8459 common.cal_mem_map_table.data,
8460 &common.cal_mem_map_table.phys);
8461
8462done:
8463 return ret;
8464}
8465
8466static int voice_alloc_rtac_mem_map_table(void)
8467{
8468 int ret = 0;
8469 size_t len;
8470
8471 ret = msm_audio_ion_alloc("voc_rtac_cal",
8472 &(common.rtac_mem_map_table.client),
8473 &(common.rtac_mem_map_table.handle),
8474 sizeof(struct vss_imemory_table_t),
8475 &common.rtac_mem_map_table.phys,
8476 &len,
8477 &(common.rtac_mem_map_table.data));
8478 if (ret < 0) {
8479 pr_err("%s: audio ION alloc failed, rc = %d\n",
8480 __func__, ret);
8481 goto done;
8482 }
8483
8484 common.rtac_mem_map_table.size = sizeof(struct vss_imemory_table_t);
8485 pr_debug("%s: data %pK phys %pK\n", __func__,
8486 common.rtac_mem_map_table.data,
8487 &common.rtac_mem_map_table.phys);
8488
8489done:
8490 return ret;
8491}
8492
8493static int voice_alloc_and_map_oob_mem(struct voice_data *v)
8494{
8495 int ret = 0;
8496
8497 if (v == NULL) {
8498 pr_err("%s: v is NULL\n", __func__);
8499
8500 return -EINVAL;
8501 }
8502
8503 if (!is_voip_memory_allocated()) {
8504 ret = voc_alloc_voip_shared_memory();
8505 if (ret < 0) {
8506 pr_err("%s: Failed to create voip oob memory %d\n",
8507 __func__, ret);
8508
8509 goto done;
8510 }
8511 }
8512
8513 ret = voice_map_memory_physical_cmd(v,
8514 &v->shmem_info.memtbl,
8515 v->shmem_info.sh_buf.buf[0].phys,
8516 v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS,
8517 VOIP_MEM_MAP_TOKEN);
8518 if (ret) {
8519 pr_err("%s: mvm_map_memory_phy failed %d\n",
8520 __func__, ret);
8521
8522 goto done;
8523 }
8524
8525done:
8526 return ret;
8527}
8528
8529uint32_t voice_get_topology(uint32_t topology_idx)
8530{
8531 uint32_t topology = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
8532 struct cal_block_data *cal_block = NULL;
8533
8534 /* initialize as default topology */
8535 if (topology_idx == CVP_VOC_RX_TOPOLOGY_CAL) {
8536 topology = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
8537 } else if (topology_idx == CVP_VOC_TX_TOPOLOGY_CAL) {
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05308538 topology = VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS_V2;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308539 } else {
8540 pr_err("%s: cal index %x is invalid!\n",
8541 __func__, topology_idx);
8542
8543 goto done;
8544 }
8545
8546 if (common.cal_data[topology_idx] == NULL) {
8547 pr_err("%s: cal type is NULL for cal index %x\n",
8548 __func__, topology_idx);
8549
8550 goto done;
8551 }
8552
8553 mutex_lock(&common.cal_data[topology_idx]->lock);
8554 cal_block = cal_utils_get_only_cal_block(
8555 common.cal_data[topology_idx]);
8556 if (cal_block == NULL) {
8557 pr_debug("%s: cal_block not found for cal index %x\n",
8558 __func__, topology_idx);
8559
8560 goto unlock;
8561 }
8562
8563 topology = ((struct audio_cal_info_voc_top *)
8564 cal_block->cal_info)->topology;
8565unlock:
8566 mutex_unlock(&common.cal_data[topology_idx]->lock);
8567done:
8568 pr_debug("%s: Using topology %d\n", __func__, topology);
8569
8570 return topology;
8571}
8572
Aditya Bavanari88513a32017-10-12 12:29:25 +05308573int voice_set_topology_specific_info(struct voice_data *v,
8574 uint32_t topology_idx)
8575{
8576 struct cal_block_data *cal_block = NULL;
8577 int ret = 0;
8578 uint32_t topo_channels;
8579
8580 if (common.cal_data[topology_idx] == NULL) {
8581 pr_err("%s: cal type is NULL for cal index %x\n",
8582 __func__, topology_idx);
8583 ret = -EINVAL;
8584 goto done;
8585 }
8586
8587 mutex_lock(&common.cal_data[topology_idx]->lock);
8588 cal_block = cal_utils_get_only_cal_block(
8589 common.cal_data[topology_idx]);
8590 if (cal_block == NULL) {
8591 pr_debug("%s: cal_block not found for cal index %x\n",
8592 __func__, topology_idx);
8593 ret = -EINVAL;
8594 goto unlock;
8595 }
8596
8597 if (topology_idx == CVP_VOC_RX_TOPOLOGY_CAL) {
8598 topo_channels = ((struct audio_cal_info_voc_top *)
8599 cal_block->cal_info)->num_channels;
8600 if (topo_channels > 0) {
8601 v->dev_rx.no_of_channels = topo_channels;
8602 pr_debug("%s: Topology Rx no of channels: %d",
8603 __func__, v->dev_rx.no_of_channels);
8604 memcpy(&v->dev_rx.channel_mapping,
8605 &((struct audio_cal_info_voc_top *)
8606 cal_block->cal_info)->channel_mapping,
8607 VSS_CHANNEL_MAPPING_SIZE);
8608 } else {
8609 pr_debug("%s: cal data is zero, default to Rx backend config\n",
8610 __func__);
8611 if (v->dev_rx.no_of_channels == NUM_CHANNELS_MONO) {
8612 v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FC;
8613 } else if (v->dev_rx.no_of_channels ==
8614 NUM_CHANNELS_STEREO) {
8615 v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FL;
8616 v->dev_rx.channel_mapping[1] = PCM_CHANNEL_FR;
8617 } else {
8618 pr_warn("%s: Unsupported Rx num channels: %d\n",
8619 __func__, v->dev_rx.no_of_channels);
8620 }
8621 }
8622 } else if (topology_idx == CVP_VOC_TX_TOPOLOGY_CAL) {
8623 topo_channels = ((struct audio_cal_info_voc_top *)
8624 cal_block->cal_info)->num_channels;
8625 if (topo_channels > 0) {
8626 v->dev_tx.no_of_channels = topo_channels;
8627 pr_debug("%s: Topology Tx no of channels: %d",
8628 __func__, v->dev_tx.no_of_channels);
8629 memcpy(&v->dev_tx.channel_mapping,
8630 &((struct audio_cal_info_voc_top *)
8631 cal_block->cal_info)->channel_mapping,
8632 VSS_CHANNEL_MAPPING_SIZE);
8633 } else {
8634 pr_debug("%s: cal data is zero, default to Tx backend config\n",
8635 __func__);
8636 if (v->dev_tx.no_of_channels == NUM_CHANNELS_MONO) {
8637 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FC;
8638 } else if (v->dev_tx.no_of_channels ==
8639 NUM_CHANNELS_STEREO) {
8640 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
8641 v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
8642 } else if (v->dev_tx.no_of_channels ==
8643 NUM_CHANNELS_QUAD) {
8644 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
8645 v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
8646 v->dev_tx.channel_mapping[2] = PCM_CHANNEL_LS;
8647 v->dev_tx.channel_mapping[3] = PCM_CHANNEL_RS;
8648 } else {
8649 pr_warn("%s: Unsupported Tx num channels: %d\n",
8650 __func__, v->dev_tx.no_of_channels);
8651 }
8652 }
8653 } else {
8654 pr_err("%s: topology index %x is invalid\n",
8655 __func__, topology_idx);
8656 }
8657unlock:
8658 mutex_unlock(&common.cal_data[topology_idx]->lock);
8659done:
8660 return ret;
8661}
8662
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308663static int get_cal_type_index(int32_t cal_type)
8664{
8665 int ret = -EINVAL;
8666
8667 switch (cal_type) {
8668 case CVP_VOC_RX_TOPOLOGY_CAL_TYPE:
8669 ret = CVP_VOC_RX_TOPOLOGY_CAL;
8670 break;
8671 case CVP_VOC_TX_TOPOLOGY_CAL_TYPE:
8672 ret = CVP_VOC_TX_TOPOLOGY_CAL;
8673 break;
8674 case CVP_VOCPROC_STATIC_CAL_TYPE:
8675 ret = CVP_VOCPROC_CAL;
8676 break;
8677 case CVP_VOCPROC_DYNAMIC_CAL_TYPE:
8678 ret = CVP_VOCVOL_CAL;
8679 break;
8680 case CVS_VOCSTRM_STATIC_CAL_TYPE:
8681 ret = CVS_VOCSTRM_CAL;
8682 break;
8683 case CVP_VOCDEV_CFG_CAL_TYPE:
8684 ret = CVP_VOCDEV_CFG_CAL;
8685 break;
8686 case CVP_VOCPROC_STATIC_COL_CAL_TYPE:
8687 ret = CVP_VOCPROC_COL_CAL;
8688 break;
8689 case CVP_VOCPROC_DYNAMIC_COL_CAL_TYPE:
8690 ret = CVP_VOCVOL_COL_CAL;
8691 break;
8692 case CVS_VOCSTRM_STATIC_COL_CAL_TYPE:
8693 ret = CVS_VOCSTRM_COL_CAL;
8694 break;
8695 case VOICE_RTAC_INFO_CAL_TYPE:
8696 ret = VOICE_RTAC_INFO_CAL;
8697 break;
8698 case VOICE_RTAC_APR_CAL_TYPE:
8699 ret = VOICE_RTAC_APR_CAL;
8700 break;
8701 default:
8702 pr_err("%s: Invalid cal type %d!\n", __func__, cal_type);
8703 }
8704 return ret;
8705}
8706
8707static int voice_prepare_volume_boost(int32_t cal_type,
8708 size_t data_size, void *data)
8709{
8710 return voc_deregister_vocproc_vol_table();
8711}
8712
8713static int voice_enable_volume_boost(int32_t cal_type,
8714 size_t data_size, void *data)
8715{
8716 return voc_register_vocproc_vol_table();
8717}
8718
8719static int voice_alloc_cal(int32_t cal_type,
8720 size_t data_size, void *data)
8721{
8722 int ret = 0;
8723 int cal_index;
8724 int cal_version;
8725
8726 pr_debug("%s\n", __func__);
8727
8728 cal_version = cal_utils_get_cal_type_version(data);
8729 common.is_per_vocoder_cal_enabled =
8730 !!(cal_version & PER_VOCODER_CAL_BIT_MASK);
8731
8732 cal_index = get_cal_type_index(cal_type);
8733 if (cal_index < 0) {
8734 pr_err("%s: Could not get cal index %d!\n",
8735 __func__, cal_index);
8736 ret = -EINVAL;
8737 goto done;
8738 }
8739
8740 ret = cal_utils_alloc_cal(data_size, data,
8741 common.cal_data[cal_index], 0, NULL);
8742 if (ret < 0) {
8743 pr_err("%s: Cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
8744 __func__, ret, cal_type);
8745 ret = -EINVAL;
8746 goto done;
8747 }
8748done:
8749 return ret;
8750}
8751
8752static int voice_dealloc_cal(int32_t cal_type,
8753 size_t data_size, void *data)
8754{
8755 int ret = 0;
8756 int cal_index;
8757
8758 pr_debug("%s\n", __func__);
8759
8760 cal_index = get_cal_type_index(cal_type);
8761 if (cal_index < 0) {
8762 pr_err("%s: Could not get cal index %d!\n",
8763 __func__, cal_index);
8764
8765 ret = -EINVAL;
8766 goto done;
8767 }
8768
8769 ret = cal_utils_dealloc_cal(data_size, data,
8770 common.cal_data[cal_index]);
8771 if (ret < 0) {
8772 pr_err("%s: Cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
8773 __func__, ret, cal_type);
8774
8775 ret = -EINVAL;
8776 goto done;
8777 }
8778done:
8779 return ret;
8780}
8781
8782static int voice_set_cal(int32_t cal_type,
8783 size_t data_size, void *data)
8784{
8785 int ret = 0;
8786 int cal_index;
8787
8788 pr_debug("%s\n", __func__);
8789
8790 cal_index = get_cal_type_index(cal_type);
8791 if (cal_index < 0) {
8792 pr_err("%s: Could not get cal index %d!\n",
8793 __func__, cal_index);
8794
8795 ret = -EINVAL;
8796 goto done;
8797 }
8798
8799 ret = cal_utils_set_cal(data_size, data,
8800 common.cal_data[cal_index], 0, NULL);
8801 if (ret < 0) {
8802 pr_err("%s: Cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
8803 __func__, ret, cal_type);
8804
8805 ret = -EINVAL;
8806 goto done;
8807 }
8808done:
8809 return ret;
8810}
8811
8812static void voice_delete_cal_data(void)
8813{
8814 pr_debug("%s\n", __func__);
8815
8816 cal_utils_destroy_cal_types(MAX_VOICE_CAL_TYPES, common.cal_data);
8817}
8818
8819static int voice_init_cal_data(void)
8820{
8821 int ret = 0;
8822 struct cal_type_info cal_type_info[] = {
8823 {{CVP_VOC_RX_TOPOLOGY_CAL_TYPE,
8824 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
8825 {NULL, NULL, cal_utils_match_buf_num} },
8826
8827 {{CVP_VOC_TX_TOPOLOGY_CAL_TYPE,
8828 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
8829 {NULL, NULL, cal_utils_match_buf_num} },
8830
8831 {{CVP_VOCPROC_STATIC_CAL_TYPE,
8832 {voice_alloc_cal, voice_dealloc_cal, NULL,
8833 voice_set_cal, NULL, NULL} },
8834 {NULL, voice_unmap_cal_memory,
8835 cal_utils_match_buf_num} },
8836
8837 {{CVP_VOCPROC_DYNAMIC_CAL_TYPE,
8838 {voice_alloc_cal, voice_dealloc_cal,
8839 voice_prepare_volume_boost,
8840 voice_set_cal, NULL,
8841 voice_enable_volume_boost} },
8842 {NULL, voice_unmap_cal_memory,
8843 cal_utils_match_buf_num} },
8844
8845 {{CVP_VOCDEV_CFG_CAL_TYPE,
8846 {voice_alloc_cal, voice_dealloc_cal, NULL,
8847 voice_set_cal, NULL, NULL} },
8848 {NULL, voice_unmap_cal_memory,
8849 cal_utils_match_buf_num} },
8850
8851 {{CVP_VOCPROC_STATIC_COL_CAL_TYPE,
8852 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
8853 {NULL, NULL, cal_utils_match_buf_num} },
8854
8855 {{CVP_VOCPROC_DYNAMIC_COL_CAL_TYPE,
8856 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
8857 {NULL, NULL, cal_utils_match_buf_num} },
8858
8859 {{CVS_VOCSTRM_STATIC_CAL_TYPE,
8860 {voice_alloc_cal, voice_dealloc_cal, NULL,
8861 voice_set_cal, NULL, NULL} },
8862 {NULL, voice_unmap_cal_memory,
8863 cal_utils_match_buf_num} },
8864
8865 {{CVS_VOCSTRM_STATIC_COL_CAL_TYPE,
8866 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
8867 {NULL, NULL, cal_utils_match_buf_num} },
8868
8869 {{VOICE_RTAC_INFO_CAL_TYPE,
8870 {NULL, NULL, NULL, NULL, NULL, NULL} },
8871 {NULL, NULL, cal_utils_match_buf_num} },
8872
8873 {{VOICE_RTAC_APR_CAL_TYPE,
8874 {NULL, NULL, NULL, NULL, NULL, NULL} },
8875 {NULL, NULL, cal_utils_match_buf_num} },
8876 };
8877
8878 ret = cal_utils_create_cal_types(MAX_VOICE_CAL_TYPES, common.cal_data,
8879 cal_type_info);
8880 if (ret < 0) {
8881 pr_err("%s: Could not create cal type!\n",
8882 __func__);
8883
8884 ret = -EINVAL;
8885 goto err;
8886 }
8887
8888 return ret;
8889err:
8890 voice_delete_cal_data();
8891 memset(&common, 0, sizeof(struct common_data));
8892 return ret;
8893}
8894
8895static int voice_send_set_sound_focus_cmd(struct voice_data *v,
8896 struct sound_focus_param soundFocusData)
8897{
8898 struct cvp_set_sound_focus_param_cmd_t cvp_set_sound_focus_param_cmd;
8899 int ret = 0;
8900 void *apr_cvp;
8901 u16 cvp_handle;
8902 int i;
8903
8904 pr_debug("%s: Enter\n", __func__);
8905
8906 if (v == NULL) {
8907 pr_err("%s: v is NULL\n", __func__);
8908
8909 ret = -EINVAL;
8910 goto done;
8911 }
8912 apr_cvp = common.apr_q6_cvp;
8913
8914 if (!apr_cvp) {
8915 pr_err("%s: apr_cvp is NULL.\n", __func__);
8916
8917 ret = -EINVAL;
8918 goto done;
8919 }
8920 cvp_handle = voice_get_cvp_handle(v);
8921
8922 /* send Sound Focus Params to cvp */
8923 cvp_set_sound_focus_param_cmd.hdr.hdr_field =
8924 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8925 APR_HDR_LEN(APR_HDR_SIZE),
8926 APR_PKT_VER);
8927 cvp_set_sound_focus_param_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8928 sizeof(cvp_set_sound_focus_param_cmd) - APR_HDR_SIZE);
8929 cvp_set_sound_focus_param_cmd.hdr.src_port =
8930 voice_get_idx_for_session(v->session_id);
8931 cvp_set_sound_focus_param_cmd.hdr.dest_port = cvp_handle;
8932 cvp_set_sound_focus_param_cmd.hdr.token = 0;
8933 cvp_set_sound_focus_param_cmd.hdr.opcode =
8934 VSS_ISOUNDFOCUS_CMD_SET_SECTORS;
8935
8936 memset(&(cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param), 0xFF,
8937 sizeof(struct vss_isoundfocus_cmd_set_sectors_t));
8938 for (i = 0; i < MAX_SECTORS; i++) {
8939 cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param.
8940 start_angles[i] = soundFocusData.start_angle[i];
8941 cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param.
8942 enables[i] = soundFocusData.enable[i];
8943 pr_debug("%s: start_angle[%d] = %d\n",
8944 __func__, i, soundFocusData.start_angle[i]);
8945 pr_debug("%s: enable[%d] = %d\n",
8946 __func__, i, soundFocusData.enable[i]);
8947 }
8948 cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param.gain_step =
8949 soundFocusData.gain_step;
8950 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
8951
8952 v->cvp_state = CMD_STATUS_FAIL;
8953 v->async_err = 0;
8954
8955 ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_sound_focus_param_cmd);
8956 if (ret < 0) {
8957 pr_err("%s: Error in sending APR command\n", __func__);
8958
8959 ret = -EINVAL;
8960 goto done;
8961 }
8962 ret = wait_event_timeout(v->cvp_wait,
8963 (v->cvp_state == CMD_STATUS_SUCCESS),
8964 msecs_to_jiffies(TIMEOUT_MS));
8965 if (!ret) {
8966 pr_err("%s: wait_event timeout\n", __func__);
8967
8968 ret = -EINVAL;
8969 goto done;
8970 }
8971
8972 if (v->async_err > 0) {
8973 pr_err("%s: DSP returned error[%s]\n",
8974 __func__, adsp_err_get_err_str(
8975 v->async_err));
8976 ret = adsp_err_get_lnx_err_code(
8977 v->async_err);
8978 goto done;
8979 }
8980
8981 if (common.is_sound_focus_resp_success) {
8982 ret = 0;
8983 } else {
8984 pr_err("%s: Error in setting sound focus params\n", __func__);
8985
8986 ret = -EINVAL;
8987 }
8988
8989done:
8990 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
8991
8992 return ret;
8993}
8994
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308995/**
8996 * voc_set_sound_focus - sends sound focus data.
8997 *
8998 * @soundFocusData: sound focus data.
8999 *
9000 * Returns 0 on success or error on failure
9001 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309002int voc_set_sound_focus(struct sound_focus_param soundFocusData)
9003{
9004 struct voice_data *v = NULL;
9005 int ret = -EINVAL;
9006 struct voice_session_itr itr;
9007
9008 pr_debug("%s: Enter\n", __func__);
9009
9010 mutex_lock(&common.common_lock);
9011 voice_itr_init(&itr, ALL_SESSION_VSID);
9012 while (voice_itr_get_next_session(&itr, &v)) {
9013 if (v != NULL) {
9014 mutex_lock(&v->lock);
9015 if (is_voc_state_active(v->voc_state) &&
9016 (v->lch_mode != VOICE_LCH_START) &&
9017 !v->disable_topology)
9018 ret = voice_send_set_sound_focus_cmd(v,
9019 soundFocusData);
9020 mutex_unlock(&v->lock);
9021 } else {
9022 pr_err("%s: invalid session\n", __func__);
9023
9024 ret = -EINVAL;
9025 break;
9026 }
9027 }
9028 mutex_unlock(&common.common_lock);
9029 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9030
9031 return ret;
9032}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309033EXPORT_SYMBOL(voc_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309034
9035static int voice_send_get_sound_focus_cmd(struct voice_data *v,
9036 struct sound_focus_param *soundFocusData)
9037{
9038 struct apr_hdr cvp_get_sound_focus_param_cmd;
9039 int ret = 0;
9040 void *apr_cvp;
9041 u16 cvp_handle;
9042 int i;
9043
9044 pr_debug("%s: Enter\n", __func__);
9045
9046 if (!v) {
9047 pr_err("%s: v is NULL\n", __func__);
9048
9049 ret = -EINVAL;
9050 goto done;
9051 }
9052 apr_cvp = common.apr_q6_cvp;
9053
9054 if (!apr_cvp) {
9055 pr_err("%s: apr_cvp is NULL\n", __func__);
9056
9057 ret = -EINVAL;
9058 goto done;
9059 }
9060
9061 cvp_handle = voice_get_cvp_handle(v);
9062
9063 /* send APR command to retrieve Sound Focus Params */
9064 cvp_get_sound_focus_param_cmd.hdr_field =
9065 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
9066 APR_HDR_LEN(APR_HDR_SIZE),
9067 APR_PKT_VER);
9068 cvp_get_sound_focus_param_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
9069 sizeof(cvp_get_sound_focus_param_cmd) - APR_HDR_SIZE);
9070 cvp_get_sound_focus_param_cmd.src_port =
9071 voice_get_idx_for_session(v->session_id);
9072 cvp_get_sound_focus_param_cmd.dest_port = cvp_handle;
9073 cvp_get_sound_focus_param_cmd.token = 0;
9074 cvp_get_sound_focus_param_cmd.opcode = VSS_ISOUNDFOCUS_CMD_GET_SECTORS;
9075
9076 v->cvp_state = CMD_STATUS_FAIL;
9077 v->async_err = 0;
9078 ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_get_sound_focus_param_cmd);
9079 if (ret < 0) {
9080 pr_err("%s: Error in sending APR command\n", __func__);
9081
9082 ret = -EINVAL;
9083 goto done;
9084 }
9085 ret = wait_event_timeout(v->cvp_wait,
9086 (v->cvp_state == CMD_STATUS_SUCCESS),
9087 msecs_to_jiffies(TIMEOUT_MS));
9088 if (!ret) {
9089 pr_err("%s: wait_event timeout\n", __func__);
9090
9091 ret = -EINVAL;
9092 goto done;
9093 }
9094
9095 if (v->async_err > 0) {
9096 pr_err("%s: DSP returned error[%s]\n",
9097 __func__, adsp_err_get_err_str(
9098 v->async_err));
9099 ret = adsp_err_get_lnx_err_code(
9100 v->async_err);
9101 goto done;
9102 }
9103
9104 if (common.is_sound_focus_resp_success) {
9105 for (i = 0; i < MAX_SECTORS; i++) {
9106 soundFocusData->start_angle[i] =
9107 common.soundFocusResponse.start_angles[i];
9108 soundFocusData->enable[i] =
9109 common.soundFocusResponse.enables[i];
9110 pr_debug("%s: start_angle[%d] = %d\n",
9111 __func__, i, soundFocusData->start_angle[i]);
9112 pr_debug("%s: enable[%d] = %d\n",
9113 __func__, i, soundFocusData->enable[i]);
9114 }
9115 soundFocusData->gain_step = common.soundFocusResponse.gain_step;
9116 pr_debug("%s: gain_step = %d\n", __func__,
9117 soundFocusData->gain_step);
9118
9119 common.is_sound_focus_resp_success = false;
9120 ret = 0;
9121 } else {
9122 pr_err("%s: Invalid payload received from CVD\n", __func__);
9123
9124 ret = -EINVAL;
9125 }
9126done:
9127 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9128
9129 return ret;
9130}
9131
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309132/**
9133 * voc_get_sound_focus - retrieves sound focus data.
9134 *
9135 * @soundFocusData: pointer to be updated with sound focus data.
9136 *
9137 * Returns 0 on success or error on failure
9138 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309139int voc_get_sound_focus(struct sound_focus_param *soundFocusData)
9140{
9141 struct voice_data *v = NULL;
9142 int ret = -EINVAL;
9143 struct voice_session_itr itr;
9144
9145 pr_debug("%s: Enter\n", __func__);
9146
9147 mutex_lock(&common.common_lock);
9148 voice_itr_init(&itr, ALL_SESSION_VSID);
9149 while (voice_itr_get_next_session(&itr, &v)) {
9150 if (v) {
9151 mutex_lock(&v->lock);
9152 if (is_voc_state_active(v->voc_state) &&
9153 (v->lch_mode != VOICE_LCH_START) &&
9154 !v->disable_topology)
9155 ret = voice_send_get_sound_focus_cmd(v,
9156 soundFocusData);
9157 mutex_unlock(&v->lock);
9158 } else {
9159 pr_err("%s: invalid session\n", __func__);
9160
9161 ret = -EINVAL;
9162 break;
9163 }
9164 }
9165 mutex_unlock(&common.common_lock);
9166 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9167
9168 return ret;
9169}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309170EXPORT_SYMBOL(voc_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309171
9172static int is_source_tracking_shared_memomry_allocated(void)
9173{
9174 bool ret;
9175
9176 pr_debug("%s: Enter\n", __func__);
9177
9178 if (common.source_tracking_sh_mem.sh_mem_block.client != NULL &&
9179 common.source_tracking_sh_mem.sh_mem_block.handle != NULL)
9180 ret = true;
9181 else
9182 ret = false;
9183
9184 pr_debug("%s: Exit\n", __func__);
9185
9186 return ret;
9187}
9188
9189static int voice_alloc_source_tracking_shared_memory(void)
9190{
9191 int ret = 0;
9192
9193 pr_debug("%s: Enter\n", __func__);
9194
9195 ret = msm_audio_ion_alloc("source_tracking_sh_mem_block",
9196 &(common.source_tracking_sh_mem.sh_mem_block.client),
9197 &(common.source_tracking_sh_mem.sh_mem_block.handle),
9198 BUFFER_BLOCK_SIZE,
9199 &(common.source_tracking_sh_mem.sh_mem_block.phys),
9200 (size_t *)&(common.source_tracking_sh_mem.sh_mem_block.size),
9201 &(common.source_tracking_sh_mem.sh_mem_block.data));
9202 if (ret < 0) {
9203 pr_err("%s: audio ION alloc failed for sh_mem block, ret = %d\n",
9204 __func__, ret);
9205
9206 ret = -EINVAL;
9207 goto done;
9208 }
9209 memset((void *)(common.source_tracking_sh_mem.sh_mem_block.data), 0,
9210 common.source_tracking_sh_mem.sh_mem_block.size);
9211
9212 pr_debug("%s: sh_mem_block: phys:[%pK], data:[0x%pK], size:[%zd]\n",
9213 __func__,
9214 &(common.source_tracking_sh_mem.sh_mem_block.phys),
9215 (void *)(common.source_tracking_sh_mem.sh_mem_block.data),
9216 (size_t)(common.source_tracking_sh_mem.sh_mem_block.size));
9217
9218 ret = msm_audio_ion_alloc("source_tracking_sh_mem_table",
9219 &(common.source_tracking_sh_mem.sh_mem_table.client),
9220 &(common.source_tracking_sh_mem.sh_mem_table.handle),
9221 sizeof(struct vss_imemory_table_t),
9222 &(common.source_tracking_sh_mem.sh_mem_table.phys),
9223 (size_t *)&(common.source_tracking_sh_mem.sh_mem_table.size),
9224 &(common.source_tracking_sh_mem.sh_mem_table.data));
9225 if (ret < 0) {
9226 pr_err("%s: audio ION alloc failed for sh_mem table, ret = %d\n",
9227 __func__, ret);
9228
9229 ret = msm_audio_ion_free(
9230 common.source_tracking_sh_mem.sh_mem_block.client,
9231 common.source_tracking_sh_mem.sh_mem_block.handle);
9232 common.source_tracking_sh_mem.sh_mem_block.client = NULL;
9233 common.source_tracking_sh_mem.sh_mem_block.handle = NULL;
9234 if (ret < 0)
9235 pr_err("%s: Error:%d freeing memory\n", __func__, ret);
9236
9237 ret = -EINVAL;
9238 goto done;
9239 }
9240 memset((void *)(common.source_tracking_sh_mem.sh_mem_table.data), 0,
9241 common.source_tracking_sh_mem.sh_mem_table.size);
9242
9243 pr_debug("%s sh_mem_table: phys:[%pK], data:[0x%pK], size:[%zd],\n",
9244 __func__,
9245 &(common.source_tracking_sh_mem.sh_mem_table.phys),
9246 (void *)(common.source_tracking_sh_mem.sh_mem_table.data),
9247 (size_t)(common.source_tracking_sh_mem.sh_mem_table.size));
9248
9249done:
9250 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9251
9252 return ret;
9253}
9254
9255static int voice_alloc_and_map_source_tracking_shared_memory(
9256 struct voice_data *v)
9257{
9258 int ret = 0;
9259
9260 pr_debug("%s: Enter\n", __func__);
9261
9262 ret = voice_alloc_source_tracking_shared_memory();
9263 if (ret) {
9264 pr_err("%s: Failed to allocate shared memory %d\n",
9265 __func__, ret);
9266
9267 ret = -EINVAL;
9268 goto done;
9269 }
9270
9271 ret = voice_map_memory_physical_cmd(v,
9272 &(common.source_tracking_sh_mem.sh_mem_table),
9273 common.source_tracking_sh_mem.sh_mem_block.phys,
9274 common.source_tracking_sh_mem.sh_mem_block.size,
9275 VOC_SOURCE_TRACKING_MEM_MAP_TOKEN);
9276 if (ret) {
9277 pr_err("%s: memory mapping failed %d\n",
9278 __func__, ret);
9279
9280 ret = -EINVAL;
9281 goto done;
9282 }
9283
9284done:
9285 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9286
9287 return ret;
9288}
9289
9290static int voice_unmap_and_free_source_tracking_shared_memory(
9291 struct voice_data *v)
9292{
9293 int ret = 0;
9294
9295 pr_debug("%s: Enter\n", __func__);
9296
9297 if (common.source_tracking_sh_mem.mem_handle != 0) {
9298 ret = voice_send_mvm_unmap_memory_physical_cmd(v,
9299 common.source_tracking_sh_mem.mem_handle);
9300 if (ret < 0) {
9301 pr_err("%s: Memory_unmap failed err %d\n",
9302 __func__, ret);
9303
9304 ret = -EINVAL;
9305 goto done;
9306 }
9307 }
9308
9309 if ((common.source_tracking_sh_mem.sh_mem_block.client == NULL) ||
9310 (common.source_tracking_sh_mem.sh_mem_block.handle == NULL))
9311 goto done;
9312
9313 ret = msm_audio_ion_free(
9314 common.source_tracking_sh_mem.sh_mem_block.client,
9315 common.source_tracking_sh_mem.sh_mem_block.handle);
9316 if (ret < 0) {
9317 pr_err("%s: Error:%d freeing memory\n", __func__, ret);
9318
9319 ret = -EINVAL;
9320 goto done;
9321 }
9322
9323done:
9324 common.source_tracking_sh_mem.mem_handle = 0;
9325 common.source_tracking_sh_mem.sh_mem_block.client = NULL;
9326 common.source_tracking_sh_mem.sh_mem_block.handle = NULL;
9327 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9328
9329 return ret;
9330}
9331
9332static int voice_send_get_source_tracking_cmd(struct voice_data *v,
9333 struct source_tracking_param *sourceTrackingData)
9334{
9335 struct cvp_get_source_tracking_param_cmd_t st_cmd;
9336 int ret = 0;
9337 void *apr_cvp;
9338 u16 cvp_handle;
9339 int i;
9340
9341 pr_debug("%s: Enter\n", __func__);
9342
9343 if (!v) {
9344 pr_err("%s: v is NULL\n", __func__);
9345 return -EINVAL;
9346 }
9347 apr_cvp = common.apr_q6_cvp;
9348
9349 if (!apr_cvp) {
9350 pr_err("%s: apr_cvp is NULL.\n", __func__);
9351 return -EINVAL;
9352 }
9353
9354 cvp_handle = voice_get_cvp_handle(v);
9355
9356 if (!is_source_tracking_shared_memomry_allocated()) {
9357 ret = voice_alloc_and_map_source_tracking_shared_memory(v);
9358 if (ret) {
9359 pr_err("%s: Fail in allocating/mapping shared memory\n",
9360 __func__);
9361
9362 ret = -EINVAL;
9363 goto done;
9364 }
9365 }
9366 st_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
9367 APR_HDR_LEN(APR_HDR_SIZE),
9368 APR_PKT_VER);
9369 st_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
9370 sizeof(st_cmd) - APR_HDR_SIZE);
9371 st_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
9372 st_cmd.hdr.dest_port = cvp_handle;
9373 st_cmd.hdr.token = 0;
9374 st_cmd.hdr.opcode = VSS_ISOURCETRACK_CMD_GET_ACTIVITY;
9375
9376 st_cmd.cvp_get_source_tracking_param.mem_handle =
9377 common.source_tracking_sh_mem.mem_handle;
9378 st_cmd.cvp_get_source_tracking_param.mem_address_lsw =
9379 lower_32_bits(common.source_tracking_sh_mem.sh_mem_block.phys);
9380 st_cmd.cvp_get_source_tracking_param.mem_address_msw =
9381 msm_audio_populate_upper_32_bits(common.source_tracking_sh_mem.
9382 sh_mem_block.phys);
9383 st_cmd.cvp_get_source_tracking_param.mem_size =
9384 (uint32_t)common.source_tracking_sh_mem.sh_mem_block.size;
9385 pr_debug("%s: mem_handle=0x%x, mem_address_lsw=0x%x, msw=0x%x, mem_size=%d\n",
9386 __func__,
9387 st_cmd.cvp_get_source_tracking_param.mem_handle,
9388 st_cmd.cvp_get_source_tracking_param.mem_address_lsw,
9389 st_cmd.cvp_get_source_tracking_param.mem_address_msw,
9390 (uint32_t)st_cmd.cvp_get_source_tracking_param.mem_size);
9391
9392 v->cvp_state = CMD_STATUS_FAIL;
9393 v->async_err = 0;
9394 ret = apr_send_pkt(apr_cvp,
9395 (uint32_t *) &st_cmd);
9396 if (ret < 0) {
9397 pr_err("%s: Error in sending APR command\n", __func__);
9398
9399 ret = -EINVAL;
9400 goto done;
9401 }
9402 ret = wait_event_timeout(v->cvp_wait,
9403 (v->cvp_state == CMD_STATUS_SUCCESS),
9404 msecs_to_jiffies(TIMEOUT_MS));
9405 if (!ret) {
9406 pr_err("%s: wait_event timeout\n", __func__);
9407
9408 ret = -EINVAL;
9409 goto done;
9410 }
9411
9412 if (v->async_err > 0) {
9413 pr_err("%s: DSP returned error[%s]\n",
9414 __func__, adsp_err_get_err_str(
9415 v->async_err));
9416 ret = adsp_err_get_lnx_err_code(
9417 v->async_err);
9418 goto done;
9419 }
9420
9421 if (common.is_source_tracking_resp_success) {
9422 for (i = 0; i < MAX_SECTORS; i++) {
9423 sourceTrackingData->vad[i] =
9424 common.sourceTrackingResponse.voice_active[i];
9425 pr_debug("%s: vad[%d] = %d\n",
9426 __func__, i, sourceTrackingData->vad[i]);
9427 }
9428 sourceTrackingData->doa_speech =
9429 common.sourceTrackingResponse.talker_doa;
9430 pr_debug("%s: doa_speech = %d\n",
9431 __func__, sourceTrackingData->doa_speech);
9432
9433 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
9434 sourceTrackingData->doa_noise[i] =
9435 common.sourceTrackingResponse.interferer_doa[i];
9436 pr_debug("%s: doa_noise[%d] = %d\n",
9437 __func__, i, sourceTrackingData->doa_noise[i]);
9438 }
9439 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
9440 sourceTrackingData->polar_activity[i] =
9441 common.sourceTrackingResponse.sound_strength[i];
9442 pr_debug("%s: polar_activity[%d] = %d\n",
9443 __func__, i, sourceTrackingData->polar_activity[i]);
9444 }
9445 common.is_source_tracking_resp_success = false;
9446 ret = 0;
9447 } else {
9448 pr_err("%s: Error response received from CVD\n", __func__);
9449
9450 ret = -EINVAL;
9451 }
9452done:
9453 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9454
9455 return ret;
9456}
9457
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309458/**
9459 * voc_get_source_tracking - retrieves source track data.
9460 *
9461 * @sourceTrackingData: pointer to be updated with source track data.
9462 *
9463 * Returns 0 on success or error on failure
9464 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309465int voc_get_source_tracking(struct source_tracking_param *sourceTrackingData)
9466{
9467 struct voice_data *v = NULL;
9468 int ret = -EINVAL;
9469 struct voice_session_itr itr;
9470
9471 pr_debug("%s: Enter\n", __func__);
9472
9473 mutex_lock(&common.common_lock);
9474
9475 voice_itr_init(&itr, ALL_SESSION_VSID);
9476 while (voice_itr_get_next_session(&itr, &v)) {
9477 if (v != NULL) {
9478 mutex_lock(&v->lock);
9479 if (is_voc_state_active(v->voc_state) &&
9480 (v->lch_mode != VOICE_LCH_START) &&
9481 !v->disable_topology)
9482 ret = voice_send_get_source_tracking_cmd(v,
9483 sourceTrackingData);
9484 mutex_unlock(&v->lock);
9485 } else {
9486 pr_err("%s: invalid session\n", __func__);
9487
9488 break;
9489 }
9490 }
9491
9492 mutex_unlock(&common.common_lock);
9493 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9494
9495 return ret;
9496}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309497EXPORT_SYMBOL(voc_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309498
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309499/**
9500 * is_voc_initialized:
9501 *
9502 * Returns voice module init status
9503 *
9504 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309505int is_voc_initialized(void)
9506{
9507 return module_initialized;
9508}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309509EXPORT_SYMBOL(is_voc_initialized);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309510
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309511int __init voice_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309512{
9513 int rc = 0, i = 0;
9514
9515 memset(&common, 0, sizeof(struct common_data));
9516
9517 /* set default value */
9518 common.default_mute_val = 0; /* default is un-mute */
9519 common.default_sample_val = 8000;
9520 common.default_vol_step_val = 0;
9521 common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
9522 common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
Laxminath Kasam38070be2017-08-17 18:21:59 +05309523 common.cvp_version = 0;
9524 common.is_avcs_version_queried = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309525 /* Initialize EC Ref media format info */
9526 common.ec_ref_ext = false;
9527 common.ec_media_fmt_info.port_id = AFE_PORT_INVALID;
9528 common.ec_media_fmt_info.num_channels = 0;
9529 common.ec_media_fmt_info.bits_per_sample = 16;
9530 common.ec_media_fmt_info.sample_rate = 8000;
9531 memset(&common.ec_media_fmt_info.channel_mapping, 0,
9532 VSS_CHANNEL_MAPPING_SIZE);
9533
9534 /* Initialize AFE Sidetone Enable */
9535 common.sidetone_enable = false;
9536
9537 /* Initialize MVS info. */
9538 common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
9539
9540 /* Initialize is low memory flag */
9541 common.is_destroy_cvd = false;
9542
9543 /* Initialize CVD version */
9544 strlcpy(common.cvd_version, CVD_VERSION_DEFAULT,
9545 sizeof(common.cvd_version));
9546 /* Initialize Per-Vocoder Calibration flag */
9547 common.is_per_vocoder_cal_enabled = false;
9548
9549 mutex_init(&common.common_lock);
9550
9551 /* Initialize session id with vsid */
9552 init_session_id();
9553
9554 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
9555
9556 /* initialize dev_rx and dev_tx */
9557 common.voice[i].dev_rx.dev_mute = common.default_mute_val;
9558 common.voice[i].dev_tx.dev_mute = common.default_mute_val;
9559 common.voice[i].dev_rx.volume_step_value =
9560 common.default_vol_step_val;
9561 common.voice[i].dev_rx.volume_ramp_duration_ms =
9562 common.default_vol_ramp_duration_ms;
9563 common.voice[i].dev_rx.dev_mute_ramp_duration_ms =
9564 common.default_mute_ramp_duration_ms;
9565 common.voice[i].dev_tx.dev_mute_ramp_duration_ms =
9566 common.default_mute_ramp_duration_ms;
9567 common.voice[i].stream_rx.stream_mute = common.default_mute_val;
9568 common.voice[i].stream_tx.stream_mute = common.default_mute_val;
9569
9570 common.voice[i].dev_tx.port_id = 0x100B;
9571 common.voice[i].dev_rx.port_id = 0x100A;
9572 common.voice[i].dev_tx.dev_id = 0;
9573 common.voice[i].dev_rx.dev_id = 0;
9574 common.voice[i].dev_tx.no_of_channels = 0;
9575 common.voice[i].dev_rx.no_of_channels = 0;
9576 common.voice[i].dev_tx.sample_rate = 8000;
9577 common.voice[i].dev_rx.sample_rate = 8000;
9578 common.voice[i].dev_tx.bits_per_sample = 16;
9579 common.voice[i].dev_rx.bits_per_sample = 16;
9580 memset(&common.voice[i].dev_tx.channel_mapping, 0,
9581 VSS_CHANNEL_MAPPING_SIZE);
9582 memset(&common.voice[i].dev_rx.channel_mapping, 0,
9583 VSS_CHANNEL_MAPPING_SIZE);
9584 common.voice[i].sidetone_gain = 0x512;
9585 common.voice[i].dtmf_rx_detect_en = 0;
9586 common.voice[i].lch_mode = 0;
9587 common.voice[i].disable_topology = false;
9588
9589 common.voice[i].voc_state = VOC_INIT;
9590
9591 init_waitqueue_head(&common.voice[i].mvm_wait);
9592 init_waitqueue_head(&common.voice[i].cvs_wait);
9593 init_waitqueue_head(&common.voice[i].cvp_wait);
9594
9595 mutex_init(&common.voice[i].lock);
9596 }
9597
9598 if (voice_init_cal_data())
9599 pr_err("%s: Could not init cal data!\n", __func__);
9600
9601 if (rc == 0)
9602 module_initialized = true;
9603
9604 pr_debug("%s: rc=%d\n", __func__, rc);
9605 return rc;
9606}
9607
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309608
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309609void __exit voice_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309610{
9611 voice_delete_cal_data();
9612 free_cal_map_table();
9613}