/* 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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);