| /* Copyright (c) 2010-2012, 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 <linux/slab.h> |
| #include <linux/kernel.h> |
| #include <linux/module.h> |
| #include <linux/miscdevice.h> |
| #include <linux/uaccess.h> |
| #include <linux/fs.h> |
| #include <linux/sched.h> |
| #include <linux/msm_audio.h> |
| #include <linux/kthread.h> |
| #include <linux/completion.h> |
| #include <linux/wait.h> |
| #include <linux/mutex.h> |
| #include <linux/delay.h> |
| |
| #include <mach/qdsp6v2/audio_dev_ctl.h> |
| #include <mach/dal.h> |
| #include <mach/qdsp6v2/q6voice.h> |
| #include <mach/qdsp6v2/rtac.h> |
| #include <mach/qdsp6v2/audio_acdb.h> |
| |
| #include <mach/qdsp6v2/q6core.h> |
| |
| |
| #define TIMEOUT_MS 3000 |
| #define SNDDEV_CAP_TTY 0x20 |
| #define CMD_STATUS_SUCCESS 0 |
| #define CMD_STATUS_FAIL 1 |
| |
| /* Voice session creates passive control sessions for MVM and CVS. */ |
| #define VOC_PATH_PASSIVE 0 |
| |
| /* VoIP session creates full control sessions for MVM and CVS. */ |
| #define VOC_PATH_FULL 1 |
| |
| #define ADSP_VERSION_CVD 0x60300000 |
| |
| #define BUFFER_PAYLOAD_SIZE 4000 |
| |
| #define VOC_REC_NONE 0xFF |
| |
| struct common_data common; |
| |
| static bool is_adsp_support_cvd(void) |
| { |
| return (common.adsp_version >= ADSP_VERSION_CVD); |
| } |
| static int voice_send_enable_vocproc_cmd(struct voice_data *v); |
| static int voice_send_netid_timing_cmd(struct voice_data *v); |
| |
| static void *voice_get_apr_mvm(void) |
| { |
| void *apr_mvm = NULL; |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) |
| apr_mvm = common.apr_mvm; |
| else |
| apr_mvm = common.apr_q6_mvm; |
| |
| pr_debug("%s: apr_mvm 0x%x\n", __func__, (unsigned int)apr_mvm); |
| |
| return apr_mvm; |
| } |
| |
| static void voice_set_apr_mvm(void *apr_mvm) |
| { |
| pr_debug("%s: apr_mvm 0x%x\n", __func__, (unsigned int)apr_mvm); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) |
| common.apr_mvm = apr_mvm; |
| else |
| common.apr_q6_mvm = apr_mvm; |
| } |
| |
| static void *voice_get_apr_cvs(void) |
| { |
| void *apr_cvs = NULL; |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) |
| apr_cvs = common.apr_cvs; |
| else |
| apr_cvs = common.apr_q6_cvs; |
| |
| pr_debug("%s: apr_cvs 0x%x\n", __func__, (unsigned int)apr_cvs); |
| |
| return apr_cvs; |
| } |
| |
| static void voice_set_apr_cvs(void *apr_cvs) |
| { |
| pr_debug("%s: apr_cvs 0x%x\n", __func__, (unsigned int)apr_cvs); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) |
| common.apr_cvs = apr_cvs; |
| else |
| common.apr_q6_cvs = apr_cvs; |
| rtac_set_voice_handle(RTAC_CVS, apr_cvs); |
| } |
| |
| static void *voice_get_apr_cvp(void) |
| { |
| void *apr_cvp = NULL; |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) |
| apr_cvp = common.apr_cvp; |
| else |
| apr_cvp = common.apr_q6_cvp; |
| |
| pr_debug("%s: apr_cvp 0x%x\n", __func__, (unsigned int)apr_cvp); |
| |
| return apr_cvp; |
| } |
| |
| static void voice_set_apr_cvp(void *apr_cvp) |
| { |
| pr_debug("%s: apr_cvp 0x%x\n", __func__, (unsigned int)apr_cvp); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) |
| common.apr_cvp = apr_cvp; |
| else |
| common.apr_q6_cvp = apr_cvp; |
| rtac_set_voice_handle(RTAC_CVP, apr_cvp); |
| } |
| |
| static u16 voice_get_mvm_handle(struct voice_data *v) |
| { |
| 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: session 0x%x, mvm_handle %d\n", |
| __func__, (unsigned int)v, mvm_handle); |
| |
| v->mvm_handle = mvm_handle; |
| } |
| |
| static u16 voice_get_cvs_handle(struct voice_data *v) |
| { |
| 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: session 0x%x, cvs_handle %d\n", |
| __func__, (unsigned int)v, cvs_handle); |
| |
| v->cvs_handle = cvs_handle; |
| } |
| |
| static u16 voice_get_cvp_handle(struct voice_data *v) |
| { |
| 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: session 0x%x, cvp_handle %d\n", |
| __func__, (unsigned int)v, cvp_handle); |
| |
| v->cvp_handle = cvp_handle; |
| } |
| |
| u16 voice_get_session_id(const 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 |
| 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 == 0) { |
| mutex_lock(&common.common_lock); |
| |
| pr_debug("%s: NULL id, voc_path is %d\n", |
| __func__, common.voc_path); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE) |
| v = &common.voice[VOC_PATH_PASSIVE]; |
| else |
| v = &common.voice[VOC_PATH_FULL]; |
| |
| mutex_unlock(&common.common_lock); |
| } else if ((session_id >= SESSION_ID_BASE) && |
| (session_id < SESSION_ID_BASE + MAX_VOC_SESSIONS)) { |
| v = &common.voice[session_id - SESSION_ID_BASE]; |
| } else { |
| pr_err("%s: Invalid session_id 0x%x\n", __func__, session_id); |
| } |
| |
| 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 void voice_auddev_cb_function(u32 evt_id, |
| union auddev_evt_data *evt_payload, |
| void *private_data); |
| |
| static int32_t modem_mvm_callback(struct apr_client_data *data, void *priv); |
| static int32_t modem_cvs_callback(struct apr_client_data *data, void *priv); |
| static int32_t modem_cvp_callback(struct apr_client_data *data, void *priv); |
| |
| static int voice_apr_register(void) |
| { |
| int rc = 0; |
| void *apr_mvm; |
| void *apr_cvs; |
| void *apr_cvp; |
| |
| if (common.adsp_version == 0) { |
| common.adsp_version = core_get_adsp_version(); |
| pr_info("adsp_ver fetched:%x\n", common.adsp_version); |
| } |
| |
| mutex_lock(&common.common_lock); |
| |
| apr_mvm = voice_get_apr_mvm(); |
| apr_cvs = voice_get_apr_cvs(); |
| apr_cvp = voice_get_apr_cvp(); |
| |
| |
| pr_debug("into voice_apr_register_callback\n"); |
| /* register callback to APR */ |
| if (apr_mvm == NULL) { |
| pr_debug("start to register MVM callback\n"); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) { |
| apr_mvm = apr_register("MODEM", "MVM", |
| modem_mvm_callback, 0xFFFFFFFF, |
| &common); |
| } else { |
| apr_mvm = apr_register("ADSP", "MVM", |
| modem_mvm_callback, 0xFFFFFFFF, |
| &common); |
| } |
| |
| if (apr_mvm == NULL) { |
| pr_err("Unable to register MVM %d\n", |
| is_adsp_support_cvd()); |
| rc = -ENODEV; |
| goto done; |
| } |
| |
| voice_set_apr_mvm(apr_mvm); |
| } |
| |
| if (apr_cvs == NULL) { |
| pr_debug("start to register CVS callback\n"); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) { |
| apr_cvs = apr_register("MODEM", "CVS", |
| modem_cvs_callback, 0xFFFFFFFF, |
| &common); |
| } else { |
| apr_cvs = apr_register("ADSP", "CVS", |
| modem_cvs_callback, 0xFFFFFFFF, |
| &common); |
| } |
| |
| if (apr_cvs == NULL) { |
| pr_err("Unable to register CVS %d\n", |
| is_adsp_support_cvd()); |
| rc = -ENODEV; |
| goto err; |
| } |
| |
| voice_set_apr_cvs(apr_cvs); |
| } |
| |
| if (apr_cvp == NULL) { |
| pr_debug("start to register CVP callback\n"); |
| |
| if (common.voc_path == VOC_PATH_PASSIVE && |
| !(is_adsp_support_cvd())) { |
| apr_cvp = apr_register("MODEM", "CVP", |
| modem_cvp_callback, 0xFFFFFFFF, |
| &common); |
| } else { |
| apr_cvp = apr_register("ADSP", "CVP", |
| modem_cvp_callback, 0xFFFFFFFF, |
| &common); |
| } |
| |
| if (apr_cvp == NULL) { |
| pr_err("Unable to register CVP %d\n", |
| is_adsp_support_cvd()); |
| rc = -ENODEV; |
| goto err1; |
| } |
| |
| voice_set_apr_cvp(apr_cvp); |
| } |
| |
| mutex_unlock(&common.common_lock); |
| |
| return 0; |
| |
| err1: |
| apr_deregister(apr_cvs); |
| apr_cvs = NULL; |
| voice_set_apr_cvs(apr_cvs); |
| err: |
| apr_deregister(apr_mvm); |
| apr_mvm = NULL; |
| voice_set_apr_mvm(apr_mvm); |
| |
| done: |
| mutex_unlock(&common.common_lock); |
| |
| return rc; |
| } |
| |
| 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 = voice_get_apr_mvm(); |
| void *apr_cvs = voice_get_apr_cvs(); |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 mvm_handle = voice_get_mvm_handle(v); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| u16 cvp_handle = voice_get_cvp_handle(v); |
| |
| pr_info("%s:\n", __func__); |
| |
| /* start to ping if modem service is up */ |
| pr_debug("in voice_create_mvm_cvs_session, mvm_hdl=%d, cvs_hdl=%d\n", |
| mvm_handle, cvs_handle); |
| /* send cmd to create mvm session and wait for response */ |
| |
| if (!mvm_handle) { |
| if (is_voice_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("Send mvm create session pkt size = %d\n", |
| 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; |
| pr_debug("%s: Creating MVM passive ctrl\n", __func__); |
| mvm_session_cmd.hdr.opcode = |
| VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION; |
| strncpy(mvm_session_cmd.mvm_session.name, |
| "default modem voice", SESSION_NAME_LEN); |
| |
| v->mvm_state = CMD_STATUS_FAIL; |
| |
| ret = apr_send_pkt(apr_mvm, |
| (uint32_t *) &mvm_session_cmd); |
| if (ret < 0) { |
| pr_err("Error 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; |
| } |
| } else { |
| 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("Send mvm create session pkt size = %d\n", |
| 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; |
| pr_debug("%s: Creating MVM full ctrl\n", __func__); |
| mvm_session_cmd.hdr.opcode = |
| VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION; |
| strncpy(mvm_session_cmd.mvm_session.name, |
| "default voip", SESSION_NAME_LEN); |
| |
| v->mvm_state = CMD_STATUS_FAIL; |
| |
| ret = apr_send_pkt(apr_mvm, |
| (uint32_t *) &mvm_session_cmd); |
| if (ret < 0) { |
| pr_err("Error sending MVM_FULL_CTL_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)) { |
| pr_info("%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); |
| pr_info("send stream create session pkt size = %d\n", |
| cvs_session_cmd.hdr.pkt_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; |
| strncpy(cvs_session_cmd.cvs_session.name, |
| "default modem voice", SESSION_NAME_LEN); |
| |
| v->cvs_state = CMD_STATUS_FAIL; |
| |
| pr_info("%s: CVS create\n", __func__); |
| 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_info("%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; |
| strncpy(cvs_full_ctl_cmd.cvs_session.name, |
| "default voip", SESSION_NAME_LEN); |
| |
| 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_info("%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: |
| apr_deregister(apr_mvm); |
| apr_mvm = NULL; |
| voice_set_apr_mvm(apr_mvm); |
| |
| apr_deregister(apr_cvs); |
| apr_cvs = NULL; |
| voice_set_apr_cvs(apr_cvs); |
| |
| apr_deregister(apr_cvp); |
| apr_cvp = NULL; |
| voice_set_apr_cvp(apr_cvp); |
| |
| cvp_handle = 0; |
| voice_set_cvp_handle(v, cvp_handle); |
| |
| cvs_handle = 0; |
| voice_set_cvs_handle(v, cvs_handle); |
| |
| 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 = voice_get_apr_mvm(); |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 mvm_handle = voice_get_mvm_handle(v); |
| u16 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_info("%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_info("%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_info("%s: MVM destroy session\n", __func__); |
| |
| 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); |
| } |
| |
| fail: |
| return 0; |
| } |
| |
| static int voice_send_tty_mode_to_modem(struct voice_data *v) |
| { |
| struct msm_snddev_info *dev_tx_info; |
| struct msm_snddev_info *dev_rx_info; |
| int tty_mode = 0; |
| int ret = 0; |
| struct mvm_set_tty_mode_cmd mvm_tty_mode_cmd; |
| void *apr_mvm = voice_get_apr_mvm(); |
| u16 mvm_handle = voice_get_mvm_handle(v); |
| |
| dev_rx_info = audio_dev_ctrl_find_dev(v->dev_rx.dev_id); |
| if (IS_ERR(dev_rx_info)) { |
| pr_err("bad dev_id %d\n", v->dev_rx.dev_id); |
| goto done; |
| } |
| |
| dev_tx_info = audio_dev_ctrl_find_dev(v->dev_tx.dev_id); |
| if (IS_ERR(dev_tx_info)) { |
| pr_err("bad dev_id %d\n", v->dev_tx.dev_id); |
| goto done; |
| } |
| |
| if ((dev_rx_info->capability & SNDDEV_CAP_TTY) && |
| (dev_tx_info->capability & SNDDEV_CAP_TTY)) |
| tty_mode = 3; /* FULL */ |
| else if (!(dev_tx_info->capability & SNDDEV_CAP_TTY) && |
| (dev_rx_info->capability & SNDDEV_CAP_TTY)) |
| tty_mode = 2; /* VCO */ |
| else if ((dev_tx_info->capability & SNDDEV_CAP_TTY) && |
| !(dev_rx_info->capability & SNDDEV_CAP_TTY)) |
| tty_mode = 1; /* HCO */ |
| |
| if (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("pkt size = %d\n", 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 = tty_mode; |
| pr_info("tty mode =%d\n", mvm_tty_mode_cmd.tty_mode.mode); |
| |
| v->mvm_state = CMD_STATUS_FAIL; |
| pr_info("%s: MVM set tty\n", __func__); |
| ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_tty_mode_cmd); |
| if (ret < 0) { |
| pr_err("Fail: sending VSS_ISTREAM_CMD_SET_TTY_MODE\n"); |
| goto done; |
| } |
| 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 done; |
| } |
| } |
| return 0; |
| done: |
| return -EINVAL; |
| } |
| |
| static int voice_send_cvs_cal_to_modem(struct voice_data *v) |
| { |
| struct apr_hdr cvs_cal_cmd_hdr; |
| uint32_t *cmd_buf; |
| struct acdb_cal_data cal_data; |
| struct acdb_atomic_cal_block *cal_blk; |
| int32_t cal_size_per_network; |
| uint32_t *cal_data_per_network; |
| int index = 0; |
| int ret = 0; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| |
| /* fill the header */ |
| cvs_cal_cmd_hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, |
| APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); |
| cvs_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| sizeof(cvs_cal_cmd_hdr) - APR_HDR_SIZE); |
| cvs_cal_cmd_hdr.src_port = v->session_id; |
| cvs_cal_cmd_hdr.dest_port = cvs_handle; |
| cvs_cal_cmd_hdr.token = 0; |
| cvs_cal_cmd_hdr.opcode = |
| VSS_ISTREAM_CMD_CACHE_CALIBRATION_DATA; |
| |
| pr_debug("voice_send_cvs_cal_to_modem\n"); |
| /* get the cvs cal data */ |
| get_vocstrm_cal(&cal_data); |
| if (cal_data.num_cal_blocks == 0) { |
| pr_err("%s: No calibration data to send!\n", __func__); |
| goto done; |
| } |
| |
| /* send cvs cal to modem */ |
| cmd_buf = kzalloc((sizeof(struct apr_hdr) + BUFFER_PAYLOAD_SIZE), |
| GFP_KERNEL); |
| if (!cmd_buf) { |
| pr_err("No memory is allocated.\n"); |
| return -ENOMEM; |
| } |
| pr_debug("----- num_cal_blocks=%d\n", (s32)cal_data.num_cal_blocks); |
| cal_blk = cal_data.cal_blocks; |
| pr_debug("cal_blk =%x\n", (uint32_t)cal_data.cal_blocks); |
| |
| for (; index < cal_data.num_cal_blocks; index++) { |
| cal_size_per_network = atomic_read(&cal_blk[index].cal_size); |
| pr_debug(" cal size =%d\n", cal_size_per_network); |
| if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE) |
| pr_err("Cal size is too big\n"); |
| cal_data_per_network = |
| (u32 *)atomic_read(&cal_blk[index].cal_kvaddr); |
| pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network); |
| cvs_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| cal_size_per_network); |
| pr_debug("header size =%d, pkt_size =%d\n", |
| APR_HDR_SIZE, cvs_cal_cmd_hdr.pkt_size); |
| memcpy(cmd_buf, &cvs_cal_cmd_hdr, APR_HDR_SIZE); |
| memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)), |
| cal_data_per_network, cal_size_per_network); |
| pr_debug("send cvs cal: index =%d\n", index); |
| v->cvs_state = CMD_STATUS_FAIL; |
| ret = apr_send_pkt(apr_cvs, cmd_buf); |
| if (ret < 0) { |
| pr_err("Fail: sending cvs cal, idx=%d\n", index); |
| continue; |
| } |
| 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; |
| } |
| } |
| kfree(cmd_buf); |
| done: |
| return 0; |
| } |
| |
| static int voice_send_cvp_cal_to_modem(struct voice_data *v) |
| { |
| struct apr_hdr cvp_cal_cmd_hdr; |
| uint32_t *cmd_buf; |
| struct acdb_cal_data cal_data; |
| struct acdb_atomic_cal_block *cal_blk; |
| int32_t cal_size_per_network; |
| uint32_t *cal_data_per_network; |
| int index = 0; |
| int ret = 0; |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 cvp_handle = voice_get_cvp_handle(v); |
| |
| |
| /* fill the header */ |
| cvp_cal_cmd_hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, |
| APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); |
| cvp_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| sizeof(cvp_cal_cmd_hdr) - APR_HDR_SIZE); |
| cvp_cal_cmd_hdr.src_port = v->session_id; |
| cvp_cal_cmd_hdr.dest_port = cvp_handle; |
| cvp_cal_cmd_hdr.token = 0; |
| cvp_cal_cmd_hdr.opcode = |
| VSS_IVOCPROC_CMD_CACHE_CALIBRATION_DATA; |
| |
| /* get cal data */ |
| get_vocproc_cal(&cal_data); |
| if (cal_data.num_cal_blocks == 0) { |
| pr_err("%s: No calibration data to send!\n", __func__); |
| goto done; |
| } |
| |
| /* send cal to modem */ |
| cmd_buf = kzalloc((sizeof(struct apr_hdr) + BUFFER_PAYLOAD_SIZE), |
| GFP_KERNEL); |
| if (!cmd_buf) { |
| pr_err("No memory is allocated.\n"); |
| return -ENOMEM; |
| } |
| pr_debug("----- num_cal_blocks=%d\n", (s32)cal_data.num_cal_blocks); |
| cal_blk = cal_data.cal_blocks; |
| pr_debug(" cal_blk =%x\n", (uint32_t)cal_data.cal_blocks); |
| |
| for (; index < cal_data.num_cal_blocks; index++) { |
| cal_size_per_network = atomic_read(&cal_blk[index].cal_size); |
| if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE) |
| pr_err("Cal size is too big\n"); |
| pr_debug(" cal size =%d\n", cal_size_per_network); |
| cal_data_per_network = |
| (u32 *)atomic_read(&cal_blk[index].cal_kvaddr); |
| pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network); |
| |
| cvp_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| cal_size_per_network); |
| memcpy(cmd_buf, &cvp_cal_cmd_hdr, APR_HDR_SIZE); |
| memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(*cmd_buf)), |
| cal_data_per_network, cal_size_per_network); |
| pr_debug("Send cvp cal\n"); |
| v->cvp_state = CMD_STATUS_FAIL; |
| pr_info("%s: CVP calib\n", __func__); |
| ret = apr_send_pkt(apr_cvp, cmd_buf); |
| if (ret < 0) { |
| pr_err("Fail: sending cvp cal, idx=%d\n", index); |
| continue; |
| } |
| 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; |
| } |
| } |
| kfree(cmd_buf); |
| done: |
| return 0; |
| } |
| |
| static int voice_send_cvp_vol_tbl_to_modem(struct voice_data *v) |
| { |
| struct apr_hdr cvp_vol_cal_cmd_hdr; |
| uint32_t *cmd_buf; |
| struct acdb_cal_data cal_data; |
| struct acdb_atomic_cal_block *cal_blk; |
| int32_t cal_size_per_network; |
| uint32_t *cal_data_per_network; |
| int index = 0; |
| int ret = 0; |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 cvp_handle = voice_get_cvp_handle(v); |
| |
| |
| /* fill the header */ |
| cvp_vol_cal_cmd_hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, |
| APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); |
| cvp_vol_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| sizeof(cvp_vol_cal_cmd_hdr) - APR_HDR_SIZE); |
| cvp_vol_cal_cmd_hdr.src_port = v->session_id; |
| cvp_vol_cal_cmd_hdr.dest_port = cvp_handle; |
| cvp_vol_cal_cmd_hdr.token = 0; |
| cvp_vol_cal_cmd_hdr.opcode = |
| VSS_IVOCPROC_CMD_CACHE_VOLUME_CALIBRATION_TABLE; |
| |
| /* get cal data */ |
| get_vocvol_cal(&cal_data); |
| if (cal_data.num_cal_blocks == 0) { |
| pr_err("%s: No calibration data to send!\n", __func__); |
| goto done; |
| } |
| |
| /* send cal to modem */ |
| cmd_buf = kzalloc((sizeof(struct apr_hdr) + BUFFER_PAYLOAD_SIZE), |
| GFP_KERNEL); |
| if (!cmd_buf) { |
| pr_err("No memory is allocated.\n"); |
| return -ENOMEM; |
| } |
| pr_debug("----- num_cal_blocks=%d\n", (s32)cal_data.num_cal_blocks); |
| cal_blk = cal_data.cal_blocks; |
| pr_debug("Cal_blk =%x\n", (uint32_t)cal_data.cal_blocks); |
| |
| for (; index < cal_data.num_cal_blocks; index++) { |
| cal_size_per_network = atomic_read(&cal_blk[index].cal_size); |
| cal_data_per_network = |
| (u32 *)atomic_read(&cal_blk[index].cal_kvaddr); |
| |
| pr_debug("Cal size =%d, index=%d\n", cal_size_per_network, |
| index); |
| pr_debug("Cal data=%x\n", (uint32_t)cal_data_per_network); |
| cvp_vol_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| cal_size_per_network); |
| memcpy(cmd_buf, &cvp_vol_cal_cmd_hdr, APR_HDR_SIZE); |
| memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)), |
| cal_data_per_network, cal_size_per_network); |
| pr_debug("Send vol table\n"); |
| |
| v->cvp_state = CMD_STATUS_FAIL; |
| ret = apr_send_pkt(apr_cvp, cmd_buf); |
| if (ret < 0) { |
| pr_err("Fail: sending cvp vol cal, idx=%d\n", index); |
| continue; |
| } |
| 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; |
| } |
| } |
| kfree(cmd_buf); |
| done: |
| return 0; |
| } |
| |
| static int voice_set_dtx(struct voice_data *v) |
| { |
| int ret = 0; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| |
| /* Set DTX */ |
| struct cvs_set_enc_dtx_mode_cmd cvs_set_dtx = { |
| .hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, |
| APR_HDR_LEN(APR_HDR_SIZE), |
| APR_PKT_VER), |
| .hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, |
| sizeof(cvs_set_dtx) - APR_HDR_SIZE), |
| .hdr.src_port = v->session_id, |
| .hdr.dest_port = cvs_handle, |
| .hdr.token = 0, |
| .hdr.opcode = VSS_ISTREAM_CMD_SET_ENC_DTX_MODE, |
| .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); |
| |
| goto done; |
| } |
| |
| 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__); |
| |
| ret = -EINVAL; |
| } |
| |
| done: |
| return ret; |
| } |
| |
| static int voice_config_cvs_vocoder(struct voice_data *v) |
| { |
| int ret = 0; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| |
| /* Set media type. */ |
| struct cvs_set_media_type_cmd cvs_set_media_cmd; |
| |
| pr_info("%s: Setting media type\n", __func__); |
| |
| 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 done; |
| } |
| |
| 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__); |
| |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| /* Set encoder properties. */ |
| switch (common.mvs_info.media_type) { |
| case VSS_MEDIA_ID_13K_MODEM: |
| case VSS_MEDIA_ID_4GV_NB_MODEM: |
| case VSS_MEDIA_ID_4GV_WB_MODEM: |
| case VSS_MEDIA_ID_EVRC_MODEM: { |
| struct cvs_set_cdma_enc_minmax_rate_cmd cvs_set_cdma_rate; |
| |
| pr_info("%s: Setting CDMA min-max rate\n", __func__); |
| |
| 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.q_min_max_rate.min_rate; |
| cvs_set_cdma_rate.cdma_rate.max_rate = |
| common.mvs_info.q_min_max_rate.max_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 CDMA_SET_ENC_MINMAX_RATE\n", |
| __func__, ret); |
| |
| goto done; |
| } |
| |
| 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__); |
| |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| if ((common.mvs_info.media_type == VSS_MEDIA_ID_4GV_NB_MODEM) || |
| (common.mvs_info.media_type == VSS_MEDIA_ID_4GV_WB_MODEM)) |
| ret = voice_set_dtx(v); |
| |
| break; |
| } |
| |
| case VSS_MEDIA_ID_AMR_NB_MODEM: { |
| struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate; |
| |
| pr_info("%s: Setting AMR rate\n", __func__); |
| |
| 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 done; |
| } |
| |
| 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__); |
| |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| ret = voice_set_dtx(v); |
| |
| break; |
| } |
| |
| case VSS_MEDIA_ID_AMR_WB_MODEM: { |
| struct cvs_set_amrwb_enc_rate_cmd cvs_set_amrwb_rate; |
| |
| pr_info("%s: Setting AMR WB rate\n", __func__); |
| |
| 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 done; |
| } |
| |
| 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__); |
| |
| ret = -EINVAL; |
| goto done; |
| } |
| |
| ret = voice_set_dtx(v); |
| |
| break; |
| } |
| |
| case VSS_MEDIA_ID_EFR_MODEM: |
| case VSS_MEDIA_ID_FR_MODEM: |
| case VSS_MEDIA_ID_HR_MODEM: |
| 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. */ |
| } |
| } |
| |
| done: |
| return ret; |
| } |
| |
| static int voice_send_start_voice_cmd(struct voice_data *v) |
| { |
| struct apr_hdr mvm_start_voice_cmd; |
| int ret = 0; |
| void *apr_mvm = voice_get_apr_mvm(); |
| u16 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_info("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_disable_vocproc(struct voice_data *v) |
| { |
| struct apr_hdr cvp_disable_cmd; |
| int ret = 0; |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 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; |
| } |
| rtac_remove_voice(v->cvs_handle); |
| |
| return 0; |
| fail: |
| return -EINVAL; |
| } |
| |
| static int voice_set_device(struct voice_data *v) |
| { |
| struct cvp_set_device_cmd cvp_setdev_cmd; |
| struct msm_snddev_info *dev_tx_info; |
| int ret = 0; |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 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; |
| |
| dev_tx_info = audio_dev_ctrl_find_dev(v->dev_tx.dev_id); |
| if (IS_ERR(dev_tx_info)) { |
| pr_err("bad dev_id %d\n", v->dev_tx.dev_id); |
| goto fail; |
| } |
| |
| cvp_setdev_cmd.cvp_set_device.tx_topology_id = |
| get_voice_tx_topology(); |
| if (cvp_setdev_cmd.cvp_set_device.tx_topology_id == 0) { |
| if (dev_tx_info->channel_mode > 1) |
| cvp_setdev_cmd.cvp_set_device.tx_topology_id = |
| VSS_IVOCPROC_TOPOLOGY_ID_TX_DM_FLUENCE; |
| else |
| cvp_setdev_cmd.cvp_set_device.tx_topology_id = |
| VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS; |
| } |
| |
| /* Use default topology if invalid value in ACDB */ |
| cvp_setdev_cmd.cvp_set_device.rx_topology_id = |
| get_voice_rx_topology(); |
| if (cvp_setdev_cmd.cvp_set_device.rx_topology_id == 0) |
| cvp_setdev_cmd.cvp_set_device.rx_topology_id = |
| VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT; |
| cvp_setdev_cmd.cvp_set_device.tx_port_id = v->dev_tx.dev_port_id; |
| cvp_setdev_cmd.cvp_set_device.rx_port_id = v->dev_rx.dev_port_id; |
| pr_info("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; |
| } |
| |
| /* send cvs cal */ |
| voice_send_cvs_cal_to_modem(v); |
| |
| /* send cvp cal */ |
| voice_send_cvp_cal_to_modem(v); |
| |
| /* send cvp vol table cal */ |
| voice_send_cvp_vol_tbl_to_modem(v); |
| |
| /* enable vocproc and wait for respose */ |
| voice_send_enable_vocproc_cmd(v); |
| |
| /* send tty mode if tty device is used */ |
| voice_send_tty_mode_to_modem(v); |
| |
| if (is_voip_session(v->session_id)) |
| voice_send_netid_timing_cmd(v); |
| |
| rtac_add_voice(v->cvs_handle, v->cvp_handle, |
| v->dev_rx.dev_port_id, v->dev_tx.dev_port_id, |
| v->session_id); |
| |
| 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 = voice_get_apr_mvm(); |
| u16 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_info("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_setup_modem_voice(struct voice_data *v) |
| { |
| struct cvp_create_full_ctl_session_cmd cvp_session_cmd; |
| int ret = 0; |
| struct msm_snddev_info *dev_tx_info; |
| void *apr_cvp = voice_get_apr_cvp(); |
| |
| /* 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_info(" 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; |
| |
| dev_tx_info = audio_dev_ctrl_find_dev(v->dev_tx.dev_id); |
| if (IS_ERR(dev_tx_info)) { |
| pr_err("bad dev_id %d\n", v->dev_tx.dev_id); |
| goto fail; |
| } |
| |
| /* Use default topology if invalid value in ACDB */ |
| cvp_session_cmd.cvp_session.tx_topology_id = |
| get_voice_tx_topology(); |
| if (cvp_session_cmd.cvp_session.tx_topology_id == 0) { |
| if (dev_tx_info->channel_mode > 1) |
| cvp_session_cmd.cvp_session.tx_topology_id = |
| VSS_IVOCPROC_TOPOLOGY_ID_TX_DM_FLUENCE; |
| else |
| cvp_session_cmd.cvp_session.tx_topology_id = |
| VSS_IVOCPROC_TOPOLOGY_ID_TX_SM_ECNS; |
| } |
| |
| cvp_session_cmd.cvp_session.rx_topology_id = |
| get_voice_rx_topology(); |
| if (cvp_session_cmd.cvp_session.rx_topology_id == 0) |
| cvp_session_cmd.cvp_session.rx_topology_id = |
| VSS_IVOCPROC_TOPOLOGY_ID_RX_DEFAULT; |
| |
| 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.dev_port_id; |
| cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.dev_port_id; |
| pr_info("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; |
| } |
| 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; |
| } |
| |
| /* send cvs cal */ |
| voice_send_cvs_cal_to_modem(v); |
| |
| /* send cvp cal */ |
| voice_send_cvp_cal_to_modem(v); |
| |
| /* send cvp vol table cal */ |
| voice_send_cvp_vol_tbl_to_modem(v); |
| |
| 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; |
| |
| u16 cvp_handle = voice_get_cvp_handle(v); |
| void *apr_cvp = voice_get_apr_cvp(); |
| |
| /* 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 = voice_get_apr_mvm(); |
| struct mvm_set_network_cmd mvm_set_network; |
| struct mvm_set_voice_timing_cmd mvm_set_voice_timing; |
| u16 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("%s: Setting network ID\n", __func__); |
| |
| 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("%s: Setting voice timing\n", __func__); |
| |
| 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_attach_vocproc(struct voice_data *v) |
| { |
| int ret = 0; |
| struct mvm_attach_vocproc_cmd mvm_a_vocproc_cmd; |
| void *apr_mvm = voice_get_apr_mvm(); |
| u16 mvm_handle = voice_get_mvm_handle(v); |
| u16 cvp_handle = voice_get_cvp_handle(v); |
| |
| /* send enable vocproc */ |
| voice_send_enable_vocproc_cmd(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_info("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_ISTREAM_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_ISTREAM_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; |
| } |
| |
| /* send tty mode if tty device is used */ |
| voice_send_tty_mode_to_modem(v); |
| |
| if (is_voip_session(v->session_id)) |
| voice_send_netid_timing_cmd(v); |
| |
| rtac_add_voice(v->cvs_handle, v->cvp_handle, |
| v->dev_rx.dev_port_id, v->dev_tx.dev_port_id, |
| v->session_id); |
| |
| return 0; |
| fail: |
| return -EINVAL; |
| } |
| |
| static int voice_destroy_modem_voice(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 = voice_get_apr_mvm(); |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 mvm_handle = voice_get_mvm_handle(v); |
| u16 cvp_handle = voice_get_cvp_handle(v); |
| |
| /* 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_info("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_ISTREAM_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_ISTREAM_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; |
| } |
| |
| /* 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_info("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(v->cvs_handle); |
| cvp_handle = 0; |
| voice_set_cvp_handle(v, cvp_handle); |
| |
| return 0; |
| |
| fail: |
| return -EINVAL; |
| } |
| |
| static int voice_send_mute_cmd_to_modem(struct voice_data *v) |
| { |
| struct cvs_set_mute_cmd cvs_mute_cmd; |
| int ret = 0; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 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__); |
| |
| fail: |
| return 0; |
| } |
| |
| static int voice_send_vol_index_to_modem(struct voice_data *v) |
| { |
| struct cvp_set_rx_volume_index_cmd cvp_vol_cmd; |
| int ret = 0; |
| void *apr_cvp = voice_get_apr_cvp(); |
| u16 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 = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| struct cvs_start_record_cmd cvs_start_record; |
| |
| pr_debug("%s: Start record %d\n", __func__, rec_mode); |
| |
| 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; |
| } |
| |
| return 0; |
| |
| fail: |
| return ret; |
| } |
| |
| static int voice_cvs_stop_record(struct voice_data *v) |
| { |
| int ret = 0; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| struct apr_hdr cvs_stop_record; |
| |
| pr_debug("%s: Stop record\n", __func__); |
| |
| 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; |
| } |
| |
| return 0; |
| |
| fail: |
| return ret; |
| } |
| |
| int voice_start_record(uint32_t rec_mode, uint32_t set) |
| { |
| int ret = 0, i; |
| u16 cvs_handle; |
| |
| pr_debug("%s: rec_mode %d, set %d\n", __func__, rec_mode, set); |
| |
| for (i = 0; i < MAX_VOC_SESSIONS; i++) { |
| struct voice_data *v = &common.voice[i]; |
| |
| mutex_lock(&v->lock); |
| |
| cvs_handle = voice_get_cvs_handle(v); |
| |
| if (cvs_handle != 0) { |
| if (set) |
| ret = voice_cvs_start_record(v, rec_mode); |
| else |
| ret = voice_cvs_stop_record(v); |
| } else { |
| /* Cache the value for later. */ |
| v->rec_info.pending = 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; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| struct apr_hdr cvs_start_playback; |
| |
| pr_debug("%s: Start playback\n", __func__); |
| |
| 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; |
| |
| return 0; |
| |
| fail: |
| return ret; |
| } |
| |
| static int voice_cvs_stop_playback(struct voice_data *v) |
| { |
| int ret = 0; |
| void *apr_cvs = voice_get_apr_cvs(); |
| u16 cvs_handle = voice_get_cvs_handle(v); |
| struct apr_hdr cvs_stop_playback; |
| |
| pr_debug("%s: Stop playback\n", __func__); |
| |
| if (v->music_info.playing) { |
| 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; |
| } else { |
| pr_err("%s: Stop playback already sent\n", __func__); |
| } |
| |
| return 0; |
| |
| fail: |
| return ret; |
| } |
| |
| int voice_start_playback(uint32_t set) |
| { |
| int ret = 0, i; |
| u16 cvs_handle; |
| |
| pr_debug("%s: Start playback %d\n", __func__, set); |
| |
| for (i = 0; i < MAX_VOC_SESSIONS; i++) { |
| struct voice_data *v = &common.voice[i]; |
| |
| mutex_lock(&v->lock); |
| |
| 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); |
| } else { |
| /* Cache the value for later. */ |
| pr_debug("%s: Caching ICP value", __func__); |
| |
| v->music_info.pending = set; |
| } |
| |
| mutex_unlock(&v->lock); |
| } |
| |
| return ret; |
| } |
| |
| static void voice_auddev_cb_function(u32 evt_id, |
| union auddev_evt_data *evt_payload, |
| void *private_data) |
| { |
| struct common_data *c = private_data; |
| struct voice_data *v = NULL; |
| |
| struct sidetone_cal sidetone_cal_data; |
| int rc = 0, i = 0; |
| int rc1 = 0; |
| |
| pr_info("auddev_cb_function, evt_id=%d,\n", evt_id); |
| |
| if (evt_payload == NULL) { |
| pr_err("%s: evt_payload is NULL pointer\n", __func__); |
| return; |
| } |
| |
| switch (evt_id) { |
| case AUDDEV_EVT_START_VOICE: |
| v = voice_get_session(evt_payload->voice_session_id); |
| if (v == NULL) { |
| pr_err("%s: v is NULL\n", __func__); |
| return; |
| } |
| |
| mutex_lock(&v->lock); |
| |
| if ((v->voc_state == VOC_INIT) || |
| (v->voc_state == VOC_RELEASE)) { |
| v->v_call_status = VOICE_CALL_START; |
| if ((v->dev_rx.enabled == VOICE_DEV_ENABLED) |
| && (v->dev_tx.enabled == VOICE_DEV_ENABLED)) { |
| rc = voice_apr_register(); |
| if (rc < 0) { |
| pr_err("%s: voice apr registration" |
| "failed\n", __func__); |
| mutex_unlock(&v->lock); |
| return; |
| } |
| rc1 = voice_create_mvm_cvs_session(v); |
| if (rc1 < 0) { |
| pr_err("%s: create mvm-cvs failed\n", |
| __func__); |
| msleep(100); |
| rc = voice_apr_register(); |
| if (rc < 0) { |
| mutex_unlock(&v->lock); |
| pr_err("%s: voice apr regn" |
| "failed\n", __func__); |
| return; |
| } |
| rc1 = voice_create_mvm_cvs_session(v); |
| if (rc1 < 0) { |
| mutex_unlock(&v->lock); |
| pr_err("%s:Retry mvmcvs " |
| "failed\n", |
| __func__); |
| return; |
| } |
| } |
| voice_setup_modem_voice(v); |
| voice_attach_vocproc(v); |
| voice_send_start_voice_cmd(v); |
| get_sidetone_cal(&sidetone_cal_data); |
| msm_snddev_enable_sidetone( |
| v->dev_rx.dev_id, |
| sidetone_cal_data.enable, |
| sidetone_cal_data.gain); |
| v->voc_state = VOC_RUN; |
| |
| /* Start in-call recording if command was |
| * pending. */ |
| if (v->rec_info.pending) { |
| voice_cvs_start_record(v, |
| v->rec_info.rec_mode); |
| |
| v->rec_info.pending = 0; |
| } |
| |
| /* Start in-call music delivery if command was |
| * pending. */ |
| if (v->music_info.pending) { |
| voice_cvs_start_playback(v); |
| |
| v->music_info.pending = 0; |
| } |
| } |
| } |
| |
| mutex_unlock(&v->lock); |
| break; |
| case AUDDEV_EVT_DEV_CHG_VOICE: |
| /* Device change is applicable to all sessions. */ |
| for (i = 0; i < MAX_VOC_SESSIONS; i++) { |
| v = &c->voice[i]; |
| |
| if (v->dev_rx.enabled == VOICE_DEV_ENABLED) |
| msm_snddev_enable_sidetone(v->dev_rx.dev_id, |
| 0, 0); |
| |
| v->dev_rx.enabled = VOICE_DEV_DISABLED; |
| v->dev_tx.enabled = VOICE_DEV_DISABLED; |
| |
| mutex_lock(&v->lock); |
| |
| if (v->voc_state == VOC_RUN) { |
| /* send cmd to modem to do voice device |
| * change */ |
| voice_disable_vocproc(v); |
| v->voc_state = VOC_CHANGE; |
| } |
| |
| mutex_unlock(&v->lock); |
| } |
| break; |
| case AUDDEV_EVT_DEV_RDY: |
| /* Device change is applicable to all sessions. */ |
| for (i = 0; i < MAX_VOC_SESSIONS; i++) { |
| v = &c->voice[i]; |
| |
| mutex_lock(&v->lock); |
| |
| if (v->voc_state == VOC_CHANGE) { |
| /* get port Ids */ |
| if (evt_payload->voc_devinfo.dev_type == |
| DIR_RX) { |
| v->dev_rx.dev_port_id = |
| evt_payload->voc_devinfo.dev_port_id; |
| v->dev_rx.sample = |
| evt_payload->voc_devinfo.dev_sample; |
| v->dev_rx.dev_id = |
| evt_payload->voc_devinfo.dev_id; |
| v->dev_rx.enabled = VOICE_DEV_ENABLED; |
| } else { |
| v->dev_tx.dev_port_id = |
| evt_payload->voc_devinfo.dev_port_id; |
| v->dev_tx.sample = |
| evt_payload->voc_devinfo.dev_sample; |
| v->dev_tx.enabled = VOICE_DEV_ENABLED; |
| v->dev_tx.dev_id = |
| evt_payload->voc_devinfo.dev_id; |
| } |
| if ((v->dev_rx.enabled == VOICE_DEV_ENABLED) && |
| (v->dev_tx.enabled == VOICE_DEV_ENABLED)) { |
| voice_set_device(v); |
| get_sidetone_cal(&sidetone_cal_data); |
| msm_snddev_enable_sidetone( |
| v->dev_rx.dev_id, |
| sidetone_cal_data.enable, |
| sidetone_cal_data.gain); |
| v->voc_state = VOC_RUN; |
| } |
| } else if ((v->voc_state == VOC_INIT) || |
| (v->voc_state == VOC_RELEASE)) { |
| /* get AFE ports */ |
| if (evt_payload->voc_devinfo.dev_type == |
| DIR_RX) { |
| /* get rx port id */ |
| v->dev_rx.dev_port_id = |
| evt_payload->voc_devinfo.dev_port_id; |
| v->dev_rx.sample = |
| evt_payload->voc_devinfo.dev_sample; |
| v->dev_rx.dev_id = |
| evt_payload->voc_devinfo.dev_id; |
| v->dev_rx.enabled = VOICE_DEV_ENABLED; |
| } else { |
| /* get tx port id */ |
| v->dev_tx.dev_port_id = |
| evt_payload->voc_devinfo.dev_port_id; |
| v->dev_tx.sample = |
| evt_payload->voc_devinfo.dev_sample; |
| v->dev_tx.dev_id = |
| evt_payload->voc_devinfo.dev_id; |
| v->dev_tx.enabled = VOICE_DEV_ENABLED; |
| } |
| if ((v->dev_rx.enabled == VOICE_DEV_ENABLED) && |
| (v->dev_tx.enabled == VOICE_DEV_ENABLED) && |
| (v->v_call_status == VOICE_CALL_START)) { |
| rc = voice_apr_register(); |
| if (rc < 0) { |
| pr_err("%s: voice apr" |
| "registration failed\n", |
| __func__); |
| mutex_unlock(&v->lock); |
| return; |
| } |
| voice_create_mvm_cvs_session(v); |
| voice_setup_modem_voice(v); |
| voice_attach_vocproc(v); |
| voice_send_start_voice_cmd(v); |
| get_sidetone_cal(&sidetone_cal_data); |
| msm_snddev_enable_sidetone( |
| v->dev_rx.dev_id, |
| sidetone_cal_data.enable, |
| sidetone_cal_data.gain); |
| v->voc_state = VOC_RUN; |
| |
| /* Start in-call recording if command |
| * was pending. */ |
| if (v->rec_info.pending) { |
| voice_cvs_start_record(v, |
| v->rec_info.rec_mode); |
| |
| v->rec_info.pending = 0; |
| } |
| |
| /* Start in-call music delivery if |
| * command was pending. */ |
| if (v->music_info.pending) { |
| voice_cvs_start_playback(v); |
| |
| v->music_info.pending = 0; |
| } |
| } |
| } |
| |
| mutex_unlock(&v->lock); |
| } |
| break; |
| case AUDDEV_EVT_DEVICE_VOL_MUTE_CHG: |
| v = voice_get_session( |
| evt_payload->voc_vm_info.voice_session_id); |
| if (v == NULL) { |
| pr_err("%s: v is NULL\n", __func__); |
| return; |
| } |
| |
| /* cache the mute and volume index value */ |
| if (evt_payload->voc_vm_info.dev_type == DIR_TX) { |
| v->dev_tx.mute = |
| evt_payload->voc_vm_info.dev_vm_val.mute; |
| |
| mutex_lock(&v->lock); |
| |
| if (v->voc_state == VOC_RUN) |
| voice_send_mute_cmd_to_modem(v); |
| |
| mutex_unlock(&v->lock); |
| } else { |
| v->dev_rx.volume = |
| evt_payload->voc_vm_info.dev_vm_val.vol; |
| |
| mutex_lock(&v->lock); |
| |
| if (v->voc_state == VOC_RUN) |
| voice_send_vol_index_to_modem(v); |
| |
| mutex_unlock(&v->lock); |
| } |
| break; |
| case AUDDEV_EVT_REL_PENDING: |
| /* Device change is applicable to all sessions. */ |
| for (i = 0; i < MAX_VOC_SESSIONS; i++) { |
| v = &c->voice[i]; |
| |
| mutex_lock(&v->lock); |
| |
| if (v->voc_state == VOC_RUN) { |
| voice_disable_vocproc(v); |
| v->voc_state = VOC_CHANGE; |
| } |
| |
| mutex_unlock(&v->lock); |
| |
| if (evt_payload->voc_devinfo.dev_type == DIR_RX) |
| v->dev_rx.enabled = VOICE_DEV_DISABLED; |
| else |
| v->dev_tx.enabled = VOICE_DEV_DISABLED; |
| } |
| |
| break; |
| case AUDDEV_EVT_END_VOICE: |
| v = voice_get_session(evt_payload->voice_session_id); |
| if (v == NULL) { |
| pr_err("%s: v is NULL\n", __func__); |
| return; |
| } |
| |
| /* recover the tx mute and rx volume to the default values */ |
| v->dev_tx.mute = c->default_mute_val; |
| v->dev_rx.volume = c->default_vol_val; |
| if (v->dev_rx.enabled == VOICE_DEV_ENABLED) |
| msm_snddev_enable_sidetone(v->dev_rx.dev_id, 0, 0); |
| |
| mutex_lock(&v->lock); |
| |
| if (v->voc_state == VOC_RUN) { |
| /* call stop modem voice */ |
| voice_send_stop_voice_cmd(v); |
| voice_destroy_modem_voice(v); |
| voice_destroy_mvm_cvs_session(v); |
| v->voc_state = VOC_RELEASE; |
| } else if (v->voc_state == VOC_CHANGE) { |
| voice_send_stop_voice_cmd(v); |
| voice_destroy_mvm_cvs_session(v); |
| v->voc_state = VOC_RELEASE; |
| } |
| |
| mutex_unlock(&v->lock); |
| |
| v->v_call_status = VOICE_CALL_END; |
| |
| break; |
| default: |
| pr_err("UNKNOWN EVENT\n"); |
| } |
| return; |
| } |
| EXPORT_SYMBOL(voice_auddev_cb_function); |
| |
| int voice_set_voc_path_full(uint32_t set) |
| { |
| pr_info("%s: %d\n", __func__, set); |
| |
| mutex_lock(&common.common_lock); |
| |
| if (set) |
| common.voc_path = VOC_PATH_FULL; |
| else |
| common.voc_path = VOC_PATH_PASSIVE; |
| |
| mutex_unlock(&common.common_lock); |
| |
| return 0; |
| } |
| EXPORT_SYMBOL(voice_set_voc_path_full); |
| |
| void voice_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 voice_config_vocoder(uint32_t media_type, |
| uint32_t rate, |
| uint32_t network_type, |
| uint32_t dtx_mode, |
| struct q_min_max_rate q_min_max_rate) |
| { |
| 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; |
| common.mvs_info.q_min_max_rate = q_min_max_rate; |
| } |
| |
| static int32_t modem_mvm_callback(struct apr_client_data *data, void *priv) |
| { |
| uint32_t *ptr; |
| struct common_data *c = priv; |
| struct voice_data *v = NULL; |
| int i = 0; |
| |
| pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port); |
| |
| if (data->opcode == RESET_EVENTS) { |
| pr_debug("%s:Reset event received in Voice service\n", |
| __func__); |
| apr_reset(c->apr_mvm); |
| c->apr_mvm = NULL; |
| 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; |
| } |
| |
| v = voice_get_session(data->dest_port); |
| if (v == NULL) { |
| pr_err("%s: v is NULL\n", __func__); |
| return -EINVAL; |
| } |
| |
| pr_debug("%s: common data 0x%x, session 0x%x\n", |
| __func__, (unsigned int)c, (unsigned int)v); |
| pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__, |
| data->payload_size, data->opcode); |
| |
| 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 */ |
| |
| if (ptr[0] == |
| VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION || |
| ptr[0] == |
| VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION) { |
| /* Passive session is used for voice call |
| * through modem. Full session is used for voice |
| * call through Q6. */ |
| 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_info("got NACK for sending \ |
| MVM create session \n"); |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_IMVM_CMD_START_VOICE) { |
| pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_ATTACH_VOCPROC) { |
| pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_IMVM_CMD_STOP_VOICE) { |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_DETACH_VOCPROC) { |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_SET_TTY_MODE) { |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == APRV2_IBASIC_CMD_DESTROY_SESSION) { |
| pr_debug("%s: DESTROY resp\n", __func__); |
| |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_IMVM_CMD_ATTACH_STREAM) { |
| pr_debug("%s: ATTACH_STREAM resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_IMVM_CMD_DETACH_STREAM) { |
| pr_debug("%s: DETACH_STREAM resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_ICOMMON_CMD_SET_NETWORK) { |
| pr_debug("%s: SET_NETWORK resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else if (ptr[0] == VSS_ICOMMON_CMD_SET_VOICE_TIMING) { |
| pr_debug("%s: SET_VOICE_TIMING resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->mvm_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->mvm_wait); |
| } else |
| pr_debug("%s: not match cmd = 0x%x\n", |
| __func__, ptr[0]); |
| } |
| } |
| |
| return 0; |
| } |
| |
| static int32_t modem_cvs_callback(struct apr_client_data *data, void *priv) |
| { |
| uint32_t *ptr; |
| struct common_data *c = priv; |
| struct voice_data *v = NULL; |
| int i = 0; |
| |
| pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port); |
| |
| if (data->opcode == RESET_EVENTS) { |
| pr_debug("%s:Reset event received in Voice service\n", |
| __func__); |
| apr_reset(c->apr_cvs); |
| c->apr_cvs = NULL; |
| 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; |
| } |
| |
| v = voice_get_session(data->dest_port); |
| if (v == NULL) { |
| pr_err("%s: v is NULL\n", __func__); |
| return -EINVAL; |
| } |
| |
| pr_debug("%s: common data 0x%x, session 0x%x\n", |
| __func__, (unsigned int)c, (unsigned int)v); |
| pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__, |
| data->payload_size, data->opcode); |
| |
| 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 modem CVS */ |
| if (ptr[0] == |
| VSS_ISTREAM_CMD_CREATE_PASSIVE_CONTROL_SESSION || |
| ptr[0] == |
| 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_info("got NACK for sending \ |
| CVS create session \n"); |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == |
| VSS_ISTREAM_CMD_CACHE_CALIBRATION_DATA) { |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == |
| VSS_ISTREAM_CMD_SET_MUTE) { |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_SET_MEDIA_TYPE) { |
| pr_debug("%s: SET_MEDIA resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == |
| VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE) { |
| pr_debug("%s: SET_AMR_RATE resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == |
| VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE) { |
| pr_debug("%s: SET_AMR_WB_RATE resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_SET_ENC_DTX_MODE) { |
| pr_debug("%s: SET_DTX resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == |
| VSS_ISTREAM_CMD_CDMA_SET_ENC_MINMAX_RATE) { |
| pr_debug("%s: SET_CDMA_RATE resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == APRV2_IBASIC_CMD_DESTROY_SESSION) { |
| pr_debug("%s: DESTROY resp\n", __func__); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_START_RECORD) { |
| pr_debug("%s: START_RECORD resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_STOP_RECORD) { |
| pr_debug("%s: STOP_RECORD resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == VOICE_CMD_SET_PARAM) { |
| rtac_make_voice_callback(RTAC_CVS, ptr, |
| data->payload_size); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_START_PLAYBACK) { |
| pr_debug("%s: START_PLAYBACK resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else if (ptr[0] == VSS_ISTREAM_CMD_STOP_PLAYBACK) { |
| pr_debug("%s: STOP_PLAYBACK resp 0x%x\n", |
| __func__, ptr[1]); |
| |
| v->cvs_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvs_wait); |
| } else |
| pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); |
| } |
| } 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_SEND_DEC_BUFFER) { |
| pr_debug("%s: Send dec buf resp\n", __func__); |
| } 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(voice_get_apr_cvs(), |
| (uint32_t *) &send_dec_buf); |
| if (ret < 0) { |
| pr_err("%s: Error %d sending DEC_BUF\n", |
| __func__, ret); |
| goto fail; |
| } |
| } else { |
| pr_err("%s: ul_cb is NULL\n", __func__); |
| } |
| } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) { |
| rtac_make_voice_callback(RTAC_CVS, data->payload, |
| data->payload_size); |
| } else { |
| pr_debug("%s: Unknown opcode 0x%x\n", __func__, data->opcode); |
| } |
| |
| fail: |
| return 0; |
| } |
| |
| static int32_t modem_cvp_callback(struct apr_client_data *data, void *priv) |
| { |
| uint32_t *ptr; |
| struct common_data *c = priv; |
| struct voice_data *v = NULL; |
| int i = 0; |
| |
| pr_debug("%s: session_id 0x%x\n", __func__, data->dest_port); |
| |
| if (data->opcode == RESET_EVENTS) { |
| pr_debug("%s:Reset event received in Voice service\n", |
| __func__); |
| apr_reset(c->apr_cvp); |
| c->apr_cvp = NULL; |
| 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; |
| } |
| |
| v = voice_get_session(data->dest_port); |
| if (v == NULL) { |
| pr_err("%s: v is NULL\n", __func__); |
| return -EINVAL; |
| } |
| |
| pr_debug("%s: common data 0x%x, session 0x%x\n", |
| __func__, (unsigned int)c, (unsigned int)v); |
| pr_debug("%s: Payload Length = %d, opcode=%x\n", __func__, |
| data->payload_size, data->opcode); |
| |
| 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 modem CVP */ |
| if (ptr[0] == |
| VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION) { |
| 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_info("got NACK from CVP create \ |
| session response\n"); |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == |
| VSS_IVOCPROC_CMD_CACHE_CALIBRATION_DATA) { |
| pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == VSS_IVOCPROC_CMD_SET_DEVICE) { |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == |
| VSS_IVOCPROC_CMD_SET_RX_VOLUME_INDEX) { |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == VSS_IVOCPROC_CMD_ENABLE) { |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == VSS_IVOCPROC_CMD_DISABLE) { |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == APRV2_IBASIC_CMD_DESTROY_SESSION) { |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == |
| VSS_IVOCPROC_CMD_CACHE_VOLUME_CALIBRATION_TABLE |
| ) { |
| |
| pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]); |
| v->cvp_state = CMD_STATUS_SUCCESS; |
| wake_up(&v->cvp_wait); |
| } else if (ptr[0] == VOICE_CMD_SET_PARAM) { |
| rtac_make_voice_callback(RTAC_CVP, ptr, |
| data->payload_size); |
| } else |
| pr_debug("%s: not match cmd = 0x%x\n", |
| __func__, ptr[0]); |
| } |
| } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) { |
| rtac_make_voice_callback(RTAC_CVP, data->payload, |
| data->payload_size); |
| } |
| return 0; |
| } |
| |
| |
| static int __init voice_init(void) |
| { |
| int rc = 0, i = 0; |
| |
| memset(&common, 0, sizeof(struct common_data)); |
| |
| /* set default value */ |
| common.default_mute_val = 1; /* default is mute */ |
| common.default_vol_val = 0; |
| common.default_sample_val = 8000; |
| |
| common.voc_path = VOC_PATH_PASSIVE; |
| |
| /* 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; |
| |
| common.voice[i].dev_rx.volume = common.default_vol_val; |
| common.voice[i].dev_tx.mute = common.default_mute_val; |
| |
| common.voice[i].voc_state = VOC_INIT; |
| |
| common.voice[i].rec_info.rec_mode = VOC_REC_NONE; |
| |
| 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); |
| |
| } |
| |
| common.device_events = AUDDEV_EVT_DEV_CHG_VOICE | |
| AUDDEV_EVT_DEV_RDY | |
| AUDDEV_EVT_REL_PENDING | |
| AUDDEV_EVT_START_VOICE | |
| AUDDEV_EVT_END_VOICE | |
| AUDDEV_EVT_DEVICE_VOL_MUTE_CHG | |
| AUDDEV_EVT_FREQ_CHG; |
| |
| pr_debug("to register call back\n"); |
| /* register callback to auddev */ |
| auddev_register_evt_listner(common.device_events, AUDDEV_CLNT_VOC, |
| 0, voice_auddev_cb_function, &common); |
| |
| return rc; |
| } |
| |
| device_initcall(voice_init); |