Merge ce9731f4349bfced5826abd4c71ba4205c6e98b8 on remote branch
Change-Id: I95d515e20765a5e048a2ea9d9135b776037b2ac4
diff --git a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
index de112bc..9553b39 100644
--- a/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/asoc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -2260,10 +2260,6 @@
snd_soc_update_bits(codec,
MSM89XX_PMIC_ANALOG_SPKR_DRV_CTL,
0xEF, 0xEF);
- else
- snd_soc_update_bits(codec,
- MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
- 0x10, 0x00);
break;
case BOOST_ALWAYS:
case BOOST_ON_FOREVER:
@@ -2272,8 +2268,6 @@
0xEF, 0xEF);
break;
case BYPASS_ALWAYS:
- snd_soc_update_bits(codec,
- MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x10, 0x00);
break;
default:
dev_err(codec->dev,
@@ -2281,6 +2275,8 @@
sdm660_cdc->boost_option);
break;
}
+ snd_soc_update_bits(codec, MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL,
+ 0x10, 0x00);
msm_anlg_cdc_dig_notifier_call(codec,
DIG_CDC_EVENT_RX3_MUTE_OFF);
snd_soc_update_bits(codec, w->reg, 0x80, 0x80);
diff --git a/asoc/codecs/wsa881x.c b/asoc/codecs/wsa881x.c
index 2ef9e0a..d2a3938 100644
--- a/asoc/codecs/wsa881x.c
+++ b/asoc/codecs/wsa881x.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -76,6 +76,7 @@
enum {
WSA881X_DEV_DOWN,
WSA881X_DEV_UP,
+ WSA881X_DEV_READY,
};
/*
@@ -99,6 +100,7 @@
int version;
struct mutex bg_lock;
struct mutex res_lock;
+ struct mutex temp_lock;
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
int state;
@@ -491,6 +493,17 @@
.read = codec_debug_read,
};
+static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x)
+{
+ mutex_lock(&wsa881x->res_lock);
+ if (wsa881x->state != WSA881X_DEV_READY) {
+ regcache_mark_dirty(wsa881x->regmap);
+ regcache_sync(wsa881x->regmap);
+ wsa881x->state = WSA881X_DEV_READY;
+ }
+ mutex_unlock(&wsa881x->res_lock);
+}
+
static const struct reg_sequence wsa881x_pre_pmu_pa[] = {
{WSA881X_SPKR_DRV_GAIN, 0x41, 0},
{WSA881X_SPKR_MISC_CTL1, 0x01, 0},
@@ -850,7 +863,9 @@
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE);
+ mutex_unlock(&wsa881x->temp_lock);
wsa881x_boost_ctrl(codec, ENABLE);
break;
case SND_SOC_DAPM_POST_PMD:
@@ -858,7 +873,9 @@
wsa881x->swr_slave->dev_num,
false);
wsa881x_boost_ctrl(codec, DISABLE);
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, DISABLE);
+ mutex_unlock(&wsa881x->temp_lock);
break;
}
return 0;
@@ -1103,13 +1120,8 @@
return -EINVAL;
}
}
- mutex_lock(&wsa881x->res_lock);
- if (!wsa881x->clk_cnt) {
- regcache_mark_dirty(wsa881x->regmap);
- regcache_sync(wsa881x->regmap);
- }
- mutex_unlock(&wsa881x->res_lock);
-
+ wsa881x_regcache_sync(wsa881x);
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE);
snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
@@ -1122,6 +1134,7 @@
wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4);
wsa881x_resource_acquire(codec, DISABLE);
+ mutex_unlock(&wsa881x->temp_lock);
return 0;
}
@@ -1137,7 +1150,6 @@
dev = wsa881x->swr_slave;
wsa881x->codec = codec;
mutex_init(&wsa881x->bg_lock);
- mutex_init(&wsa881x->res_lock);
wsa881x_init(codec);
snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name),
"%s.%x", "wsatz", (u8)dev->addr);
@@ -1159,7 +1171,6 @@
if (wsa881x->tz_pdata.tz_dev)
wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev);
mutex_destroy(&wsa881x->bg_lock);
- mutex_destroy(&wsa881x->res_lock);
return 0;
}
@@ -1342,6 +1353,8 @@
__func__);
goto dev_err;
}
+ mutex_init(&wsa881x->res_lock);
+ mutex_init(&wsa881x->temp_lock);
return 0;
@@ -1364,6 +1377,8 @@
}
debugfs_remove_recursive(debugfs_wsa881x_dent);
debugfs_wsa881x_dent = NULL;
+ mutex_destroy(&wsa881x->res_lock);
+ mutex_destroy(&wsa881x->temp_lock);
snd_soc_unregister_codec(&pdev->dev);
if (wsa881x->pd_gpio)
gpio_free(wsa881x->pd_gpio);
@@ -1422,6 +1437,11 @@
dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__);
return -EINVAL;
}
+ if (wsa881x->state == WSA881X_DEV_READY) {
+ dev_dbg(&pdev->dev, "%s: device already active\n", __func__);
+ return 0;
+ }
+
wsa881x->bg_cnt = 0;
wsa881x->clk_cnt = 0;
while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
@@ -1429,8 +1449,8 @@
usleep_range(1000, 1100);
}
pdev->dev_num = devnum;
- regcache_mark_dirty(wsa881x->regmap);
- regcache_sync(wsa881x->regmap);
+ wsa881x_regcache_sync(wsa881x);
+
return 0;
}
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 e821717..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);
}
}
@@ -3693,6 +3769,10 @@
msm_route_ec_ref_rx = 23;
ec_ref_port_id = AFE_PORT_ID_HDMI_OVER_DP_RX;
break;
+ case 24:
+ msm_route_ec_ref_rx = 24;
+ ec_ref_port_id = AFE_PORT_ID_PRIMARY_TDM_RX_1;
+ break;
default:
msm_route_ec_ref_rx = 0; /* NONE */
pr_err("%s EC ref rx %ld not valid\n",
@@ -3716,7 +3796,8 @@
"SLIM_5_RX", "SLIM_1_TX", "QUAT_TDM_TX_1",
"QUAT_TDM_RX_0", "QUAT_TDM_RX_1", "QUAT_TDM_RX_2", "SLIM_6_RX",
"TERT_MI2S_RX", "QUAT_MI2S_RX", "TERT_TDM_TX_0", "USB_AUDIO_RX",
- "INT0_MI2S_RX", "INT4_MI2S_RX", "INT3_MI2S_TX", "DISPLAY_PORT"};
+ "INT0_MI2S_RX", "INT4_MI2S_RX", "INT3_MI2S_TX", "DISPLAY_PORT",
+ "PRI_TDM_RX_1"};
static const struct soc_enum msm_route_ec_ref_rx_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ec_ref_rx), ec_ref_rx),
@@ -15670,6 +15751,7 @@
{"AUDIO_REF_EC_UL1 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"AUDIO_REF_EC_UL1 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
{"AUDIO_REF_EC_UL1 MUX", "SLIM_1_TX", "SLIMBUS_1_TX"},
+ {"AUDIO_REF_EC_UL1 MUX", "PRI_TDM_TX_3", "PRI_TDM_TX_3"},
{"AUDIO_REF_EC_UL1 MUX", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"},
{"AUDIO_REF_EC_UL1 MUX", "QUAT_TDM_RX_0", "QUAT_TDM_RX_0"},
{"AUDIO_REF_EC_UL1 MUX", "QUAT_TDM_RX_1", "QUAT_TDM_RX_1"},
@@ -15705,6 +15787,7 @@
{"AUDIO_REF_EC_UL8 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
{"AUDIO_REF_EC_UL8 MUX", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"AUDIO_REF_EC_UL8 MUX", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
+ {"AUDIO_REF_EC_UL8 MUX", "PRI_TDM_TX_3", "PRI_TDM_TX_3"},
{"AUDIO_REF_EC_UL9 MUX", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"AUDIO_REF_EC_UL9 MUX", "SEC_MI2S_TX", "SEC_MI2S_TX"},
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/asoc/msm-pcm-voice-v2.c b/asoc/msm-pcm-voice-v2.c
index 7447d0c..10e1207 100644
--- a/asoc/msm-pcm-voice-v2.c
+++ b/asoc/msm-pcm-voice-v2.c
@@ -720,7 +720,9 @@
{
int rc;
bool destroy_cvd = false;
+ bool vote_bms = false;
const char *is_destroy_cvd = "qcom,destroy-cvd";
+ const char *is_vote_bms = "qcom,vote-bms";
if (!is_voc_initialized()) {
pr_debug("%s: voice module not initialized yet, deferring probe()\n",
@@ -747,6 +749,10 @@
is_destroy_cvd);
voc_set_destroy_cvd_flag(destroy_cvd);
+ vote_bms = of_property_read_bool(pdev->dev.of_node,
+ is_vote_bms);
+ voc_set_vote_bms_flag(vote_bms);
+
rc = snd_soc_register_platform(&pdev->dev,
&msm_soc_platform);
diff --git a/asoc/sdm660-common.h b/asoc/sdm660-common.h
index 65f9d5b..3df6bf8 100644
--- a/asoc/sdm660-common.h
+++ b/asoc/sdm660-common.h
@@ -122,6 +122,10 @@
struct mutex cdc_int_mclk0_mutex;
struct delayed_work disable_int_mclk0_work;
struct afe_clk_set digital_cdc_core_clk;
+ int gpio_linein_det;
+ int gpio_lineout_det;
+ int linein_det_swh;
+ int lineout_det_swh;
};
int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
diff --git a/asoc/sdm660-ext-dai-links.c b/asoc/sdm660-ext-dai-links.c
index 91554f7..3568ebb 100644
--- a/asoc/sdm660-ext-dai-links.c
+++ b/asoc/sdm660-ext-dai-links.c
@@ -2000,6 +2000,23 @@
},
};
+static struct snd_soc_dai_link msm_afe_rxtx_lb_be_dai_link[] = {
+ {
+ .name = LPASS_BE_AFE_LOOPBACK_TX,
+ .stream_name = "AFE Loopback Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.24577",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .id = MSM_BACKEND_DAI_AFE_LOOPBACK_TX,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+};
+
+
static struct snd_soc_dai_link msm_wcn_be_dai_links[] = {
{
.name = LPASS_BE_SLIMBUS_7_RX,
@@ -2079,7 +2096,8 @@
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links) +
ARRAY_SIZE(msm_wcn_be_dai_links) +
-ARRAY_SIZE(ext_disp_be_dai_link)];
+ARRAY_SIZE(ext_disp_be_dai_link) +
+ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link)];
static struct snd_soc_dai_link msm_ext_tavil_dai_links[
ARRAY_SIZE(msm_ext_common_fe_dai) +
@@ -2090,7 +2108,8 @@
ARRAY_SIZE(msm_mi2s_be_dai_links) +
ARRAY_SIZE(msm_auxpcm_be_dai_links) +
ARRAY_SIZE(msm_wcn_be_dai_links) +
-ARRAY_SIZE(ext_disp_be_dai_link)];
+ARRAY_SIZE(ext_disp_be_dai_link) +
+ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link)];
/**
* populate_snd_card_dailinks - prepares dailink array and initializes card.
@@ -2182,6 +2201,14 @@
sizeof(ext_disp_be_dai_link));
len5 += ARRAY_SIZE(ext_disp_be_dai_link);
}
+ if (of_property_read_bool(dev->of_node, "qcom,afe-rxtx-lb")) {
+ dev_dbg(dev, "%s(): AFE RX to TX loopback supported\n",
+ __func__);
+ memcpy(msm_ext_tasha_dai_links + len5,
+ msm_afe_rxtx_lb_be_dai_link,
+ sizeof(msm_afe_rxtx_lb_be_dai_link));
+ len5 += ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
+ }
msm_ext_dai_links = msm_ext_tasha_dai_links;
} else if (strnstr(card->name, "tavil", strlen(card->name))) {
len1 = ARRAY_SIZE(msm_ext_common_fe_dai);
@@ -2231,6 +2258,14 @@
sizeof(ext_disp_be_dai_link));
len5 += ARRAY_SIZE(ext_disp_be_dai_link);
}
+ if (of_property_read_bool(dev->of_node, "qcom,afe-rxtx-lb")) {
+ dev_dbg(dev, "%s(): AFE RX to TX loopback supported\n",
+ __func__);
+ memcpy(msm_ext_tavil_dai_links + len5,
+ msm_afe_rxtx_lb_be_dai_link,
+ sizeof(msm_afe_rxtx_lb_be_dai_link));
+ len5 += ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
+ }
msm_ext_dai_links = msm_ext_tavil_dai_links;
} else {
dev_err(dev, "%s: failing as no matching card name\n",
diff --git a/asoc/sdm660-external.c b/asoc/sdm660-external.c
index 91accff..ca1d2aa 100644
--- a/asoc/sdm660-external.c
+++ b/asoc/sdm660-external.c
@@ -22,6 +22,7 @@
#include "msm-pcm-routing-v2.h"
#include "sdm660-common.h"
#include "sdm660-external.h"
+#include "codecs/msm-cdc-pinctrl.h"
#include "codecs/wcd9335.h"
#include "codecs/wcd934x/wcd934x.h"
#include "codecs/wcd934x/wcd934x-mbhc.h"
@@ -37,6 +38,8 @@
#define WSA8810_NAME_1 "wsa881x.20170211"
#define WSA8810_NAME_2 "wsa881x.20170212"
+#define MSM_HIFI_ON 1
+
static int msm_ext_spk_control = 1;
static struct wcd_mbhc_config *wcd_mbhc_cfg_ptr;
@@ -48,6 +51,7 @@
static struct msm_asoc_wcd93xx_codec msm_codec_fn;
static struct platform_device *spdev;
+static int msm_hifi_control;
static bool is_initial_boot;
@@ -108,8 +112,40 @@
[SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
};
+static struct snd_soc_jack linein_jack;
+
+static struct snd_soc_jack_pin linein_jack_pins[] = {
+ {
+ .pin = "Linein",
+ .mask = SND_JACK_LINEIN,
+ },
+};
+
+static struct snd_soc_jack_gpio linein_jack_gpio = {
+ .name = "Linein detection",
+ .report = SND_JACK_LINEIN,
+ .debounce_time = 800,
+};
+
+static struct snd_soc_jack lineout_jack;
+
+static struct snd_soc_jack_pin lineout_jack_pins[] = {
+ {
+ .pin = "Lineout",
+ .mask = SND_JACK_LINEOUT,
+ },
+};
+
+static struct snd_soc_jack_gpio lineout_jack_gpio = {
+ .name = "Lineout detection",
+ .report = SND_JACK_LINEOUT,
+ .debounce_time = 800,
+};
+
static int msm_vi_feed_tx_ch = 2;
-static const char *const slim_rx_ch_text[] = {"One", "Two"};
+static const char *const slim_rx_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven",
+ "Eight"};
static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven",
"Eight"};
@@ -130,6 +166,8 @@
static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
"KHZ_44P1", "KHZ_48",
"KHZ_88P2", "KHZ_96"};
+static const char *const hifi_text[] = {"Off", "On"};
+
static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text);
@@ -150,6 +188,7 @@
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(hifi_function, hifi_text);
static int slim_get_sample_rate_val(int sample_rate)
{
@@ -738,6 +777,56 @@
return 1;
}
+static int msm_hifi_ctrl(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+
+ pr_debug("%s: msm_hifi_control = %d\n", __func__,
+ msm_hifi_control);
+
+ if (!pdata || !pdata->hph_en1_gpio_p) {
+ pr_err("%s: hph_en1_gpio is invalid\n", __func__);
+ return -EINVAL;
+ }
+ if (msm_hifi_control == MSM_HIFI_ON) {
+ msm_cdc_pinctrl_select_active_state(pdata->hph_en1_gpio_p);
+ /* 5msec delay needed as per HW requirement */
+ usleep_range(5000, 5010);
+ } else {
+ msm_cdc_pinctrl_select_sleep_state(pdata->hph_en1_gpio_p);
+ }
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static int msm_hifi_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_hifi_control = %d\n",
+ __func__, msm_hifi_control);
+ ucontrol->value.integer.value[0] = msm_hifi_control;
+
+ return 0;
+}
+
+static int msm_hifi_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+ pr_debug("%s() ucontrol->value.integer.value[0] = %ld\n",
+ __func__, ucontrol->value.integer.value[0]);
+
+ msm_hifi_control = ucontrol->value.integer.value[0];
+ msm_hifi_ctrl(codec);
+
+ return 0;
+}
+
static void *def_ext_mbhc_cal(void)
{
void *wcd_mbhc_cal;
@@ -887,6 +976,8 @@
SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
msm_bt_sample_rate_tx_get,
msm_bt_sample_rate_tx_put),
+ SOC_ENUM_EXT("HiFi Function", hifi_function, msm_hifi_get,
+ msm_hifi_put),
};
static int msm_slim_get_ch_from_beid(int32_t id)
@@ -1536,6 +1627,39 @@
return 0;
}
+static int msm_hifi_ctrl_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *k, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+
+ pr_debug("%s: msm_hifi_control = %d\n", __func__, msm_hifi_control);
+
+ if (!pdata || !pdata->hph_en0_gpio_p) {
+ pr_err("%s: hph_en0_gpio is invalid\n", __func__);
+ return -EINVAL;
+ }
+
+ if (msm_hifi_control != MSM_HIFI_ON) {
+ pr_debug("%s: HiFi mixer control is not set\n",
+ __func__);
+ return 0;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ msm_cdc_pinctrl_select_active_state(pdata->hph_en0_gpio_p);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ msm_cdc_pinctrl_select_sleep_state(pdata->hph_en0_gpio_p);
+ break;
+ }
+
+ return 0;
+}
+
static int msm_ext_prepare_hifi(struct msm_asoc_mach_data *pdata)
{
int ret = 0;
@@ -1575,6 +1699,7 @@
SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
+ SND_SOC_DAPM_SPK("hifi amp", msm_hifi_ctrl_event),
SND_SOC_DAPM_MIC("Handset Mic", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("Secondary Mic", NULL),
@@ -1592,6 +1717,8 @@
SND_SOC_DAPM_MIC("Digital Mic4", NULL),
SND_SOC_DAPM_MIC("Digital Mic5", NULL),
SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+ SND_SOC_DAPM_HP("Lineout", NULL),
+ SND_SOC_DAPM_MIC("Linein", NULL),
};
static struct snd_soc_dapm_route wcd_audio_paths_tasha[] = {
@@ -1929,6 +2056,26 @@
tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec);
}
+
+ if (gpio_is_valid(pdata->gpio_linein_det)) {
+ snd_soc_card_jack_new(rtd->card, "Linein", SND_JACK_LINEIN,
+ &linein_jack, linein_jack_pins,
+ ARRAY_SIZE(linein_jack_pins));
+
+ linein_jack_gpio.invert = pdata->linein_det_swh;
+ linein_jack_gpio.gpio = pdata->gpio_linein_det;
+ snd_soc_jack_add_gpios(&linein_jack, 1, &linein_jack_gpio);
+ }
+
+ if (gpio_is_valid(pdata->gpio_lineout_det)) {
+ snd_soc_card_jack_new(rtd->card, "Lineout", SND_JACK_LINEOUT,
+ &lineout_jack, lineout_jack_pins,
+ ARRAY_SIZE(lineout_jack_pins));
+
+ lineout_jack_gpio.invert = pdata->lineout_det_swh;
+ lineout_jack_gpio.gpio = pdata->gpio_lineout_det;
+ snd_soc_jack_add_gpios(&lineout_jack, 1, &lineout_jack_gpio);
+ }
done:
msm_set_codec_reg_done(true);
return 0;
@@ -2007,6 +2154,34 @@
"qcom,hph-en0-gpio", pdev->dev.of_node->full_name);
}
+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,linein-det-swh",
+ &pdata->linein_det_swh);
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: missing %s in dt node\n",
+ __func__, "qcom,linein-det-swh");
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, "qcom,lineout-det-swh",
+ &pdata->lineout_det_swh);
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: missing %s in dt node\n",
+ __func__, "qcom,lineout-det-swh");
+ }
+
+ pdata->gpio_linein_det = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,linein-det-gpio", 0);
+ if (pdata->gpio_linein_det < 0) {
+ dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
+ "qcom,linein-det-gpio", pdev->dev.of_node->full_name);
+ }
+
+ pdata->gpio_lineout_det = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,lineout-det-gpio", 0);
+ if (pdata->gpio_lineout_det < 0) {
+ dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
+ "qcom,lineout-det-gpio", pdev->dev.of_node->full_name);
+ }
+
ret = msm_ext_prepare_hifi(pdata);
if (ret) {
dev_dbg(&pdev->dev, "msm_ext_prepare_hifi failed (%d)\n",
diff --git a/dsp/audio_cal_utils.c b/dsp/audio_cal_utils.c
index ad1dc3d..c6449dd 100644
--- a/dsp/audio_cal_utils.c
+++ b/dsp/audio_cal_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -63,6 +63,7 @@
break;
case ADM_AUDPROC_CAL_TYPE:
case ADM_LSM_AUDPROC_CAL_TYPE:
+ case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
size = sizeof(struct audio_cal_info_audproc);
break;
case ADM_AUDVOL_CAL_TYPE:
@@ -213,6 +214,7 @@
break;
case ADM_AUDPROC_CAL_TYPE:
case ADM_LSM_AUDPROC_CAL_TYPE:
+ case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
size = sizeof(struct audio_cal_type_audproc);
break;
case ADM_AUDVOL_CAL_TYPE:
diff --git a/dsp/codecs/audio_aac.c b/dsp/codecs/audio_aac.c
index c742f72..44444ef 100644
--- a/dsp/codecs/audio_aac.c
+++ b/dsp/codecs/audio_aac.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -230,7 +230,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_ioctl(file, cmd, arg);
if (rc)
- pr_err("%s[%pK]:Failed in utils_ioctl: %d\n",
+ pr_err_ratelimited("%s[%pK]:Failed in utils_ioctl: %d\n",
__func__, audio, rc);
}
}
@@ -339,7 +339,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_compat_ioctl(file, cmd, arg);
if (rc)
- pr_err("%s[%pK]:Failed in utils_ioctl: %d\n",
+ pr_err_ratelimited("%s[%pK]:Failed in utils_ioctl: %d\n",
__func__, audio, rc);
}
}
diff --git a/dsp/codecs/audio_alac.c b/dsp/codecs/audio_alac.c
index cfb3087..975a1e9 100644
--- a/dsp/codecs/audio_alac.c
+++ b/dsp/codecs/audio_alac.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -151,7 +151,7 @@
default: {
rc = audio->codec_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
@@ -253,7 +253,7 @@
default: {
rc = audio->codec_compat_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
diff --git a/dsp/codecs/audio_ape.c b/dsp/codecs/audio_ape.c
index 3df6347..f2a6bf7 100644
--- a/dsp/codecs/audio_ape.c
+++ b/dsp/codecs/audio_ape.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -137,7 +137,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
@@ -235,7 +235,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_compat_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
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/codecs/audio_utils_aio.c b/dsp/codecs/audio_utils_aio.c
index e8f22e7..9c8b3b8 100644
--- a/dsp/codecs/audio_utils_aio.c
+++ b/dsp/codecs/audio_utils_aio.c
@@ -1,6 +1,6 @@
/* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -201,17 +201,17 @@
if (audio->enabled) {
rc = q6asm_cmd(audio->ac, CMD_PAUSE);
if (rc < 0)
- pr_err("%s[%pK]: pause cmd failed rc=%d\n",
+ pr_err_ratelimited("%s[%pK]: pause cmd failed rc=%d\n",
__func__, audio, rc);
if (rc == 0) {
/* Send suspend only if pause was successful */
rc = q6asm_cmd(audio->ac, CMD_SUSPEND);
if (rc < 0)
- pr_err("%s[%pK]: suspend cmd failed rc=%d\n",
+ pr_err_ratelimited("%s[%pK]: suspend cmd failed rc=%d\n",
__func__, audio, rc);
} else
- pr_err("%s[%pK]: not sending suspend since pause failed\n",
+ pr_err_ratelimited("%s[%pK]: not sending suspend since pause failed\n",
__func__, audio);
} else
@@ -230,7 +230,7 @@
if (!(audio->drv_status & ADRV_STATUS_PAUSE)) {
rc = audio_aio_pause(audio);
if (rc < 0)
- pr_err("%s[%pK}: pause cmd failed rc=%d\n",
+ pr_err_ratelimited("%s[%pK}: pause cmd failed rc=%d\n",
__func__, audio,
rc);
else
@@ -238,13 +238,13 @@
}
rc = q6asm_cmd(audio->ac, CMD_FLUSH);
if (rc < 0)
- pr_err("%s[%pK]: flush cmd failed rc=%d\n",
+ pr_err_ratelimited("%s[%pK]: flush cmd failed rc=%d\n",
__func__, audio, rc);
/* Not in stop state, reenable the stream */
if (audio->stopped == 0) {
rc = audio_aio_enable(audio);
if (rc)
- pr_err("%s[%pK]:audio re-enable failed\n",
+ pr_err_ratelimited("%s[%pK]:audio re-enable failed\n",
__func__, audio);
else {
audio->enabled = 1;
@@ -268,7 +268,7 @@
rc = q6asm_cmd(audio->ac, CMD_OUT_FLUSH);
if (rc < 0)
- pr_err("%s[%pK}: output port flush cmd failed rc=%d\n",
+ pr_err_ratelimited("%s[%pK}: output port flush cmd failed rc=%d\n",
__func__, audio, rc);
return rc;
}
@@ -402,7 +402,7 @@
/* Close the session */
rc = q6asm_cmd(audio->ac, CMD_CLOSE);
if (rc < 0)
- pr_err("%s[%pK]:Failed to close the session rc=%d\n",
+ pr_err_ratelimited("%s[%pK]:Failed to close the session rc=%d\n",
__func__, audio, rc);
audio->stopped = 1;
wake_up(&audio->write_wait);
@@ -677,7 +677,7 @@
pr_debug("%s[%pK]: EOS cmd sent to DSP\n", __func__, audio);
if (rc < 0)
- pr_err("%s[%pK]: q6asm_cmd failed, rc = %d",
+ pr_err_ratelimited("%s[%pK]: q6asm_cmd failed, rc = %d",
__func__, audio, rc);
pr_debug("%s[%pK]: wait for RENDERED_EOS from DSP\n"
@@ -1422,7 +1422,7 @@
mutex_lock(&audio->read_lock);
rc = audio_aio_outport_flush(audio);
if (rc < 0) {
- pr_err("%s[%pK]: AUDIO_OUTPORT_FLUSH failed\n",
+ pr_err_ratelimited("%s[%pK]: AUDIO_OUTPORT_FLUSH failed\n",
__func__, audio);
rc = -EINTR;
}
@@ -1436,7 +1436,7 @@
audio->stopped = 1;
rc = audio_aio_flush(audio);
if (rc < 0) {
- pr_err("%s[%pK]:Audio Stop procedure failed rc=%d\n",
+ pr_err_ratelimited("%s[%pK]:Audio Stop procedure failed rc=%d\n",
__func__, audio, rc);
mutex_unlock(&audio->lock);
break;
@@ -1457,7 +1457,7 @@
if (arg == 1) {
rc = audio_aio_pause(audio);
if (rc < 0) {
- pr_err("%s[%pK]: pause FAILED rc=%d\n",
+ pr_err_ratelimited("%s[%pK]: pause FAILED rc=%d\n",
__func__, audio, rc);
mutex_unlock(&audio->lock);
break;
@@ -1467,7 +1467,7 @@
if (audio->drv_status & ADRV_STATUS_PAUSE) {
rc = audio_aio_enable(audio);
if (rc)
- pr_err("%s[%pK]: audio enable failed\n",
+ pr_err_ratelimited("%s[%pK]: audio enable failed\n",
__func__, audio);
else {
audio->drv_status &= ~ADRV_STATUS_PAUSE;
@@ -1494,7 +1494,7 @@
/* Flush input / Output buffer in software*/
audio_aio_ioport_reset(audio);
if (rc < 0) {
- pr_err("%s[%pK]:AUDIO_FLUSH interrupted\n",
+ pr_err_ratelimited("%s[%pK]:AUDIO_FLUSH interrupted\n",
__func__, audio);
rc = -EINTR;
} else {
@@ -1514,7 +1514,7 @@
mutex_lock(&audio->lock);
if (copy_to_user((void *)arg, &audio->ac->session,
sizeof(u16))) {
- pr_err("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n",
+ pr_err_ratelimited("%s: copy_to_user for AUDIO_GET_SESSION_ID failed\n",
__func__);
rc = -EFAULT;
}
@@ -1524,7 +1524,7 @@
case AUDIO_PM_AWAKE: {
if ((audio->audio_ws_mgr == NULL) ||
(audio->miscdevice == NULL)) {
- pr_err("%s[%pK]: invalid ws_mgr or miscdevice",
+ pr_err_ratelimited("%s[%pK]: invalid ws_mgr or miscdevice",
__func__, audio);
rc = -EACCES;
break;
@@ -1544,7 +1544,7 @@
case AUDIO_PM_RELAX: {
if ((audio->audio_ws_mgr == NULL) ||
(audio->miscdevice == NULL)) {
- pr_err("%s[%pK]: invalid ws_mgr or miscdevice",
+ pr_err_ratelimited("%s[%pK]: invalid ws_mgr or miscdevice",
__func__, audio);
rc = -EACCES;
break;
diff --git a/dsp/codecs/audio_wma.c b/dsp/codecs/audio_wma.c
index ef9c8c6..0e8341e 100644
--- a/dsp/codecs/audio_wma.c
+++ b/dsp/codecs/audio_wma.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -126,7 +126,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
@@ -215,7 +215,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_compat_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
diff --git a/dsp/codecs/audio_wmapro.c b/dsp/codecs/audio_wmapro.c
index 2182618..6b1e46f 100644
--- a/dsp/codecs/audio_wmapro.c
+++ b/dsp/codecs/audio_wmapro.c
@@ -2,7 +2,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -177,7 +177,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
@@ -287,7 +287,7 @@
pr_debug("%s[%pK]: Calling utils ioctl\n", __func__, audio);
rc = audio->codec_compat_ioctl(file, cmd, arg);
if (rc)
- pr_err("Failed in utils_ioctl: %d\n", rc);
+ pr_err_ratelimited("Failed in utils_ioctl: %d\n", rc);
break;
}
}
diff --git a/dsp/q6adm.c b/dsp/q6adm.c
index 74a9244..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,87 +717,96 @@
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) {
+ if (ret) {
pr_err("%s: fail to get channel weight with error %d\n",
__func__, ret);
goto fail_cmd;
@@ -2158,7 +2171,8 @@
struct cal_block_data, list);
if (cal_index == ADM_AUDPROC_CAL ||
- cal_index == ADM_LSM_AUDPROC_CAL) {
+ cal_index == ADM_LSM_AUDPROC_CAL ||
+ cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
audproc_cal_info = cal_block->cal_info;
if ((audproc_cal_info->path == path) &&
(cal_block->cal_data.size > 0))
@@ -2192,7 +2206,8 @@
struct cal_block_data, list);
if (cal_index == ADM_AUDPROC_CAL ||
- cal_index == ADM_LSM_AUDPROC_CAL) {
+ cal_index == ADM_LSM_AUDPROC_CAL ||
+ cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
audproc_cal_info = cal_block->cal_info;
if ((audproc_cal_info->path == path) &&
(audproc_cal_info->app_type == app_type) &&
@@ -2230,7 +2245,8 @@
struct cal_block_data, list);
if (cal_index == ADM_AUDPROC_CAL ||
- cal_index == ADM_LSM_AUDPROC_CAL) {
+ cal_index == ADM_LSM_AUDPROC_CAL ||
+ cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
audproc_cal_info = cal_block->cal_info;
if ((audproc_cal_info->path == path) &&
(audproc_cal_info->app_type == app_type) &&
@@ -2317,12 +2333,18 @@
{
pr_debug("%s: port id 0x%x copp_idx %d\n", __func__, port_id, copp_idx);
- if (passthr_mode != LISTEN)
+ if (passthr_mode != LISTEN) {
send_adm_cal_type(ADM_AUDPROC_CAL, path, port_id, copp_idx,
perf_mode, app_type, acdb_id, sample_rate);
- else
+ } else {
send_adm_cal_type(ADM_LSM_AUDPROC_CAL, path, port_id, copp_idx,
perf_mode, app_type, acdb_id, sample_rate);
+
+ send_adm_cal_type(ADM_LSM_AUDPROC_PERSISTENT_CAL, path,
+ port_id, copp_idx, perf_mode, app_type,
+ acdb_id, sample_rate);
+ }
+
send_adm_cal_type(ADM_AUDVOL_CAL, path, port_id, copp_idx, perf_mode,
app_type, acdb_id, sample_rate);
}
@@ -2624,6 +2646,7 @@
}
if ((topology == VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY) ||
+ (topology == VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
(topology == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
(topology == VPM_TX_DM_RFECNS_COPP_TOPOLOGY))
rate = 16000;
@@ -3492,6 +3515,9 @@
case ADM_RTAC_AUDVOL_CAL_TYPE:
ret = ADM_RTAC_AUDVOL_CAL;
break;
+ case ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE:
+ ret = ADM_LSM_AUDPROC_PERSISTENT_CAL;
+ break;
default:
pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
}
@@ -3713,6 +3739,12 @@
adm_set_cal, NULL, NULL} },
{adm_map_cal_data, adm_unmap_cal_data,
cal_utils_match_buf_num} },
+
+ {{ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
+ {adm_alloc_cal, adm_dealloc_cal, NULL,
+ adm_set_cal, NULL, NULL} },
+ {adm_map_cal_data, adm_unmap_cal_data,
+ cal_utils_match_buf_num} },
};
pr_debug("%s:\n", __func__);
@@ -4503,6 +4535,13 @@
rc = -ENOMEM;
goto unlock;
}
+ } else if (cal_index == ADM_LSM_AUDPROC_PERSISTENT_CAL) {
+ if (cal_block->cal_data.size > AUD_PROC_PERSIST_BLOCK_SIZE) {
+ pr_err("%s:persist invalid size exp/actual[%zd, %d]\n",
+ __func__, cal_block->cal_data.size, *size);
+ rc = -ENOMEM;
+ goto unlock;
+ }
} else if (cal_index == ADM_AUDVOL_CAL) {
if (cal_block->cal_data.size > AUD_VOL_BLOCK_SIZE) {
pr_err("%s:aud_vol:invalid size exp/actual[%zd, %d]\n",
diff --git a/dsp/q6asm.c b/dsp/q6asm.c
index 8701962..4091faf 100644
--- a/dsp/q6asm.c
+++ b/dsp/q6asm.c
@@ -9543,11 +9543,11 @@
int cnt = 0;
if (!ac) {
- pr_err("%s: APR handle NULL\n", __func__);
+ pr_err_ratelimited("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
if (ac->apr == NULL) {
- pr_err("%s: AC APR handle NULL\n", __func__);
+ pr_err_ratelimited("%s: AC APR handle NULL\n", __func__);
return -EINVAL;
}
q6asm_stream_add_hdr(ac, &hdr, sizeof(hdr), TRUE, stream_id);
@@ -9707,11 +9707,11 @@
int rc;
if (!ac) {
- pr_err("%s: APR handle NULL\n", __func__);
+ pr_err_ratelimited("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
if (ac->apr == NULL) {
- pr_err("%s: AC APR handle NULL\n", __func__);
+ pr_err_ratelimited("%s: AC APR handle NULL\n", __func__);
return -EINVAL;
}
q6asm_stream_add_hdr_async(ac, &hdr, sizeof(hdr), TRUE, stream_id);
@@ -9796,11 +9796,11 @@
int rc = 0;
if (!ac) {
- pr_err("%s: APR handle NULL\n", __func__);
+ pr_err_ratelimited("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
if (ac->apr == NULL) {
- pr_err("%s: AC APR handle NULL\n", __func__);
+ pr_err_ratelimited("%s: AC APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: session[%d]\n", __func__, ac->session);
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/dsp/rtac.c b/dsp/rtac.c
index 0455779..a4dec9a 100644
--- a/dsp/rtac.c
+++ b/dsp/rtac.c
@@ -35,7 +35,7 @@
#define MAX_PAYLOAD_SIZE 4076
#define RTAC_MAX_ACTIVE_VOICE_COMBOS 2
#define RTAC_MAX_ACTIVE_POPP 8
-#define RTAC_BUF_SIZE 57344
+#define RTAC_BUF_SIZE 163840
#define TIMEOUT_MS 1000
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index a608a66..d313d64 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -4015,6 +4015,7 @@
#define DEFAULT_POPP_TOPOLOGY 0x00010BE4
#define COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY 0x0001076B
#define COMPRESSED_PASSTHROUGH_NONE_TOPOLOGY 0x00010774
+#define VPM_TX_SM_ECNS_COPP_TOPOLOGY 0x00010F71
#define VPM_TX_SM_ECNS_V2_COPP_TOPOLOGY 0x00010F89
#define VPM_TX_DM_FLUENCE_COPP_TOPOLOGY 0x00010F72
#define VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY 0x00010F75
diff --git a/include/dsp/q6adm-v2.h b/include/dsp/q6adm-v2.h
index e8000ab..5308b6e 100644
--- a/include/dsp/q6adm-v2.h
+++ b/include/dsp/q6adm-v2.h
@@ -27,8 +27,12 @@
((MAX_MODULES_IN_TOPO + 1) * sizeof(uint32_t))
#define AUD_PROC_BLOCK_SIZE 4096
#define AUD_VOL_BLOCK_SIZE 4096
+#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,
@@ -38,6 +42,7 @@
ADM_RTAC_APR_CAL,
ADM_SRS_TRUMEDIA,
ADM_RTAC_AUDVOL_CAL,
+ ADM_LSM_AUDPROC_PERSISTENT_CAL,
ADM_MAX_CAL_TYPES
};
@@ -184,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);
diff --git a/include/uapi/Android.mk b/include/uapi/Android.mk
index 36bcfde..b8c209a 100644
--- a/include/uapi/Android.mk
+++ b/include/uapi/Android.mk
@@ -17,6 +17,7 @@
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_PREBUILT_INT_KERNEL)
GEN := $(addprefix $(UAPI_OUT)/,$(AUDIO_KERNEL_HEADERS))
+$(GEN): $(KERNEL_USR)
$(GEN): PRIVATE_PATH := $(MYLOCAL_PATH)
$(GEN): PRIVATE_CUSTOM_TOOL = $(shell cd $(PRODUCT_OUT)/obj/KERNEL_OBJ; $(BUILD_ROOT_RELATIVE)$(HEADER_INSTALL_DIR)/headers_install.sh $(BUILD_ROOT_RELATIVE)$(dir $@) $(BUILD_ROOT_RELATIVE)$(subst $(UAPI_OUT),$(MYLOCAL_PATH),$(dir $@)) $(notdir $@))
$(GEN): $(addprefix $(MYLOCAL_PATH)/,$(AUDIO_KERNEL_HEADERS))
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 3b97ab2..c5811d0 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -103,6 +103,7 @@
AFE_LSM_TX_CAL_TYPE,
ADM_LSM_TOPOLOGY_CAL_TYPE,
ADM_LSM_AUDPROC_CAL_TYPE,
+ ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE,
MAX_CAL_TYPES,
};
@@ -115,6 +116,7 @@
#define AFE_LSM_TX_CAL_TYPE AFE_LSM_TX_CAL_TYPE
#define ADM_LSM_TOPOLOGY_CAL_TYPE ADM_LSM_TOPOLOGY_CAL_TYPE
#define ADM_LSM_AUDPROC_CAL_TYPE ADM_LSM_AUDPROC_CAL_TYPE
+#define ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE ADM_LSM_AUDPROC_PERSISTENT_CAL_TYPE
#define LSM_CAL_TYPES
#define TOPOLOGY_SPECIFIC_CHANNEL_INFO
diff --git a/soc/soundwire.c b/soc/soundwire.c
index cda4789..69a9ed4 100644
--- a/soc/soundwire.c
+++ b/soc/soundwire.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -245,7 +245,7 @@
if (!dev->group_id)
return 0;
- if (master->gr_sid == dev_num)
+ if (master->gr_sid != dev_num)
return 0;
if (master->remove_from_group && master->remove_from_group(master))
diff --git a/soc/swr-wcd-ctrl.c b/soc/swr-wcd-ctrl.c
index c5ba37b..455e03b 100644
--- a/soc/swr-wcd-ctrl.c
+++ b/soc/swr-wcd-ctrl.c
@@ -1756,6 +1756,8 @@
(swrm->state == SWR_MSTR_UP)) {
dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n",
__func__, swrm->state);
+ list_for_each_entry(swr_dev, &mstr->devices, dev_list)
+ swr_reset_device(swr_dev);
} else {
pm_runtime_mark_last_busy(&pdev->dev);
mutex_unlock(&swrm->reslock);