Merge "asoc: sdm660: Add changes to enable HiFi mode"
diff --git a/asoc/msm-compress-q6-v2.c b/asoc/msm-compress-q6-v2.c
index c98c1cf..5dc1ad2 100644
--- a/asoc/msm-compress-q6-v2.c
+++ b/asoc/msm-compress-q6-v2.c
@@ -3894,6 +3894,16 @@
return 0;
}
+static int msm_compr_chmix_cfg_ctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 128;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xFFFFFFFF;
+ return 0;
+}
+
static int msm_compr_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
@@ -4317,6 +4327,112 @@
return 0;
}
+static int msm_compr_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_component_get_drvdata(comp);
+ struct snd_compr_stream *cstream = NULL;
+ struct snd_soc_pcm_runtime *rtd = NULL;
+ u64 fe_id = kcontrol->private_value;
+ int ip_channel_cnt, op_channel_cnt;
+ int i, index = 0;
+ int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL];
+ bool use_default_chmap = true;
+ char *chmap = NULL;
+
+ pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s: Received out of bounds fe_id %llu\n",
+ __func__, fe_id);
+ return -EINVAL;
+ }
+ cstream = pdata->cstream[fe_id];
+ if (!cstream) {
+ pr_err("%s: stream inactive\n", __func__);
+ return -EINVAL;
+ }
+ rtd = cstream->private_data;
+ if (!rtd) {
+ pr_err("%s: stream inactive\n", __func__);
+ return -EINVAL;
+ }
+
+ use_default_chmap = !(pdata->ch_map[rtd->dai_link->id]->set_ch_map);
+ chmap = pdata->ch_map[rtd->dai_link->id]->channel_map;
+
+ ip_channel_cnt = ucontrol->value.integer.value[index++];
+ op_channel_cnt = ucontrol->value.integer.value[index++];
+ /*
+ * wght coeff of first out channel corresponding to each in channel
+ * are sent followed by second out channel for each in channel etc.
+ */
+ memset(ch_coeff, 0, sizeof(ch_coeff));
+ for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) {
+ ch_coeff[i] =
+ ucontrol->value.integer.value[index++];
+ }
+
+ msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt,
+ ch_coeff, SESSION_TYPE_RX, use_default_chmap, chmap);
+
+ return 0;
+}
+
+static int msm_compr_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int msm_compr_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Audio Stream";
+ const char *deviceNo = "NN";
+ const char *suffix = "Channel Mix Cfg";
+ int ctl_len;
+ char *mixer_str = NULL;
+ struct snd_kcontrol_new chmix_cfg_controls[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_compr_chmix_cfg_ctl_info,
+ .get = msm_compr_chmix_cfg_ctl_get,
+ .put = msm_compr_chmix_cfg_ctl_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
+ __func__, rtd->dai_link->name, rtd->dai_link->id,
+ rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
+ strlen(suffix) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str)
+ return -ENOMEM;
+
+ snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
+ rtd->pcm->device, suffix);
+
+ chmix_cfg_controls[0].name = mixer_str;
+ chmix_cfg_controls[0].private_value = rtd->dai_link->id;
+ pr_debug("%s: Registering new mixer ctl %s", __func__, mixer_str);
+ snd_soc_add_platform_controls(rtd->platform,
+ chmix_cfg_controls,
+ ARRAY_SIZE(chmix_cfg_controls));
+ kfree(mixer_str);
+ return 0;
+}
+
static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
{
const char *mixer_ctl_name = "Playback Channel Map";
@@ -4513,6 +4629,9 @@
if (rc)
pr_err("%s: Could not add Compr Channel Map Control\n",
__func__);
+ rc = msm_compr_add_chmix_cfg_controls(rtd);
+ if (rc)
+ pr_err("%s: add chmix cfg controls failed:%d\n", __func__, rc);
return 0;
}
diff --git a/asoc/msm-pcm-q6-v2.c b/asoc/msm-pcm-q6-v2.c
index 4c9215f..3792021 100644
--- a/asoc/msm-pcm-q6-v2.c
+++ b/asoc/msm-pcm-q6-v2.c
@@ -1753,6 +1753,150 @@
return 0;
}
+static int msm_pcm_chmix_cfg_ctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 128;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xFFFFFFFF;
+ return 0;
+}
+
+static int msm_pcm_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *usr_info = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_platform *platform;
+ struct msm_plat_data *pdata;
+ struct snd_pcm_substream *substream;
+ struct msm_audio *prtd;
+ u64 fe_id = kcontrol->private_value;
+ int ip_channel_cnt, op_channel_cnt;
+ int i, index = 0, ret = 0;
+ int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL];
+ bool use_default_chmap = true;
+ char *ch_map = NULL;
+
+ pr_debug("%s: fe_id- %llu\n", __func__, fe_id);
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s: Received out of bounds fe_id %llu\n",
+ __func__, fe_id);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (!usr_info) {
+ pr_err("%s: usr_info is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ platform = snd_soc_component_to_platform(usr_info);
+ if (!platform) {
+ pr_err("%s: platform is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ pdata = dev_get_drvdata(platform->dev);
+ if (!pdata) {
+ pr_err("%s: pdata is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+
+ if (!substream) {
+ pr_err("%s substream not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!substream->runtime) {
+ pr_err("%s substream runtime not found\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ prtd = substream->runtime->private_data;
+ if (!prtd) {
+ pr_err("%s: stream inactive\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+ use_default_chmap = !prtd->set_channel_map;
+ ch_map = prtd->channel_map;
+ ip_channel_cnt = ucontrol->value.integer.value[index++];
+ op_channel_cnt = ucontrol->value.integer.value[index++];
+ /*
+ * wght coeff of first out channel corresponding to each in channel
+ * are sent followed by second out channel for each in channel etc.
+ */
+ memset(ch_coeff, 0, sizeof(ch_coeff));
+ for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) {
+ ch_coeff[i] =
+ ucontrol->value.integer.value[index++];
+ }
+
+ msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt,
+ ch_coeff, SESSION_TYPE_RX, use_default_chmap, ch_map);
+done:
+ return ret;
+}
+
+static int msm_pcm_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ return 0;
+}
+
+static int msm_pcm_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Audio Stream";
+ const char *deviceNo = "NN";
+ const char *suffix = "Channel Mix Cfg";
+ char *mixer_str = NULL;
+ int ctl_len = 0;
+ struct msm_plat_data *pdata;
+ struct snd_kcontrol_new chmix_cfg_controls[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_pcm_chmix_cfg_ctl_info,
+ .get = msm_pcm_chmix_cfg_ctl_get,
+ .put = msm_pcm_chmix_cfg_ctl_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s: NULL rtd\n", __func__);
+ return -EINVAL;
+ }
+
+ ctl_len = strlen(mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 + strlen(suffix) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str)
+ return -ENOMEM;
+
+ snprintf(mixer_str, ctl_len, "%s %d %s",
+ mixer_ctl_name, rtd->pcm->device, suffix);
+ chmix_cfg_controls[0].name = mixer_str;
+ chmix_cfg_controls[0].private_value = rtd->dai_link->id;
+ pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
+ pdata = dev_get_drvdata(rtd->platform->dev);
+ if (pdata) {
+ if (!pdata->pcm)
+ pdata->pcm = rtd->pcm;
+ snd_soc_add_platform_controls(rtd->platform,
+ chmix_cfg_controls,
+ ARRAY_SIZE(chmix_cfg_controls));
+ } else {
+ pr_err("%s: NULL pdata\n", __func__);
+ return -EINVAL;
+ }
+ kfree(mixer_str);
+ return 0;
+}
+
static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
{
int ret = 0;
@@ -1765,6 +1909,9 @@
if (ret)
pr_err("%s: pcm add app type controls failed:%d\n",
__func__, ret);
+ ret = msm_pcm_add_chmix_cfg_controls(rtd);
+ if (ret)
+ pr_err("%s: add chmix cfg controls failed:%d\n", __func__, ret);
return ret;
}
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 0426679..35b2bdb 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -792,6 +792,79 @@
return rc;
}
+/*
+ * msm_pcm_routing_send_chmix_cfg
+ *
+ * Receives fe_id, ip_channel_cnt, op_channel_cnt, channel weight, session_type
+ * use_default_chmap and channel map to map in channel mixer and send to
+ * adm programmable matrix.
+ *
+ * fe_id - Passed value, frontend id which is wanted
+ * ip_channel_cnt - Passed value, number of input channels
+ * op_channel_cnt - Passed value, number of output channels
+ * ch_wght_coeff - Passed reference, weights for each output channel
+ * session_type - Passed value, session_type for RX or TX
+ * use_default_chmap - true if default channel map to be used
+ * ch_map - input/output channel map for playback/capture session respectively
+ */
+
+int msm_pcm_routing_send_chmix_cfg(int fe_id, int ip_channel_cnt,
+ int op_channel_cnt, int *ch_wght_coeff,
+ int session_type, bool use_default_chmap,
+ char *channel_map)
+{
+ int rc = 0, idx = 0, i, j;
+ int be_index = 0, port_id, index = 0;
+ unsigned int session_id = 0;
+
+ pr_debug("%s: fe_id[%d] ip_ch[%d] op_ch[%d] sess_type [%d]\n",
+ __func__, fe_id, ip_channel_cnt, op_channel_cnt, session_type);
+
+ if (!use_default_chmap && (channel_map == NULL)) {
+ pr_err("%s: No valid chan map and can't use default\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if ((ch_wght_coeff == NULL) || (op_channel_cnt > ADM_MAX_CHANNELS) ||
+ (ip_channel_cnt > ADM_MAX_CHANNELS)) {
+ pr_err("%s: Invalid channels or null coefficients\n", __func__);
+ return -EINVAL;
+ }
+
+ for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) {
+ port_id = msm_bedais[be_index].port_id;
+ if (!msm_bedais[be_index].active ||
+ !test_bit(fe_id, &msm_bedais[be_index].fe_sessions[0]))
+ continue;
+
+ session_id = fe_dai_map[fe_id][session_type].strm_id;
+ channel_mixer[fe_id].input_channels[0] = ip_channel_cnt;
+ channel_mixer[fe_id].output_channel = op_channel_cnt;
+ channel_mixer[fe_id].rule = 0;
+
+ for (j = 0; j < op_channel_cnt; j++) {
+ for (i = 0; i < ip_channel_cnt; i++)
+ channel_mixer[fe_id].channel_weight[j][i] =
+ ch_wght_coeff[index++];
+ }
+ for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) {
+ unsigned long copp =
+ session_copp_map[fe_id][session_type][be_index];
+ if (!test_bit(idx, &copp))
+ continue;
+ rc = adm_programable_channel_mixer(port_id,
+ idx, session_id, session_type,
+ channel_mixer + fe_id, 0,
+ use_default_chmap, channel_map);
+ if (rc < 0)
+ pr_err("%s: err setting channel mix config\n",
+ __func__);
+ }
+ }
+ return 0;
+}
+
int msm_pcm_routing_reg_stream_app_type_cfg(
int fedai_id, int session_type, int be_id,
struct msm_pcm_stream_app_type_cfg *cfg_data)
@@ -1326,6 +1399,8 @@
int sess_type = 0;
int i = 0, j = 0, be_id;
int ret = 0;
+ bool use_default_chmap = true;
+ char *ch_map = NULL;
if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
pr_err("%s: invalid FE %d\n", __func__, fe_id);
@@ -1368,7 +1443,8 @@
ret = adm_programable_channel_mixer(
msm_bedais[be_id].port_id,
copp_idx, dspst_id, sess_type,
- channel_mixer + fe_id, i);
+ channel_mixer + fe_id, i,
+ use_default_chmap, ch_map);
}
}
diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h
index c2422d6..93f6ceb 100644
--- a/asoc/msm-pcm-routing-v2.h
+++ b/asoc/msm-pcm-routing-v2.h
@@ -525,4 +525,8 @@
int msm_pcm_routing_get_stream_app_type_cfg(
int fedai_id, int session_type, int *be_id,
struct msm_pcm_stream_app_type_cfg *cfg_data);
+int msm_pcm_routing_send_chmix_cfg(int fe_id, int ip_channel_cnt,
+ int op_channel_cnt, int *ch_wght_coeff,
+ int session_type, bool use_default_chmap,
+ char *channel_map);
#endif /*_MSM_PCM_H*/
diff --git a/dsp/codecs/audio_utils.c b/dsp/codecs/audio_utils.c
index 15ee9f5..e559678 100644
--- a/dsp/codecs/audio_utils.c
+++ b/dsp/codecs/audio_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2018, 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
@@ -760,6 +760,10 @@
}
bytes_to_copy =
(size + audio->out_frame_info[idx][1]);
+ if (bytes_to_copy == 0) {
+ rc = 0;
+ break;
+ }
/* Number of frames information copied */
buf += sizeof(unsigned char);
count -= sizeof(unsigned char);
@@ -793,8 +797,10 @@
pr_debug("%s:session id %d: read: %zd bytes\n", __func__,
audio->ac->session, (buf-start));
- if (buf > start)
- return buf - start;
+ if (!rc) {
+ if (buf > start)
+ return buf - start;
+ }
return rc;
}
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index 1596418..e42e329 100644
--- a/dsp/q6adm.c
+++ b/dsp/q6adm.c
@@ -635,18 +635,21 @@
* session_type - Passed value, session_type for RX or TX
* ch_mixer - Passed value, ch_mixer for which channel mixer config is needed
* channel_index - Passed value, channel_index for which channel is needed
+ * use_default_chmap - true if default channel map to be used
+ * ch_map - input/output channel map for playback/capture session respectively
*/
int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
int session_type,
struct msm_pcm_channel_mixer *ch_mixer,
- int channel_index)
+ int channel_index, bool use_default_chmap,
+ char *ch_map)
{
struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL;
struct adm_param_data_v5 data_v5;
int ret = 0, port_idx, sz = 0, param_size = 0;
u16 *adm_pspd_params;
u16 *ptr;
- int index = 0;
+ int index = 0, i;
pr_debug("%s: port_id = %d\n", __func__, port_id);
port_id = afe_convert_virtual_to_portid(port_id);
@@ -671,7 +674,8 @@
ch_mixer->input_channels[channel_index] +
ch_mixer->input_channels[channel_index] *
ch_mixer->output_channel);
- roundup(param_size, 4);
+ /* Params size should be multiple of 4 bytes i.e 32bit aligned */
+ param_size = round_up(param_size, 4);
sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
sizeof(struct default_chmixer_param_id_coeff) +
@@ -713,84 +717,93 @@
adm_pspd_params[3] = ch_mixer->input_channels[channel_index];
index = 4;
- if (ch_mixer->output_channel == 1) {
- adm_pspd_params[index] = PCM_CHANNEL_FC;
- } else if (ch_mixer->output_channel == 2) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- } else if (ch_mixer->output_channel == 3) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
- } else if (ch_mixer->output_channel == 4) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 3] = PCM_CHANNEL_RS;
- } else if (ch_mixer->output_channel == 5) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
- adm_pspd_params[index + 3] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 4] = PCM_CHANNEL_RS;
- } else if (ch_mixer->output_channel == 6) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
- adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
- adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
- } else if (ch_mixer->output_channel == 8) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
- adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
- adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
- adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
- adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
+ if ((session_type == SESSION_TYPE_TX) && !use_default_chmap && ch_map) {
+ for (i = 0; i < ch_mixer->output_channel; i++)
+ adm_pspd_params[index++] = ch_map[i];
+ } else {
+ if (ch_mixer->output_channel == 1) {
+ adm_pspd_params[index] = PCM_CHANNEL_FC;
+ } else if (ch_mixer->output_channel == 2) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ } else if (ch_mixer->output_channel == 3) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
+ } else if (ch_mixer->output_channel == 4) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_RS;
+ } else if (ch_mixer->output_channel == 5) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 4] = PCM_CHANNEL_RS;
+ } else if (ch_mixer->output_channel == 6) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
+ adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
+ } else if (ch_mixer->output_channel == 8) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
+ adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
+ adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
+ adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
+ }
+ index = index + ch_mixer->output_channel;
}
- index = index + ch_mixer->output_channel;
- if (ch_mixer->input_channels[channel_index] == 1) {
- adm_pspd_params[index] = PCM_CHANNEL_FC;
- } else if (ch_mixer->input_channels[channel_index] == 2) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- } else if (ch_mixer->input_channels[channel_index] == 3) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
- } else if (ch_mixer->input_channels[channel_index] == 4) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 3] = PCM_CHANNEL_RS;
- } else if (ch_mixer->input_channels[channel_index] == 5) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
- adm_pspd_params[index + 3] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 4] = PCM_CHANNEL_RS;
- } else if (ch_mixer->input_channels[channel_index] == 6) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
- adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
- adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
- } else if (ch_mixer->input_channels[channel_index] == 8) {
- adm_pspd_params[index] = PCM_CHANNEL_FL;
- adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
- adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
- adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
- adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
- adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
- adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
- adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
+ if ((session_type == SESSION_TYPE_RX) && !use_default_chmap && ch_map) {
+ for (i = 0; i < ch_mixer->input_channels[channel_index]; i++)
+ adm_pspd_params[index++] = ch_map[i];
+ } else {
+ if (ch_mixer->input_channels[channel_index] == 1) {
+ adm_pspd_params[index] = PCM_CHANNEL_FC;
+ } else if (ch_mixer->input_channels[channel_index] == 2) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ } else if (ch_mixer->input_channels[channel_index] == 3) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
+ } else if (ch_mixer->input_channels[channel_index] == 4) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_RS;
+ } else if (ch_mixer->input_channels[channel_index] == 5) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_FC;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 4] = PCM_CHANNEL_RS;
+ } else if (ch_mixer->input_channels[channel_index] == 6) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
+ adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
+ } else if (ch_mixer->input_channels[channel_index] == 8) {
+ adm_pspd_params[index] = PCM_CHANNEL_FL;
+ adm_pspd_params[index + 1] = PCM_CHANNEL_FR;
+ adm_pspd_params[index + 2] = PCM_CHANNEL_LFE;
+ adm_pspd_params[index + 3] = PCM_CHANNEL_FC;
+ adm_pspd_params[index + 4] = PCM_CHANNEL_LS;
+ adm_pspd_params[index + 5] = PCM_CHANNEL_RS;
+ adm_pspd_params[index + 6] = PCM_CHANNEL_LB;
+ adm_pspd_params[index + 7] = PCM_CHANNEL_RB;
+ }
+ index = index + ch_mixer->input_channels[channel_index];
}
-
- index = index + ch_mixer->input_channels[channel_index];
ret = adm_populate_channel_weight(&adm_pspd_params[index],
ch_mixer, channel_index);
if (ret) {
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index 4d86def..e5b1139 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -141,6 +141,8 @@
static int voice_send_get_source_tracking_cmd(struct voice_data *v,
struct source_tracking_param *sourceTrackingData);
+static void voice_vote_powerstate_to_bms(struct voice_data *v, bool state);
+
static void voice_itr_init(struct voice_session_itr *itr,
u32 session_id)
{
@@ -1950,6 +1952,47 @@
EXPORT_SYMBOL(voc_set_destroy_cvd_flag);
/**
+ * voc_set_vote_bms_flag -
+ * set flag for BMS voting
+ *
+ * @is_destroy_cvd: bool value used to indicate
+ * to vote for BMS or not in voice call.
+ *
+ */
+void voc_set_vote_bms_flag(bool is_vote_bms)
+{
+ pr_debug("%s: flag value: %d\n", __func__, is_vote_bms);
+ common.is_vote_bms = is_vote_bms;
+}
+EXPORT_SYMBOL(voc_set_vote_bms_flag);
+
+static void voice_vote_powerstate_to_bms(struct voice_data *v, bool state)
+{
+ union power_supply_propval psp_val;
+
+ if (!v->psy)
+ v->psy = power_supply_get_by_name("bms");
+
+ psp_val.intval = VMBMS_VOICE_CALL_BIT;
+ if (v->psy && !(is_voip_session(v->session_id) ||
+ is_vowlan_session(v->session_id))) {
+ if (state) {
+ pr_debug("%s : Vote High power to BMS\n",
+ __func__);
+ power_supply_set_property(v->psy,
+ POWER_SUPPLY_PROP_HI_POWER, &psp_val);
+ } else {
+ pr_debug("%s: Vote low power to BMS\n",
+ __func__);
+ power_supply_set_property(v->psy,
+ POWER_SUPPLY_PROP_LOW_POWER, &psp_val);
+ }
+ } else {
+ pr_debug("%s: No OP", __func__);
+ }
+}
+
+/**
* voc_alloc_cal_shared_memory -
* Alloc mem map table for calibration
*
@@ -2422,6 +2465,10 @@
v->async_err);
goto fail;
}
+ if (common.is_vote_bms) {
+ /* vote high power to BMS during call start */
+ voice_vote_powerstate_to_bms(v, true);
+ }
return 0;
fail:
return ret;
@@ -6873,6 +6920,10 @@
voice_destroy_mvm_cvs_session(v);
v->voc_state = VOC_RELEASE;
+ if (common.is_vote_bms) {
+ /* vote low power to BMS during call stop */
+ voice_vote_powerstate_to_bms(v, false);
+ }
} else {
pr_err("%s: Error: End voice called in state %d\n",
__func__, v->voc_state);
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index 79bda97..5308b6e 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.h
@@ -30,6 +30,9 @@
#define AUD_PROC_PERSIST_BLOCK_SIZE (2 * 1024 * 1020)
#define AUDIO_RX_CALIBRATION_SIZE (AUD_PROC_BLOCK_SIZE + \
AUD_VOL_BLOCK_SIZE)
+#define SESSION_TYPE_RX 0
+#define SESSION_TYPE_TX 1
+
enum {
ADM_CUSTOM_TOP_CAL = 0,
ADM_AUDPROC_CAL,
@@ -186,7 +189,8 @@
int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id,
int session_type,
struct msm_pcm_channel_mixer *ch_mixer,
- int channel_index);
+ int channel_index, bool use_default_chmap,
+ char *ch_map);
void msm_dts_srs_acquire_lock(void);
void msm_dts_srs_release_lock(void);
#endif /* __Q6_ADM_V2_H__ */
diff --git a/include/dsp/q6voice.h b/include/dsp/q6voice.h
index 86be4e1..4d1cf92 100644
--- a/include/dsp/q6voice.h
+++ b/include/dsp/q6voice.h
@@ -13,6 +13,8 @@
#define __QDSP6VOICE_H__
#include <linux/msm_ion.h>
+#include <linux/power_supply.h>
+#include <uapi/linux/vm_bms.h>
#include <sound/voice_params.h>
#include <dsp/rtac.h>
#include <dsp/q6core.h>
@@ -1916,6 +1918,8 @@
bool mic_break_status;
struct work_struct voice_mic_break_work;
+
+ struct power_supply *psy;
};
struct cal_mem {
@@ -1980,6 +1984,7 @@
bool sidetone_enable;
bool mic_break_enable;
struct audio_uevent_data *uevent_data;
+ bool is_vote_bms;
};
struct voice_session_itr {
@@ -2107,6 +2112,7 @@
int voc_disable_device(uint32_t session_id);
int voc_enable_device(uint32_t session_id);
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,
struct media_format_info *finfo);