blob: e5b11393c03c89e0ec86fb05c35f9cdc7ae7c704 [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{
7430 uint32_t *ptr = NULL;
7431 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) {
7501 if (data->payload_size) {
7502 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
7571 if (data->payload_size && data->token == VOIP_MEM_MAP_TOKEN) {
7572 ptr = data->payload;
7573 if (ptr[0]) {
7574 v->shmem_info.mem_handle = ptr[0];
7575 pr_debug("%s: shared mem_handle: 0x[%x]\n",
7576 __func__, v->shmem_info.mem_handle);
7577 v->mvm_state = CMD_STATUS_SUCCESS;
7578 wake_up(&v->mvm_wait);
7579 }
7580 } else if (data->payload_size &&
7581 data->token == VOC_CAL_MEM_MAP_TOKEN) {
7582 ptr = data->payload;
7583 if (ptr[0]) {
7584 c->cal_mem_handle = ptr[0];
7585
7586 pr_debug("%s: cal mem handle 0x%x\n",
7587 __func__, c->cal_mem_handle);
7588
7589 v->mvm_state = CMD_STATUS_SUCCESS;
7590 wake_up(&v->mvm_wait);
7591 }
7592 } else if (data->payload_size &&
7593 data->token == VOC_VOICE_HOST_PCM_MAP_TOKEN) {
7594 ptr = data->payload;
7595 if (ptr[0]) {
7596 common.voice_host_pcm_mem_handle = ptr[0];
7597
7598 pr_debug("%s: vhpcm mem handle 0x%x\n",
7599 __func__,
7600 common.voice_host_pcm_mem_handle);
7601 v->mvm_state = CMD_STATUS_SUCCESS;
7602 wake_up(&v->mvm_wait);
7603 }
7604 } else if (data->payload_size &&
7605 data->token == VOC_RTAC_MEM_MAP_TOKEN) {
7606 ptr = data->payload;
7607 if (ptr[0]) {
7608 c->rtac_mem_handle = ptr[0];
7609
7610 pr_debug("%s: cal mem handle 0x%x\n",
7611 __func__, c->rtac_mem_handle);
7612
7613 v->mvm_state = CMD_STATUS_SUCCESS;
7614 wake_up(&v->mvm_wait);
7615 }
7616 } else if (data->payload_size &&
7617 data->token == VOC_SOURCE_TRACKING_MEM_MAP_TOKEN) {
7618 ptr = data->payload;
7619 if (ptr[0]) {
7620 common.source_tracking_sh_mem.mem_handle =
7621 ptr[0];
7622
7623 pr_debug("%s: Source Tracking shared mem handle 0x%x\n",
7624 __func__,
7625 common.source_tracking_sh_mem.mem_handle);
7626
7627 v->mvm_state = CMD_STATUS_SUCCESS;
7628 wake_up(&v->mvm_wait);
7629 }
7630 } else {
7631 pr_err("%s: Unknown mem map token %d\n",
7632 __func__, data->token);
7633 }
7634 } else if (data->opcode == VSS_IVERSION_RSP_GET) {
7635 pr_debug("%s: Received VSS_IVERSION_RSP_GET\n", __func__);
7636
7637 if (data->payload_size) {
7638 version_rsp =
7639 (struct vss_iversion_rsp_get_t *)data->payload;
7640 memcpy(common.cvd_version, version_rsp->version,
7641 CVD_VERSION_STRING_MAX_SIZE);
7642 pr_debug("%s: CVD Version = %s\n",
7643 __func__, common.cvd_version);
7644
7645 v->mvm_state = CMD_STATUS_SUCCESS;
7646 wake_up(&v->mvm_wait);
7647 }
Vignesh Kulothungan78d3e822018-03-13 16:05:20 -07007648 } else if (data->opcode == VSS_ICOMMON_EVT_VOICE_ACTIVITY_UPDATE) {
7649 if (data->payload_size ==
7650 sizeof(struct vss_evt_voice_activity)) {
7651 voice_act_update =
7652 (struct vss_evt_voice_activity *)
7653 data->payload;
7654
7655 /* Drop notifications other than Mic Break */
7656 if ((voice_act_update->activity
7657 != VSS_ICOMMON_VOICE_ACTIVITY_MIC_BREAK)
7658 && (voice_act_update->activity
7659 != VSS_ICOMMON_VOICE_ACITIVTY_MIC_UNBREAK))
7660 return 0;
7661
7662 switch (voice_act_update->activity) {
7663 case VSS_ICOMMON_VOICE_ACTIVITY_MIC_BREAK:
7664 v->mic_break_status = true;
7665 break;
7666 case VSS_ICOMMON_VOICE_ACITIVTY_MIC_UNBREAK:
7667 v->mic_break_status = false;
7668 break;
7669 }
7670
7671 if (c->mic_break_enable)
7672 schedule_work(&(v->voice_mic_break_work));
7673 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307674 }
Vignesh Kulothungan78d3e822018-03-13 16:05:20 -07007675
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05307676 return 0;
7677}
7678
7679static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv)
7680{
7681 uint32_t *ptr = NULL;
7682 struct common_data *c = NULL;
7683 struct voice_data *v = NULL;
7684 int i = 0;
7685
7686 if ((data == NULL) || (priv == NULL)) {
7687 pr_err("%s: data or priv is NULL\n", __func__);
7688 return -EINVAL;
7689 }
7690
7691 c = priv;
7692
7693 pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port);
7694 pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__,
7695 data->payload_size, data->opcode);
7696
7697 if (data->opcode == RESET_EVENTS) {
7698 pr_debug("%s: Reset event received in Voice service\n",
7699 __func__);
7700
7701 apr_reset(c->apr_q6_cvs);
7702 c->apr_q6_cvs = NULL;
7703
7704 /* Sub-system restart is applicable to all sessions. */
7705 for (i = 0; i < MAX_VOC_SESSIONS; i++)
7706 c->voice[i].cvs_handle = 0;
7707
7708 cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
7709 common.cal_data);
7710
7711 /* Free the ION memory and clear handles for Source Tracking */
7712 if (is_source_tracking_shared_memomry_allocated()) {
7713 msm_audio_ion_free(
7714 common.source_tracking_sh_mem.sh_mem_block.client,
7715 common.source_tracking_sh_mem.sh_mem_block.handle);
7716 common.source_tracking_sh_mem.mem_handle = 0;
7717 common.source_tracking_sh_mem.sh_mem_block.client =
7718 NULL;
7719 common.source_tracking_sh_mem.sh_mem_block.handle =
7720 NULL;
7721 }
7722 voc_set_error_state(data->reset_proc);
7723 return 0;
7724 }
7725
7726 v = voice_get_session_by_idx(data->dest_port);
7727 if (v == NULL) {
7728 pr_err("%s: v is NULL\n", __func__);
7729
7730 return -EINVAL;
7731 }
7732
7733 if (data->opcode == APR_BASIC_RSP_RESULT) {
7734 if (data->payload_size) {
7735 ptr = data->payload;
7736
7737 pr_debug("%x %x\n", ptr[0], ptr[1]);
7738 if (ptr[1] != 0) {
7739 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
7740 __func__, ptr[0], ptr[1]);
7741 }
7742 /*response from CVS */
7743 switch (ptr[0]) {
7744 case VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION:
7745 case VSS_ISTREAM_CMD_CREATE_FULL_CONTROL_SESSION:
7746 if (!ptr[1]) {
7747 pr_debug("%s: CVS handle is %d\n",
7748 __func__, data->src_port);
7749 voice_set_cvs_handle(v, data->src_port);
7750 } else
7751 pr_err("got NACK for sending CVS create session\n");
7752 v->cvs_state = CMD_STATUS_SUCCESS;
7753 v->async_err = ptr[1];
7754 wake_up(&v->cvs_wait);
7755 break;
7756 case VSS_IVOLUME_CMD_MUTE_V2:
7757 case VSS_ISTREAM_CMD_SET_MEDIA_TYPE:
7758 case VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE:
7759 case VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE:
7760 case VSS_ISTREAM_CMD_SET_ENC_DTX_MODE:
7761 case VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE:
7762 case APRV2_IBASIC_CMD_DESTROY_SESSION:
7763 case VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA_V2:
7764 case VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA:
7765 case VSS_ISTREAM_CMD_REGISTER_STATIC_CALIBRATION_DATA:
7766 case VSS_ISTREAM_CMD_DEREGISTER_STATIC_CALIBRATION_DATA:
7767 case VSS_ICOMMON_CMD_MAP_MEMORY:
7768 case VSS_ICOMMON_CMD_UNMAP_MEMORY:
7769 case VSS_ICOMMON_CMD_SET_UI_PROPERTY:
7770 case VSS_IPLAYBACK_CMD_START:
7771 case VSS_IPLAYBACK_CMD_STOP:
7772 case VSS_IRECORD_CMD_START:
7773 case VSS_IRECORD_CMD_STOP:
7774 case VSS_ISTREAM_CMD_SET_PACKET_EXCHANGE_MODE:
7775 case VSS_ISTREAM_CMD_SET_OOB_PACKET_EXCHANGE_CONFIG:
7776 case VSS_ISTREAM_CMD_SET_RX_DTMF_DETECTION:
7777 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7778 v->cvs_state = CMD_STATUS_SUCCESS;
7779 v->async_err = ptr[1];
7780 wake_up(&v->cvs_wait);
7781 break;
7782 case VSS_ICOMMON_CMD_SET_PARAM_V2:
7783 pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2\n",
7784 __func__);
7785 rtac_make_voice_callback(RTAC_CVS, ptr,
7786 data->payload_size);
7787 break;
7788 case VSS_ICOMMON_CMD_GET_PARAM_V2:
7789 pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n",
7790 __func__);
7791 /* Should only come here if there is an APR */
7792 /* error or malformed APR packet. Otherwise */
7793 /* response will be returned as */
7794 /* VSS_ICOMMON_RSP_GET_PARAM */
7795 if (ptr[1] != 0) {
7796 pr_err("%s: CVP get param error = %d, resuming\n",
7797 __func__, ptr[1]);
7798 rtac_make_voice_callback(RTAC_CVP,
7799 data->payload,
7800 data->payload_size);
7801 }
7802 break;
7803 default:
7804 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
7805 break;
7806 }
7807 }
7808 } else if (data->opcode ==
7809 VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_READY) {
7810 int ret = 0;
7811 u16 cvs_handle;
7812 uint32_t *cvs_voc_pkt;
7813 struct cvs_enc_buffer_consumed_cmd send_enc_buf_consumed_cmd;
7814 void *apr_cvs;
7815
7816 pr_debug("Encoder buffer is ready\n");
7817
7818 apr_cvs = common.apr_q6_cvs;
7819 if (!apr_cvs) {
7820 pr_err("%s: apr_cvs is NULL\n", __func__);
7821 return -EINVAL;
7822 }
7823 cvs_handle = voice_get_cvs_handle(v);
7824
7825 send_enc_buf_consumed_cmd.hdr.hdr_field =
7826 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7827 APR_HDR_LEN(APR_HDR_SIZE),
7828 APR_PKT_VER);
7829 send_enc_buf_consumed_cmd.hdr.pkt_size =
7830 APR_PKT_SIZE(APR_HDR_SIZE,
7831 sizeof(send_enc_buf_consumed_cmd) - APR_HDR_SIZE);
7832
7833 send_enc_buf_consumed_cmd.hdr.src_port =
7834 voice_get_idx_for_session(v->session_id);
7835 send_enc_buf_consumed_cmd.hdr.dest_port = cvs_handle;
7836 send_enc_buf_consumed_cmd.hdr.token = 0;
7837 send_enc_buf_consumed_cmd.hdr.opcode =
7838 VSS_ISTREAM_EVT_OOB_NOTIFY_ENC_BUFFER_CONSUMED;
7839
7840 cvs_voc_pkt = v->shmem_info.sh_buf.buf[1].data;
7841 if (cvs_voc_pkt != NULL && common.mvs_info.ul_cb != NULL) {
7842 /* cvs_voc_pkt[0] contains tx timestamp */
7843 common.mvs_info.ul_cb((uint8_t *)&cvs_voc_pkt[3],
7844 cvs_voc_pkt[2],
7845 cvs_voc_pkt[0],
7846 common.mvs_info.private_data);
7847 } else
7848 pr_err("%s: cvs_voc_pkt or ul_cb is NULL\n", __func__);
7849
7850 ret = apr_send_pkt(apr_cvs,
7851 (uint32_t *) &send_enc_buf_consumed_cmd);
7852 if (ret < 0) {
7853 pr_err("%s: Err send ENC_BUF_CONSUMED_NOTIFY %d\n",
7854 __func__, ret);
7855 goto fail;
7856 }
7857 } else if (data->opcode == VSS_ISTREAM_EVT_SEND_ENC_BUFFER) {
7858 pr_debug("Recd VSS_ISTREAM_EVT_SEND_ENC_BUFFER\n");
7859 } else if (data->opcode ==
7860 VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_REQUEST) {
7861 int ret = 0;
7862 u16 cvs_handle;
7863 uint32_t *cvs_voc_pkt;
7864 struct cvs_dec_buffer_ready_cmd send_dec_buf;
7865 void *apr_cvs;
7866
7867 apr_cvs = common.apr_q6_cvs;
7868
7869 if (!apr_cvs) {
7870 pr_err("%s: apr_cvs is NULL\n", __func__);
7871 return -EINVAL;
7872 }
7873 cvs_handle = voice_get_cvs_handle(v);
7874
7875 send_dec_buf.hdr.hdr_field =
7876 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
7877 APR_HDR_LEN(APR_HDR_SIZE),
7878 APR_PKT_VER);
7879
7880 send_dec_buf.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
7881 sizeof(send_dec_buf) - APR_HDR_SIZE);
7882
7883 send_dec_buf.hdr.src_port =
7884 voice_get_idx_for_session(v->session_id);
7885 send_dec_buf.hdr.dest_port = cvs_handle;
7886 send_dec_buf.hdr.token = 0;
7887 send_dec_buf.hdr.opcode =
7888 VSS_ISTREAM_EVT_OOB_NOTIFY_DEC_BUFFER_READY;
7889
7890 cvs_voc_pkt = (uint32_t *)(v->shmem_info.sh_buf.buf[0].data);
7891 if (cvs_voc_pkt != NULL && common.mvs_info.dl_cb != NULL) {
7892 /* Set timestamp to 0 and advance the pointer */
7893 cvs_voc_pkt[0] = 0;
7894 /* Set media_type and advance the pointer */
7895 cvs_voc_pkt[1] = common.mvs_info.media_type;
7896 common.mvs_info.dl_cb(
7897 (uint8_t *)&cvs_voc_pkt[2],
7898 common.mvs_info.private_data);
7899 ret = apr_send_pkt(apr_cvs, (uint32_t *) &send_dec_buf);
7900 if (ret < 0) {
7901 pr_err("%s: Err send DEC_BUF_READY_NOTIFI %d\n",
7902 __func__, ret);
7903 goto fail;
7904 }
7905 } else {
7906 pr_debug("%s: voc_pkt or dl_cb is NULL\n", __func__);
7907 goto fail;
7908 }
7909 } else if (data->opcode == VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER) {
7910 pr_debug("Recd VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER\n");
7911 } else if (data->opcode == VSS_ISTREAM_EVT_SEND_DEC_BUFFER) {
7912 pr_debug("Send dec buf resp\n");
7913 } else if (data->opcode == APR_RSP_ACCEPTED) {
7914 ptr = data->payload;
7915 if (ptr[0])
7916 pr_debug("%s: APR_RSP_ACCEPTED for 0x%x:\n",
7917 __func__, ptr[0]);
7918 } else if (data->opcode == VSS_ISTREAM_EVT_NOT_READY) {
7919 pr_debug("Recd VSS_ISTREAM_EVT_NOT_READY\n");
7920 } else if (data->opcode == VSS_ISTREAM_EVT_READY) {
7921 pr_debug("Recd VSS_ISTREAM_EVT_READY\n");
7922 } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) {
7923 pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__);
7924 ptr = data->payload;
7925 if (ptr[0] != 0) {
7926 pr_err("%s: VSS_ICOMMON_RSP_GET_PARAM returned error = 0x%x\n",
7927 __func__, ptr[0]);
7928 }
7929 rtac_make_voice_callback(RTAC_CVS, data->payload,
7930 data->payload_size);
7931 } else if (data->opcode == VSS_ISTREAM_EVT_RX_DTMF_DETECTED) {
7932 struct vss_istream_evt_rx_dtmf_detected *dtmf_rx_detected;
7933 uint32_t *voc_pkt = data->payload;
7934 uint32_t pkt_len = data->payload_size;
7935
7936 if ((voc_pkt != NULL) &&
7937 (pkt_len ==
7938 sizeof(struct vss_istream_evt_rx_dtmf_detected))) {
7939
7940 dtmf_rx_detected =
7941 (struct vss_istream_evt_rx_dtmf_detected *) voc_pkt;
7942 pr_debug("RX_DTMF_DETECTED low_freq=%d high_freq=%d\n",
7943 dtmf_rx_detected->low_freq,
7944 dtmf_rx_detected->high_freq);
7945 if (c->dtmf_info.dtmf_rx_ul_cb)
7946 c->dtmf_info.dtmf_rx_ul_cb((uint8_t *)voc_pkt,
7947 voc_get_session_name(v->session_id),
7948 c->dtmf_info.private_data);
7949 } else {
7950 pr_err("Invalid packet\n");
7951 }
7952 } else
7953 pr_debug("Unknown opcode 0x%x\n", data->opcode);
7954
7955fail:
7956 return 0;
7957}
7958
7959static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv)
7960{
7961 uint32_t *ptr = NULL;
7962 struct common_data *c = NULL;
7963 struct voice_data *v = NULL;
7964 int i = 0;
7965
7966 if ((data == NULL) || (priv == NULL)) {
7967 pr_err("%s: data or priv is NULL\n", __func__);
7968 return -EINVAL;
7969 }
7970
7971 c = priv;
7972
7973 if (data->opcode == RESET_EVENTS) {
7974 pr_debug("%s: Reset event received in Voice service\n",
7975 __func__);
7976
7977 apr_reset(c->apr_q6_cvp);
7978 c->apr_q6_cvp = NULL;
7979 cal_utils_clear_cal_block_q6maps(MAX_VOICE_CAL_TYPES,
7980 common.cal_data);
7981
7982 /* Sub-system restart is applicable to all sessions. */
7983 for (i = 0; i < MAX_VOC_SESSIONS; i++)
7984 c->voice[i].cvp_handle = 0;
7985
7986 /*
7987 * Free the ION memory and clear handles for
7988 * Source Tracking
7989 */
7990 if (is_source_tracking_shared_memomry_allocated()) {
7991 msm_audio_ion_free(
7992 common.source_tracking_sh_mem.sh_mem_block.client,
7993 common.source_tracking_sh_mem.sh_mem_block.handle);
7994 common.source_tracking_sh_mem.mem_handle = 0;
7995 common.source_tracking_sh_mem.sh_mem_block.client =
7996 NULL;
7997 common.source_tracking_sh_mem.sh_mem_block.handle =
7998 NULL;
7999 }
8000 voc_set_error_state(data->reset_proc);
8001 return 0;
8002 }
8003
8004 v = voice_get_session_by_idx(data->dest_port);
8005 if (v == NULL) {
8006 pr_err("%s: v is NULL\n", __func__);
8007
8008 return -EINVAL;
8009 }
8010
8011 if (data->opcode == APR_BASIC_RSP_RESULT) {
8012 if (data->payload_size) {
8013 ptr = data->payload;
8014
8015 pr_debug("%x %x\n", ptr[0], ptr[1]);
8016 if (ptr[1] != 0) {
8017 pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
8018 __func__, ptr[0], ptr[1]);
8019 }
8020 switch (ptr[0]) {
8021 case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2:
8022 case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V3:
8023 /*response from CVP */
8024 pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
8025 if (!ptr[1]) {
8026 voice_set_cvp_handle(v, data->src_port);
8027 pr_debug("status: %d, cvphdl=%d\n",
8028 ptr[1], data->src_port);
8029 } else
8030 pr_err("got NACK from CVP create session response\n");
8031 v->cvp_state = CMD_STATUS_SUCCESS;
8032 v->async_err = ptr[1];
8033 wake_up(&v->cvp_wait);
8034 break;
8035 case VSS_IVOCPROC_CMD_SET_DEVICE_V2:
8036 case VSS_IVOCPROC_CMD_SET_DEVICE_V3:
8037 case VSS_IVOLUME_CMD_SET_STEP:
8038 case VSS_IVOCPROC_CMD_ENABLE:
8039 case VSS_IVOCPROC_CMD_DISABLE:
8040 case APRV2_IBASIC_CMD_DESTROY_SESSION:
8041 case VSS_IVOCPROC_CMD_REGISTER_VOL_CALIBRATION_DATA:
8042 case VSS_IVOCPROC_CMD_DEREGISTER_VOL_CALIBRATION_DATA:
8043 case VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA_V2:
8044 case VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA:
8045 case VSS_IVOCPROC_CMD_REGISTER_DYNAMIC_CALIBRATION_DATA:
8046 case VSS_IVOCPROC_CMD_DEREGISTER_DYNAMIC_CALIBRATION_DATA:
8047 case VSS_IVOCPROC_CMD_REGISTER_STATIC_CALIBRATION_DATA:
8048 case VSS_IVOCPROC_CMD_DEREGISTER_STATIC_CALIBRATION_DATA:
8049 case VSS_IVOCPROC_CMD_REGISTER_DEVICE_CONFIG:
8050 case VSS_IVOCPROC_CMD_DEREGISTER_DEVICE_CONFIG:
8051 case VSS_ICOMMON_CMD_MAP_MEMORY:
8052 case VSS_ICOMMON_CMD_UNMAP_MEMORY:
8053 case VSS_IVOLUME_CMD_MUTE_V2:
8054 case VSS_IVPCM_CMD_START_V2:
8055 case VSS_IVPCM_CMD_STOP:
8056 case VSS_IVOCPROC_CMD_TOPOLOGY_SET_DEV_CHANNELS:
8057 case VSS_IVOCPROC_CMD_TOPOLOGY_COMMIT:
8058 v->cvp_state = CMD_STATUS_SUCCESS;
8059 v->async_err = ptr[1];
8060 wake_up(&v->cvp_wait);
8061 break;
8062 case VSS_IVPCM_EVT_PUSH_BUFFER_V2:
8063 break;
8064 case VSS_ICOMMON_CMD_SET_PARAM_V2:
8065 switch (data->token) {
8066 case VOC_SET_MEDIA_FORMAT_PARAM_TOKEN:
Laxminath Kasam38070be2017-08-17 18:21:59 +05308067 case VOC_GENERIC_SET_PARAM_TOKEN:
8068 pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called\n",
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308069 __func__);
8070 v->cvp_state = CMD_STATUS_SUCCESS;
8071 v->async_err = ptr[1];
8072 wake_up(&v->cvp_wait);
8073 break;
8074 case VOC_RTAC_SET_PARAM_TOKEN:
8075 pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by rtac\n",
8076 __func__);
8077 rtac_make_voice_callback(
8078 RTAC_CVP, ptr,
8079 data->payload_size);
8080 break;
8081 default:
8082 pr_debug("%s: invalid token for command VSS_ICOMMON_CMD_SET_PARAM_V2: %d\n",
8083 __func__, data->token);
8084 break;
8085 }
8086 break;
8087 case VSS_ICOMMON_CMD_GET_PARAM_V2:
8088 pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n",
8089 __func__);
8090 /* Should only come here if there is an APR */
8091 /* error or malformed APR packet. Otherwise */
8092 /* response will be returned as */
8093 /* VSS_ICOMMON_RSP_GET_PARAM */
8094 if (ptr[1] != 0) {
8095 pr_err("%s: CVP get param error = %d, resuming\n",
8096 __func__, ptr[1]);
8097 rtac_make_voice_callback(RTAC_CVP,
8098 data->payload,
8099 data->payload_size);
8100 }
8101 break;
8102 case VSS_ISOUNDFOCUS_CMD_SET_SECTORS:
8103 if (!ptr[1])
8104 common.is_sound_focus_resp_success =
8105 true;
8106 else
8107 common.is_sound_focus_resp_success =
8108 false;
8109 v->cvp_state = CMD_STATUS_SUCCESS;
8110 v->async_err = ptr[1];
8111 wake_up(&v->cvp_wait);
8112 break;
8113 case VSS_ISOUNDFOCUS_CMD_GET_SECTORS:
8114 /*
8115 * Should only come here if there is an error
8116 * response received from ADSP. Otherwise
8117 * response will be returned as
8118 * VSS_ISOUNDFOCUS_RSP_GET_SECTORS
8119 */
8120 pr_err("%s: VSS_ISOUNDFOCUS_CMD_GET_SECTORS failed\n",
8121 __func__);
8122
8123 common.is_sound_focus_resp_success = false;
8124 v->cvp_state = CMD_STATUS_SUCCESS;
8125 v->async_err = ptr[1];
8126 wake_up(&v->cvp_wait);
8127 break;
8128 case VSS_ISOURCETRACK_CMD_GET_ACTIVITY:
8129 if (!ptr[1]) {
8130 /* Read data from shared memory */
8131 memcpy(&common.sourceTrackingResponse,
8132 common.source_tracking_sh_mem.
8133 sh_mem_block.data,
8134 sizeof(struct
8135 vss_isourcetrack_activity_data_t));
8136 common.is_source_tracking_resp_success =
8137 true;
8138 } else {
8139 common.is_source_tracking_resp_success =
8140 false;
8141 pr_err("%s: Error received for source tracking params\n",
8142 __func__);
8143 }
8144 v->cvp_state = CMD_STATUS_SUCCESS;
8145 v->async_err = ptr[1];
8146 wake_up(&v->cvp_wait);
8147 break;
8148 default:
8149 pr_debug("%s: not match cmd = 0x%x\n",
8150 __func__, ptr[0]);
8151 break;
8152 }
8153 }
8154 } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) {
8155 pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__);
8156 ptr = data->payload;
8157 if (ptr[0] != 0) {
8158 pr_err("%s: VSS_ICOMMON_RSP_GET_PARAM returned error = 0x%x\n",
8159 __func__, ptr[0]);
8160 }
8161 rtac_make_voice_callback(RTAC_CVP, data->payload,
8162 data->payload_size);
8163 } else if (data->opcode == VSS_IVPCM_EVT_NOTIFY_V2) {
8164 if ((data->payload != NULL) && data->payload_size ==
8165 sizeof(struct vss_ivpcm_evt_notify_v2_t) &&
8166 common.hostpcm_info.hostpcm_evt_cb != NULL) {
8167 common.hostpcm_info.hostpcm_evt_cb(data->payload,
8168 voc_get_session_name(v->session_id),
8169 common.hostpcm_info.private_data);
8170 }
8171 } else if (data->opcode == VSS_ISOUNDFOCUS_RSP_GET_SECTORS) {
8172 if (data->payload && (data->payload_size ==
8173 sizeof(struct vss_isoundfocus_rsp_get_sectors_t))) {
8174 common.is_sound_focus_resp_success = true;
8175 memcpy(&common.soundFocusResponse,
8176 (struct vss_isoundfocus_rsp_get_sectors_t *)
8177 data->payload,
8178 sizeof(struct
8179 vss_isoundfocus_rsp_get_sectors_t));
8180 } else {
8181 common.is_sound_focus_resp_success = false;
8182 pr_debug("%s: Invalid payload received from CVD\n",
8183 __func__);
8184 }
8185 v->cvp_state = CMD_STATUS_SUCCESS;
8186 wake_up(&v->cvp_wait);
8187 }
8188 return 0;
8189}
8190
8191static int voice_free_oob_shared_mem(void)
8192{
8193 int rc = 0;
8194 int cnt = 0;
8195 int bufcnt = NUM_OF_BUFFERS;
8196 struct voice_data *v = voice_get_session(
8197 common.voice[VOC_PATH_FULL].session_id);
8198
8199 mutex_lock(&common.common_lock);
8200 if (v == NULL) {
8201 pr_err("%s: v is NULL\n", __func__);
8202
8203 rc = -EINVAL;
8204 goto done;
8205 }
8206
8207 rc = msm_audio_ion_free(v->shmem_info.sh_buf.client,
8208 v->shmem_info.sh_buf.handle);
8209 v->shmem_info.sh_buf.client = NULL;
8210 v->shmem_info.sh_buf.handle = NULL;
8211 if (rc < 0) {
8212 pr_err("%s: Error:%d freeing memory\n", __func__, rc);
8213
8214 goto done;
8215 }
8216
8217
8218 while (cnt < bufcnt) {
8219 v->shmem_info.sh_buf.buf[cnt].data = NULL;
8220 v->shmem_info.sh_buf.buf[cnt].phys = 0;
8221 cnt++;
8222 }
8223
8224 v->shmem_info.sh_buf.client = NULL;
8225 v->shmem_info.sh_buf.handle = NULL;
8226
8227done:
8228 mutex_unlock(&common.common_lock);
8229 return rc;
8230}
8231
8232static int voice_alloc_oob_shared_mem(void)
8233{
8234 int cnt = 0;
8235 int rc = 0;
8236 size_t len;
8237 void *mem_addr;
8238 dma_addr_t phys;
8239 int bufsz = BUFFER_BLOCK_SIZE;
8240 int bufcnt = NUM_OF_BUFFERS;
8241 struct voice_data *v = voice_get_session(
8242 common.voice[VOC_PATH_FULL].session_id);
8243
8244 mutex_lock(&common.common_lock);
8245 if (v == NULL) {
8246 pr_err("%s: v is NULL\n", __func__);
8247
8248 rc = -EINVAL;
8249 goto done;
8250 }
8251
8252 rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
8253 &(v->shmem_info.sh_buf.handle),
8254 bufsz*bufcnt,
8255 &phys, &len,
8256 &mem_addr);
8257 if (rc < 0) {
8258 pr_err("%s: audio ION alloc failed, rc = %d\n",
8259 __func__, rc);
8260
8261 goto done;
8262 }
8263
8264 while (cnt < bufcnt) {
8265 v->shmem_info.sh_buf.buf[cnt].data = mem_addr + (cnt * bufsz);
8266 v->shmem_info.sh_buf.buf[cnt].phys = phys + (cnt * bufsz);
8267 v->shmem_info.sh_buf.buf[cnt].size = bufsz;
8268 cnt++;
8269 }
8270
8271 pr_debug("%s buf[0].data:[%pK], buf[0].phys:[%pK], &buf[0].phys:[%pK],\n",
8272 __func__,
8273 (void *)v->shmem_info.sh_buf.buf[0].data,
8274 &v->shmem_info.sh_buf.buf[0].phys,
8275 (void *)&v->shmem_info.sh_buf.buf[0].phys);
8276 pr_debug("%s: buf[1].data:[%pK], buf[1].phys[%pK], &buf[1].phys[%pK]\n",
8277 __func__,
8278 (void *)v->shmem_info.sh_buf.buf[1].data,
8279 &v->shmem_info.sh_buf.buf[1].phys,
8280 (void *)&v->shmem_info.sh_buf.buf[1].phys);
8281
8282 memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
8283
8284done:
8285 mutex_unlock(&common.common_lock);
8286 return rc;
8287}
8288
8289static int voice_alloc_oob_mem_table(void)
8290{
8291 int rc = 0;
8292 size_t len;
8293 struct voice_data *v = voice_get_session(
8294 common.voice[VOC_PATH_FULL].session_id);
8295
8296 mutex_lock(&common.common_lock);
8297 if (v == NULL) {
8298 pr_err("%s: v is NULL\n", __func__);
8299
8300 rc = -EINVAL;
8301 goto done;
8302 }
8303
8304 rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
8305 &(v->shmem_info.memtbl.handle),
8306 sizeof(struct vss_imemory_table_t),
8307 &v->shmem_info.memtbl.phys,
8308 &len,
8309 &(v->shmem_info.memtbl.data));
8310 if (rc < 0) {
8311 pr_err("%s: audio ION alloc failed, rc = %d\n",
8312 __func__, rc);
8313
8314 goto done;
8315 }
8316
8317 v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
8318 pr_debug("%s data[%pK]phys[%pK][%pK]\n", __func__,
8319 (void *)v->shmem_info.memtbl.data,
8320 &v->shmem_info.memtbl.phys,
8321 (void *)&v->shmem_info.memtbl.phys);
8322
8323done:
8324 mutex_unlock(&common.common_lock);
8325 return rc;
8326}
8327
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308328/**
8329 * voc_send_cvp_start_vocpcm -
8330 * command to start voice hpcm
8331 *
8332 * @session_id: voice session ID to send this command
8333 *
8334 * Returns 0 on success or error on failure
8335 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308336int voc_send_cvp_start_vocpcm(uint32_t session_id,
8337 struct vss_ivpcm_tap_point *vpcm_tp,
8338 uint32_t no_of_tp)
8339{
8340 struct cvp_start_cmd cvp_start_cmd;
8341 int ret = 0;
8342 void *apr_cvp;
8343 u16 cvp_handle;
8344 struct voice_data *v = voice_get_session(session_id);
8345 int i = 0;
8346
8347 if (v == NULL) {
8348 pr_err("%s: v is NULL\n", __func__);
8349 ret = -EINVAL;
8350 goto done;
8351 }
8352 apr_cvp = common.apr_q6_cvp;
8353
8354 if (!apr_cvp) {
8355 pr_err("%s: apr_cvp is NULL.\n", __func__);
8356 ret = -EINVAL;
8357 goto done;
8358 }
8359
8360 cvp_handle = voice_get_cvp_handle(v);
8361
8362 /* Fill the header */
8363 cvp_start_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8364 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
8365 cvp_start_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8366 sizeof(struct vss_ivpcm_tap_point) * no_of_tp) +
8367 sizeof(cvp_start_cmd.vpcm_start_cmd.num_tap_points) +
8368 sizeof(cvp_start_cmd.vpcm_start_cmd.mem_handle);
8369 cvp_start_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
8370 cvp_start_cmd.hdr.dest_port = cvp_handle;
8371 cvp_start_cmd.hdr.token = 0;
8372 cvp_start_cmd.hdr.opcode = VSS_IVPCM_CMD_START_V2;
8373
8374 for (i = 0; i < no_of_tp; i++) {
8375 cvp_start_cmd.vpcm_start_cmd.tap_points[i].tap_point =
8376 vpcm_tp[i].tap_point;
8377 cvp_start_cmd.vpcm_start_cmd.tap_points[i].direction =
8378 vpcm_tp[i].direction;
8379 cvp_start_cmd.vpcm_start_cmd.tap_points[i].sampling_rate =
8380 vpcm_tp[i].sampling_rate;
8381 cvp_start_cmd.vpcm_start_cmd.tap_points[i].duration = 0;
8382 }
8383
8384 cvp_start_cmd.vpcm_start_cmd.mem_handle =
8385 common.voice_host_pcm_mem_handle;
8386 cvp_start_cmd.vpcm_start_cmd.num_tap_points = no_of_tp;
8387
8388 v->cvp_state = CMD_STATUS_FAIL;
8389 v->async_err = 0;
8390 ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_start_cmd);
8391 if (ret < 0) {
8392 pr_err("%s: Fail: sending vocpcm map memory,\n", __func__);
8393 goto done;
8394 }
8395 ret = wait_event_timeout(v->cvp_wait,
8396 (v->cvp_state == CMD_STATUS_SUCCESS),
8397 msecs_to_jiffies(TIMEOUT_MS));
8398 if (!ret) {
8399 pr_err("%s: wait_event timeout\n", __func__);
8400 goto done;
8401 }
8402 if (v->async_err > 0) {
8403 pr_err("%s: DSP returned error[%s]\n",
8404 __func__, adsp_err_get_err_str(
8405 v->async_err));
8406 ret = adsp_err_get_lnx_err_code(
8407 v->async_err);
8408 goto done;
8409 }
8410
8411done:
8412 return ret;
8413}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308414EXPORT_SYMBOL(voc_send_cvp_start_vocpcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308415
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308416/**
8417 * voc_send_cvp_stop_vocpcm -
8418 * command to stop voice hpcm
8419 *
8420 * @session_id: voice session ID to send this command
8421 *
8422 * Returns 0 on success or error on failure
8423 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308424int voc_send_cvp_stop_vocpcm(uint32_t session_id)
8425{
8426 struct cvp_command vpcm_stop_cmd;
8427 int ret = 0;
8428 void *apr_cvp;
8429 u16 cvp_handle;
8430 struct voice_data *v = voice_get_session(session_id);
8431
8432 if (v == NULL) {
8433 pr_err("%s: v is NULL\n", __func__);
8434 ret = -EINVAL;
8435 goto done;
8436 }
8437 apr_cvp = common.apr_q6_cvp;
8438
8439 if (!apr_cvp) {
8440 pr_err("%s: apr_cvp is NULL.\n", __func__);
8441 ret = -EINVAL;
8442 goto done;
8443 }
8444
8445 cvp_handle = voice_get_cvp_handle(v);
8446
8447 /* fill in the header */
8448 vpcm_stop_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8449 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
8450 vpcm_stop_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8451 sizeof(vpcm_stop_cmd) - APR_HDR_SIZE);
8452 vpcm_stop_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
8453 vpcm_stop_cmd.hdr.dest_port = cvp_handle;
8454 vpcm_stop_cmd.hdr.token = 0;
8455 vpcm_stop_cmd.hdr.opcode = VSS_IVPCM_CMD_STOP;
8456
8457 v->cvp_state = CMD_STATUS_FAIL;
8458 v->async_err = 0;
8459 ret = apr_send_pkt(apr_cvp, (uint32_t *) &vpcm_stop_cmd);
8460 if (ret < 0) {
8461 pr_err("Fail: sending vocpcm stop,\n");
8462 goto done;
8463 }
8464 ret = wait_event_timeout(v->cvp_wait,
8465 (v->cvp_state == CMD_STATUS_SUCCESS),
8466 msecs_to_jiffies(TIMEOUT_MS));
8467 if (!ret) {
8468 pr_err("%s: wait_event timeout\n", __func__);
8469 goto done;
8470 }
8471
8472 if (v->async_err > 0) {
8473 pr_err("%s: DSP returned error[%s]\n",
8474 __func__, adsp_err_get_err_str(
8475 v->async_err));
8476 ret = adsp_err_get_lnx_err_code(
8477 v->async_err);
8478 goto done;
8479 }
8480
8481done:
8482 return ret;
8483}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308484EXPORT_SYMBOL(voc_send_cvp_stop_vocpcm);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308485
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308486/**
8487 * voc_send_cvp_map_vocpcm_memory -
8488 * command to map memory for voice hpcm
8489 *
8490 * @session_id: voice session ID to send this command
8491 * @tp_mem_table: tap point memory table of hpcm
8492 * paddr: Physical address of hpcm memory mapped area.
8493 * bufsize: Buffer size of memory mapped area
8494 *
8495 * Returns 0 on success or error on failure
8496 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308497int voc_send_cvp_map_vocpcm_memory(uint32_t session_id,
8498 struct mem_map_table *tp_mem_table,
8499 phys_addr_t paddr, uint32_t bufsize)
8500{
8501 return voice_map_memory_physical_cmd(voice_get_session(session_id),
8502 tp_mem_table,
8503 (dma_addr_t) paddr, bufsize,
8504 VOC_VOICE_HOST_PCM_MAP_TOKEN);
8505}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308506EXPORT_SYMBOL(voc_send_cvp_map_vocpcm_memory);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308507
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308508/**
8509 * voc_send_cvp_unmap_vocpcm_memory -
8510 * command to unmap memory for voice hpcm
8511 *
8512 * @session_id: voice session ID to send this command
8513 *
8514 * Returns 0 on success or error on failure
8515 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308516int voc_send_cvp_unmap_vocpcm_memory(uint32_t session_id)
8517{
8518 int ret = 0;
8519
8520 ret = voice_send_mvm_unmap_memory_physical_cmd(
8521 voice_get_session(session_id),
8522 common.voice_host_pcm_mem_handle);
8523
8524 if (ret == 0)
8525 common.voice_host_pcm_mem_handle = 0;
8526
8527 return ret;
8528}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308529EXPORT_SYMBOL(voc_send_cvp_unmap_vocpcm_memory);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308530
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308531/**
8532 * voc_send_cvp_vocpcm_push_buf_evt - Send buf event command
8533 *
8534 * @session_id: voice session ID to send this command
8535 * @push_buff_evt: pointer with buffer event details
8536 *
8537 * Returns 0 on success or error on failure
8538 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308539int voc_send_cvp_vocpcm_push_buf_evt(uint32_t session_id,
8540 struct vss_ivpcm_evt_push_buffer_v2_t *push_buff_evt)
8541{
8542 struct cvp_push_buf_cmd vpcm_push_buf_cmd;
8543 int ret = 0;
8544 void *apr_cvp;
8545 u16 cvp_handle;
8546 struct voice_data *v = voice_get_session(session_id);
8547
8548 if (v == NULL) {
8549 pr_err("%s: v is NULL\n", __func__);
8550 ret = -EINVAL;
8551 goto done;
8552 }
8553 apr_cvp = common.apr_q6_cvp;
8554
8555 if (!apr_cvp) {
8556 pr_err("%s: apr_cvp is NULL.\n", __func__);
8557 ret = -EINVAL;
8558 goto done;
8559 }
8560
8561 memset(&vpcm_push_buf_cmd, 0, sizeof(vpcm_push_buf_cmd));
8562 cvp_handle = voice_get_cvp_handle(v);
8563
8564 /* fill in the header */
8565 vpcm_push_buf_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
8566 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
8567 vpcm_push_buf_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
8568 sizeof(vpcm_push_buf_cmd) - APR_HDR_SIZE);
8569 vpcm_push_buf_cmd.hdr.src_port =
8570 voice_get_idx_for_session(v->session_id);
8571 vpcm_push_buf_cmd.hdr.dest_port = cvp_handle;
8572 vpcm_push_buf_cmd.hdr.token = 0;
8573 vpcm_push_buf_cmd.hdr.opcode = VSS_IVPCM_EVT_PUSH_BUFFER_V2;
8574
8575 vpcm_push_buf_cmd.vpcm_evt_push_buffer.tap_point =
8576 push_buff_evt->tap_point;
8577 vpcm_push_buf_cmd.vpcm_evt_push_buffer.push_buf_mask =
8578 push_buff_evt->push_buf_mask;
8579 vpcm_push_buf_cmd.vpcm_evt_push_buffer.out_buf_mem_address =
8580 push_buff_evt->out_buf_mem_address;
8581 vpcm_push_buf_cmd.vpcm_evt_push_buffer.in_buf_mem_address =
8582 push_buff_evt->in_buf_mem_address;
8583 vpcm_push_buf_cmd.vpcm_evt_push_buffer.out_buf_mem_size =
8584 push_buff_evt->out_buf_mem_size;
8585 vpcm_push_buf_cmd.vpcm_evt_push_buffer.in_buf_mem_size =
8586 push_buff_evt->in_buf_mem_size;
8587 vpcm_push_buf_cmd.vpcm_evt_push_buffer.sampling_rate =
8588 push_buff_evt->sampling_rate;
8589 vpcm_push_buf_cmd.vpcm_evt_push_buffer.num_in_channels =
8590 push_buff_evt->num_in_channels;
8591
8592 ret = apr_send_pkt(apr_cvp, (uint32_t *) &vpcm_push_buf_cmd);
8593 if (ret < 0) {
8594 pr_err("Fail: sending vocpcm map memory,\n");
8595 goto done;
8596 }
8597
8598done:
8599 return ret;
8600}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308601EXPORT_SYMBOL(voc_send_cvp_vocpcm_push_buf_evt);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308602
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308603/**
8604 * voc_register_hpcm_evt_cb - Updates hostpcm info.
8605 *
8606 * @hostpcm_cb: callback function for hostpcm event
8607 * @private_data: private data for hostpcm
8608 *
8609 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308610void voc_register_hpcm_evt_cb(hostpcm_cb_fn hostpcm_cb,
8611 void *private_data)
8612{
8613 common.hostpcm_info.hostpcm_evt_cb = hostpcm_cb;
8614 common.hostpcm_info.private_data = private_data;
8615}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308616EXPORT_SYMBOL(voc_register_hpcm_evt_cb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308617
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308618/**
8619 * voc_deregister_hpcm_evt_cb - resets hostpcm info.
8620 *
8621 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308622void voc_deregister_hpcm_evt_cb(void)
8623{
8624 common.hostpcm_info.hostpcm_evt_cb = NULL;
8625 common.hostpcm_info.private_data = NULL;
8626}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308627EXPORT_SYMBOL(voc_deregister_hpcm_evt_cb);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308628
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308629/**
8630 * voc_get_cvd_version - retrieve CVD version.
8631 *
8632 * @cvd_version: pointer to be updated with CVD version info.
8633 *
8634 * Returns 0 on success or error on failure
8635 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308636int voc_get_cvd_version(char *cvd_version)
8637{
8638 int ret = 0;
8639 struct voice_data *v = voice_get_session(VOICE_SESSION_VSID);
8640
8641
8642 if (v == NULL) {
8643 pr_err("%s: invalid session_id 0x%x\n",
8644 __func__, VOICE_SESSION_VSID);
8645
8646 ret = -EINVAL;
8647 goto done;
8648 }
8649
8650 if (is_cvd_version_queried()) {
8651 pr_debug("%s: Returning the cached value %s\n",
8652 __func__, common.cvd_version);
8653
8654 goto done;
8655 }
8656
8657 /* Register callback to APR */
8658 ret = voice_apr_register(VOICE_SESSION_VSID);
8659 if (ret < 0) {
8660 pr_err("%s: apr register failed\n", __func__);
8661 goto done;
8662 }
8663
8664 mutex_lock(&common.common_lock);
8665 mutex_lock(&v->lock);
8666 ret = voice_send_mvm_cvd_version_cmd(v);
8667 if (ret < 0) {
8668 pr_err("%s: voice_send_mvm_cvd_version_cmd failed\n", __func__);
8669 goto unlock;
8670 }
8671 ret = 0;
8672
8673unlock:
8674 mutex_unlock(&v->lock);
8675 mutex_unlock(&common.common_lock);
8676
8677done:
8678 if (cvd_version)
8679 memcpy(cvd_version, common.cvd_version,
8680 CVD_VERSION_STRING_MAX_SIZE);
8681
8682 return ret;
8683}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05308684EXPORT_SYMBOL(voc_get_cvd_version);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308685
8686static int voice_alloc_cal_mem_map_table(void)
8687{
8688 int ret = 0;
8689 size_t len;
8690
8691 ret = msm_audio_ion_alloc("voc_cal",
8692 &(common.cal_mem_map_table.client),
8693 &(common.cal_mem_map_table.handle),
8694 sizeof(struct vss_imemory_table_t),
8695 &common.cal_mem_map_table.phys,
8696 &len,
8697 &(common.cal_mem_map_table.data));
8698 if ((ret < 0) && (ret != -EPROBE_DEFER)) {
8699 pr_err("%s: audio ION alloc failed, rc = %d\n",
8700 __func__, ret);
8701 goto done;
8702 }
8703
8704 common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
8705 pr_debug("%s: data %pK phys %pK\n", __func__,
8706 common.cal_mem_map_table.data,
8707 &common.cal_mem_map_table.phys);
8708
8709done:
8710 return ret;
8711}
8712
8713static int voice_alloc_rtac_mem_map_table(void)
8714{
8715 int ret = 0;
8716 size_t len;
8717
8718 ret = msm_audio_ion_alloc("voc_rtac_cal",
8719 &(common.rtac_mem_map_table.client),
8720 &(common.rtac_mem_map_table.handle),
8721 sizeof(struct vss_imemory_table_t),
8722 &common.rtac_mem_map_table.phys,
8723 &len,
8724 &(common.rtac_mem_map_table.data));
8725 if (ret < 0) {
8726 pr_err("%s: audio ION alloc failed, rc = %d\n",
8727 __func__, ret);
8728 goto done;
8729 }
8730
8731 common.rtac_mem_map_table.size = sizeof(struct vss_imemory_table_t);
8732 pr_debug("%s: data %pK phys %pK\n", __func__,
8733 common.rtac_mem_map_table.data,
8734 &common.rtac_mem_map_table.phys);
8735
8736done:
8737 return ret;
8738}
8739
8740static int voice_alloc_and_map_oob_mem(struct voice_data *v)
8741{
8742 int ret = 0;
8743
8744 if (v == NULL) {
8745 pr_err("%s: v is NULL\n", __func__);
8746
8747 return -EINVAL;
8748 }
8749
8750 if (!is_voip_memory_allocated()) {
8751 ret = voc_alloc_voip_shared_memory();
8752 if (ret < 0) {
8753 pr_err("%s: Failed to create voip oob memory %d\n",
8754 __func__, ret);
8755
8756 goto done;
8757 }
8758 }
8759
8760 ret = voice_map_memory_physical_cmd(v,
8761 &v->shmem_info.memtbl,
8762 v->shmem_info.sh_buf.buf[0].phys,
8763 v->shmem_info.sh_buf.buf[0].size * NUM_OF_BUFFERS,
8764 VOIP_MEM_MAP_TOKEN);
8765 if (ret) {
8766 pr_err("%s: mvm_map_memory_phy failed %d\n",
8767 __func__, ret);
8768
8769 goto done;
8770 }
8771
8772done:
8773 return ret;
8774}
8775
8776uint32_t voice_get_topology(uint32_t topology_idx)
8777{
8778 uint32_t topology = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
8779 struct cal_block_data *cal_block = NULL;
8780
8781 /* initialize as default topology */
8782 if (topology_idx == CVP_VOC_RX_TOPOLOGY_CAL) {
8783 topology = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT;
8784 } else if (topology_idx == CVP_VOC_TX_TOPOLOGY_CAL) {
Laxminath Kasam8f7ccc22017-08-28 17:35:04 +05308785 topology = VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS_V2;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308786 } else {
8787 pr_err("%s: cal index %x is invalid!\n",
8788 __func__, topology_idx);
8789
8790 goto done;
8791 }
8792
8793 if (common.cal_data[topology_idx] == NULL) {
8794 pr_err("%s: cal type is NULL for cal index %x\n",
8795 __func__, topology_idx);
8796
8797 goto done;
8798 }
8799
8800 mutex_lock(&common.cal_data[topology_idx]->lock);
8801 cal_block = cal_utils_get_only_cal_block(
8802 common.cal_data[topology_idx]);
8803 if (cal_block == NULL) {
8804 pr_debug("%s: cal_block not found for cal index %x\n",
8805 __func__, topology_idx);
8806
8807 goto unlock;
8808 }
8809
8810 topology = ((struct audio_cal_info_voc_top *)
8811 cal_block->cal_info)->topology;
8812unlock:
8813 mutex_unlock(&common.cal_data[topology_idx]->lock);
8814done:
8815 pr_debug("%s: Using topology %d\n", __func__, topology);
8816
8817 return topology;
8818}
8819
Aditya Bavanari88513a32017-10-12 12:29:25 +05308820int voice_set_topology_specific_info(struct voice_data *v,
8821 uint32_t topology_idx)
8822{
8823 struct cal_block_data *cal_block = NULL;
8824 int ret = 0;
8825 uint32_t topo_channels;
8826
8827 if (common.cal_data[topology_idx] == NULL) {
8828 pr_err("%s: cal type is NULL for cal index %x\n",
8829 __func__, topology_idx);
8830 ret = -EINVAL;
8831 goto done;
8832 }
8833
8834 mutex_lock(&common.cal_data[topology_idx]->lock);
8835 cal_block = cal_utils_get_only_cal_block(
8836 common.cal_data[topology_idx]);
8837 if (cal_block == NULL) {
8838 pr_debug("%s: cal_block not found for cal index %x\n",
8839 __func__, topology_idx);
8840 ret = -EINVAL;
8841 goto unlock;
8842 }
8843
8844 if (topology_idx == CVP_VOC_RX_TOPOLOGY_CAL) {
8845 topo_channels = ((struct audio_cal_info_voc_top *)
8846 cal_block->cal_info)->num_channels;
8847 if (topo_channels > 0) {
8848 v->dev_rx.no_of_channels = topo_channels;
8849 pr_debug("%s: Topology Rx no of channels: %d",
8850 __func__, v->dev_rx.no_of_channels);
8851 memcpy(&v->dev_rx.channel_mapping,
8852 &((struct audio_cal_info_voc_top *)
8853 cal_block->cal_info)->channel_mapping,
8854 VSS_CHANNEL_MAPPING_SIZE);
8855 } else {
8856 pr_debug("%s: cal data is zero, default to Rx backend config\n",
8857 __func__);
8858 if (v->dev_rx.no_of_channels == NUM_CHANNELS_MONO) {
8859 v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FC;
8860 } else if (v->dev_rx.no_of_channels ==
8861 NUM_CHANNELS_STEREO) {
8862 v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FL;
8863 v->dev_rx.channel_mapping[1] = PCM_CHANNEL_FR;
8864 } else {
8865 pr_warn("%s: Unsupported Rx num channels: %d\n",
8866 __func__, v->dev_rx.no_of_channels);
8867 }
8868 }
8869 } else if (topology_idx == CVP_VOC_TX_TOPOLOGY_CAL) {
8870 topo_channels = ((struct audio_cal_info_voc_top *)
8871 cal_block->cal_info)->num_channels;
8872 if (topo_channels > 0) {
8873 v->dev_tx.no_of_channels = topo_channels;
8874 pr_debug("%s: Topology Tx no of channels: %d",
8875 __func__, v->dev_tx.no_of_channels);
8876 memcpy(&v->dev_tx.channel_mapping,
8877 &((struct audio_cal_info_voc_top *)
8878 cal_block->cal_info)->channel_mapping,
8879 VSS_CHANNEL_MAPPING_SIZE);
8880 } else {
8881 pr_debug("%s: cal data is zero, default to Tx backend config\n",
8882 __func__);
8883 if (v->dev_tx.no_of_channels == NUM_CHANNELS_MONO) {
8884 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FC;
8885 } else if (v->dev_tx.no_of_channels ==
8886 NUM_CHANNELS_STEREO) {
8887 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
8888 v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
8889 } else if (v->dev_tx.no_of_channels ==
Aditya Bavanaria8349a42017-12-13 09:30:15 +05308890 NUM_CHANNELS_THREE) {
8891 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
8892 v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
8893 v->dev_tx.channel_mapping[2] = PCM_CHANNEL_FC;
8894 } else if (v->dev_tx.no_of_channels ==
Aditya Bavanari88513a32017-10-12 12:29:25 +05308895 NUM_CHANNELS_QUAD) {
8896 v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
8897 v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
8898 v->dev_tx.channel_mapping[2] = PCM_CHANNEL_LS;
8899 v->dev_tx.channel_mapping[3] = PCM_CHANNEL_RS;
8900 } else {
8901 pr_warn("%s: Unsupported Tx num channels: %d\n",
8902 __func__, v->dev_tx.no_of_channels);
8903 }
8904 }
8905 } else {
8906 pr_err("%s: topology index %x is invalid\n",
8907 __func__, topology_idx);
8908 }
8909unlock:
8910 mutex_unlock(&common.cal_data[topology_idx]->lock);
8911done:
8912 return ret;
8913}
8914
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05308915static int get_cal_type_index(int32_t cal_type)
8916{
8917 int ret = -EINVAL;
8918
8919 switch (cal_type) {
8920 case CVP_VOC_RX_TOPOLOGY_CAL_TYPE:
8921 ret = CVP_VOC_RX_TOPOLOGY_CAL;
8922 break;
8923 case CVP_VOC_TX_TOPOLOGY_CAL_TYPE:
8924 ret = CVP_VOC_TX_TOPOLOGY_CAL;
8925 break;
8926 case CVP_VOCPROC_STATIC_CAL_TYPE:
8927 ret = CVP_VOCPROC_CAL;
8928 break;
8929 case CVP_VOCPROC_DYNAMIC_CAL_TYPE:
8930 ret = CVP_VOCVOL_CAL;
8931 break;
8932 case CVS_VOCSTRM_STATIC_CAL_TYPE:
8933 ret = CVS_VOCSTRM_CAL;
8934 break;
8935 case CVP_VOCDEV_CFG_CAL_TYPE:
8936 ret = CVP_VOCDEV_CFG_CAL;
8937 break;
8938 case CVP_VOCPROC_STATIC_COL_CAL_TYPE:
8939 ret = CVP_VOCPROC_COL_CAL;
8940 break;
8941 case CVP_VOCPROC_DYNAMIC_COL_CAL_TYPE:
8942 ret = CVP_VOCVOL_COL_CAL;
8943 break;
8944 case CVS_VOCSTRM_STATIC_COL_CAL_TYPE:
8945 ret = CVS_VOCSTRM_COL_CAL;
8946 break;
8947 case VOICE_RTAC_INFO_CAL_TYPE:
8948 ret = VOICE_RTAC_INFO_CAL;
8949 break;
8950 case VOICE_RTAC_APR_CAL_TYPE:
8951 ret = VOICE_RTAC_APR_CAL;
8952 break;
8953 default:
8954 pr_err("%s: Invalid cal type %d!\n", __func__, cal_type);
8955 }
8956 return ret;
8957}
8958
8959static int voice_prepare_volume_boost(int32_t cal_type,
8960 size_t data_size, void *data)
8961{
8962 return voc_deregister_vocproc_vol_table();
8963}
8964
8965static int voice_enable_volume_boost(int32_t cal_type,
8966 size_t data_size, void *data)
8967{
8968 return voc_register_vocproc_vol_table();
8969}
8970
8971static int voice_alloc_cal(int32_t cal_type,
8972 size_t data_size, void *data)
8973{
8974 int ret = 0;
8975 int cal_index;
8976 int cal_version;
8977
8978 pr_debug("%s\n", __func__);
8979
8980 cal_version = cal_utils_get_cal_type_version(data);
8981 common.is_per_vocoder_cal_enabled =
8982 !!(cal_version & PER_VOCODER_CAL_BIT_MASK);
8983
8984 cal_index = get_cal_type_index(cal_type);
8985 if (cal_index < 0) {
8986 pr_err("%s: Could not get cal index %d!\n",
8987 __func__, cal_index);
8988 ret = -EINVAL;
8989 goto done;
8990 }
8991
8992 ret = cal_utils_alloc_cal(data_size, data,
8993 common.cal_data[cal_index], 0, NULL);
8994 if (ret < 0) {
8995 pr_err("%s: Cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
8996 __func__, ret, cal_type);
8997 ret = -EINVAL;
8998 goto done;
8999 }
9000done:
9001 return ret;
9002}
9003
9004static int voice_dealloc_cal(int32_t cal_type,
9005 size_t data_size, void *data)
9006{
9007 int ret = 0;
9008 int cal_index;
9009
9010 pr_debug("%s\n", __func__);
9011
9012 cal_index = get_cal_type_index(cal_type);
9013 if (cal_index < 0) {
9014 pr_err("%s: Could not get cal index %d!\n",
9015 __func__, cal_index);
9016
9017 ret = -EINVAL;
9018 goto done;
9019 }
9020
9021 ret = cal_utils_dealloc_cal(data_size, data,
9022 common.cal_data[cal_index]);
9023 if (ret < 0) {
9024 pr_err("%s: Cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
9025 __func__, ret, cal_type);
9026
9027 ret = -EINVAL;
9028 goto done;
9029 }
9030done:
9031 return ret;
9032}
9033
9034static int voice_set_cal(int32_t cal_type,
9035 size_t data_size, void *data)
9036{
9037 int ret = 0;
9038 int cal_index;
9039
9040 pr_debug("%s\n", __func__);
9041
9042 cal_index = get_cal_type_index(cal_type);
9043 if (cal_index < 0) {
9044 pr_err("%s: Could not get cal index %d!\n",
9045 __func__, cal_index);
9046
9047 ret = -EINVAL;
9048 goto done;
9049 }
9050
9051 ret = cal_utils_set_cal(data_size, data,
9052 common.cal_data[cal_index], 0, NULL);
9053 if (ret < 0) {
9054 pr_err("%s: Cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
9055 __func__, ret, cal_type);
9056
9057 ret = -EINVAL;
9058 goto done;
9059 }
9060done:
9061 return ret;
9062}
9063
9064static void voice_delete_cal_data(void)
9065{
9066 pr_debug("%s\n", __func__);
9067
9068 cal_utils_destroy_cal_types(MAX_VOICE_CAL_TYPES, common.cal_data);
9069}
9070
9071static int voice_init_cal_data(void)
9072{
9073 int ret = 0;
9074 struct cal_type_info cal_type_info[] = {
9075 {{CVP_VOC_RX_TOPOLOGY_CAL_TYPE,
9076 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
9077 {NULL, NULL, cal_utils_match_buf_num} },
9078
9079 {{CVP_VOC_TX_TOPOLOGY_CAL_TYPE,
9080 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
9081 {NULL, NULL, cal_utils_match_buf_num} },
9082
9083 {{CVP_VOCPROC_STATIC_CAL_TYPE,
9084 {voice_alloc_cal, voice_dealloc_cal, NULL,
9085 voice_set_cal, NULL, NULL} },
9086 {NULL, voice_unmap_cal_memory,
9087 cal_utils_match_buf_num} },
9088
9089 {{CVP_VOCPROC_DYNAMIC_CAL_TYPE,
9090 {voice_alloc_cal, voice_dealloc_cal,
9091 voice_prepare_volume_boost,
9092 voice_set_cal, NULL,
9093 voice_enable_volume_boost} },
9094 {NULL, voice_unmap_cal_memory,
9095 cal_utils_match_buf_num} },
9096
9097 {{CVP_VOCDEV_CFG_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_STATIC_COL_CAL_TYPE,
9104 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
9105 {NULL, NULL, cal_utils_match_buf_num} },
9106
9107 {{CVP_VOCPROC_DYNAMIC_COL_CAL_TYPE,
9108 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
9109 {NULL, NULL, cal_utils_match_buf_num} },
9110
9111 {{CVS_VOCSTRM_STATIC_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 {{CVS_VOCSTRM_STATIC_COL_CAL_TYPE,
9118 {NULL, NULL, NULL, voice_set_cal, NULL, NULL} },
9119 {NULL, NULL, cal_utils_match_buf_num} },
9120
9121 {{VOICE_RTAC_INFO_CAL_TYPE,
9122 {NULL, NULL, NULL, NULL, NULL, NULL} },
9123 {NULL, NULL, cal_utils_match_buf_num} },
9124
9125 {{VOICE_RTAC_APR_CAL_TYPE,
9126 {NULL, NULL, NULL, NULL, NULL, NULL} },
9127 {NULL, NULL, cal_utils_match_buf_num} },
9128 };
9129
9130 ret = cal_utils_create_cal_types(MAX_VOICE_CAL_TYPES, common.cal_data,
9131 cal_type_info);
9132 if (ret < 0) {
9133 pr_err("%s: Could not create cal type!\n",
9134 __func__);
9135
9136 ret = -EINVAL;
9137 goto err;
9138 }
9139
9140 return ret;
9141err:
9142 voice_delete_cal_data();
9143 memset(&common, 0, sizeof(struct common_data));
9144 return ret;
9145}
9146
9147static int voice_send_set_sound_focus_cmd(struct voice_data *v,
9148 struct sound_focus_param soundFocusData)
9149{
9150 struct cvp_set_sound_focus_param_cmd_t cvp_set_sound_focus_param_cmd;
9151 int ret = 0;
9152 void *apr_cvp;
9153 u16 cvp_handle;
9154 int i;
9155
9156 pr_debug("%s: Enter\n", __func__);
9157
9158 if (v == NULL) {
9159 pr_err("%s: v is NULL\n", __func__);
9160
9161 ret = -EINVAL;
9162 goto done;
9163 }
9164 apr_cvp = common.apr_q6_cvp;
9165
9166 if (!apr_cvp) {
9167 pr_err("%s: apr_cvp is NULL.\n", __func__);
9168
9169 ret = -EINVAL;
9170 goto done;
9171 }
9172 cvp_handle = voice_get_cvp_handle(v);
9173
9174 /* send Sound Focus Params to cvp */
9175 cvp_set_sound_focus_param_cmd.hdr.hdr_field =
9176 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
9177 APR_HDR_LEN(APR_HDR_SIZE),
9178 APR_PKT_VER);
9179 cvp_set_sound_focus_param_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
9180 sizeof(cvp_set_sound_focus_param_cmd) - APR_HDR_SIZE);
9181 cvp_set_sound_focus_param_cmd.hdr.src_port =
9182 voice_get_idx_for_session(v->session_id);
9183 cvp_set_sound_focus_param_cmd.hdr.dest_port = cvp_handle;
9184 cvp_set_sound_focus_param_cmd.hdr.token = 0;
9185 cvp_set_sound_focus_param_cmd.hdr.opcode =
9186 VSS_ISOUNDFOCUS_CMD_SET_SECTORS;
9187
9188 memset(&(cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param), 0xFF,
9189 sizeof(struct vss_isoundfocus_cmd_set_sectors_t));
9190 for (i = 0; i < MAX_SECTORS; i++) {
9191 cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param.
9192 start_angles[i] = soundFocusData.start_angle[i];
9193 cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param.
9194 enables[i] = soundFocusData.enable[i];
9195 pr_debug("%s: start_angle[%d] = %d\n",
9196 __func__, i, soundFocusData.start_angle[i]);
9197 pr_debug("%s: enable[%d] = %d\n",
9198 __func__, i, soundFocusData.enable[i]);
9199 }
9200 cvp_set_sound_focus_param_cmd.cvp_set_sound_focus_param.gain_step =
9201 soundFocusData.gain_step;
9202 pr_debug("%s: gain_step = %d\n", __func__, soundFocusData.gain_step);
9203
9204 v->cvp_state = CMD_STATUS_FAIL;
9205 v->async_err = 0;
9206
9207 ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_set_sound_focus_param_cmd);
9208 if (ret < 0) {
9209 pr_err("%s: Error in sending APR command\n", __func__);
9210
9211 ret = -EINVAL;
9212 goto done;
9213 }
9214 ret = wait_event_timeout(v->cvp_wait,
9215 (v->cvp_state == CMD_STATUS_SUCCESS),
9216 msecs_to_jiffies(TIMEOUT_MS));
9217 if (!ret) {
9218 pr_err("%s: wait_event timeout\n", __func__);
9219
9220 ret = -EINVAL;
9221 goto done;
9222 }
9223
9224 if (v->async_err > 0) {
9225 pr_err("%s: DSP returned error[%s]\n",
9226 __func__, adsp_err_get_err_str(
9227 v->async_err));
9228 ret = adsp_err_get_lnx_err_code(
9229 v->async_err);
9230 goto done;
9231 }
9232
9233 if (common.is_sound_focus_resp_success) {
9234 ret = 0;
9235 } else {
9236 pr_err("%s: Error in setting sound focus params\n", __func__);
9237
9238 ret = -EINVAL;
9239 }
9240
9241done:
9242 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9243
9244 return ret;
9245}
9246
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309247/**
9248 * voc_set_sound_focus - sends sound focus data.
9249 *
9250 * @soundFocusData: sound focus data.
9251 *
9252 * Returns 0 on success or error on failure
9253 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309254int voc_set_sound_focus(struct sound_focus_param soundFocusData)
9255{
9256 struct voice_data *v = NULL;
9257 int ret = -EINVAL;
9258 struct voice_session_itr itr;
9259
9260 pr_debug("%s: Enter\n", __func__);
9261
9262 mutex_lock(&common.common_lock);
9263 voice_itr_init(&itr, ALL_SESSION_VSID);
9264 while (voice_itr_get_next_session(&itr, &v)) {
9265 if (v != NULL) {
9266 mutex_lock(&v->lock);
9267 if (is_voc_state_active(v->voc_state) &&
9268 (v->lch_mode != VOICE_LCH_START) &&
9269 !v->disable_topology)
9270 ret = voice_send_set_sound_focus_cmd(v,
9271 soundFocusData);
9272 mutex_unlock(&v->lock);
9273 } else {
9274 pr_err("%s: invalid session\n", __func__);
9275
9276 ret = -EINVAL;
9277 break;
9278 }
9279 }
9280 mutex_unlock(&common.common_lock);
9281 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9282
9283 return ret;
9284}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309285EXPORT_SYMBOL(voc_set_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309286
9287static int voice_send_get_sound_focus_cmd(struct voice_data *v,
9288 struct sound_focus_param *soundFocusData)
9289{
9290 struct apr_hdr cvp_get_sound_focus_param_cmd;
9291 int ret = 0;
9292 void *apr_cvp;
9293 u16 cvp_handle;
9294 int i;
9295
9296 pr_debug("%s: Enter\n", __func__);
9297
9298 if (!v) {
9299 pr_err("%s: v is NULL\n", __func__);
9300
9301 ret = -EINVAL;
9302 goto done;
9303 }
9304 apr_cvp = common.apr_q6_cvp;
9305
9306 if (!apr_cvp) {
9307 pr_err("%s: apr_cvp is NULL\n", __func__);
9308
9309 ret = -EINVAL;
9310 goto done;
9311 }
9312
9313 cvp_handle = voice_get_cvp_handle(v);
9314
9315 /* send APR command to retrieve Sound Focus Params */
9316 cvp_get_sound_focus_param_cmd.hdr_field =
9317 APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
9318 APR_HDR_LEN(APR_HDR_SIZE),
9319 APR_PKT_VER);
9320 cvp_get_sound_focus_param_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
9321 sizeof(cvp_get_sound_focus_param_cmd) - APR_HDR_SIZE);
9322 cvp_get_sound_focus_param_cmd.src_port =
9323 voice_get_idx_for_session(v->session_id);
9324 cvp_get_sound_focus_param_cmd.dest_port = cvp_handle;
9325 cvp_get_sound_focus_param_cmd.token = 0;
9326 cvp_get_sound_focus_param_cmd.opcode = VSS_ISOUNDFOCUS_CMD_GET_SECTORS;
9327
9328 v->cvp_state = CMD_STATUS_FAIL;
9329 v->async_err = 0;
9330 ret = apr_send_pkt(apr_cvp, (uint32_t *)&cvp_get_sound_focus_param_cmd);
9331 if (ret < 0) {
9332 pr_err("%s: Error in sending APR command\n", __func__);
9333
9334 ret = -EINVAL;
9335 goto done;
9336 }
9337 ret = wait_event_timeout(v->cvp_wait,
9338 (v->cvp_state == CMD_STATUS_SUCCESS),
9339 msecs_to_jiffies(TIMEOUT_MS));
9340 if (!ret) {
9341 pr_err("%s: wait_event timeout\n", __func__);
9342
9343 ret = -EINVAL;
9344 goto done;
9345 }
9346
9347 if (v->async_err > 0) {
9348 pr_err("%s: DSP returned error[%s]\n",
9349 __func__, adsp_err_get_err_str(
9350 v->async_err));
9351 ret = adsp_err_get_lnx_err_code(
9352 v->async_err);
9353 goto done;
9354 }
9355
9356 if (common.is_sound_focus_resp_success) {
9357 for (i = 0; i < MAX_SECTORS; i++) {
9358 soundFocusData->start_angle[i] =
9359 common.soundFocusResponse.start_angles[i];
9360 soundFocusData->enable[i] =
9361 common.soundFocusResponse.enables[i];
9362 pr_debug("%s: start_angle[%d] = %d\n",
9363 __func__, i, soundFocusData->start_angle[i]);
9364 pr_debug("%s: enable[%d] = %d\n",
9365 __func__, i, soundFocusData->enable[i]);
9366 }
9367 soundFocusData->gain_step = common.soundFocusResponse.gain_step;
9368 pr_debug("%s: gain_step = %d\n", __func__,
9369 soundFocusData->gain_step);
9370
9371 common.is_sound_focus_resp_success = false;
9372 ret = 0;
9373 } else {
9374 pr_err("%s: Invalid payload received from CVD\n", __func__);
9375
9376 ret = -EINVAL;
9377 }
9378done:
9379 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9380
9381 return ret;
9382}
9383
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309384/**
9385 * voc_get_sound_focus - retrieves sound focus data.
9386 *
9387 * @soundFocusData: pointer to be updated with sound focus data.
9388 *
9389 * Returns 0 on success or error on failure
9390 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309391int voc_get_sound_focus(struct sound_focus_param *soundFocusData)
9392{
9393 struct voice_data *v = NULL;
9394 int ret = -EINVAL;
9395 struct voice_session_itr itr;
9396
9397 pr_debug("%s: Enter\n", __func__);
9398
9399 mutex_lock(&common.common_lock);
9400 voice_itr_init(&itr, ALL_SESSION_VSID);
9401 while (voice_itr_get_next_session(&itr, &v)) {
9402 if (v) {
9403 mutex_lock(&v->lock);
9404 if (is_voc_state_active(v->voc_state) &&
9405 (v->lch_mode != VOICE_LCH_START) &&
9406 !v->disable_topology)
9407 ret = voice_send_get_sound_focus_cmd(v,
9408 soundFocusData);
9409 mutex_unlock(&v->lock);
9410 } else {
9411 pr_err("%s: invalid session\n", __func__);
9412
9413 ret = -EINVAL;
9414 break;
9415 }
9416 }
9417 mutex_unlock(&common.common_lock);
9418 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9419
9420 return ret;
9421}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309422EXPORT_SYMBOL(voc_get_sound_focus);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309423
9424static int is_source_tracking_shared_memomry_allocated(void)
9425{
9426 bool ret;
9427
9428 pr_debug("%s: Enter\n", __func__);
9429
9430 if (common.source_tracking_sh_mem.sh_mem_block.client != NULL &&
9431 common.source_tracking_sh_mem.sh_mem_block.handle != NULL)
9432 ret = true;
9433 else
9434 ret = false;
9435
9436 pr_debug("%s: Exit\n", __func__);
9437
9438 return ret;
9439}
9440
9441static int voice_alloc_source_tracking_shared_memory(void)
9442{
9443 int ret = 0;
9444
9445 pr_debug("%s: Enter\n", __func__);
9446
9447 ret = msm_audio_ion_alloc("source_tracking_sh_mem_block",
9448 &(common.source_tracking_sh_mem.sh_mem_block.client),
9449 &(common.source_tracking_sh_mem.sh_mem_block.handle),
9450 BUFFER_BLOCK_SIZE,
9451 &(common.source_tracking_sh_mem.sh_mem_block.phys),
9452 (size_t *)&(common.source_tracking_sh_mem.sh_mem_block.size),
9453 &(common.source_tracking_sh_mem.sh_mem_block.data));
9454 if (ret < 0) {
9455 pr_err("%s: audio ION alloc failed for sh_mem block, ret = %d\n",
9456 __func__, ret);
9457
9458 ret = -EINVAL;
9459 goto done;
9460 }
9461 memset((void *)(common.source_tracking_sh_mem.sh_mem_block.data), 0,
9462 common.source_tracking_sh_mem.sh_mem_block.size);
9463
9464 pr_debug("%s: sh_mem_block: phys:[%pK], data:[0x%pK], size:[%zd]\n",
9465 __func__,
9466 &(common.source_tracking_sh_mem.sh_mem_block.phys),
9467 (void *)(common.source_tracking_sh_mem.sh_mem_block.data),
9468 (size_t)(common.source_tracking_sh_mem.sh_mem_block.size));
9469
9470 ret = msm_audio_ion_alloc("source_tracking_sh_mem_table",
9471 &(common.source_tracking_sh_mem.sh_mem_table.client),
9472 &(common.source_tracking_sh_mem.sh_mem_table.handle),
9473 sizeof(struct vss_imemory_table_t),
9474 &(common.source_tracking_sh_mem.sh_mem_table.phys),
9475 (size_t *)&(common.source_tracking_sh_mem.sh_mem_table.size),
9476 &(common.source_tracking_sh_mem.sh_mem_table.data));
9477 if (ret < 0) {
9478 pr_err("%s: audio ION alloc failed for sh_mem table, ret = %d\n",
9479 __func__, ret);
9480
9481 ret = msm_audio_ion_free(
9482 common.source_tracking_sh_mem.sh_mem_block.client,
9483 common.source_tracking_sh_mem.sh_mem_block.handle);
9484 common.source_tracking_sh_mem.sh_mem_block.client = NULL;
9485 common.source_tracking_sh_mem.sh_mem_block.handle = NULL;
9486 if (ret < 0)
9487 pr_err("%s: Error:%d freeing memory\n", __func__, ret);
9488
9489 ret = -EINVAL;
9490 goto done;
9491 }
9492 memset((void *)(common.source_tracking_sh_mem.sh_mem_table.data), 0,
9493 common.source_tracking_sh_mem.sh_mem_table.size);
9494
9495 pr_debug("%s sh_mem_table: phys:[%pK], data:[0x%pK], size:[%zd],\n",
9496 __func__,
9497 &(common.source_tracking_sh_mem.sh_mem_table.phys),
9498 (void *)(common.source_tracking_sh_mem.sh_mem_table.data),
9499 (size_t)(common.source_tracking_sh_mem.sh_mem_table.size));
9500
9501done:
9502 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9503
9504 return ret;
9505}
9506
9507static int voice_alloc_and_map_source_tracking_shared_memory(
9508 struct voice_data *v)
9509{
9510 int ret = 0;
9511
9512 pr_debug("%s: Enter\n", __func__);
9513
9514 ret = voice_alloc_source_tracking_shared_memory();
9515 if (ret) {
9516 pr_err("%s: Failed to allocate shared memory %d\n",
9517 __func__, ret);
9518
9519 ret = -EINVAL;
9520 goto done;
9521 }
9522
9523 ret = voice_map_memory_physical_cmd(v,
9524 &(common.source_tracking_sh_mem.sh_mem_table),
9525 common.source_tracking_sh_mem.sh_mem_block.phys,
9526 common.source_tracking_sh_mem.sh_mem_block.size,
9527 VOC_SOURCE_TRACKING_MEM_MAP_TOKEN);
9528 if (ret) {
9529 pr_err("%s: memory mapping failed %d\n",
9530 __func__, ret);
9531
9532 ret = -EINVAL;
9533 goto done;
9534 }
9535
9536done:
9537 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9538
9539 return ret;
9540}
9541
9542static int voice_unmap_and_free_source_tracking_shared_memory(
9543 struct voice_data *v)
9544{
9545 int ret = 0;
9546
9547 pr_debug("%s: Enter\n", __func__);
9548
9549 if (common.source_tracking_sh_mem.mem_handle != 0) {
9550 ret = voice_send_mvm_unmap_memory_physical_cmd(v,
9551 common.source_tracking_sh_mem.mem_handle);
9552 if (ret < 0) {
9553 pr_err("%s: Memory_unmap failed err %d\n",
9554 __func__, ret);
9555
9556 ret = -EINVAL;
9557 goto done;
9558 }
9559 }
9560
9561 if ((common.source_tracking_sh_mem.sh_mem_block.client == NULL) ||
9562 (common.source_tracking_sh_mem.sh_mem_block.handle == NULL))
9563 goto done;
9564
9565 ret = msm_audio_ion_free(
9566 common.source_tracking_sh_mem.sh_mem_block.client,
9567 common.source_tracking_sh_mem.sh_mem_block.handle);
9568 if (ret < 0) {
9569 pr_err("%s: Error:%d freeing memory\n", __func__, ret);
9570
9571 ret = -EINVAL;
9572 goto done;
9573 }
9574
9575done:
9576 common.source_tracking_sh_mem.mem_handle = 0;
9577 common.source_tracking_sh_mem.sh_mem_block.client = NULL;
9578 common.source_tracking_sh_mem.sh_mem_block.handle = NULL;
9579 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9580
9581 return ret;
9582}
9583
9584static int voice_send_get_source_tracking_cmd(struct voice_data *v,
9585 struct source_tracking_param *sourceTrackingData)
9586{
9587 struct cvp_get_source_tracking_param_cmd_t st_cmd;
9588 int ret = 0;
9589 void *apr_cvp;
9590 u16 cvp_handle;
9591 int i;
9592
9593 pr_debug("%s: Enter\n", __func__);
9594
9595 if (!v) {
9596 pr_err("%s: v is NULL\n", __func__);
9597 return -EINVAL;
9598 }
9599 apr_cvp = common.apr_q6_cvp;
9600
9601 if (!apr_cvp) {
9602 pr_err("%s: apr_cvp is NULL.\n", __func__);
9603 return -EINVAL;
9604 }
9605
9606 cvp_handle = voice_get_cvp_handle(v);
9607
9608 if (!is_source_tracking_shared_memomry_allocated()) {
9609 ret = voice_alloc_and_map_source_tracking_shared_memory(v);
9610 if (ret) {
9611 pr_err("%s: Fail in allocating/mapping shared memory\n",
9612 __func__);
9613
9614 ret = -EINVAL;
9615 goto done;
9616 }
9617 }
9618 st_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
9619 APR_HDR_LEN(APR_HDR_SIZE),
9620 APR_PKT_VER);
9621 st_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
9622 sizeof(st_cmd) - APR_HDR_SIZE);
9623 st_cmd.hdr.src_port = voice_get_idx_for_session(v->session_id);
9624 st_cmd.hdr.dest_port = cvp_handle;
9625 st_cmd.hdr.token = 0;
9626 st_cmd.hdr.opcode = VSS_ISOURCETRACK_CMD_GET_ACTIVITY;
9627
9628 st_cmd.cvp_get_source_tracking_param.mem_handle =
9629 common.source_tracking_sh_mem.mem_handle;
9630 st_cmd.cvp_get_source_tracking_param.mem_address_lsw =
9631 lower_32_bits(common.source_tracking_sh_mem.sh_mem_block.phys);
9632 st_cmd.cvp_get_source_tracking_param.mem_address_msw =
9633 msm_audio_populate_upper_32_bits(common.source_tracking_sh_mem.
9634 sh_mem_block.phys);
9635 st_cmd.cvp_get_source_tracking_param.mem_size =
9636 (uint32_t)common.source_tracking_sh_mem.sh_mem_block.size;
9637 pr_debug("%s: mem_handle=0x%x, mem_address_lsw=0x%x, msw=0x%x, mem_size=%d\n",
9638 __func__,
9639 st_cmd.cvp_get_source_tracking_param.mem_handle,
9640 st_cmd.cvp_get_source_tracking_param.mem_address_lsw,
9641 st_cmd.cvp_get_source_tracking_param.mem_address_msw,
9642 (uint32_t)st_cmd.cvp_get_source_tracking_param.mem_size);
9643
9644 v->cvp_state = CMD_STATUS_FAIL;
9645 v->async_err = 0;
9646 ret = apr_send_pkt(apr_cvp,
9647 (uint32_t *) &st_cmd);
9648 if (ret < 0) {
9649 pr_err("%s: Error in sending APR command\n", __func__);
9650
9651 ret = -EINVAL;
9652 goto done;
9653 }
9654 ret = wait_event_timeout(v->cvp_wait,
9655 (v->cvp_state == CMD_STATUS_SUCCESS),
9656 msecs_to_jiffies(TIMEOUT_MS));
9657 if (!ret) {
9658 pr_err("%s: wait_event timeout\n", __func__);
9659
9660 ret = -EINVAL;
9661 goto done;
9662 }
9663
9664 if (v->async_err > 0) {
9665 pr_err("%s: DSP returned error[%s]\n",
9666 __func__, adsp_err_get_err_str(
9667 v->async_err));
9668 ret = adsp_err_get_lnx_err_code(
9669 v->async_err);
9670 goto done;
9671 }
9672
9673 if (common.is_source_tracking_resp_success) {
9674 for (i = 0; i < MAX_SECTORS; i++) {
9675 sourceTrackingData->vad[i] =
9676 common.sourceTrackingResponse.voice_active[i];
9677 pr_debug("%s: vad[%d] = %d\n",
9678 __func__, i, sourceTrackingData->vad[i]);
9679 }
9680 sourceTrackingData->doa_speech =
9681 common.sourceTrackingResponse.talker_doa;
9682 pr_debug("%s: doa_speech = %d\n",
9683 __func__, sourceTrackingData->doa_speech);
9684
9685 for (i = 0; i < MAX_NOISE_SOURCE_INDICATORS; i++) {
9686 sourceTrackingData->doa_noise[i] =
9687 common.sourceTrackingResponse.interferer_doa[i];
9688 pr_debug("%s: doa_noise[%d] = %d\n",
9689 __func__, i, sourceTrackingData->doa_noise[i]);
9690 }
9691 for (i = 0; i < MAX_POLAR_ACTIVITY_INDICATORS; i++) {
9692 sourceTrackingData->polar_activity[i] =
9693 common.sourceTrackingResponse.sound_strength[i];
9694 pr_debug("%s: polar_activity[%d] = %d\n",
9695 __func__, i, sourceTrackingData->polar_activity[i]);
9696 }
9697 common.is_source_tracking_resp_success = false;
9698 ret = 0;
9699 } else {
9700 pr_err("%s: Error response received from CVD\n", __func__);
9701
9702 ret = -EINVAL;
9703 }
9704done:
9705 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9706
9707 return ret;
9708}
9709
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309710/**
9711 * voc_get_source_tracking - retrieves source track data.
9712 *
9713 * @sourceTrackingData: pointer to be updated with source track data.
9714 *
9715 * Returns 0 on success or error on failure
9716 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309717int voc_get_source_tracking(struct source_tracking_param *sourceTrackingData)
9718{
9719 struct voice_data *v = NULL;
9720 int ret = -EINVAL;
9721 struct voice_session_itr itr;
9722
9723 pr_debug("%s: Enter\n", __func__);
9724
9725 mutex_lock(&common.common_lock);
9726
9727 voice_itr_init(&itr, ALL_SESSION_VSID);
9728 while (voice_itr_get_next_session(&itr, &v)) {
9729 if (v != NULL) {
9730 mutex_lock(&v->lock);
9731 if (is_voc_state_active(v->voc_state) &&
9732 (v->lch_mode != VOICE_LCH_START) &&
9733 !v->disable_topology)
9734 ret = voice_send_get_source_tracking_cmd(v,
9735 sourceTrackingData);
9736 mutex_unlock(&v->lock);
9737 } else {
9738 pr_err("%s: invalid session\n", __func__);
9739
9740 break;
9741 }
9742 }
9743
9744 mutex_unlock(&common.common_lock);
9745 pr_debug("%s: Exit, ret=%d\n", __func__, ret);
9746
9747 return ret;
9748}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309749EXPORT_SYMBOL(voc_get_source_tracking);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309750
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309751/**
9752 * is_voc_initialized:
9753 *
9754 * Returns voice module init status
9755 *
9756 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309757int is_voc_initialized(void)
9758{
9759 return module_initialized;
9760}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309761EXPORT_SYMBOL(is_voc_initialized);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309762
Vignesh Kulothungan78d3e822018-03-13 16:05:20 -07009763static void voc_release_uevent_data(struct kobject *kobj)
9764{
9765 struct audio_uevent_data *data = container_of(kobj,
9766 struct audio_uevent_data,
9767 kobj);
9768 kfree(data);
9769}
9770
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05309771int __init voice_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309772{
9773 int rc = 0, i = 0;
9774
9775 memset(&common, 0, sizeof(struct common_data));
9776
9777 /* set default value */
9778 common.default_mute_val = 0; /* default is un-mute */
9779 common.default_sample_val = 8000;
9780 common.default_vol_step_val = 0;
9781 common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
9782 common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
Laxminath Kasam38070be2017-08-17 18:21:59 +05309783 common.cvp_version = 0;
9784 common.is_avcs_version_queried = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309785 /* Initialize EC Ref media format info */
9786 common.ec_ref_ext = false;
9787 common.ec_media_fmt_info.port_id = AFE_PORT_INVALID;
9788 common.ec_media_fmt_info.num_channels = 0;
9789 common.ec_media_fmt_info.bits_per_sample = 16;
9790 common.ec_media_fmt_info.sample_rate = 8000;
9791 memset(&common.ec_media_fmt_info.channel_mapping, 0,
9792 VSS_CHANNEL_MAPPING_SIZE);
9793
9794 /* Initialize AFE Sidetone Enable */
9795 common.sidetone_enable = false;
9796
9797 /* Initialize MVS info. */
9798 common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
9799
9800 /* Initialize is low memory flag */
9801 common.is_destroy_cvd = false;
9802
9803 /* Initialize CVD version */
9804 strlcpy(common.cvd_version, CVD_VERSION_DEFAULT,
9805 sizeof(common.cvd_version));
9806 /* Initialize Per-Vocoder Calibration flag */
9807 common.is_per_vocoder_cal_enabled = false;
9808
9809 mutex_init(&common.common_lock);
9810
Vignesh Kulothungan78d3e822018-03-13 16:05:20 -07009811 common.uevent_data = kzalloc(sizeof(*(common.uevent_data)), GFP_KERNEL);
9812 if (!common.uevent_data)
9813 return -ENOMEM;
9814
9815 /*
9816 * Set release function to cleanup memory related to kobject
9817 * before initializing the kobject.
9818 */
9819 common.uevent_data->ktype.release = voc_release_uevent_data;
9820 q6core_init_uevent_data(common.uevent_data, "q6voice_uevent");
9821 common.mic_break_enable = false;
9822
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309823 /* Initialize session id with vsid */
9824 init_session_id();
9825
9826 for (i = 0; i < MAX_VOC_SESSIONS; i++) {
9827
9828 /* initialize dev_rx and dev_tx */
9829 common.voice[i].dev_rx.dev_mute = common.default_mute_val;
9830 common.voice[i].dev_tx.dev_mute = common.default_mute_val;
9831 common.voice[i].dev_rx.volume_step_value =
9832 common.default_vol_step_val;
9833 common.voice[i].dev_rx.volume_ramp_duration_ms =
9834 common.default_vol_ramp_duration_ms;
9835 common.voice[i].dev_rx.dev_mute_ramp_duration_ms =
9836 common.default_mute_ramp_duration_ms;
9837 common.voice[i].dev_tx.dev_mute_ramp_duration_ms =
9838 common.default_mute_ramp_duration_ms;
9839 common.voice[i].stream_rx.stream_mute = common.default_mute_val;
9840 common.voice[i].stream_tx.stream_mute = common.default_mute_val;
9841
9842 common.voice[i].dev_tx.port_id = 0x100B;
9843 common.voice[i].dev_rx.port_id = 0x100A;
9844 common.voice[i].dev_tx.dev_id = 0;
9845 common.voice[i].dev_rx.dev_id = 0;
9846 common.voice[i].dev_tx.no_of_channels = 0;
9847 common.voice[i].dev_rx.no_of_channels = 0;
9848 common.voice[i].dev_tx.sample_rate = 8000;
9849 common.voice[i].dev_rx.sample_rate = 8000;
9850 common.voice[i].dev_tx.bits_per_sample = 16;
9851 common.voice[i].dev_rx.bits_per_sample = 16;
9852 memset(&common.voice[i].dev_tx.channel_mapping, 0,
9853 VSS_CHANNEL_MAPPING_SIZE);
9854 memset(&common.voice[i].dev_rx.channel_mapping, 0,
9855 VSS_CHANNEL_MAPPING_SIZE);
9856 common.voice[i].sidetone_gain = 0x512;
9857 common.voice[i].dtmf_rx_detect_en = 0;
9858 common.voice[i].lch_mode = 0;
9859 common.voice[i].disable_topology = false;
9860
9861 common.voice[i].voc_state = VOC_INIT;
9862
Vignesh Kulothungan78d3e822018-03-13 16:05:20 -07009863 INIT_WORK(&common.voice[i].voice_mic_break_work,
9864 voice_mic_break_work_fn);
9865
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309866 init_waitqueue_head(&common.voice[i].mvm_wait);
9867 init_waitqueue_head(&common.voice[i].cvs_wait);
9868 init_waitqueue_head(&common.voice[i].cvp_wait);
9869
9870 mutex_init(&common.voice[i].lock);
9871 }
9872
9873 if (voice_init_cal_data())
9874 pr_err("%s: Could not init cal data!\n", __func__);
9875
9876 if (rc == 0)
9877 module_initialized = true;
9878
9879 pr_debug("%s: rc=%d\n", __func__, rc);
9880 return rc;
9881}
9882
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309883
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05309884void voice_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309885{
Vignesh Kulothungan78d3e822018-03-13 16:05:20 -07009886 q6core_destroy_uevent_data(common.uevent_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05309887 voice_delete_cal_data();
9888 free_cal_map_table();
9889}