diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2016-12-20 14:04:49 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2016-12-20 14:04:49 -0800 |
commit | 314122fcd05fe0f710edb9368247c732cc840d78 (patch) | |
tree | 0a97e368f777a372824d9df056d3646b62ed9316 /sound | |
parent | b0ba6bde9d794e09bde7372a314a52ec9020eaab (diff) | |
parent | dd764997fa84cf5e42beb3cb9f3e5cceee5058ea (diff) |
Merge "msm: qdsp6v2: extend media format provided to voice driver"
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c | 62 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/q6voice.c | 315 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/q6voice.h | 123 | ||||
-rw-r--r-- | sound/soc/msm/qdsp6v2/rtac.c | 24 |
4 files changed, 459 insertions, 65 deletions
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 01902f7f571d..8c545560cf10 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -1481,6 +1481,7 @@ static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set) { u32 session_id = 0; u16 path_type; + struct media_format_info voc_be_media_format; pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set); @@ -1513,8 +1514,22 @@ static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set) if (set) { if (msm_bedais[reg].active) { voc_set_route_flag(session_id, path_type, 1); + + memset(&voc_be_media_format, 0, + sizeof(struct media_format_info)); + + voc_be_media_format.port_id = msm_bedais[reg].port_id; + voc_be_media_format.num_channels = + msm_bedais[reg].channel; + voc_be_media_format.sample_rate = + msm_bedais[reg].sample_rate; + voc_be_media_format.bits_per_sample = + msm_bedais[reg].format; + /* Defaulting this to 1 for voice call usecases */ + voc_be_media_format.channel_mapping[0] = 1; + voc_set_device_config(session_id, path_type, - msm_bedais[reg].channel, msm_bedais[reg].port_id); + &voc_be_media_format); if (voc_get_route_flag(session_id, TX_PATH) && voc_get_route_flag(session_id, RX_PATH)) @@ -2381,9 +2396,9 @@ static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol, } pr_debug("%s: val = %d ext_ec_ref_port_id = 0x%0x state = %d\n", - __func__, msm_route_ext_ec_ref, ext_ec_ref_port_id, state); + __func__, msm_route_ext_ec_ref, ext_ec_ref_port_id, state); - if (!voc_set_ext_ec_ref(ext_ec_ref_port_id, state)) { + if (!voc_set_ext_ec_ref_port_id(ext_ec_ref_port_id, state)) { mutex_unlock(&routing_lock); snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update); } else { @@ -11433,6 +11448,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) uint16_t bits_per_sample = 16, voc_path_type; struct msm_pcm_routing_fdai_data *fdai; u32 session_id; + struct media_format_info voc_be_media_format; pr_debug("%s: substream->pcm->id:%s\n", __func__, substream->pcm->id); @@ -11545,8 +11561,8 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) { session_id = msm_pcm_routing_get_voc_sessionid(i); if (session_id) { - pr_debug("%s voice session_id: 0x%x", - __func__, session_id); + pr_debug("%s voice session_id: 0x%x\n", __func__, + session_id); if (session_type == SESSION_TYPE_TX) voc_path_type = TX_PATH; @@ -11554,8 +11570,19 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) voc_path_type = RX_PATH; voc_set_route_flag(session_id, voc_path_type, 1); - voc_set_device_config(session_id, voc_path_type, - bedai->channel, bedai->port_id); + + memset(&voc_be_media_format, 0, + sizeof(struct media_format_info)); + + voc_be_media_format.port_id = bedai->port_id; + voc_be_media_format.num_channels = bedai->channel; + voc_be_media_format.sample_rate = bedai->sample_rate; + voc_be_media_format.bits_per_sample = bedai->format; + /* Defaulting this to 1 for voice call usecases */ + voc_be_media_format.channel_mapping[0] = 1; + + voc_set_device_config(session_id, voc_path_type, + &voc_be_media_format); if (voc_get_route_flag(session_id, RX_PATH) && voc_get_route_flag(session_id, TX_PATH)) @@ -11563,6 +11590,27 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream) } } + /* Check if backend is an external ec ref port and set as needed */ + if (unlikely(bedai->port_id == voc_get_ext_ec_ref_port_id())) { + + memset(&voc_be_media_format, 0, + sizeof(struct media_format_info)); + + /* Get format info for ec ref port from msm_bedais[] */ + voc_be_media_format.port_id = bedai->port_id; + voc_be_media_format.num_channels = bedai->channel; + voc_be_media_format.bits_per_sample = bedai->format; + voc_be_media_format.sample_rate = bedai->sample_rate; + /* Defaulting this to 1 for voice call usecases */ + voc_be_media_format.channel_mapping[0] = 1; + voc_set_ext_ec_ref_media_fmt_info(&voc_be_media_format); + pr_debug("%s: EC Ref media format info set to port_id=%d, num_channels=%d, bits_per_sample=%d, sample_rate=%d\n", + __func__, voc_be_media_format.port_id, + voc_be_media_format.num_channels, + voc_be_media_format.bits_per_sample, + voc_be_media_format.sample_rate); + } + done: mutex_unlock(&routing_lock); diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c index b242a8fe6017..5cff3dd1ed4f 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.c +++ b/sound/soc/msm/qdsp6v2/q6voice.c @@ -78,7 +78,10 @@ static int voice_send_cvp_register_cal_cmd(struct voice_data *v); static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v); static int voice_send_cvp_register_vol_cal_cmd(struct voice_data *v); static int voice_send_cvp_deregister_vol_cal_cmd(struct voice_data *v); +static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v); static int voice_send_cvp_device_channels_cmd(struct voice_data *v); +static int voice_send_cvp_media_format_cmd(struct voice_data *v, + uint32_t param_type); static int voice_send_cvp_topology_commit_cmd(struct voice_data *v); static int voice_cvs_stop_playback(struct voice_data *v); @@ -2398,7 +2401,7 @@ static int voice_send_set_device_cmd(struct voice_data *v) cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING; cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id = - common.ec_port_id; + common.ec_media_fmt_info.port_id; } else { cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING; @@ -2752,7 +2755,7 @@ static int voice_send_cvp_create_cmd(struct voice_data *v) cvp_session_cmd.cvp_session.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING; cvp_session_cmd.cvp_session.ec_ref_port_id = - common.ec_port_id; + common.ec_media_fmt_info.port_id; } else { cvp_session_cmd.cvp_session.vocproc_mode = VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING; @@ -3826,10 +3829,10 @@ static int voice_setup_vocproc(struct voice_data *v) goto fail; } - ret = voice_send_cvp_device_channels_cmd(v); + ret = voice_send_cvp_media_fmt_info_cmd(v); if (ret < 0) { - pr_err("%s: Set device channels failed err:%d\n", - __func__, ret); + pr_err("%s: Set media format info failed err:%d\n", __func__, + ret); goto fail; } @@ -3983,6 +3986,158 @@ done: return ret; } +static int voice_send_cvp_media_fmt_info_cmd(struct voice_data *v) +{ + int ret; + + if (voice_get_cvd_int_version(common.cvd_version) >= + CVD_INT_VERSION_2_3) { + ret = voice_send_cvp_media_format_cmd(v, RX_PATH); + if (ret < 0) + goto done; + + ret = voice_send_cvp_media_format_cmd(v, TX_PATH); + if (ret < 0) + goto done; + + if (common.ec_ref_ext) + ret = voice_send_cvp_media_format_cmd(v, EC_REF_PATH); + } else { + ret = voice_send_cvp_device_channels_cmd(v); + } + +done: + return ret; +} + +static int voice_send_cvp_media_format_cmd(struct voice_data *v, + uint32_t param_type) +{ + int ret = 0; + struct cvp_set_media_format_cmd cvp_set_media_format_cmd; + void *apr_cvp; + u16 cvp_handle; + struct vss_icommon_param_data_t *media_fmt_param_data = + &cvp_set_media_format_cmd.cvp_set_param_v2.param_data; + struct vss_param_endpoint_media_format_info_t *media_fmt_info = + &media_fmt_param_data->media_format_info; + + if (v == NULL) { + pr_err("%s: v is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + apr_cvp = common.apr_q6_cvp; + if (!apr_cvp) { + pr_err("%s: apr_cvp is NULL.\n", __func__); + ret = -EINVAL; + goto done; + } + + cvp_handle = voice_get_cvp_handle(v); + memset(&cvp_set_media_format_cmd, 0, sizeof(cvp_set_media_format_cmd)); + + /* Fill header data */ + cvp_set_media_format_cmd.hdr.hdr_field = + APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, APR_HDR_LEN(APR_HDR_SIZE), + APR_PKT_VER); + cvp_set_media_format_cmd.hdr.pkt_size = + APR_PKT_SIZE(APR_HDR_SIZE, + sizeof(cvp_set_media_format_cmd) - APR_HDR_SIZE); + cvp_set_media_format_cmd.hdr.src_svc = 0; + cvp_set_media_format_cmd.hdr.src_domain = APR_DOMAIN_APPS; + cvp_set_media_format_cmd.hdr.src_port = + voice_get_idx_for_session(v->session_id); + cvp_set_media_format_cmd.hdr.dest_svc = 0; + cvp_set_media_format_cmd.hdr.dest_domain = APR_DOMAIN_ADSP; + cvp_set_media_format_cmd.hdr.dest_port = cvp_handle; + cvp_set_media_format_cmd.hdr.token = VOC_SET_MEDIA_FORMAT_PARAM_TOKEN; + cvp_set_media_format_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_PARAM_V2; + + /* Fill param data */ + cvp_set_media_format_cmd.cvp_set_param_v2.mem_size = + sizeof(struct vss_icommon_param_data_t); + media_fmt_param_data->module_id = VSS_MODULE_CVD_GENERIC; + media_fmt_param_data->param_size = + sizeof(struct vss_param_endpoint_media_format_info_t); + + /* Fill device specific data */ + switch (param_type) { + case RX_PATH: + media_fmt_param_data->param_id = + VSS_PARAM_RX_PORT_ENDPOINT_MEDIA_INFO; + media_fmt_info->port_id = v->dev_rx.port_id; + media_fmt_info->num_channels = v->dev_rx.no_of_channels; + media_fmt_info->bits_per_sample = v->dev_rx.bits_per_sample; + media_fmt_info->sample_rate = v->dev_rx.sample_rate; + memcpy(&media_fmt_info->channel_mapping, + &v->dev_rx.channel_mapping, VSS_CHANNEL_MAPPING_SIZE); + break; + + case TX_PATH: + media_fmt_param_data->param_id = + VSS_PARAM_TX_PORT_ENDPOINT_MEDIA_INFO; + media_fmt_info->port_id = v->dev_tx.port_id; + media_fmt_info->num_channels = v->dev_tx.no_of_channels; + media_fmt_info->bits_per_sample = v->dev_tx.bits_per_sample; + media_fmt_info->sample_rate = v->dev_tx.sample_rate; + memcpy(&media_fmt_info->channel_mapping, + &v->dev_tx.channel_mapping, VSS_CHANNEL_MAPPING_SIZE); + break; + + case EC_REF_PATH: + media_fmt_param_data->param_id = + VSS_PARAM_EC_REF_PORT_ENDPOINT_MEDIA_INFO; + media_fmt_info->port_id = common.ec_media_fmt_info.port_id; + media_fmt_info->num_channels = + common.ec_media_fmt_info.num_channels; + media_fmt_info->bits_per_sample = + common.ec_media_fmt_info.bits_per_sample; + media_fmt_info->sample_rate = + common.ec_media_fmt_info.sample_rate; + memcpy(&media_fmt_info->channel_mapping, + &common.ec_media_fmt_info.channel_mapping, + VSS_CHANNEL_MAPPING_SIZE); + break; + + default: + pr_err("%s: Invalid param type %d\n", __func__, param_type); + ret = -EINVAL; + goto done; + } + + /* Send command */ + v->cvp_state = CMD_STATUS_FAIL; + v->async_err = 0; + ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_set_media_format_cmd); + if (ret < 0) { + pr_err("%s: Fail in sending VSS_ICOMMON_CMD_SET_PARAM_V2\n", + __func__); + ret = -EINVAL; + goto done; + } + + 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__); + ret = -EINVAL; + goto done; + } + + if (v->async_err > 0) { + pr_err("%s: DSP returned error[%s] handle = %d\n", __func__, + adsp_err_get_err_str(v->async_err), cvp_handle); + ret = adsp_err_get_lnx_err_code(v->async_err); + goto done; + } + +done: + return ret; +} + static int voice_send_cvp_topology_commit_cmd(struct voice_data *v) { int ret = 0; @@ -5743,7 +5898,7 @@ int voc_set_rx_vol_step(uint32_t session_id, uint32_t dir, uint32_t vol_step, } int voc_set_device_config(uint32_t session_id, uint8_t path_dir, - uint8_t no_of_channels, uint32_t port_id) + struct media_format_info *finfo) { struct voice_data *v = voice_get_session(session_id); @@ -5753,22 +5908,55 @@ int voc_set_device_config(uint32_t session_id, uint8_t path_dir, return -EINVAL; } - pr_debug("%s: path_dir=%d port_id=%x, channels=%d\n", - __func__, path_dir, port_id, no_of_channels); + pr_debug("%s: path_dir=%d port_id=%x, channels=%d, sample_rate=%d, bits_per_sample=%d\n", + __func__, path_dir, finfo->port_id, finfo->num_channels, + finfo->sample_rate, finfo->bits_per_sample); mutex_lock(&v->lock); - if (path_dir == RX_PATH) { - v->dev_rx.port_id = q6audio_get_port_id(port_id); - v->dev_rx.no_of_channels = no_of_channels; - } else { - v->dev_tx.port_id = q6audio_get_port_id(port_id); - v->dev_tx.no_of_channels = no_of_channels; + switch (path_dir) { + case RX_PATH: + v->dev_rx.port_id = q6audio_get_port_id(finfo->port_id); + v->dev_rx.no_of_channels = finfo->num_channels; + v->dev_rx.sample_rate = finfo->sample_rate; + v->dev_rx.bits_per_sample = finfo->bits_per_sample; + memcpy(&v->dev_rx.channel_mapping, &finfo->channel_mapping, + VSS_CHANNEL_MAPPING_SIZE); + break; + case TX_PATH: + v->dev_tx.port_id = q6audio_get_port_id(finfo->port_id); + v->dev_tx.no_of_channels = finfo->num_channels; + v->dev_tx.sample_rate = finfo->sample_rate; + v->dev_tx.bits_per_sample = finfo->bits_per_sample; + memcpy(&v->dev_tx.channel_mapping, &finfo->channel_mapping, + VSS_CHANNEL_MAPPING_SIZE); + break; + default: + pr_err("%s: Invalid path_dir %d\n", __func__, path_dir); + return -EINVAL; } + mutex_unlock(&v->lock); return 0; } +int voc_set_ext_ec_ref_media_fmt_info(struct media_format_info *finfo) +{ + mutex_lock(&common.common_lock); + if (common.ec_ref_ext) { + common.ec_media_fmt_info.num_channels = finfo->num_channels; + common.ec_media_fmt_info.bits_per_sample = + finfo->bits_per_sample; + common.ec_media_fmt_info.sample_rate = finfo->sample_rate; + memcpy(&common.ec_media_fmt_info.channel_mapping, + &finfo->channel_mapping, VSS_CHANNEL_MAPPING_SIZE); + } else { + pr_debug("%s: Ext Ec Ref not active, returning", __func__); + } + mutex_unlock(&common.common_lock); + return 0; +} + int voc_set_route_flag(uint32_t session_id, uint8_t path_dir, uint8_t set) { struct voice_data *v = voice_get_session(session_id); @@ -5982,9 +6170,9 @@ int voc_enable_device(uint32_t session_id) goto done; } - ret = voice_send_cvp_device_channels_cmd(v); + ret = voice_send_cvp_media_fmt_info_cmd(v); if (ret < 0) { - pr_err("%s: Set device channels failed\n", __func__); + pr_err("%s: Set format failed err:%d\n", __func__, ret); goto done; } @@ -6179,7 +6367,7 @@ fail: return ret; } -int voc_set_ext_ec_ref(uint16_t port_id, bool state) +int voc_set_ext_ec_ref_port_id(uint16_t port_id, bool state) { int ret = 0; @@ -6190,17 +6378,25 @@ int voc_set_ext_ec_ref(uint16_t port_id, bool state) ret = -EINVAL; goto exit; } - common.ec_port_id = port_id; common.ec_ref_ext = true; } else { common.ec_ref_ext = false; - common.ec_port_id = port_id; } + /* Cache EC Fromat Info in common */ + common.ec_media_fmt_info.port_id = port_id; exit: mutex_unlock(&common.common_lock); return ret; } +int voc_get_ext_ec_ref_port_id(void) +{ + if (common.ec_ref_ext) + return common.ec_media_fmt_info.port_id; + else + return AFE_PORT_INVALID; +} + void voc_register_mvs_cb(ul_cb_fn ul_cb, dl_cb_fn dl_cb, voip_ssr_cb ssr_cb, @@ -6557,18 +6753,19 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) v->async_err = ptr[1]; wake_up(&v->cvs_wait); break; - case VOICE_CMD_SET_PARAM: - pr_debug("%s: VOICE_CMD_SET_PARAM\n", __func__); + case VSS_ICOMMON_CMD_SET_PARAM_V2: + pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2\n", + __func__); rtac_make_voice_callback(RTAC_CVS, ptr, data->payload_size); break; - case VOICE_CMD_GET_PARAM: - pr_debug("%s: VOICE_CMD_GET_PARAM\n", - __func__); + case VSS_ICOMMON_CMD_GET_PARAM_V2: + pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n", + __func__); /* Should only come here if there is an APR */ /* error or malformed APR packet. Otherwise */ /* response will be returned as */ - /* VOICE_EVT_GET_PARAM_ACK */ + /* VSS_ICOMMON_RSP_GET_PARAM */ if (ptr[1] != 0) { pr_err("%s: CVP get param error = %d, resuming\n", __func__, ptr[1]); @@ -6695,12 +6892,12 @@ static int32_t qdsp_cvs_callback(struct apr_client_data *data, void *priv) pr_debug("Recd VSS_ISTREAM_EVT_NOT_READY\n"); } else if (data->opcode == VSS_ISTREAM_EVT_READY) { pr_debug("Recd VSS_ISTREAM_EVT_READY\n"); - } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) { - pr_debug("%s: VOICE_EVT_GET_PARAM_ACK\n", __func__); + } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) { + pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__); ptr = data->payload; if (ptr[0] != 0) { - pr_err("%s: VOICE_EVT_GET_PARAM_ACK returned error = 0x%x\n", - __func__, ptr[0]); + pr_err("%s: VSS_ICOMMON_RSP_GET_PARAM returned error = 0x%x\n", + __func__, ptr[0]); } rtac_make_voice_callback(RTAC_CVS, data->payload, data->payload_size); @@ -6837,18 +7034,35 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv) break; case VSS_IVPCM_EVT_PUSH_BUFFER_V2: break; - case VOICE_CMD_SET_PARAM: - pr_debug("%s: VOICE_CMD_SET_PARAM\n", __func__); - rtac_make_voice_callback(RTAC_CVP, ptr, - data->payload_size); + case VSS_ICOMMON_CMD_SET_PARAM_V2: + switch (data->token) { + case VOC_SET_MEDIA_FORMAT_PARAM_TOKEN: + pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by voice_send_cvp_media_format_cmd\n", + __func__); + v->cvp_state = CMD_STATUS_SUCCESS; + v->async_err = ptr[1]; + wake_up(&v->cvp_wait); + break; + case VOC_RTAC_SET_PARAM_TOKEN: + pr_debug("%s: VSS_ICOMMON_CMD_SET_PARAM_V2 called by rtac\n", + __func__); + rtac_make_voice_callback( + RTAC_CVP, ptr, + data->payload_size); + break; + default: + pr_debug("%s: invalid token for command VSS_ICOMMON_CMD_SET_PARAM_V2: %d\n", + __func__, data->token); + break; + } break; - case VOICE_CMD_GET_PARAM: - pr_debug("%s: VOICE_CMD_GET_PARAM\n", - __func__); + case VSS_ICOMMON_CMD_GET_PARAM_V2: + pr_debug("%s: VSS_ICOMMON_CMD_GET_PARAM_V2\n", + __func__); /* Should only come here if there is an APR */ /* error or malformed APR packet. Otherwise */ /* response will be returned as */ - /* VOICE_EVT_GET_PARAM_ACK */ + /* VSS_ICOMMON_RSP_GET_PARAM */ if (ptr[1] != 0) { pr_err("%s: CVP get param error = %d, resuming\n", __func__, ptr[1]); @@ -6909,12 +7123,12 @@ static int32_t qdsp_cvp_callback(struct apr_client_data *data, void *priv) break; } } - } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) { - pr_debug("%s: VOICE_EVT_GET_PARAM_ACK\n", __func__); + } else if (data->opcode == VSS_ICOMMON_RSP_GET_PARAM) { + pr_debug("%s: VSS_ICOMMON_RSP_GET_PARAM\n", __func__); ptr = data->payload; if (ptr[0] != 0) { - pr_err("%s: VOICE_EVT_GET_PARAM_ACK returned error = 0x%x\n", - __func__, ptr[0]); + pr_err("%s: VSS_ICOMMON_RSP_GET_PARAM returned error = 0x%x\n", + __func__, ptr[0]); } rtac_make_voice_callback(RTAC_CVP, data->payload, data->payload_size); @@ -8335,7 +8549,16 @@ static int __init voice_init(void) common.default_vol_step_val = 0; common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION; common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION; + + /* Initialize EC Ref media format info */ common.ec_ref_ext = false; + common.ec_media_fmt_info.port_id = AFE_PORT_INVALID; + common.ec_media_fmt_info.num_channels = 0; + common.ec_media_fmt_info.bits_per_sample = 16; + common.ec_media_fmt_info.sample_rate = 8000; + memset(&common.ec_media_fmt_info.channel_mapping, 0, + VSS_CHANNEL_MAPPING_SIZE); + /* Initialize MVS info. */ common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT; @@ -8373,8 +8596,16 @@ static int __init voice_init(void) common.voice[i].dev_rx.port_id = 0x100A; common.voice[i].dev_tx.dev_id = 0; common.voice[i].dev_rx.dev_id = 0; - common.voice[i].dev_rx.no_of_channels = 0; common.voice[i].dev_tx.no_of_channels = 0; + common.voice[i].dev_rx.no_of_channels = 0; + common.voice[i].dev_tx.sample_rate = 8000; + common.voice[i].dev_rx.sample_rate = 8000; + common.voice[i].dev_tx.bits_per_sample = 16; + common.voice[i].dev_rx.bits_per_sample = 16; + memset(&common.voice[i].dev_tx.channel_mapping, 0, + VSS_CHANNEL_MAPPING_SIZE); + memset(&common.voice[i].dev_rx.channel_mapping, 0, + VSS_CHANNEL_MAPPING_SIZE); common.voice[i].sidetone_gain = 0x512; common.voice[i].dtmf_rx_detect_en = 0; common.voice[i].lch_mode = 0; diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h index 834fe7c05306..9c3ec62a980d 100644 --- a/sound/soc/msm/qdsp6v2/q6voice.h +++ b/sound/soc/msm/qdsp6v2/q6voice.h @@ -22,6 +22,8 @@ #define SESSION_NAME_LEN 20 #define NUM_OF_MEMORY_BLOCKS 1 #define NUM_OF_BUFFERS 2 +#define VSS_NUM_CHANNELS_MAX 8 +#define VSS_CHANNEL_MAPPING_SIZE (sizeof(uint8_t) * VSS_NUM_CHANNELS_MAX) /* * BUFFER BLOCK SIZE based on * the supported page size @@ -98,7 +100,9 @@ struct stream_data { /* Device information payload structure */ struct device_data { uint32_t dev_mute; - uint32_t sample; + uint32_t sample_rate; + uint16_t bits_per_sample; + uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX]; uint32_t enabled; uint32_t dev_id; uint32_t port_id; @@ -108,6 +112,25 @@ struct device_data { uint32_t no_of_channels; }; +/* + * Format information structure to match + * vss_param_endpoint_media_format_info_t + */ +struct media_format_info { + uint32_t port_id; + uint16_t num_channels; + uint16_t bits_per_sample; + uint32_t sample_rate; + uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX]; +}; + +enum { + VOC_NO_SET_PARAM_TOKEN = 0, + VOC_RTAC_SET_PARAM_TOKEN, + VOC_SET_MEDIA_FORMAT_PARAM_TOKEN, + VOC_SET_PARAM_TOKEN_MAX +}; + struct voice_dev_route_state { u16 rx_route_flag; u16 tx_route_flag; @@ -190,6 +213,81 @@ struct vss_unmap_memory_cmd { struct vss_icommon_cmd_unmap_memory_t vss_unmap_mem; } __packed; +struct vss_param_endpoint_media_format_info_t { + /* AFE port ID to which this media format corresponds to. */ + uint32_t port_id; + /* + * Number of channels of data. + * Supported values: 1 to 8 + */ + uint16_t num_channels; + /* + * Bits per sample of data. + * Supported values: 16 and 24 + */ + uint16_t bits_per_sample; + /* + * Sampling rate in Hz. + * Supported values: 8000, 11025, 16000, 22050, 24000, 32000, + * 44100, 48000, 88200, 96000, 176400, and 192000 + */ + uint32_t sample_rate; + /* + * The channel[i] mapping describes channel i. Each element i + * of the array describes channel i inside the data buffer. An + * unused or unknown channel is set to 0. + */ + uint8_t channel_mapping[VSS_NUM_CHANNELS_MAX]; +} __packed; + +struct vss_icommon_param_data_t { + /* Valid ID of the module. */ + uint32_t module_id; + /* Valid ID of the parameter. */ + uint32_t param_id; + /* + * Data size of the structure relating to the param_id/module_id + * combination in uint8_t bytes. + */ + uint16_t param_size; + /* This field must be set to zero. */ + uint16_t reserved; + /* + * Parameter data payload when inband. Should have size param_size. + * Bit size of payload must be a multiple of 4. + */ + union { + struct vss_param_endpoint_media_format_info_t media_format_info; + }; +} __packed; + +/* Payload structure for the VSS_ICOMMON_CMD_SET_PARAM_V2 command. */ +struct vss_icommon_cmd_set_param_v2_t { + /* + * Pointer to the unique identifier for an address (physical/virtual). + * + * If the parameter data payload is within the message payload + * (in-band), set this field to 0. The parameter data begins at the + * specified data payload address. + * + * If the parameter data is out-of-band, this field is the handle to + * the physical address in the shared memory that holds the parameter + * data. + */ + uint32_t mem_handle; + /* + * Location of the parameter data payload. + * + * The payload is an array of vss_icommon_param_data_t. If the + * mem_handle is 0, this field is ignored. + */ + uint64_t mem_address; + /* Size of the parameter data payload in bytes. */ + uint32_t mem_size; + /* Parameter data payload when the data is inband. */ + struct vss_icommon_param_data_t param_data; +} __packed; + /* TO MVM commands */ #define VSS_IMVM_CMD_CREATE_PASSIVE_CONTROL_SESSION 0x000110FF /**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */ @@ -577,6 +675,14 @@ struct vss_imemory_cmd_unmap_t { #define VSS_IRECORD_MODE_TX_RX_MIXING 0x00010F7B /* Select mixed Tx and Rx paths. */ +#define VSS_PARAM_TX_PORT_ENDPOINT_MEDIA_INFO 0x00013253 + +#define VSS_PARAM_RX_PORT_ENDPOINT_MEDIA_INFO 0x00013254 + +#define VSS_PARAM_EC_REF_PORT_ENDPOINT_MEDIA_INFO 0x00013255 + +#define VSS_MODULE_CVD_GENERIC 0x0001316E + #define VSS_ISTREAM_EVT_NOT_READY 0x000110FD #define VSS_ISTREAM_EVT_READY 0x000110FC @@ -1378,6 +1484,11 @@ struct cvp_set_dev_channels_cmd { struct vss_ivocproc_cmd_topology_set_dev_channels_t cvp_set_channels; } __packed; +struct cvp_set_media_format_cmd { + struct apr_hdr hdr; + struct vss_icommon_cmd_set_param_v2_t cvp_set_param_v2; +} __packed; + struct cvp_set_vp3_data_cmd { struct apr_hdr hdr; } __packed; @@ -1613,7 +1724,7 @@ struct common_data { uint32_t default_vol_ramp_duration_ms; uint32_t default_mute_ramp_duration_ms; bool ec_ref_ext; - uint16_t ec_port_id; + struct media_format_info ec_media_fmt_info; /* APR to MVM in the Q6 */ void *apr_q6_mvm; @@ -1685,9 +1796,9 @@ enum { enum { RX_PATH = 0, TX_PATH, + EC_REF_PATH, }; - #define VOC_PATH_PASSIVE 0 #define VOC_PATH_FULL 1 #define VOC_PATH_VOLTE_PASSIVE 2 @@ -1773,7 +1884,9 @@ uint32_t voc_get_session_id(char *name); int voc_start_playback(uint32_t set, uint16_t port_id); int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id); int voice_get_idx_for_session(u32 session_id); -int voc_set_ext_ec_ref(uint16_t port_id, bool state); +int voc_set_ext_ec_ref_port_id(uint16_t port_id, bool state); +int voc_get_ext_ec_ref_port_id(void); +int voc_set_ext_ec_ref_media_fmt_info(struct media_format_info *finfo); int voc_update_amr_vocoder_rate(uint32_t session_id); int voc_disable_device(uint32_t session_id); int voc_enable_device(uint32_t session_id); @@ -1781,7 +1894,7 @@ void voc_set_destroy_cvd_flag(bool is_destroy_cvd); void voc_set_vote_bms_flag(bool is_vote_bms); int voc_disable_topology(uint32_t session_id, uint32_t disable); int voc_set_device_config(uint32_t session_id, uint8_t path_dir, - uint8_t no_of_channels, uint32_t dev_port_id); + struct media_format_info *finfo); uint32_t voice_get_topology(uint32_t topology_idx); int voc_set_sound_focus(struct sound_focus_param sound_focus_param); int voc_get_sound_focus(struct sound_focus_param *soundFocusData); diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c index 188f0d3e8c5d..82551fb8ed71 100644 --- a/sound/soc/msm/qdsp6v2/rtac.c +++ b/sound/soc/msm/qdsp6v2/rtac.c @@ -1484,7 +1484,7 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) goto err; } - if (opcode == VOICE_CMD_SET_PARAM) { + if (opcode == VSS_ICOMMON_CMD_SET_PARAM_V2) { /* set payload size to in-band payload */ /* set data size to actual out of band payload size */ data_size = payload_size - 4 * sizeof(u32); @@ -1537,7 +1537,9 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) voice_params.dest_svc = 0; voice_params.dest_domain = APR_DOMAIN_MODEM; voice_params.dest_port = (u16)dest_port; - voice_params.token = 0; + voice_params.token = (opcode == VSS_ICOMMON_CMD_SET_PARAM_V2) ? + VOC_RTAC_SET_PARAM_TOKEN : + 0; voice_params.opcode = opcode; /* fill for out-of-band */ @@ -1582,7 +1584,7 @@ int send_voice_apr(u32 mode, void *buf, u32 opcode) goto err; } - if (opcode == VOICE_CMD_GET_PARAM) { + if (opcode == VSS_ICOMMON_CMD_GET_PARAM_V2) { bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data. kvaddr)[2] + 3 * sizeof(u32); @@ -1675,20 +1677,20 @@ static long rtac_ioctl_shared(struct file *f, ASM_STREAM_CMD_SET_PP_PARAMS_V2); break; case AUDIO_GET_RTAC_CVS_CAL: - result = send_voice_apr(RTAC_CVS, (void *)arg, - VOICE_CMD_GET_PARAM); + result = send_voice_apr(RTAC_CVS, (void *) arg, + VSS_ICOMMON_CMD_GET_PARAM_V2); break; case AUDIO_SET_RTAC_CVS_CAL: - result = send_voice_apr(RTAC_CVS, (void *)arg, - VOICE_CMD_SET_PARAM); + result = send_voice_apr(RTAC_CVS, (void *) arg, + VSS_ICOMMON_CMD_SET_PARAM_V2); break; case AUDIO_GET_RTAC_CVP_CAL: - result = send_voice_apr(RTAC_CVP, (void *)arg, - VOICE_CMD_GET_PARAM); + result = send_voice_apr(RTAC_CVP, (void *) arg, + VSS_ICOMMON_CMD_GET_PARAM_V2); break; case AUDIO_SET_RTAC_CVP_CAL: - result = send_voice_apr(RTAC_CVP, (void *)arg, - VOICE_CMD_SET_PARAM); + result = send_voice_apr(RTAC_CVP, (void *) arg, + VSS_ICOMMON_CMD_SET_PARAM_V2); break; case AUDIO_GET_RTAC_AFE_CAL: result = send_rtac_afe_apr((void *)arg, |