/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include "sound/apr_audio.h" #include "sound/q6afe.h" #include "q6voice.h" #define TIMEOUT_MS 3000 #define CMD_STATUS_SUCCESS 0 #define CMD_STATUS_FAIL 1 #define CAL_BUFFER_SIZE 4096 #define NUM_CVP_CAL_BLOCKS 75 #define NUM_CVS_CAL_BLOCKS 15 #define CVP_CAL_SIZE (NUM_CVP_CAL_BLOCKS * CAL_BUFFER_SIZE) #define CVS_CAL_SIZE (NUM_CVS_CAL_BLOCKS * CAL_BUFFER_SIZE) #define VOICE_CAL_BUFFER_SIZE (CVP_CAL_SIZE + CVS_CAL_SIZE) /* Total cal needed to support concurrent VOIP & VOLTE sessions */ /* Due to memory map issue on Q6 separate memory has to be used */ /* for VOIP & VOLTE */ #define TOTAL_VOICE_CAL_SIZE (NUM_VOICE_CAL_BUFFERS * VOICE_CAL_BUFFER_SIZE) static struct common_data common; static int voice_send_enable_vocproc_cmd(struct voice_data *v); static int voice_send_netid_timing_cmd(struct voice_data *v); static int voice_send_attach_vocproc_cmd(struct voice_data *v); static int voice_send_set_device_cmd(struct voice_data *v); static int voice_send_disable_vocproc_cmd(struct voice_data *v); static int voice_send_vol_index_cmd(struct voice_data *v); static int voice_send_cvp_map_memory_cmd(struct voice_data *v, uint32_t paddr, uint32_t mem_size); static int voice_send_cvp_unmap_memory_cmd(struct voice_data *v, uint32_t paddr); static int voice_send_cvs_map_memory_cmd(struct voice_data *v); static int voice_send_cvs_unmap_memory_cmd(struct voice_data *v); static int voice_send_cvs_register_cal_cmd(struct voice_data *v); static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v); static int voice_send_cvp_register_cal_cmd(struct voice_data *v); static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v); static int voice_send_cvp_register_vol_cal_table_cmd(struct voice_data *v); static int voice_send_cvp_deregister_vol_cal_table_cmd(struct voice_data *v); static int voice_send_set_widevoice_enable_cmd(struct voice_data *v); static int voice_send_set_pp_enable_cmd(struct voice_data *v, uint32_t module_id, int enable); static int voice_cvs_stop_playback(struct voice_data *v); static int voice_cvs_start_playback(struct voice_data *v); static int voice_cvs_start_record(struct voice_data *v, uint32_t rec_mode); static int voice_cvs_stop_record(struct voice_data *v); static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv); static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv); static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv); static int voice_send_set_device_cmd_v2(struct voice_data *v); static u16 voice_get_mvm_handle(struct voice_data *v) { if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return 0; } pr_debug("%s: mvm_handle %d\n", __func__, v->mvm_handle); return v->mvm_handle; } static void voice_set_mvm_handle(struct voice_data *v, u16 mvm_handle) { pr_debug("%s: mvm_handle %d\n", __func__, mvm_handle); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return; } v->mvm_handle = mvm_handle; } static u16 voice_get_cvs_handle(struct voice_data *v) { if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return 0; } pr_debug("%s: cvs_handle %d\n", __func__, v->cvs_handle); return v->cvs_handle; } static void voice_set_cvs_handle(struct voice_data *v, u16 cvs_handle) { pr_debug("%s: cvs_handle %d\n", __func__, cvs_handle); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return; } v->cvs_handle = cvs_handle; } static u16 voice_get_cvp_handle(struct voice_data *v) { if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return 0; } pr_debug("%s: cvp_handle %d\n", __func__, v->cvp_handle); return v->cvp_handle; } static void voice_set_cvp_handle(struct voice_data *v, u16 cvp_handle) { pr_debug("%s: cvp_handle %d\n", __func__, cvp_handle); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return; } v->cvp_handle = cvp_handle; } char *voc_get_session_name(u16 session_id) { char *session_name = NULL; if (session_id == common.voice[VOC_PATH_PASSIVE].session_id) { session_name = VOICE_SESSION_NAME; } else if (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id) { session_name = VOLTE_SESSION_NAME; } else if (session_id == common.voice[VOC_PATH_FULL].session_id) { session_name = VOIP_SESSION_NAME; } return session_name; } uint16_t voc_get_session_id(char *name) { u16 session_id = 0; if (name != NULL) { if (!strncmp(name, "Voice session", 13)) session_id = common.voice[VOC_PATH_PASSIVE].session_id; else if (!strncmp(name, "VoLTE session", 13)) session_id = common.voice[VOC_PATH_VOLTE_PASSIVE].session_id; else if (!strncmp(name, "Voice2 session", 14)) session_id = common.voice[VOC_PATH_VOICE2_PASSIVE].session_id; else session_id = common.voice[VOC_PATH_FULL].session_id; pr_debug("%s: %s has session id 0x%x\n", __func__, name, session_id); } return session_id; } static struct voice_data *voice_get_session(u16 session_id) { struct voice_data *v = NULL; if ((session_id >= SESSION_ID_BASE) && (session_id < SESSION_ID_BASE + MAX_VOC_SESSIONS)) { v = &common.voice[session_id - SESSION_ID_BASE]; } pr_debug("%s: session_id 0x%x session handle 0x%x\n", __func__, session_id, (unsigned int)v); return v; } static bool is_voice_session(u16 session_id) { return (session_id == common.voice[VOC_PATH_PASSIVE].session_id); } static bool is_voip_session(u16 session_id) { return (session_id == common.voice[VOC_PATH_FULL].session_id); } static bool is_volte_session(u16 session_id) { return (session_id == common.voice[VOC_PATH_VOLTE_PASSIVE].session_id); } static bool is_voice2_session(u16 session_id) { return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id); } /* Only for memory allocated in the voice driver */ /* which includes voip & volte */ static int voice_get_cal_kernel_addr(int16_t session_id, int cal_type, uint32_t *kvaddr) { int i, result = 0; pr_debug("%s\n", __func__); if (kvaddr == NULL) { pr_err("%s: NULL pointer sent to function\n", __func__); result = -EINVAL; goto done; } else if (is_voip_session(session_id)) { i = VOIP_CAL; } else if (is_volte_session(session_id)) { i = VOLTE_CAL; } else { result = -EINVAL; goto done; } if (common.voice_cal[i].cal_data[cal_type].kvaddr == 0) { pr_err("%s: NULL pointer for session_id %d, type %d, cal_type %d\n", __func__, session_id, i, cal_type); result = -EFAULT; goto done; } *kvaddr = common.voice_cal[i].cal_data[cal_type].kvaddr; done: return result; } /* Only for memory allocated in the voice driver */ /* which includes voip & volte */ static int voice_get_cal_phys_addr(int16_t session_id, int cal_type, uint32_t *paddr) { int i, result = 0; pr_debug("%s\n", __func__); if (paddr == NULL) { pr_err("%s: NULL pointer sent to function\n", __func__); result = -EINVAL; goto done; } else if (is_voip_session(session_id)) { i = VOIP_CAL; } else if (is_volte_session(session_id)) { i = VOLTE_CAL; } else { result = -EINVAL; goto done; } if (common.voice_cal[i].cal_data[cal_type].paddr == 0) { pr_err("%s: No addr for session_id %d, type %d, cal_type %d\n", __func__, session_id, i, cal_type); result = -EFAULT; goto done; } *paddr = common.voice_cal[i].cal_data[cal_type].paddr; done: return result; } static int voice_apr_register(void) { pr_debug("%s\n", __func__); mutex_lock(&common.common_lock); /* register callback to APR */ if (common.apr_q6_mvm == NULL) { pr_debug("%s: Start to register MVM callback\n", __func__); common.apr_q6_mvm = apr_register("ADSP", "MVM", qdsp_mvm_callback, 0xFFFFFFFF, &common); if (common.apr_q6_mvm == NULL) { pr_err("%s: Unable to register MVM\n", __func__); goto err; } } if (common.apr_q6_cvs == NULL) { pr_debug("%s: Start to register CVS callback\n", __func__); common.apr_q6_cvs = apr_register("ADSP", "CVS", qdsp_cvs_callback, 0xFFFFFFFF, &common); if (common.apr_q6_cvs == NULL) { pr_err("%s: Unable to register CVS\n", __func__); goto err; } rtac_set_voice_handle(RTAC_CVS, common.apr_q6_cvs); } if (common.apr_q6_cvp == NULL) { pr_debug("%s: Start to register CVP callback\n", __func__); common.apr_q6_cvp = apr_register("ADSP", "CVP", qdsp_cvp_callback, 0xFFFFFFFF, &common); if (common.apr_q6_cvp == NULL) { pr_err("%s: Unable to register CVP\n", __func__); goto err; } rtac_set_voice_handle(RTAC_CVP, common.apr_q6_cvp); } mutex_unlock(&common.common_lock); return 0; err: if (common.apr_q6_cvs != NULL) { apr_deregister(common.apr_q6_cvs); common.apr_q6_cvs = NULL; rtac_set_voice_handle(RTAC_CVS, NULL); } if (common.apr_q6_mvm != NULL) { apr_deregister(common.apr_q6_mvm); common.apr_q6_mvm = NULL; } mutex_unlock(&common.common_lock); return -ENODEV; } static int voice_send_dual_control_cmd(struct voice_data *v) { int ret = 0; struct mvm_modem_dual_control_session_cmd mvm_voice_ctl_cmd; void *apr_mvm; u16 mvm_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } pr_debug("%s: VoLTE/Voice2 command to MVM\n", __func__); if (is_volte_session(v->session_id) || is_voice2_session(v->session_id)) { mvm_handle = voice_get_mvm_handle(v); mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_voice_ctl_cmd.hdr.pkt_size = APR_PKT_SIZE( APR_HDR_SIZE, sizeof(mvm_voice_ctl_cmd) - APR_HDR_SIZE); pr_debug("%s: send mvm Voice Ctl pkt size = %d\n", __func__, mvm_voice_ctl_cmd.hdr.pkt_size); mvm_voice_ctl_cmd.hdr.src_port = v->session_id; mvm_voice_ctl_cmd.hdr.dest_port = mvm_handle; mvm_voice_ctl_cmd.hdr.token = 0; mvm_voice_ctl_cmd.hdr.opcode = VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL; mvm_voice_ctl_cmd.voice_ctl.enable_flag = true; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_voice_ctl_cmd); if (ret < 0) { pr_err("%s: Error sending MVM Voice CTL CMD\n", __func__); ret = -EINVAL; goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); ret = -EINVAL; goto fail; } } ret = 0; fail: return ret; } static int voice_create_mvm_cvs_session(struct voice_data *v) { int ret = 0; struct mvm_create_ctl_session_cmd mvm_session_cmd; struct cvs_create_passive_ctl_session_cmd cvs_session_cmd; struct cvs_create_full_ctl_session_cmd cvs_full_ctl_cmd; struct mvm_attach_stream_cmd attach_stream_cmd; void *apr_mvm, *apr_cvs, *apr_cvp; u16 mvm_handle, cvs_handle, cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; apr_cvs = common.apr_q6_cvs; apr_cvp = common.apr_q6_cvp; if (!apr_mvm || !apr_cvs || !apr_cvp) { pr_err("%s: apr_mvm or apr_cvs or apr_cvp is NULL\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); cvs_handle = voice_get_cvs_handle(v); cvp_handle = voice_get_cvp_handle(v); pr_debug("%s: mvm_hdl=%d, cvs_hdl=%d\n", __func__, mvm_handle, cvs_handle); /* send cmd to create mvm session and wait for response */ if (!mvm_handle) { if (is_voice_session(v->session_id) || is_volte_session(v->session_id) || is_voice2_session(v->session_id)) { mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_session_cmd.hdr.pkt_size = APR_PKT_SIZE( APR_HDR_SIZE, sizeof(mvm_session_cmd) - APR_HDR_SIZE); pr_debug("%s: send mvm create session pkt size = %d\n", __func__, mvm_session_cmd.hdr.pkt_size); mvm_session_cmd.hdr.src_port = v->session_id; mvm_session_cmd.hdr.dest_port = 0; mvm_session_cmd.hdr.token = 0; mvm_session_cmd.hdr.opcode = VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION; if (is_volte_session(v->session_id)) { strlcpy(mvm_session_cmd.mvm_session.name, "default volte voice", sizeof(mvm_session_cmd.mvm_session.name) - 1); } else if (is_voice2_session(v->session_id)) { strlcpy(mvm_session_cmd.mvm_session.name, "default modem voice2", sizeof(mvm_session_cmd.mvm_session.name)); } else { strlcpy(mvm_session_cmd.mvm_session.name, "default modem voice", sizeof(mvm_session_cmd.mvm_session.name) - 1); } v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_session_cmd); if (ret < 0) { pr_err("%s: Error sending MVM_CONTROL_SESSION\n", __func__); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } } else { pr_debug("%s: creating MVM full ctrl\n", __func__); mvm_session_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_session_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_session_cmd) - APR_HDR_SIZE); mvm_session_cmd.hdr.src_port = v->session_id; mvm_session_cmd.hdr.dest_port = 0; mvm_session_cmd.hdr.token = 0; mvm_session_cmd.hdr.opcode = VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION; strlcpy(mvm_session_cmd.mvm_session.name, "default voip", sizeof(mvm_session_cmd.mvm_session.name)); v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_session_cmd); if (ret < 0) { pr_err("Fail in sending MVM_CONTROL_SESSION\n"); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } } /* Get the created MVM handle. */ mvm_handle = voice_get_mvm_handle(v); } /* send cmd to create cvs session */ if (!cvs_handle) { if (is_voice_session(v->session_id) || is_volte_session(v->session_id) || is_voice2_session(v->session_id)) { pr_debug("%s: creating CVS passive session\n", __func__); cvs_session_cmd.hdr.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_session_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_session_cmd) - APR_HDR_SIZE); cvs_session_cmd.hdr.src_port = v->session_id; cvs_session_cmd.hdr.dest_port = 0; cvs_session_cmd.hdr.token = 0; cvs_session_cmd.hdr.opcode = VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION; if (is_volte_session(v->session_id)) { strlcpy(cvs_session_cmd.cvs_session.name, "default volte voice", sizeof(cvs_session_cmd.cvs_session.name) - 1); } else if (is_voice2_session(v->session_id)) { strlcpy(cvs_session_cmd.cvs_session.name, "default modem voice2", sizeof(cvs_session_cmd.cvs_session.name)); } else { strlcpy(cvs_session_cmd.cvs_session.name, "default modem voice", sizeof(cvs_session_cmd.cvs_session.name) - 1); } v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_session_cmd); if (ret < 0) { pr_err("Fail in sending STREAM_CONTROL_SESSION\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } /* Get the created CVS handle. */ cvs_handle = voice_get_cvs_handle(v); } else { pr_debug("%s: creating CVS full session\n", __func__); cvs_full_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_full_ctl_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_full_ctl_cmd) - APR_HDR_SIZE); cvs_full_ctl_cmd.hdr.src_port = v->session_id; cvs_full_ctl_cmd.hdr.dest_port = 0; cvs_full_ctl_cmd.hdr.token = 0; cvs_full_ctl_cmd.hdr.opcode = VSS_ISTREAM_CMD_CREATE_FULL_CONTROL_SESSION; cvs_full_ctl_cmd.cvs_session.direction = 2; cvs_full_ctl_cmd.cvs_session.enc_media_type = common.mvs_info.media_type; cvs_full_ctl_cmd.cvs_session.dec_media_type = common.mvs_info.media_type; cvs_full_ctl_cmd.cvs_session.network_id = common.mvs_info.network_type; strlcpy(cvs_full_ctl_cmd.cvs_session.name, "default q6 voice", sizeof(cvs_full_ctl_cmd.cvs_session.name)); v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_full_ctl_cmd); if (ret < 0) { pr_err("%s: Err %d sending CREATE_FULL_CTRL\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } /* Get the created CVS handle. */ cvs_handle = voice_get_cvs_handle(v); /* Attach MVM to CVS. */ pr_debug("%s: Attach MVM to stream\n", __func__); attach_stream_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); attach_stream_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(attach_stream_cmd) - APR_HDR_SIZE); attach_stream_cmd.hdr.src_port = v->session_id; attach_stream_cmd.hdr.dest_port = mvm_handle; attach_stream_cmd.hdr.token = 0; attach_stream_cmd.hdr.opcode = VSS_IMVM_CMD_ATTACH_STREAM; attach_stream_cmd.attach_stream.handle = cvs_handle; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &attach_stream_cmd); if (ret < 0) { pr_err("%s: Error %d sending ATTACH_STREAM\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } } } return 0; fail: return -EINVAL; } static int voice_destroy_mvm_cvs_session(struct voice_data *v) { int ret = 0; struct mvm_detach_stream_cmd detach_stream; struct apr_hdr mvm_destroy; struct apr_hdr cvs_destroy; void *apr_mvm, *apr_cvs; u16 mvm_handle, cvs_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; apr_cvs = common.apr_q6_cvs; if (!apr_mvm || !apr_cvs) { pr_err("%s: apr_mvm or apr_cvs is NULL\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); cvs_handle = voice_get_cvs_handle(v); /* MVM, CVS sessions are destroyed only for Full control sessions. */ if (is_voip_session(v->session_id)) { pr_debug("%s: MVM detach stream\n", __func__); /* Detach voice stream. */ detach_stream.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); detach_stream.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(detach_stream) - APR_HDR_SIZE); detach_stream.hdr.src_port = v->session_id; detach_stream.hdr.dest_port = mvm_handle; detach_stream.hdr.token = 0; detach_stream.hdr.opcode = VSS_IMVM_CMD_DETACH_STREAM; detach_stream.detach_stream.handle = cvs_handle; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &detach_stream); if (ret < 0) { pr_err("%s: Error %d sending DETACH_STREAM\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait event timeout\n", __func__); goto fail; } /* Destroy CVS. */ pr_debug("%s: CVS destroy session\n", __func__); cvs_destroy.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_destroy.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_destroy) - APR_HDR_SIZE); cvs_destroy.src_port = v->session_id; cvs_destroy.dest_port = cvs_handle; cvs_destroy.token = 0; cvs_destroy.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_destroy); if (ret < 0) { pr_err("%s: Error %d sending CVS DESTROY\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait event timeout\n", __func__); goto fail; } cvs_handle = 0; voice_set_cvs_handle(v, cvs_handle); /* Destroy MVM. */ pr_debug("MVM destroy session\n"); mvm_destroy.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_destroy.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_destroy) - APR_HDR_SIZE); mvm_destroy.src_port = v->session_id; mvm_destroy.dest_port = mvm_handle; mvm_destroy.token = 0; mvm_destroy.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_destroy); if (ret < 0) { pr_err("%s: Error %d sending MVM DESTROY\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait event timeout\n", __func__); goto fail; } mvm_handle = 0; voice_set_mvm_handle(v, mvm_handle); } return 0; fail: return -EINVAL; } static int voice_send_tty_mode_cmd(struct voice_data *v) { int ret = 0; struct mvm_set_tty_mode_cmd mvm_tty_mode_cmd; void *apr_mvm; u16 mvm_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); if (v->tty_mode) { /* send tty mode cmd to mvm */ mvm_tty_mode_cmd.hdr.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_tty_mode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_tty_mode_cmd) - APR_HDR_SIZE); pr_debug("%s: pkt size = %d\n", __func__, mvm_tty_mode_cmd.hdr.pkt_size); mvm_tty_mode_cmd.hdr.src_port = v->session_id; mvm_tty_mode_cmd.hdr.dest_port = mvm_handle; mvm_tty_mode_cmd.hdr.token = 0; mvm_tty_mode_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_TTY_MODE; mvm_tty_mode_cmd.tty_mode.mode = v->tty_mode; pr_debug("tty mode =%d\n", mvm_tty_mode_cmd.tty_mode.mode); v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_tty_mode_cmd); if (ret < 0) { pr_err("%s: Error %d sending SET_TTY_MODE\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } } return 0; fail: return -EINVAL; } static int voice_set_dtx(struct voice_data *v) { int ret = 0; void *apr_cvs; u16 cvs_handle; struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); /* Set DTX */ cvs_set_dtx.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_set_dtx.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_set_dtx) - APR_HDR_SIZE); cvs_set_dtx.hdr.src_port = v->session_id; cvs_set_dtx.hdr.dest_port = cvs_handle; cvs_set_dtx.hdr.token = 0; cvs_set_dtx.hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE; cvs_set_dtx.dtx_mode.enable = common.mvs_info.dtx_mode; pr_debug("%s: Setting DTX %d\n", __func__, common.mvs_info.dtx_mode); v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_dtx); if (ret < 0) { pr_err("%s: Error %d sending SET_DTX\n", __func__, ret); return -EINVAL; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); return -EINVAL; } return 0; } static int voice_send_dtmf_rx_detection_cmd(struct voice_data *v, uint32_t enable) { int ret = 0; void *apr_cvs; u16 cvs_handle; struct cvs_set_rx_dtmf_detection_cmd cvs_dtmf_rx_detection; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); /* Set SET_DTMF_RX_DETECTION */ cvs_dtmf_rx_detection.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_dtmf_rx_detection.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_dtmf_rx_detection) - APR_HDR_SIZE); cvs_dtmf_rx_detection.hdr.src_port = v->session_id; cvs_dtmf_rx_detection.hdr.dest_port = cvs_handle; cvs_dtmf_rx_detection.hdr.token = 0; cvs_dtmf_rx_detection.hdr.opcode = VSS_ISTREAM_CMD_SET_RX_DTMF_DETECTION; cvs_dtmf_rx_detection.cvs_dtmf_det.enable = enable; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_dtmf_rx_detection); if (ret < 0) { pr_err("%s: Error %d sending SET_DTMF_RX_DETECTION\n", __func__, ret); return -EINVAL; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); return -EINVAL; } return ret; } void voc_disable_dtmf_det_on_active_sessions(void) { struct voice_data *v = NULL; int i; for (i = 0; i < MAX_VOC_SESSIONS; i++) { v = &common.voice[i]; if ((v->dtmf_rx_detect_en) && ((v->voc_state == VOC_RUN) || (v->voc_state == VOC_CHANGE) || (v->voc_state == VOC_STANDBY))) { pr_debug("disable dtmf det on ses_id=%d\n", v->session_id); voice_send_dtmf_rx_detection_cmd(v, 0); } } } int voc_enable_dtmf_rx_detection(uint16_t session_id, uint32_t enable) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->dtmf_rx_detect_en = enable; if ((v->voc_state == VOC_RUN) || (v->voc_state == VOC_CHANGE) || (v->voc_state == VOC_STANDBY)) ret = voice_send_dtmf_rx_detection_cmd(v, v->dtmf_rx_detect_en); mutex_unlock(&v->lock); return ret; } static int voice_config_cvs_vocoder(struct voice_data *v) { int ret = 0; void *apr_cvs; u16 cvs_handle; /* Set media type. */ struct cvs_set_media_type_cmd cvs_set_media_cmd; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); cvs_set_media_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_set_media_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_set_media_cmd) - APR_HDR_SIZE); cvs_set_media_cmd.hdr.src_port = v->session_id; cvs_set_media_cmd.hdr.dest_port = cvs_handle; cvs_set_media_cmd.hdr.token = 0; cvs_set_media_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_MEDIA_TYPE; cvs_set_media_cmd.media_type.tx_media_id = common.mvs_info.media_type; cvs_set_media_cmd.media_type.rx_media_id = common.mvs_info.media_type; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_media_cmd); if (ret < 0) { pr_err("%s: Error %d sending SET_MEDIA_TYPE\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } /* Set encoder properties. */ switch (common.mvs_info.media_type) { case VSS_MEDIA_ID_EVRC_MODEM: case VSS_MEDIA_ID_4GV_NB_MODEM: case VSS_MEDIA_ID_4GV_WB_MODEM: { struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate; pr_debug("Setting EVRC min-max rate\n"); cvs_set_cdma_rate.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_set_cdma_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_set_cdma_rate) - APR_HDR_SIZE); cvs_set_cdma_rate.hdr.src_port = v->session_id; cvs_set_cdma_rate.hdr.dest_port = cvs_handle; cvs_set_cdma_rate.hdr.token = 0; cvs_set_cdma_rate.hdr.opcode = VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE; cvs_set_cdma_rate.cdma_rate.min_rate = common.mvs_info.rate; cvs_set_cdma_rate.cdma_rate.max_rate = common.mvs_info.rate; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_cdma_rate); if (ret < 0) { pr_err("%s: Error %d sending SET_EVRC_MINMAX_RATE\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } break; } case VSS_MEDIA_ID_AMR_NB_MODEM: { struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate; pr_debug("Setting AMR rate\n"); cvs_set_amr_rate.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_set_amr_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_set_amr_rate) - APR_HDR_SIZE); cvs_set_amr_rate.hdr.src_port = v->session_id; cvs_set_amr_rate.hdr.dest_port = cvs_handle; cvs_set_amr_rate.hdr.token = 0; cvs_set_amr_rate.hdr.opcode = VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE; cvs_set_amr_rate.amr_rate.mode = common.mvs_info.rate; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_amr_rate); if (ret < 0) { pr_err("%s: Error %d sending SET_AMR_RATE\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } ret = voice_set_dtx(v); if (ret < 0) goto fail; break; } case VSS_MEDIA_ID_AMR_WB_MODEM: { struct cvs_set_amrwb_enc_rate_cmd cvs_set_amrwb_rate; pr_debug("Setting AMR WB rate\n"); cvs_set_amrwb_rate.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_set_amrwb_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_set_amrwb_rate) - APR_HDR_SIZE); cvs_set_amrwb_rate.hdr.src_port = v->session_id; cvs_set_amrwb_rate.hdr.dest_port = cvs_handle; cvs_set_amrwb_rate.hdr.token = 0; cvs_set_amrwb_rate.hdr.opcode = VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE; cvs_set_amrwb_rate.amrwb_rate.mode = common.mvs_info.rate; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_amrwb_rate); if (ret < 0) { pr_err("%s: Error %d sending SET_AMRWB_RATE\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } ret = voice_set_dtx(v); if (ret < 0) goto fail; break; } case VSS_MEDIA_ID_G729: case VSS_MEDIA_ID_G711_ALAW: case VSS_MEDIA_ID_G711_MULAW: { ret = voice_set_dtx(v); break; } default: /* Do nothing. */ break; } return 0; fail: return -EINVAL; } static int voice_send_start_voice_cmd(struct voice_data *v) { struct apr_hdr mvm_start_voice_cmd; int ret = 0; void *apr_mvm; u16 mvm_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); mvm_start_voice_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_start_voice_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_start_voice_cmd) - APR_HDR_SIZE); pr_debug("send mvm_start_voice_cmd pkt size = %d\n", mvm_start_voice_cmd.pkt_size); mvm_start_voice_cmd.src_port = v->session_id; mvm_start_voice_cmd.dest_port = mvm_handle; mvm_start_voice_cmd.token = 0; mvm_start_voice_cmd.opcode = VSS_IMVM_CMD_START_VOICE; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_start_voice_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IMVM_CMD_START_VOICE\n"); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_disable_vocproc_cmd(struct voice_data *v) { struct apr_hdr cvp_disable_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr regist failed\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* disable vocproc and wait for respose */ cvp_disable_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_disable_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_disable_cmd) - APR_HDR_SIZE); pr_debug("cvp_disable_cmd pkt size = %d, cvp_handle=%d\n", cvp_disable_cmd.pkt_size, cvp_handle); cvp_disable_cmd.src_port = v->session_id; cvp_disable_cmd.dest_port = cvp_handle; cvp_disable_cmd.token = 0; cvp_disable_cmd.opcode = VSS_IVOCPROC_CMD_DISABLE; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_disable_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IVOCPROC_CMD_DISABLE\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static void voc_get_tx_rx_topology(struct voice_data *v, uint32_t *tx_topology_id, uint32_t *rx_topology_id) { uint32_t tx_id = 0; uint32_t rx_id = 0; if (v->disable_topology) { tx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE; rx_id = VSS_IVOCPROC_TOPOLOGY_ID_NONE; } else { /* Use default topology if invalid value in ACDB */ tx_id = get_voice_tx_topology(); if (tx_id == 0) tx_id = VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS; rx_id = get_voice_rx_topology(); if (rx_id == 0) rx_id = VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT; } *tx_topology_id = tx_id; *rx_topology_id = rx_id; } static int voice_send_set_device_cmd(struct voice_data *v) { struct cvp_set_device_cmd cvp_setdev_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* set device and wait for response */ cvp_setdev_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_setdev_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_setdev_cmd) - APR_HDR_SIZE); pr_debug(" send create cvp setdev, pkt size = %d\n", cvp_setdev_cmd.hdr.pkt_size); cvp_setdev_cmd.hdr.src_port = v->session_id; cvp_setdev_cmd.hdr.dest_port = cvp_handle; cvp_setdev_cmd.hdr.token = 0; cvp_setdev_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE; voc_get_tx_rx_topology(v, &cvp_setdev_cmd.cvp_set_device.tx_topology_id, &cvp_setdev_cmd.cvp_set_device.rx_topology_id); cvp_setdev_cmd.cvp_set_device.tx_port_id = v->dev_tx.port_id; cvp_setdev_cmd.cvp_set_device.rx_port_id = v->dev_rx.port_id; pr_debug("topology=%d , tx_port_id=%d, rx_port_id=%d\n", cvp_setdev_cmd.cvp_set_device.tx_topology_id, cvp_setdev_cmd.cvp_set_device.tx_port_id, cvp_setdev_cmd.cvp_set_device.rx_port_id); v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd); if (ret < 0) { pr_err("Fail in sending VOCPROC_FULL_CONTROL_SESSION\n"); goto fail; } pr_debug("wait for cvp create session event\n"); ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_set_device_cmd_v2(struct voice_data *v) { struct cvp_set_device_cmd_v2 cvp_setdev_cmd_v2; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* set device and wait for response */ cvp_setdev_cmd_v2.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_setdev_cmd_v2.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_setdev_cmd_v2) - APR_HDR_SIZE); cvp_setdev_cmd_v2.hdr.src_port = v->session_id; cvp_setdev_cmd_v2.hdr.dest_port = cvp_handle; cvp_setdev_cmd_v2.hdr.token = 0; cvp_setdev_cmd_v2.hdr.opcode = VSS_IVOCPROC_CMD_SET_DEVICE_V2; voc_get_tx_rx_topology(v, &cvp_setdev_cmd_v2.cvp_set_device_v2.tx_topology_id, &cvp_setdev_cmd_v2.cvp_set_device_v2.rx_topology_id); cvp_setdev_cmd_v2.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id; cvp_setdev_cmd_v2.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id; if (common.ec_ref_ext == true) { cvp_setdev_cmd_v2.cvp_set_device_v2.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING; cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id = common.ec_port_id; } else { cvp_setdev_cmd_v2.cvp_set_device_v2.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING; cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id = VSS_IVOCPROC_PORT_ID_NONE; } pr_debug("%s:topology=%d , tx_port_id=%d, rx_port_id=%d\n" "ec_ref_port_id = %x\n", __func__, cvp_setdev_cmd_v2.cvp_set_device_v2.tx_topology_id, cvp_setdev_cmd_v2.cvp_set_device_v2.tx_port_id, cvp_setdev_cmd_v2.cvp_set_device_v2.rx_port_id, cvp_setdev_cmd_v2.cvp_set_device_v2.ec_ref_port_id); v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_setdev_cmd_v2); if (ret < 0) { pr_err("Fail in sending VOCPROC_FULL_CONTROL_SESSION\n"); goto fail; } pr_debug("wait for cvp create session event\n"); ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_stop_voice_cmd(struct voice_data *v) { struct apr_hdr mvm_stop_voice_cmd; int ret = 0; void *apr_mvm; u16 mvm_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); mvm_stop_voice_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_stop_voice_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_stop_voice_cmd) - APR_HDR_SIZE); pr_debug("send mvm_stop_voice_cmd pkt size = %d\n", mvm_stop_voice_cmd.pkt_size); mvm_stop_voice_cmd.src_port = v->session_id; mvm_stop_voice_cmd.dest_port = mvm_handle; mvm_stop_voice_cmd.token = 0; mvm_stop_voice_cmd.opcode = VSS_IMVM_CMD_STOP_VOICE; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_stop_voice_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IMVM_CMD_STOP_VOICE\n"); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvs_register_cal_cmd(struct voice_data *v) { struct cvs_register_cal_data_cmd cvs_reg_cal_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvs; u16 cvs_handle; uint32_t cal_paddr = 0; uint32_t cal_buf = 0; /* get the cvs cal data */ get_all_vocstrm_cal(&cal_block); if (cal_block.cal_size == 0) goto fail; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } if (is_volte_session(v->session_id) || is_voip_session(v->session_id)) { ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL, &cal_paddr); if (ret < 0) return ret; ret = voice_get_cal_kernel_addr(v->session_id, CVS_CAL, &cal_buf); if (ret < 0) return ret; memcpy((void *)cal_buf, (void *)cal_block.cal_kvaddr, cal_block.cal_size); } else { cal_paddr = cal_block.cal_paddr; } cvs_handle = voice_get_cvs_handle(v); /* fill in the header */ cvs_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_reg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_reg_cal_cmd) - APR_HDR_SIZE); cvs_reg_cal_cmd.hdr.src_port = v->session_id; cvs_reg_cal_cmd.hdr.dest_port = cvs_handle; cvs_reg_cal_cmd.hdr.token = 0; cvs_reg_cal_cmd.hdr.opcode = VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA; cvs_reg_cal_cmd.cvs_cal_data.phys_addr = cal_paddr; cvs_reg_cal_cmd.cvs_cal_data.mem_size = cal_block.cal_size; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_reg_cal_cmd); if (ret < 0) { pr_err("Fail: sending cvs cal,\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v) { struct cvs_deregister_cal_data_cmd cvs_dereg_cal_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvs; u16 cvs_handle; get_all_vocstrm_cal(&cal_block); if (cal_block.cal_size == 0) return 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); /* fill in the header */ cvs_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_dereg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_dereg_cal_cmd) - APR_HDR_SIZE); cvs_dereg_cal_cmd.hdr.src_port = v->session_id; cvs_dereg_cal_cmd.hdr.dest_port = cvs_handle; cvs_dereg_cal_cmd.hdr.token = 0; cvs_dereg_cal_cmd.hdr.opcode = VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_dereg_cal_cmd); if (ret < 0) { pr_err("Fail: sending cvs cal,\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_get_cal_paddr_size(struct voice_data *v, uint32_t *cal_paddr, uint32_t *cal_size) { int ret = 0; struct acdb_cal_block cal_block; /* get all cvp cal data */ get_all_cvp_cal(&cal_block); if (cal_block.cal_size == 0) goto fail; if (is_volte_session(v->session_id) || is_voip_session(v->session_id)) { ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL, cal_paddr); if (ret < 0) return ret; } else { *cal_paddr = cal_block.cal_paddr; } if (cal_size) *cal_size = cal_block.cal_size; return 0; fail: return -EINVAL; } static int voice_send_cvp_map_memory_cmd(struct voice_data *v, uint32_t paddr, uint32_t mem_size) { struct vss_map_memory_cmd cvp_map_mem_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_map_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_map_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_map_mem_cmd) - APR_HDR_SIZE); cvp_map_mem_cmd.hdr.src_port = v->session_id; cvp_map_mem_cmd.hdr.dest_port = cvp_handle; cvp_map_mem_cmd.hdr.token = 0; cvp_map_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_MAP_MEMORY; pr_debug("%s, phys_addr: 0x%x, mem_size: %d\n", __func__, paddr, mem_size); cvp_map_mem_cmd.vss_map_mem.phys_addr = paddr; cvp_map_mem_cmd.vss_map_mem.mem_size = mem_size; cvp_map_mem_cmd.vss_map_mem.mem_pool_id = VSS_ICOMMON_MAP_MEMORY_SHMEM8_4K_POOL; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_map_mem_cmd); if (ret < 0) { pr_err("Fail: mapping cvp memory,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvp_unmap_memory_cmd(struct voice_data *v, uint32_t paddr) { struct vss_unmap_memory_cmd cvp_unmap_mem_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_unmap_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_unmap_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_unmap_mem_cmd) - APR_HDR_SIZE); cvp_unmap_mem_cmd.hdr.src_port = v->session_id; cvp_unmap_mem_cmd.hdr.dest_port = cvp_handle; cvp_unmap_mem_cmd.hdr.token = 0; cvp_unmap_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_UNMAP_MEMORY; cvp_unmap_mem_cmd.vss_unmap_mem.phys_addr = paddr; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_unmap_mem_cmd); if (ret < 0) { pr_err("Fail: sending cvp cal,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvs_map_memory_cmd(struct voice_data *v) { struct vss_map_memory_cmd cvs_map_mem_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvs; u16 cvs_handle; uint32_t cal_paddr = 0; /* get all cvs cal data */ get_all_vocstrm_cal(&cal_block); if (cal_block.cal_size == 0) goto fail; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } if (is_volte_session(v->session_id) || is_voip_session(v->session_id)) { ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL, &cal_paddr); if (ret < 0) return ret; } else { cal_paddr = cal_block.cal_paddr; } cvs_handle = voice_get_cvs_handle(v); /* fill in the header */ cvs_map_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_map_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_map_mem_cmd) - APR_HDR_SIZE); cvs_map_mem_cmd.hdr.src_port = v->session_id; cvs_map_mem_cmd.hdr.dest_port = cvs_handle; cvs_map_mem_cmd.hdr.token = 0; cvs_map_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_MAP_MEMORY; pr_debug("%s, phys_addr: 0x%x, mem_size: %d\n", __func__, cal_paddr, cal_block.cal_size); cvs_map_mem_cmd.vss_map_mem.phys_addr = cal_paddr; cvs_map_mem_cmd.vss_map_mem.mem_size = cal_block.cal_size; cvs_map_mem_cmd.vss_map_mem.mem_pool_id = VSS_ICOMMON_MAP_MEMORY_SHMEM8_4K_POOL; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_map_mem_cmd); if (ret < 0) { pr_err("Fail: sending cvs cal,\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvs_unmap_memory_cmd(struct voice_data *v) { struct vss_unmap_memory_cmd cvs_unmap_mem_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvs; u16 cvs_handle; uint32_t cal_paddr = 0; get_all_vocstrm_cal(&cal_block); if (cal_block.cal_size == 0) return 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } if (is_volte_session(v->session_id) || is_voip_session(v->session_id)) { ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL, &cal_paddr); if (ret < 0) return ret; } else { cal_paddr = cal_block.cal_paddr; } cvs_handle = voice_get_cvs_handle(v); /* fill in the header */ cvs_unmap_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_unmap_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_unmap_mem_cmd) - APR_HDR_SIZE); cvs_unmap_mem_cmd.hdr.src_port = v->session_id; cvs_unmap_mem_cmd.hdr.dest_port = cvs_handle; cvs_unmap_mem_cmd.hdr.token = 0; cvs_unmap_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_UNMAP_MEMORY; cvs_unmap_mem_cmd.vss_unmap_mem.phys_addr = cal_paddr; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_unmap_mem_cmd); if (ret < 0) { pr_err("Fail: sending cvs cal,\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvp_register_cal_cmd(struct voice_data *v) { struct cvp_register_cal_data_cmd cvp_reg_cal_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvp; u16 cvp_handle; uint32_t cal_paddr = 0; uint32_t cal_buf = 0; /* get the cvp cal data */ get_all_vocproc_cal(&cal_block); if (cal_block.cal_size == 0) goto fail; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } if (is_volte_session(v->session_id) || is_voip_session(v->session_id)) { ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL, &cal_paddr); if (ret < 0) return ret; ret = voice_get_cal_kernel_addr(v->session_id, CVP_CAL, &cal_buf); if (ret < 0) return ret; memcpy((void *)cal_buf, (void *)cal_block.cal_kvaddr, cal_block.cal_size); } else { cal_paddr = cal_block.cal_paddr; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_reg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_reg_cal_cmd) - APR_HDR_SIZE); cvp_reg_cal_cmd.hdr.src_port = v->session_id; cvp_reg_cal_cmd.hdr.dest_port = cvp_handle; cvp_reg_cal_cmd.hdr.token = 0; cvp_reg_cal_cmd.hdr.opcode = VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA; cvp_reg_cal_cmd.cvp_cal_data.phys_addr = cal_paddr; cvp_reg_cal_cmd.cvp_cal_data.mem_size = cal_block.cal_size; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_reg_cal_cmd); if (ret < 0) { pr_err("Fail: sending cvp cal,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v) { struct cvp_deregister_cal_data_cmd cvp_dereg_cal_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvp; u16 cvp_handle; get_all_vocproc_cal(&cal_block); if (cal_block.cal_size == 0) return 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_dereg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_dereg_cal_cmd) - APR_HDR_SIZE); cvp_dereg_cal_cmd.hdr.src_port = v->session_id; cvp_dereg_cal_cmd.hdr.dest_port = cvp_handle; cvp_dereg_cal_cmd.hdr.token = 0; cvp_dereg_cal_cmd.hdr.opcode = VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_dereg_cal_cmd); if (ret < 0) { pr_err("Fail: sending cvp cal,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvp_register_vol_cal_table_cmd(struct voice_data *v) { struct cvp_register_vol_cal_table_cmd cvp_reg_cal_tbl_cmd; struct acdb_cal_block vol_block; struct acdb_cal_block voc_block; int ret = 0; void *apr_cvp; u16 cvp_handle; uint32_t cal_paddr = 0; uint32_t cal_buf = 0; /* get the cvp vol cal data */ get_all_vocvol_cal(&vol_block); get_all_vocproc_cal(&voc_block); if (vol_block.cal_size == 0) goto fail; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } if (is_volte_session(v->session_id) || is_voip_session(v->session_id)) { ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL, &cal_paddr); if (ret < 0) return ret; cal_paddr += voc_block.cal_size; ret = voice_get_cal_kernel_addr(v->session_id, CVP_CAL, &cal_buf); if (ret < 0) return ret; memcpy((void *)(cal_buf + voc_block.cal_size), (void *)vol_block.cal_kvaddr, vol_block.cal_size); } else { cal_paddr = vol_block.cal_paddr; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_reg_cal_tbl_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_reg_cal_tbl_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_reg_cal_tbl_cmd) - APR_HDR_SIZE); cvp_reg_cal_tbl_cmd.hdr.src_port = v->session_id; cvp_reg_cal_tbl_cmd.hdr.dest_port = cvp_handle; cvp_reg_cal_tbl_cmd.hdr.token = 0; cvp_reg_cal_tbl_cmd.hdr.opcode = VSS_IVOCPROC_CMD_REGISTER_VOLUME_CAL_TABLE; cvp_reg_cal_tbl_cmd.cvp_vol_cal_tbl.phys_addr = cal_paddr; cvp_reg_cal_tbl_cmd.cvp_vol_cal_tbl.mem_size = vol_block.cal_size; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_reg_cal_tbl_cmd); if (ret < 0) { pr_err("Fail: sending cvp cal table,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_cvp_deregister_vol_cal_table_cmd(struct voice_data *v) { struct cvp_deregister_vol_cal_table_cmd cvp_dereg_cal_tbl_cmd; struct acdb_cal_block cal_block; int ret = 0; void *apr_cvp; u16 cvp_handle; get_all_vocvol_cal(&cal_block); if (cal_block.cal_size == 0) return 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_dereg_cal_tbl_cmd.hdr.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_dereg_cal_tbl_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_dereg_cal_tbl_cmd) - APR_HDR_SIZE); cvp_dereg_cal_tbl_cmd.hdr.src_port = v->session_id; cvp_dereg_cal_tbl_cmd.hdr.dest_port = cvp_handle; cvp_dereg_cal_tbl_cmd.hdr.token = 0; cvp_dereg_cal_tbl_cmd.hdr.opcode = VSS_IVOCPROC_CMD_DEREGISTER_VOLUME_CAL_TABLE; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_dereg_cal_tbl_cmd); if (ret < 0) { pr_err("Fail: sending cvp cal table,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_set_widevoice_enable_cmd(struct voice_data *v) { struct mvm_set_widevoice_enable_cmd mvm_set_wv_cmd; int ret = 0; void *apr_mvm; u16 mvm_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); /* fill in the header */ mvm_set_wv_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_set_wv_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_set_wv_cmd) - APR_HDR_SIZE); mvm_set_wv_cmd.hdr.src_port = v->session_id; mvm_set_wv_cmd.hdr.dest_port = mvm_handle; mvm_set_wv_cmd.hdr.token = 0; mvm_set_wv_cmd.hdr.opcode = VSS_IWIDEVOICE_CMD_SET_WIDEVOICE; mvm_set_wv_cmd.vss_set_wv.enable = v->wv_enable; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_wv_cmd); if (ret < 0) { pr_err("Fail: sending mvm set widevoice enable,\n"); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_set_pp_enable_cmd(struct voice_data *v, uint32_t module_id, int enable) { struct cvs_set_pp_enable_cmd cvs_set_pp_cmd; int ret = 0; void *apr_cvs; u16 cvs_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); /* fill in the header */ cvs_set_pp_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_set_pp_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_set_pp_cmd) - APR_HDR_SIZE); cvs_set_pp_cmd.hdr.src_port = v->session_id; cvs_set_pp_cmd.hdr.dest_port = cvs_handle; cvs_set_pp_cmd.hdr.token = 0; cvs_set_pp_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_UI_PROPERTY; cvs_set_pp_cmd.vss_set_pp.module_id = module_id; cvs_set_pp_cmd.vss_set_pp.param_id = VOICE_PARAM_MOD_ENABLE; cvs_set_pp_cmd.vss_set_pp.param_size = MOD_ENABLE_PARAM_LEN; cvs_set_pp_cmd.vss_set_pp.reserved = 0; cvs_set_pp_cmd.vss_set_pp.enable = enable; cvs_set_pp_cmd.vss_set_pp.reserved_field = 0; pr_debug("voice_send_set_pp_enable_cmd, module_id=%d, enable=%d\n", module_id, enable); v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_pp_cmd); if (ret < 0) { pr_err("Fail: sending cvs set slowtalk enable,\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_setup_vocproc(struct voice_data *v) { struct cvp_create_full_ctl_session_cmd cvp_session_cmd; int ret = 0; void *apr_cvp; uint32_t cal_paddr = 0; uint32_t cal_size = 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } /* create cvp session and wait for response */ cvp_session_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_session_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_session_cmd) - APR_HDR_SIZE); pr_debug(" send create cvp session, pkt size = %d\n", cvp_session_cmd.hdr.pkt_size); cvp_session_cmd.hdr.src_port = v->session_id; cvp_session_cmd.hdr.dest_port = 0; cvp_session_cmd.hdr.token = 0; cvp_session_cmd.hdr.opcode = VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION; voc_get_tx_rx_topology(v, &cvp_session_cmd.cvp_session.tx_topology_id, &cvp_session_cmd.cvp_session.rx_topology_id); cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/ cvp_session_cmd.cvp_session.network_id = VSS_NETWORK_ID_DEFAULT; cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id; cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.port_id; pr_debug("topology=%d net_id=%d, dir=%d tx_port_id=%d, rx_port_id=%d\n", cvp_session_cmd.cvp_session.tx_topology_id, cvp_session_cmd.cvp_session.network_id, cvp_session_cmd.cvp_session.direction, cvp_session_cmd.cvp_session.tx_port_id, cvp_session_cmd.cvp_session.rx_port_id); v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_session_cmd); if (ret < 0) { pr_err("Fail in sending VOCPROC_FULL_CONTROL_SESSION\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } if (common.ec_ref_ext == true) { ret = voice_send_set_device_cmd_v2(v); if (ret < 0) pr_err("%s: set device V2 failed rc =%x\n", __func__, ret); goto fail; } /* send cvs cal */ ret = voice_send_cvs_map_memory_cmd(v); if (!ret) voice_send_cvs_register_cal_cmd(v); /* send cvp and vol cal */ if (!voice_get_cal_paddr_size(v, &cal_paddr, &cal_size) && !voice_send_cvp_map_memory_cmd(v, cal_paddr, cal_size)) { voice_send_cvp_register_cal_cmd(v); voice_send_cvp_register_vol_cal_table_cmd(v); } /* enable vocproc */ ret = voice_send_enable_vocproc_cmd(v); if (ret < 0) goto fail; /* attach vocproc */ ret = voice_send_attach_vocproc_cmd(v); if (ret < 0) goto fail; /* send tty mode if tty device is used */ voice_send_tty_mode_cmd(v); /* enable widevoice if wv_enable is set */ if (v->wv_enable) voice_send_set_widevoice_enable_cmd(v); /* enable slowtalk if st_enable is set */ if (v->st_enable) voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_ST, v->st_enable); voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_FENS, v->fens_enable); if (is_voip_session(v->session_id)) voice_send_netid_timing_cmd(v); /* Start in-call music delivery if this feature is enabled */ if (v->music_info.play_enable) voice_cvs_start_playback(v); /* Start in-call recording if this feature is enabled */ if (v->rec_info.rec_enable) voice_cvs_start_record(v, v->rec_info.rec_mode); if (v->dtmf_rx_detect_en) voice_send_dtmf_rx_detection_cmd(v, v->dtmf_rx_detect_en); rtac_add_voice(voice_get_cvs_handle(v), voice_get_cvp_handle(v), v->dev_rx.port_id, v->dev_tx.port_id, v->session_id); return 0; fail: return -EINVAL; } static int voice_send_enable_vocproc_cmd(struct voice_data *v) { int ret = 0; struct apr_hdr cvp_enable_cmd; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* enable vocproc and wait for respose */ cvp_enable_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_enable_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_enable_cmd) - APR_HDR_SIZE); pr_debug("cvp_enable_cmd pkt size = %d, cvp_handle=%d\n", cvp_enable_cmd.pkt_size, cvp_handle); cvp_enable_cmd.src_port = v->session_id; cvp_enable_cmd.dest_port = cvp_handle; cvp_enable_cmd.token = 0; cvp_enable_cmd.opcode = VSS_IVOCPROC_CMD_ENABLE; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_enable_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IVOCPROC_CMD_ENABLE\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_netid_timing_cmd(struct voice_data *v) { int ret = 0; void *apr_mvm; u16 mvm_handle; struct mvm_set_network_cmd mvm_set_network; struct mvm_set_voice_timing_cmd mvm_set_voice_timing; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); ret = voice_config_cvs_vocoder(v); if (ret < 0) { pr_err("%s: Error %d configuring CVS voc", __func__, ret); goto fail; } /* Set network ID. */ pr_debug("Setting network ID\n"); mvm_set_network.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_set_network.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_set_network) - APR_HDR_SIZE); mvm_set_network.hdr.src_port = v->session_id; mvm_set_network.hdr.dest_port = mvm_handle; mvm_set_network.hdr.token = 0; mvm_set_network.hdr.opcode = VSS_ICOMMON_CMD_SET_NETWORK; mvm_set_network.network.network_id = common.mvs_info.network_type; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_network); if (ret < 0) { pr_err("%s: Error %d sending SET_NETWORK\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } /* Set voice timing. */ pr_debug("Setting voice timing\n"); mvm_set_voice_timing.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_set_voice_timing.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_set_voice_timing) - APR_HDR_SIZE); mvm_set_voice_timing.hdr.src_port = v->session_id; mvm_set_voice_timing.hdr.dest_port = mvm_handle; mvm_set_voice_timing.hdr.token = 0; mvm_set_voice_timing.hdr.opcode = VSS_ICOMMON_CMD_SET_VOICE_TIMING; mvm_set_voice_timing.timing.mode = 0; mvm_set_voice_timing.timing.enc_offset = 8000; mvm_set_voice_timing.timing.dec_req_offset = 3300; mvm_set_voice_timing.timing.dec_offset = 8300; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_voice_timing); if (ret < 0) { pr_err("%s: Error %d sending SET_TIMING\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_send_attach_vocproc_cmd(struct voice_data *v) { int ret = 0; struct mvm_attach_vocproc_cmd mvm_a_vocproc_cmd; void *apr_mvm; u16 mvm_handle, cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); cvp_handle = voice_get_cvp_handle(v); /* attach vocproc and wait for response */ mvm_a_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_a_vocproc_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_a_vocproc_cmd) - APR_HDR_SIZE); pr_debug("send mvm_a_vocproc_cmd pkt size = %d\n", mvm_a_vocproc_cmd.hdr.pkt_size); mvm_a_vocproc_cmd.hdr.src_port = v->session_id; mvm_a_vocproc_cmd.hdr.dest_port = mvm_handle; mvm_a_vocproc_cmd.hdr.token = 0; mvm_a_vocproc_cmd.hdr.opcode = VSS_IMVM_CMD_ATTACH_VOCPROC; mvm_a_vocproc_cmd.mvm_attach_cvp_handle.handle = cvp_handle; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_a_vocproc_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IMVM_CMD_ATTACH_VOCPROC\n"); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } static int voice_destroy_vocproc(struct voice_data *v) { struct mvm_detach_vocproc_cmd mvm_d_vocproc_cmd; struct apr_hdr cvp_destroy_session_cmd; int ret = 0; void *apr_mvm, *apr_cvp; u16 mvm_handle, cvp_handle; uint32_t paddr = 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; apr_cvp = common.apr_q6_cvp; if (!apr_mvm || !apr_cvp) { pr_err("%s: apr_mvm or apr_cvp is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); cvp_handle = voice_get_cvp_handle(v); /* stop playback or recording */ v->music_info.force = 1; voice_cvs_stop_playback(v); voice_cvs_stop_record(v); /* send stop voice cmd */ voice_send_stop_voice_cmd(v); /* send stop dtmf detecton cmd */ if (v->dtmf_rx_detect_en) voice_send_dtmf_rx_detection_cmd(v, 0); /* Clear mute setting */ v->dev_tx.mute = common.default_mute_val; /* clear disable topology setting */ v->disable_topology = false; /* detach VOCPROC and wait for response from mvm */ mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_d_vocproc_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_d_vocproc_cmd) - APR_HDR_SIZE); pr_debug("mvm_d_vocproc_cmd pkt size = %d\n", mvm_d_vocproc_cmd.hdr.pkt_size); mvm_d_vocproc_cmd.hdr.src_port = v->session_id; mvm_d_vocproc_cmd.hdr.dest_port = mvm_handle; mvm_d_vocproc_cmd.hdr.token = 0; mvm_d_vocproc_cmd.hdr.opcode = VSS_IMVM_CMD_DETACH_VOCPROC; mvm_d_vocproc_cmd.mvm_detach_cvp_handle.handle = cvp_handle; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_d_vocproc_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IMVM_CMD_DETACH_VOCPROC\n"); goto fail; } ret = wait_event_timeout(v->mvm_wait, (v->mvm_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } /* deregister cvp and vol cal */ voice_send_cvp_deregister_vol_cal_table_cmd(v); voice_send_cvp_deregister_cal_cmd(v); if (!voice_get_cal_paddr_size(v, &paddr, NULL)) voice_send_cvp_unmap_memory_cmd(v, paddr); /* deregister cvs cal */ voice_send_cvs_deregister_cal_cmd(v); voice_send_cvs_unmap_memory_cmd(v); /* destrop cvp session */ cvp_destroy_session_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_destroy_session_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_destroy_session_cmd) - APR_HDR_SIZE); pr_debug("cvp_destroy_session_cmd pkt size = %d\n", cvp_destroy_session_cmd.pkt_size); cvp_destroy_session_cmd.src_port = v->session_id; cvp_destroy_session_cmd.dest_port = cvp_handle; cvp_destroy_session_cmd.token = 0; cvp_destroy_session_cmd.opcode = APRV2_IBASIC_CMD_DESTROY_SESSION; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_destroy_session_cmd); if (ret < 0) { pr_err("Fail in sending APRV2_IBASIC_CMD_DESTROY_SESSION\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } rtac_remove_voice(voice_get_cvs_handle(v)); cvp_handle = 0; voice_set_cvp_handle(v, cvp_handle); return 0; fail: return -EINVAL; } static int voice_send_mute_cmd(struct voice_data *v) { struct cvs_set_mute_cmd cvs_mute_cmd; int ret = 0; void *apr_cvs; u16 cvs_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); /* send mute/unmute to cvs */ cvs_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_mute_cmd) - APR_HDR_SIZE); cvs_mute_cmd.hdr.src_port = v->session_id; cvs_mute_cmd.hdr.dest_port = cvs_handle; cvs_mute_cmd.hdr.token = 0; cvs_mute_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_MUTE; cvs_mute_cmd.cvs_set_mute.direction = 0; /*tx*/ cvs_mute_cmd.cvs_set_mute.mute_flag = v->dev_tx.mute; pr_info(" mute value =%d\n", cvs_mute_cmd.cvs_set_mute.mute_flag); v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_mute_cmd); if (ret < 0) { pr_err("Fail: send STREAM SET MUTE\n"); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) pr_err("%s: wait_event timeout\n", __func__); return 0; fail: return -EINVAL; } static int voice_send_rx_device_mute_cmd(struct voice_data *v) { struct cvp_set_mute_cmd cvp_mute_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); cvp_mute_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_mute_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_mute_cmd) - APR_HDR_SIZE); cvp_mute_cmd.hdr.src_port = v->session_id; cvp_mute_cmd.hdr.dest_port = cvp_handle; cvp_mute_cmd.hdr.token = 0; cvp_mute_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_MUTE; cvp_mute_cmd.cvp_set_mute.direction = 1; cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_mute_cmd); if (ret < 0) { pr_err("Fail in sending RX device mute cmd\n"); return -EINVAL; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); return -EINVAL; } return 0; } static int voice_send_vol_index_cmd(struct voice_data *v) { struct cvp_set_rx_volume_index_cmd cvp_vol_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* send volume index to cvp */ cvp_vol_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_vol_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvp_vol_cmd) - APR_HDR_SIZE); cvp_vol_cmd.hdr.src_port = v->session_id; cvp_vol_cmd.hdr.dest_port = cvp_handle; cvp_vol_cmd.hdr.token = 0; cvp_vol_cmd.hdr.opcode = VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX; cvp_vol_cmd.cvp_set_vol_idx.vol_index = v->dev_rx.volume; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_vol_cmd); if (ret < 0) { pr_err("Fail in sending RX VOL INDEX\n"); return -EINVAL; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); return -EINVAL; } return 0; } static int voice_cvs_start_record(struct voice_data *v, uint32_t rec_mode) { int ret = 0; void *apr_cvs; u16 cvs_handle; struct cvs_start_record_cmd cvs_start_record; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); if (!v->rec_info.recording) { cvs_start_record.hdr.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_start_record.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_start_record) - APR_HDR_SIZE); cvs_start_record.hdr.src_port = v->session_id; cvs_start_record.hdr.dest_port = cvs_handle; cvs_start_record.hdr.token = 0; cvs_start_record.hdr.opcode = VSS_ISTREAM_CMD_START_RECORD; if (rec_mode == VOC_REC_UPLINK) { cvs_start_record.rec_mode.rx_tap_point = VSS_TAP_POINT_NONE; cvs_start_record.rec_mode.tx_tap_point = VSS_TAP_POINT_STREAM_END; } else if (rec_mode == VOC_REC_DOWNLINK) { cvs_start_record.rec_mode.rx_tap_point = VSS_TAP_POINT_STREAM_END; cvs_start_record.rec_mode.tx_tap_point = VSS_TAP_POINT_NONE; } else if (rec_mode == VOC_REC_BOTH) { cvs_start_record.rec_mode.rx_tap_point = VSS_TAP_POINT_STREAM_END; cvs_start_record.rec_mode.tx_tap_point = VSS_TAP_POINT_STREAM_END; } else { pr_err("%s: Invalid in-call rec_mode %d\n", __func__, rec_mode); ret = -EINVAL; goto fail; } v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_record); if (ret < 0) { pr_err("%s: Error %d sending START_RECORD\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } v->rec_info.recording = 1; } else { pr_debug("%s: Start record already sent\n", __func__); } return 0; fail: return ret; } static int voice_cvs_stop_record(struct voice_data *v) { int ret = 0; void *apr_cvs; u16 cvs_handle; struct apr_hdr cvs_stop_record; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); if (v->rec_info.recording) { cvs_stop_record.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_stop_record.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_stop_record) - APR_HDR_SIZE); cvs_stop_record.src_port = v->session_id; cvs_stop_record.dest_port = cvs_handle; cvs_stop_record.token = 0; cvs_stop_record.opcode = VSS_ISTREAM_CMD_STOP_RECORD; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_stop_record); if (ret < 0) { pr_err("%s: Error %d sending STOP_RECORD\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } v->rec_info.recording = 0; } else { pr_debug("%s: Stop record already sent\n", __func__); } return 0; fail: return ret; } int voc_start_record(uint32_t port_id, uint32_t set) { int ret = 0; int rec_mode = 0; u16 cvs_handle; int i, rec_set = 0; for (i = 0; i < MAX_VOC_SESSIONS; i++) { struct voice_data *v = &common.voice[i]; pr_debug("%s: i:%d port_id: %d, set: %d\n", __func__, i, port_id, set); mutex_lock(&v->lock); rec_mode = v->rec_info.rec_mode; rec_set = set; if (set) { if ((v->rec_route_state.ul_flag != 0) && (v->rec_route_state.dl_flag != 0)) { pr_debug("%s: i=%d, rec mode already set.\n", __func__, i); mutex_unlock(&v->lock); if (i < MAX_VOC_SESSIONS) continue; else return 0; } if (port_id == VOICE_RECORD_TX) { if ((v->rec_route_state.ul_flag == 0) && (v->rec_route_state.dl_flag == 0)) { rec_mode = VOC_REC_UPLINK; v->rec_route_state.ul_flag = 1; } else if ((v->rec_route_state.ul_flag == 0) && (v->rec_route_state.dl_flag != 0)) { voice_cvs_stop_record(v); rec_mode = VOC_REC_BOTH; v->rec_route_state.ul_flag = 1; } } else if (port_id == VOICE_RECORD_RX) { if ((v->rec_route_state.ul_flag == 0) && (v->rec_route_state.dl_flag == 0)) { rec_mode = VOC_REC_DOWNLINK; v->rec_route_state.dl_flag = 1; } else if ((v->rec_route_state.ul_flag != 0) && (v->rec_route_state.dl_flag == 0)) { voice_cvs_stop_record(v); rec_mode = VOC_REC_BOTH; v->rec_route_state.dl_flag = 1; } } rec_set = 1; } else { if ((v->rec_route_state.ul_flag == 0) && (v->rec_route_state.dl_flag == 0)) { pr_debug("%s: i=%d, rec already stops.\n", __func__, i); mutex_unlock(&v->lock); if (i < MAX_VOC_SESSIONS) continue; else return 0; } if (port_id == VOICE_RECORD_TX) { if ((v->rec_route_state.ul_flag != 0) && (v->rec_route_state.dl_flag == 0)) { v->rec_route_state.ul_flag = 0; rec_set = 0; } else if ((v->rec_route_state.ul_flag != 0) && (v->rec_route_state.dl_flag != 0)) { voice_cvs_stop_record(v); v->rec_route_state.ul_flag = 0; rec_mode = VOC_REC_DOWNLINK; rec_set = 1; } } else if (port_id == VOICE_RECORD_RX) { if ((v->rec_route_state.ul_flag == 0) && (v->rec_route_state.dl_flag != 0)) { v->rec_route_state.dl_flag = 0; rec_set = 0; } else if ((v->rec_route_state.ul_flag != 0) && (v->rec_route_state.dl_flag != 0)) { voice_cvs_stop_record(v); v->rec_route_state.dl_flag = 0; rec_mode = VOC_REC_UPLINK; rec_set = 1; } } } pr_debug("%s: i=%d, mode =%d, set =%d\n", __func__, i, rec_mode, rec_set); cvs_handle = voice_get_cvs_handle(v); if (cvs_handle != 0) { if (rec_set) ret = voice_cvs_start_record(v, rec_mode); else ret = voice_cvs_stop_record(v); } /* Cache the value */ v->rec_info.rec_enable = rec_set; v->rec_info.rec_mode = rec_mode; mutex_unlock(&v->lock); } return ret; } static int voice_cvs_start_playback(struct voice_data *v) { int ret = 0; struct apr_hdr cvs_start_playback; void *apr_cvs; u16 cvs_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); if (!v->music_info.playing && v->music_info.count) { cvs_start_playback.hdr_field = APR_HDR_FIELD( APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_start_playback.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_start_playback) - APR_HDR_SIZE); cvs_start_playback.src_port = v->session_id; cvs_start_playback.dest_port = cvs_handle; cvs_start_playback.token = 0; cvs_start_playback.opcode = VSS_ISTREAM_CMD_START_PLAYBACK; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_start_playback); if (ret < 0) { pr_err("%s: Error %d sending START_PLAYBACK\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } v->music_info.playing = 1; } else { pr_debug("%s: Start playback already sent\n", __func__); } return 0; fail: return ret; } static int voice_cvs_stop_playback(struct voice_data *v) { int ret = 0; struct apr_hdr cvs_stop_playback; void *apr_cvs; u16 cvs_handle; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvs = common.apr_q6_cvs; if (!apr_cvs) { pr_err("%s: apr_cvs is NULL.\n", __func__); return -EINVAL; } cvs_handle = voice_get_cvs_handle(v); if (v->music_info.playing && ((!v->music_info.count) || (v->music_info.force))) { cvs_stop_playback.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvs_stop_playback.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(cvs_stop_playback) - APR_HDR_SIZE); cvs_stop_playback.src_port = v->session_id; cvs_stop_playback.dest_port = cvs_handle; cvs_stop_playback.token = 0; cvs_stop_playback.opcode = VSS_ISTREAM_CMD_STOP_PLAYBACK; v->cvs_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_stop_playback); if (ret < 0) { pr_err("%s: Error %d sending STOP_PLAYBACK\n", __func__, ret); goto fail; } ret = wait_event_timeout(v->cvs_wait, (v->cvs_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } v->music_info.playing = 0; v->music_info.force = 0; } else { pr_debug("%s: Stop playback already sent\n", __func__); } return 0; fail: return ret; } int voc_start_playback(uint32_t set) { int ret = 0; u16 cvs_handle; int i; for (i = 0; i < MAX_VOC_SESSIONS; i++) { struct voice_data *v = &common.voice[i]; mutex_lock(&v->lock); v->music_info.play_enable = set; if (set) v->music_info.count++; else v->music_info.count--; pr_debug("%s: music_info count =%d\n", __func__, v->music_info.count); cvs_handle = voice_get_cvs_handle(v); if (cvs_handle != 0) { if (set) ret = voice_cvs_start_playback(v); else ret = voice_cvs_stop_playback(v); } mutex_unlock(&v->lock); } return ret; } int voc_disable_cvp(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); uint32_t paddr = 0; int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); if (v->voc_state == VOC_RUN) { if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX && v->dev_rx.port_id != RT_PROXY_PORT_001_RX) afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id, 0, 0); rtac_remove_voice(voice_get_cvs_handle(v)); /* send cmd to dsp to disable vocproc */ ret = voice_send_disable_vocproc_cmd(v); if (ret < 0) { pr_err("%s: disable vocproc failed\n", __func__); goto fail; } /* deregister cvp and vol cal */ voice_send_cvp_deregister_vol_cal_table_cmd(v); voice_send_cvp_deregister_cal_cmd(v); voice_get_cal_paddr_size(v, &paddr, NULL); voice_send_cvp_unmap_memory_cmd(v, paddr); if (common.ec_ref_ext == true) voc_set_ext_ec_ref(AFE_PORT_INVALID, false); v->voc_state = VOC_CHANGE; } fail: mutex_unlock(&v->lock); return ret; } int voc_enable_cvp(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); struct sidetone_cal sidetone_cal_data; uint32_t cal_paddr = 0; uint32_t cal_size = 0; int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); if (v->voc_state == VOC_CHANGE) { if (common.ec_ref_ext == true) { ret = voice_send_set_device_cmd_v2(v); if (ret < 0) pr_err("%s: set device V2 failed\n" "rc =%x\n", __func__, ret); goto fail; } else { ret = voice_send_set_device_cmd(v); if (ret < 0) { pr_err("%s: set device failed rc=%x\n", __func__, ret); goto fail; } } /* send cvp and vol cal */ if (!voice_get_cal_paddr_size(v, &cal_paddr, &cal_size) && !voice_send_cvp_map_memory_cmd(v, cal_paddr, cal_size)) { voice_send_cvp_register_cal_cmd(v); voice_send_cvp_register_vol_cal_table_cmd(v); } ret = voice_send_enable_vocproc_cmd(v); if (ret < 0) { pr_err("%s: enable vocproc failed\n", __func__); goto fail; } /* send tty mode if tty device is used */ voice_send_tty_mode_cmd(v); /* enable widevoice if wv_enable is set */ if (v->wv_enable) voice_send_set_widevoice_enable_cmd(v); /* enable slowtalk */ if (v->st_enable) voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_ST, v->st_enable); /* enable FENS */ if (v->fens_enable) voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_FENS, v->fens_enable); get_sidetone_cal(&sidetone_cal_data); if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX && v->dev_rx.port_id != RT_PROXY_PORT_001_RX) { ret = afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id, sidetone_cal_data.enable, sidetone_cal_data.gain); if (ret < 0) pr_err("%s: AFE command sidetone failed\n", __func__); } rtac_add_voice(voice_get_cvs_handle(v), voice_get_cvp_handle(v), v->dev_rx.port_id, v->dev_tx.port_id, v->session_id); v->voc_state = VOC_RUN; } fail: mutex_unlock(&v->lock); return ret; } int voc_disable_topology(uint16_t session_id, uint32_t disable) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->disable_topology = disable; mutex_unlock(&v->lock); return ret; } int voc_set_tx_mute(uint16_t session_id, uint32_t dir, uint32_t mute) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->dev_tx.mute = mute; if ((v->voc_state == VOC_RUN) || (v->voc_state == VOC_CHANGE) || (v->voc_state == VOC_STANDBY)) ret = voice_send_mute_cmd(v); mutex_unlock(&v->lock); return ret; } int voc_set_rx_device_mute(uint16_t session_id, uint32_t mute) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->dev_rx.mute = mute; if (v->voc_state == VOC_RUN) ret = voice_send_rx_device_mute_cmd(v); mutex_unlock(&v->lock); return ret; } int voc_get_rx_device_mute(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); ret = v->dev_rx.mute; mutex_unlock(&v->lock); return ret; } int voc_set_tty_mode(uint16_t session_id, uint8_t tty_mode) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->tty_mode = tty_mode; mutex_unlock(&v->lock); return ret; } uint8_t voc_get_tty_mode(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); ret = v->tty_mode; mutex_unlock(&v->lock); return ret; } int voc_set_widevoice_enable(uint16_t session_id, uint32_t wv_enable) { struct voice_data *v = voice_get_session(session_id); u16 mvm_handle; int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->wv_enable = wv_enable; mvm_handle = voice_get_mvm_handle(v); if (mvm_handle != 0) voice_send_set_widevoice_enable_cmd(v); mutex_unlock(&v->lock); return ret; } uint32_t voc_get_widevoice_enable(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); ret = v->wv_enable; mutex_unlock(&v->lock); return ret; } int voc_set_pp_enable(uint16_t session_id, uint32_t module_id, uint32_t enable) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); if (module_id == MODULE_ID_VOICE_MODULE_ST) v->st_enable = enable; else if (module_id == MODULE_ID_VOICE_MODULE_FENS) v->fens_enable = enable; if (v->voc_state == VOC_RUN) { if (module_id == MODULE_ID_VOICE_MODULE_ST) ret = voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_ST, enable); else if (module_id == MODULE_ID_VOICE_MODULE_FENS) ret = voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_FENS, enable); } mutex_unlock(&v->lock); return ret; } int voc_get_pp_enable(uint16_t session_id, uint32_t module_id) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); if (module_id == MODULE_ID_VOICE_MODULE_ST) ret = v->st_enable; else if (module_id == MODULE_ID_VOICE_MODULE_FENS) ret = v->fens_enable; mutex_unlock(&v->lock); return ret; } int voc_set_rx_vol_index(uint16_t session_id, uint32_t dir, uint32_t vol_idx) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); v->dev_rx.volume = vol_idx; if ((v->voc_state == VOC_RUN) || (v->voc_state == VOC_CHANGE) || (v->voc_state == VOC_STANDBY)) ret = voice_send_vol_index_cmd(v); mutex_unlock(&v->lock); return ret; } int voc_set_rxtx_port(uint16_t session_id, uint32_t port_id, uint32_t dev_type) { struct voice_data *v = voice_get_session(session_id); if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } pr_debug("%s: port_id=%d, type=%d\n", __func__, port_id, dev_type); mutex_lock(&v->lock); if (dev_type == DEV_RX) v->dev_rx.port_id = port_id; else v->dev_tx.port_id = port_id; mutex_unlock(&v->lock); return 0; } int voc_set_route_flag(uint16_t session_id, uint8_t path_dir, uint8_t set) { struct voice_data *v = voice_get_session(session_id); if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } pr_debug("%s: path_dir=%d, set=%d\n", __func__, path_dir, set); mutex_lock(&v->lock); if (path_dir == RX_PATH) v->voc_route_state.rx_route_flag = set; else v->voc_route_state.tx_route_flag = set; mutex_unlock(&v->lock); return 0; } uint8_t voc_get_route_flag(uint16_t session_id, uint8_t path_dir) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return 0; } mutex_lock(&v->lock); if (path_dir == RX_PATH) ret = v->voc_route_state.rx_route_flag; else ret = v->voc_route_state.tx_route_flag; mutex_unlock(&v->lock); return ret; } int voc_end_voice_call(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); if (v->voc_state == VOC_RUN || v->voc_state == VOC_STANDBY) { if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX && v->dev_rx.port_id != RT_PROXY_PORT_001_RX) afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id, 0, 0); ret = voice_destroy_vocproc(v); if (ret < 0) pr_err("%s: destroy voice failed\n", __func__); voice_destroy_mvm_cvs_session(v); if (common.ec_ref_ext == true) voc_set_ext_ec_ref(AFE_PORT_INVALID, false); v->voc_state = VOC_RELEASE; } mutex_unlock(&v->lock); return ret; } int voc_resume_voice_call(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); struct apr_hdr mvm_start_voice_cmd; int ret = 0; void *apr_mvm; u16 mvm_handle; pr_debug("%s:\n", __func__); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); return -EINVAL; } mvm_handle = voice_get_mvm_handle(v); mvm_start_voice_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_start_voice_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_start_voice_cmd) - APR_HDR_SIZE); pr_debug("send mvm_start_voice_cmd pkt size = %d\n", mvm_start_voice_cmd.pkt_size); mvm_start_voice_cmd.src_port = v->session_id; mvm_start_voice_cmd.dest_port = mvm_handle; mvm_start_voice_cmd.token = 0; mvm_start_voice_cmd.opcode = VSS_IMVM_CMD_START_VOICE; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_start_voice_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IMVM_CMD_START_VOICE\n"); goto fail; } v->voc_state = VOC_RUN; return 0; fail: return -EINVAL; } int voc_start_voice_call(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); struct sidetone_cal sidetone_cal_data; int ret = 0; if (v == NULL) { pr_err("%s: invalid session_id 0x%x\n", __func__, session_id); return -EINVAL; } mutex_lock(&v->lock); if ((v->voc_state == VOC_INIT) || (v->voc_state == VOC_RELEASE)) { ret = voice_apr_register(); if (ret < 0) { pr_err("%s: apr register failed\n", __func__); goto fail; } ret = voice_create_mvm_cvs_session(v); if (ret < 0) { pr_err("create mvm and cvs failed\n"); goto fail; } ret = voice_send_dual_control_cmd(v); if (ret < 0) { pr_err("Err Dual command failed\n"); goto fail; } ret = voice_setup_vocproc(v); if (ret < 0) { pr_err("setup voice failed\n"); goto fail; } ret = voice_send_vol_index_cmd(v); if (ret < 0) pr_err("voice volume failed\n"); ret = voice_send_mute_cmd(v); if (ret < 0) pr_err("voice mute failed\n"); ret = voice_send_start_voice_cmd(v); if (ret < 0) { pr_err("start voice failed\n"); goto fail; } get_sidetone_cal(&sidetone_cal_data); if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX && v->dev_rx.port_id != RT_PROXY_PORT_001_RX) { ret = afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id, sidetone_cal_data.enable, sidetone_cal_data.gain); if (ret < 0) pr_err("AFE command sidetone failed\n"); } v->voc_state = VOC_RUN; } else if (v->voc_state == VOC_STANDBY) { pr_err("Error: PCM Prepare when in Standby\n"); ret = -EINVAL; goto fail; } fail: mutex_unlock(&v->lock); return ret; } int voc_standby_voice_call(uint16_t session_id) { struct voice_data *v = voice_get_session(session_id); struct apr_hdr mvm_standby_voice_cmd; void *apr_mvm; u16 mvm_handle; int ret = 0; pr_debug("%s: voc state=%d", __func__, v->voc_state); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } if (v->voc_state == VOC_RUN) { apr_mvm = common.apr_q6_mvm; if (!apr_mvm) { pr_err("%s: apr_mvm is NULL.\n", __func__); ret = -EINVAL; goto fail; } mvm_handle = voice_get_mvm_handle(v); mvm_standby_voice_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); mvm_standby_voice_cmd.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(mvm_standby_voice_cmd) - APR_HDR_SIZE); pr_debug("send mvm_standby_voice_cmd pkt size = %d\n", mvm_standby_voice_cmd.pkt_size); mvm_standby_voice_cmd.src_port = v->session_id; mvm_standby_voice_cmd.dest_port = mvm_handle; mvm_standby_voice_cmd.token = 0; mvm_standby_voice_cmd.opcode = VSS_IMVM_CMD_STANDBY_VOICE; v->mvm_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_mvm, (uint32_t *)&mvm_standby_voice_cmd); if (ret < 0) { pr_err("Fail in sending VSS_IMVM_CMD_STANDBY_VOICE\n"); ret = -EINVAL; goto fail; } v->voc_state = VOC_STANDBY; } fail: return ret; } int voc_set_ext_ec_ref(uint16_t port_id, bool state) { int ret = 0; mutex_lock(&common.common_lock); if (state == true) { if (port_id == AFE_PORT_INVALID) { pr_err("%s: Invalid port id", __func__); ret = -EINVAL; goto fail; } common.ec_port_id = port_id; common.ec_ref_ext = true; } else { common.ec_ref_ext = false; common.ec_port_id = port_id; } fail: mutex_unlock(&common.common_lock); return ret; } void voc_register_mvs_cb(ul_cb_fn ul_cb, dl_cb_fn dl_cb, void *private_data) { common.mvs_info.ul_cb = ul_cb; common.mvs_info.dl_cb = dl_cb; common.mvs_info.private_data = private_data; } void voc_register_dtmf_rx_detection_cb(dtmf_rx_det_cb_fn dtmf_rx_ul_cb, void *private_data) { common.dtmf_info.dtmf_rx_ul_cb = dtmf_rx_ul_cb; common.dtmf_info.private_data = private_data; } void voc_register_hpcm_evt_cb(hostpcm_cb_fn hostpcm_cb, void *private_data) { common.hostpcm_info.hostpcm_evt_cb = hostpcm_cb; common.hostpcm_info.private_data = private_data; } void voc_config_vocoder(uint32_t media_type, uint32_t rate, uint32_t network_type, uint32_t dtx_mode) { common.mvs_info.media_type = media_type; common.mvs_info.rate = rate; common.mvs_info.network_type = network_type; common.mvs_info.dtx_mode = dtx_mode; } static int32_t qdsp_mvm_callback(struct apr_client_data *data, void *priv) { uint32_t *ptr = NULL; struct common_data *c = NULL; struct voice_data *v = NULL; int i = 0; if ((data == NULL) || (priv == NULL)) { pr_err("%s: data or priv is NULL\n", __func__); return -EINVAL; } c = priv; pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port); v = voice_get_session(data->dest_port); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__, data->payload_size, data->opcode); if (data->opcode == RESET_EVENTS) { pr_debug("%s: Reset event received in Voice service\n", __func__); apr_reset(c->apr_q6_mvm); c->apr_q6_mvm = NULL; /* Sub-system restart is applicable to all sessions. */ for (i = 0; i < MAX_VOC_SESSIONS; i++) c->voice[i].mvm_handle = 0; return 0; } if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->payload_size) { ptr = data->payload; pr_info("%x %x\n", ptr[0], ptr[1]); /* ping mvm service ACK */ switch (ptr[0]) { case VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION: case VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION: /* Passive session is used for CS call * Full session is used for VoIP call. */ pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); if (!ptr[1]) { pr_debug("%s: MVM handle is %d\n", __func__, data->src_port); voice_set_mvm_handle(v, data->src_port); } else pr_err("got NACK for sending \ MVM create session \n"); v->mvm_state = CMD_STATUS_SUCCESS; wake_up(&v->mvm_wait); break; case VSS_IMVM_CMD_START_VOICE: case VSS_IMVM_CMD_ATTACH_VOCPROC: case VSS_IMVM_CMD_STOP_VOICE: case VSS_IMVM_CMD_DETACH_VOCPROC: case VSS_ISTREAM_CMD_SET_TTY_MODE: case APRV2_IBASIC_CMD_DESTROY_SESSION: case VSS_IMVM_CMD_ATTACH_STREAM: case VSS_IMVM_CMD_DETACH_STREAM: case VSS_ICOMMON_CMD_SET_NETWORK: case VSS_ICOMMON_CMD_SET_VOICE_TIMING: case VSS_IWIDEVOICE_CMD_SET_WIDEVOICE: case VSS_IMVM_CMD_SET_POLICY_DUAL_CONTROL: case VSS_IMVM_CMD_STANDBY_VOICE: pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); v->mvm_state = CMD_STATUS_SUCCESS; wake_up(&v->mvm_wait); break; default: pr_debug("%s: not match cmd = 0x%x\n", __func__, ptr[0]); break; } } } return 0; } static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) { uint32_t *ptr = NULL; struct common_data *c = NULL; struct voice_data *v = NULL; int i = 0; if ((data == NULL) || (priv == NULL)) { pr_err("%s: data or priv is NULL\n", __func__); return -EINVAL; } c = priv; pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port); v = voice_get_session(data->dest_port); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__, data->payload_size, data->opcode); if (data->opcode == RESET_EVENTS) { pr_debug("%s: Reset event received in Voice service\n", __func__); apr_reset(c->apr_q6_cvs); c->apr_q6_cvs = NULL; /* Sub-system restart is applicable to all sessions. */ for (i = 0; i < MAX_VOC_SESSIONS; i++) c->voice[i].cvs_handle = 0; return 0; } if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->payload_size) { ptr = data->payload; pr_info("%x %x\n", ptr[0], ptr[1]); /*response from CVS */ switch (ptr[0]) { case VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION: case VSS_ISTREAM_CMD_CREATE_FULL_CONTROL_SESSION: if (!ptr[1]) { pr_debug("%s: CVS handle is %d\n", __func__, data->src_port); voice_set_cvs_handle(v, data->src_port); } else pr_err("got NACK for sending \ CVS create session \n"); v->cvs_state = CMD_STATUS_SUCCESS; wake_up(&v->cvs_wait); break; case VSS_ISTREAM_CMD_SET_MUTE: case VSS_ISTREAM_CMD_SET_MEDIA_TYPE: case VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE: case VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE: case VSS_ISTREAM_CMD_SET_ENC_DTX_MODE: case VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE: case APRV2_IBASIC_CMD_DESTROY_SESSION: case VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA: case VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA: case VSS_ICOMMON_CMD_MAP_MEMORY: case VSS_ICOMMON_CMD_UNMAP_MEMORY: case VSS_ICOMMON_CMD_SET_UI_PROPERTY: case VSS_ISTREAM_CMD_START_PLAYBACK: case VSS_ISTREAM_CMD_STOP_PLAYBACK: case VSS_ISTREAM_CMD_START_RECORD: case VSS_ISTREAM_CMD_STOP_RECORD: case VSS_ISTREAM_CMD_SET_RX_DTMF_DETECTION: pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); v->cvs_state = CMD_STATUS_SUCCESS; wake_up(&v->cvs_wait); break; case VOICE_CMD_SET_PARAM: rtac_make_voice_callback(RTAC_CVS, ptr, data->payload_size); break; default: pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); break; } } } else if (data->opcode == VSS_ISTREAM_EVT_SEND_ENC_BUFFER) { uint32_t *voc_pkt = data->payload; uint32_t pkt_len = data->payload_size; if (voc_pkt != NULL && c->mvs_info.ul_cb != NULL) { pr_debug("%s: Media type is 0x%x\n", __func__, voc_pkt[0]); /* Remove media ID from payload. */ voc_pkt++; pkt_len = pkt_len - 4; c->mvs_info.ul_cb((uint8_t *)voc_pkt, pkt_len, c->mvs_info.private_data); } else pr_err("%s: voc_pkt is 0x%x ul_cb is 0x%x\n", __func__, (unsigned int)voc_pkt, (unsigned int) c->mvs_info.ul_cb); } else if (data->opcode == VSS_ISTREAM_EVT_REQUEST_DEC_BUFFER) { struct cvs_send_dec_buf_cmd send_dec_buf; int ret = 0; uint32_t pkt_len = 0; if (c->mvs_info.dl_cb != NULL) { send_dec_buf.dec_buf.media_id = c->mvs_info.media_type; c->mvs_info.dl_cb( (uint8_t *)&send_dec_buf.dec_buf.packet_data, &pkt_len, c->mvs_info.private_data); send_dec_buf.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); send_dec_buf.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(send_dec_buf.dec_buf.media_id) + pkt_len); send_dec_buf.hdr.src_port = v->session_id; send_dec_buf.hdr.dest_port = voice_get_cvs_handle(v); send_dec_buf.hdr.token = 0; send_dec_buf.hdr.opcode = VSS_ISTREAM_EVT_SEND_DEC_BUFFER; ret = apr_send_pkt(c->apr_q6_cvs, (uint32_t *) &send_dec_buf); if (ret < 0) { pr_err("%s: Error %d sending DEC_BUF\n", __func__, ret); goto fail; } } else pr_debug("%s: dl_cb is NULL\n", __func__); } else if (data->opcode == VSS_ISTREAM_EVT_SEND_DEC_BUFFER) { pr_debug("Send dec buf resp\n"); } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) { rtac_make_voice_callback(RTAC_CVS, data->payload, data->payload_size); } else if (data->opcode == VSS_ISTREAM_EVT_RX_DTMF_DETECTED) { struct vss_istream_evt_rx_dtmf_detected *dtmf_rx_detected; uint32_t *voc_pkt = data->payload; uint32_t pkt_len = data->payload_size; if ((voc_pkt != NULL) && (pkt_len == sizeof(struct vss_istream_evt_rx_dtmf_detected))) { dtmf_rx_detected = (struct vss_istream_evt_rx_dtmf_detected *) voc_pkt; pr_debug("RX_DTMF_DETECTED low_freq=%d high_freq=%d\n", dtmf_rx_detected->low_freq, dtmf_rx_detected->high_freq); if (c->dtmf_info.dtmf_rx_ul_cb) c->dtmf_info.dtmf_rx_ul_cb((uint8_t *)voc_pkt, voc_get_session_name(v->session_id), c->dtmf_info.private_data); } else { pr_err("Invalid packet\n"); } } else { pr_debug("Unknown opcode 0x%x\n", data->opcode); } fail: return 0; } static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv) { uint32_t *ptr = NULL; struct common_data *c = NULL; struct voice_data *v = NULL; int i = 0; if ((data == NULL) || (priv == NULL)) { pr_err("%s: data or priv is NULL\n", __func__); return -EINVAL; } c = priv; v = voice_get_session(data->dest_port); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__, data->payload_size, data->opcode); if (data->opcode == RESET_EVENTS) { pr_debug("%s: Reset event received in Voice service\n", __func__); apr_reset(c->apr_q6_cvp); c->apr_q6_cvp = NULL; /* Sub-system restart is applicable to all sessions. */ for (i = 0; i < MAX_VOC_SESSIONS; i++) c->voice[i].cvp_handle = 0; return 0; } if (data->opcode == APR_BASIC_RSP_RESULT) { if (data->payload_size) { ptr = data->payload; pr_info("%x %x\n", ptr[0], ptr[1]); switch (ptr[0]) { case VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION: /*response from CVP */ pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); if (!ptr[1]) { voice_set_cvp_handle(v, data->src_port); pr_debug("cvphdl=%d\n", data->src_port); } else pr_err("got NACK from CVP create \ session response\n"); v->cvp_state = CMD_STATUS_SUCCESS; wake_up(&v->cvp_wait); break; case VSS_IVOCPROC_CMD_SET_DEVICE_V2: case VSS_IVOCPROC_CMD_SET_DEVICE: case VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX: case VSS_IVOCPROC_CMD_ENABLE: case VSS_IVOCPROC_CMD_DISABLE: case APRV2_IBASIC_CMD_DESTROY_SESSION: case VSS_IVOCPROC_CMD_REGISTER_VOLUME_CAL_TABLE: case VSS_IVOCPROC_CMD_DEREGISTER_VOLUME_CAL_TABLE: case VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA: case VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA: case VSS_ICOMMON_CMD_MAP_MEMORY: case VSS_ICOMMON_CMD_UNMAP_MEMORY: case VSS_IVOCPROC_CMD_SET_MUTE: case VSS_IVPCM_CMD_START: case VSS_IVPCM_CMD_STOP: v->cvp_state = CMD_STATUS_SUCCESS; wake_up(&v->cvp_wait); break; case VSS_IVPCM_EVT_PUSH_BUFFER: break; case VOICE_CMD_SET_PARAM: rtac_make_voice_callback(RTAC_CVP, ptr, data->payload_size); break; default: pr_debug("%s: not match cmd = 0x%x\n", __func__, ptr[0]); break; } } } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) { rtac_make_voice_callback(RTAC_CVP, data->payload, data->payload_size); } else if (data->opcode == VSS_IVPCM_EVT_NOTIFY) { struct vss_ivpcm_evt_notify *notify_evt; if ((data->payload != NULL) && data->payload_size == sizeof(struct vss_ivpcm_evt_notify)) { notify_evt = (struct vss_ivpcm_evt_notify *)data->payload; c->hostpcm_info.hostpcm_evt_cb(data->payload, voc_get_session_name(v->session_id), c->hostpcm_info.private_data); } } return 0; } int voc_send_cvp_vocpcm_push_buf_evt(u16 session_id, struct vss_ivpcm_evt_push_buffer *push_buff_evt) { struct cvp_push_buf_cmd vpcm_push_buf_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; struct voice_data *v = voice_get_session(session_id); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ vpcm_push_buf_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); vpcm_push_buf_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(vpcm_push_buf_cmd) - APR_HDR_SIZE); vpcm_push_buf_cmd.hdr.src_port = v->session_id; vpcm_push_buf_cmd.hdr.dest_port = cvp_handle; vpcm_push_buf_cmd.hdr.token = 0; vpcm_push_buf_cmd.hdr.opcode = VSS_IVPCM_EVT_PUSH_BUFFER; vpcm_push_buf_cmd.vpcm_evt_push_buffer.tap_point = push_buff_evt->tap_point; vpcm_push_buf_cmd.vpcm_evt_push_buffer.push_buf_mask = push_buff_evt->push_buf_mask; vpcm_push_buf_cmd.vpcm_evt_push_buffer.out_buf_addr = push_buff_evt->out_buf_addr; vpcm_push_buf_cmd.vpcm_evt_push_buffer.in_buf_addr = push_buff_evt->in_buf_addr; vpcm_push_buf_cmd.vpcm_evt_push_buffer.out_buf_size = push_buff_evt->out_buf_size; vpcm_push_buf_cmd.vpcm_evt_push_buffer.in_buf_size = push_buff_evt->in_buf_size; vpcm_push_buf_cmd.vpcm_evt_push_buffer.sampling_rate = push_buff_evt->sampling_rate; vpcm_push_buf_cmd.vpcm_evt_push_buffer.num_in_channels = push_buff_evt->num_in_channels; ret = apr_send_pkt(apr_cvp, (uint32_t *) &vpcm_push_buf_cmd); if (ret < 0) { pr_err("Fail: sending vocpcm map memory,\n"); goto fail; } return 0; fail: return -EINVAL; } int voc_send_cvp_stop_vocpcm(u16 session_id) { struct cvp_stop_cmd vpcm_stop_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; struct voice_data *v = voice_get_session(session_id); if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ vpcm_stop_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); vpcm_stop_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(vpcm_stop_cmd) - APR_HDR_SIZE); vpcm_stop_cmd.hdr.src_port = v->session_id; vpcm_stop_cmd.hdr.dest_port = cvp_handle; vpcm_stop_cmd.hdr.token = 0; vpcm_stop_cmd.hdr.opcode = VSS_IVPCM_CMD_STOP; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &vpcm_stop_cmd); if (ret < 0) { pr_err("Fail: sending vocpcm stop,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } int voc_send_cvp_start_vocpcm(u16 session_id, struct vss_ivpcm_tap_point *vpcm_tp, uint32_t no_of_tp) { struct cvp_start_cmd cvp_start_cmd; int ret = 0; void *apr_cvp; u16 cvp_handle; struct voice_data *v = voice_get_session(session_id); int i = 0; if (v == NULL) { pr_err("%s: v is NULL\n", __func__); return -EINVAL; } apr_cvp = common.apr_q6_cvp; if (!apr_cvp) { pr_err("%s: apr_cvp is NULL.\n", __func__); return -EINVAL; } cvp_handle = voice_get_cvp_handle(v); /* fill in the header */ cvp_start_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); cvp_start_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, sizeof(struct vss_ivpcm_tap_point) * no_of_tp) + sizeof(no_of_tp); cvp_start_cmd.hdr.src_port = v->session_id; cvp_start_cmd.hdr.dest_port = cvp_handle; cvp_start_cmd.hdr.token = 0; cvp_start_cmd.hdr.opcode = VSS_IVPCM_CMD_START; for (i = 0; i < no_of_tp; i++) { cvp_start_cmd.vpcm_start_cmd.tap_points[i].tap_point = vpcm_tp[i].tap_point; cvp_start_cmd.vpcm_start_cmd.tap_points[i].direction = vpcm_tp[i].direction; cvp_start_cmd.vpcm_start_cmd.tap_points[i].sampling_rate = vpcm_tp[i].sampling_rate; cvp_start_cmd.vpcm_start_cmd.tap_points[i].duration = 0; } cvp_start_cmd.vpcm_start_cmd.num_tap_points = no_of_tp; v->cvp_state = CMD_STATUS_FAIL; ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_start_cmd); if (ret < 0) { pr_err("Fail: sending vocpcm map memory,\n"); goto fail; } ret = wait_event_timeout(v->cvp_wait, (v->cvp_state == CMD_STATUS_SUCCESS), msecs_to_jiffies(TIMEOUT_MS)); if (!ret) { pr_err("%s: wait_event timeout\n", __func__); goto fail; } return 0; fail: return -EINVAL; } int voc_send_cvp_unmap_vocpcm_memory(u16 session_id, uint32_t paddr) { return voice_send_cvp_unmap_memory_cmd( voice_get_session(session_id), paddr); } int voc_send_cvp_map_vocpcm_memory(u16 session_id, uint32_t paddr, uint32_t bufsize) { return voice_send_cvp_map_memory_cmd(voice_get_session(session_id), paddr, bufsize); } static void voice_allocate_shared_memory(void) { int i, j, result; int offset = 0; int mem_len; unsigned long paddr; void *kvptr; pr_debug("%s\n", __func__); common.ion_client = msm_ion_client_create(UINT_MAX, "q6voice_client"); if (IS_ERR_OR_NULL((void *)common.ion_client)) { pr_err("%s: ION create client failed\n", __func__); goto err; } common.ion_handle = ion_alloc(common.ion_client, TOTAL_VOICE_CAL_SIZE, SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID), 0); if (IS_ERR_OR_NULL((void *) common.ion_handle)) { pr_err("%s: ION memory allocation failed\n", __func__); goto err_ion_client; } result = ion_phys(common.ion_client, common.ion_handle, &paddr, (size_t *)&mem_len); if (result) { pr_err("%s: ION Get Physical failed, rc = %d\n", __func__, result); goto err_ion_handle; } kvptr = ion_map_kernel(common.ion_client, common.ion_handle); if (IS_ERR_OR_NULL(kvptr)) { pr_err("%s: ION memory mapping failed\n", __func__); goto err_ion_handle; } /* Make all phys & buf point to the correct address */ for (i = 0; i < NUM_VOICE_CAL_BUFFERS; i++) { for (j = 0; j < NUM_VOICE_CAL_TYPES; j++) { common.voice_cal[i].cal_data[j].paddr = (uint32_t)(paddr + offset); common.voice_cal[i].cal_data[j].kvaddr = (uint32_t)((uint8_t *)kvptr + offset); if (j == CVP_CAL) offset += CVP_CAL_SIZE; else offset += CVS_CAL_SIZE; pr_debug("%s: kernel addr = 0x%x, phys addr = 0x%x\n", __func__, common.voice_cal[i].cal_data[j].kvaddr, common.voice_cal[i].cal_data[j].paddr); } } return; err_ion_handle: ion_free(common.ion_client, common.ion_handle); err_ion_client: ion_client_destroy(common.ion_client); err: return; } static int __init voice_init(void) { int rc = 0, i = 0; memset(&common, 0, sizeof(struct common_data)); /* Allocate shared memory */ voice_allocate_shared_memory(); /* set default value */ common.default_mute_val = 0; /* default is un-mute */ common.default_vol_val = 0; common.default_sample_val = 8000; common.ec_ref_ext = false; /* Initialize MVS info. */ common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT; mutex_init(&common.common_lock); for (i = 0; i < MAX_VOC_SESSIONS; i++) { common.voice[i].session_id = SESSION_ID_BASE + i; /* initialize dev_rx and dev_tx */ common.voice[i].dev_rx.volume = common.default_vol_val; common.voice[i].dev_rx.mute = 0; common.voice[i].dev_tx.mute = common.default_mute_val; common.voice[i].dev_tx.port_id = 1; common.voice[i].dev_rx.port_id = 0; common.voice[i].sidetone_gain = 0x512; common.voice[i].dtmf_rx_detect_en = 0; common.voice[i].disable_topology = false; common.voice[i].voc_state = VOC_INIT; init_waitqueue_head(&common.voice[i].mvm_wait); init_waitqueue_head(&common.voice[i].cvs_wait); init_waitqueue_head(&common.voice[i].cvp_wait); mutex_init(&common.voice[i].lock); } return rc; } device_initcall(voice_init);