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