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