OSDN Git Service

msm: qdsp6v2: extend media format provided to voice driver
authorSiena Richard <sienar@codeaurora.org>
Tue, 13 Sep 2016 20:43:35 +0000 (13:43 -0700)
committerGerrit - the friendly Code Review server <code-review@localhost>
Fri, 9 Dec 2016 18:59:54 +0000 (10:59 -0800)
Extend the media format options passed to the voice driver to
include sample rate, bits per sample, and channel mapping in
addition to port ID and the number of channels. Additional media type
information is provide to help avoid additional buffers required in
case of non-fractional sample rate for post processing voice data.

CRs-Fixed: 1065881
Change-Id: Ib69b57dc677b87fecfd689df7f8fc7ec8b4bc59f
Signed-off-by: Siena Richard <sienar@codeaurora.org>
include/sound/apr_audio-v2.h
sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
sound/soc/msm/qdsp6v2/q6voice.c
sound/soc/msm/qdsp6v2/q6voice.h
sound/soc/msm/qdsp6v2/rtac.c

index e01e16e..f9be3e0 100644 (file)
@@ -8016,11 +8016,10 @@ struct asm_eq_params {
 /*     Band cut equalizer effect.*/
 #define ASM_PARAM_EQ_BAND_CUT       6
 
-/* Voice get & set params */
-#define VOICE_CMD_SET_PARAM                            0x0001133D
-#define VOICE_CMD_GET_PARAM                            0x0001133E
-#define VOICE_EVT_GET_PARAM_ACK                                0x00011008
-
+/* Get & set params */
+#define VSS_ICOMMON_CMD_SET_PARAM_V2   0x0001133D
+#define VSS_ICOMMON_CMD_GET_PARAM_V2   0x0001133E
+#define VSS_ICOMMON_RSP_GET_PARAM      0x00011008
 
 /** ID of the Bass Boost module.
     This module supports the following parameter IDs:
index a456cc2..80acf19 100644 (file)
@@ -1466,6 +1466,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);
 
@@ -1498,8 +1499,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))
@@ -2366,9 +2381,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 {
@@ -11411,6 +11426,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);
@@ -11523,8 +11539,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;
@@ -11532,8 +11548,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))
@@ -11541,6 +11568,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);
 
index b242a8f..5cff3dd 100644 (file)
@@ -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;
index 834fe7c..9c3ec62 100644 (file)
@@ -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);
index 188f0d3..82551fb 100644 (file)
@@ -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,