Merge "ASoc: msm: add support for mixing data from different COPPs"
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 900d245..e689e93 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -65,6 +65,20 @@
unsigned int session_id;
};
+struct default_chmixer_param_id_coeff {
+ uint32_t index;
+ uint16_t num_output_channels;
+ uint16_t num_input_channels;
+};
+
+struct msm_pcm_channel_mixer {
+ int output_channel;
+ int input_channels[ADM_MAX_CHANNELS];
+ bool enable;
+ int rule;
+ int channel_weight[ADM_MAX_CHANNELS][ADM_MAX_CHANNELS];
+};
+
int srs_trumedia_open(int port_id, int copp_idx, __s32 srs_tech_id,
void *srs_params);
@@ -166,4 +180,8 @@
struct source_tracking_param *sourceTrackingData);
int adm_swap_speaker_channels(int port_id, int copp_idx, int sample_rate,
bool spk_swap);
+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);
#endif /* __Q6_ADM_V2_H__ */
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
index 43b2073..a8fcd34 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -1400,8 +1400,26 @@
}
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- if (atomic_inc_return(&supply->ref) == 1)
+ if (atomic_inc_return(&supply->ref) == 1) {
+ ret = regulator_set_voltage(supply->supply,
+ supply->min_uv,
+ supply->max_uv);
+ if (ret) {
+ dev_err(codec->dev,
+ "Setting regulator voltage(en) for micbias with err = %d\n",
+ ret);
+ goto out;
+ }
+ ret = regulator_set_load(supply->supply,
+ supply->optimum_ua);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Setting regulator optimum mode(en) failed for micbias with err = %d\n",
+ ret);
+ goto out;
+ }
ret = regulator_enable(supply->supply);
+ }
if (ret)
dev_err(codec->dev, "%s: Failed to enable %s\n",
__func__,
@@ -1413,12 +1431,27 @@
__func__, on_demand_supply_name[w->shift]);
goto out;
}
- if (atomic_dec_return(&supply->ref) == 0)
+ if (atomic_dec_return(&supply->ref) == 0) {
ret = regulator_disable(supply->supply);
if (ret)
dev_err(codec->dev, "%s: Failed to disable %s\n",
__func__,
on_demand_supply_name[w->shift]);
+ ret = regulator_set_voltage(supply->supply,
+ 0,
+ supply->max_uv);
+ if (ret) {
+ dev_err(codec->dev,
+ "Setting regulator voltage(dis) failed for micbias with err = %d\n",
+ ret);
+ goto out;
+ }
+ ret = regulator_set_load(supply->supply, 0);
+ if (ret < 0)
+ dev_err(codec->dev,
+ "Setting regulator optimum mode(dis) failed for micbias with err = %d\n",
+ ret);
+ }
break;
default:
break;
@@ -3685,6 +3718,30 @@
return NULL;
}
+static void msm_anlg_cdc_update_micbias_regulator(
+ const struct sdm660_cdc_priv *sdm660_cdc,
+ const char *name,
+ struct on_demand_supply *micbias_supply)
+{
+ int i;
+ struct sdm660_cdc_pdata *pdata = sdm660_cdc->dev->platform_data;
+
+ for (i = 0; i < sdm660_cdc->num_of_supplies; i++) {
+ if (sdm660_cdc->supplies[i].supply &&
+ !strcmp(sdm660_cdc->supplies[i].supply, name)) {
+ micbias_supply->supply =
+ sdm660_cdc->supplies[i].consumer;
+ micbias_supply->min_uv = pdata->regulator[i].min_uv;
+ micbias_supply->max_uv = pdata->regulator[i].max_uv;
+ micbias_supply->optimum_ua =
+ pdata->regulator[i].optimum_ua;
+ return;
+ }
+ }
+
+ dev_err(sdm660_cdc->dev, "Error: regulator not found:%s\n", name);
+}
+
static int msm_anlg_cdc_device_down(struct snd_soc_codec *codec)
{
struct msm_asoc_mach_data *pdata = NULL;
@@ -4114,10 +4171,10 @@
wcd9xxx_spmi_set_codec(codec);
- sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].supply =
- msm_anlg_cdc_find_regulator(
+ msm_anlg_cdc_update_micbias_regulator(
sdm660_cdc,
- on_demand_supply_name[ON_DEMAND_MICBIAS]);
+ on_demand_supply_name[ON_DEMAND_MICBIAS],
+ &sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS]);
atomic_set(&sdm660_cdc->on_demand_list[ON_DEMAND_MICBIAS].ref,
0);
@@ -4183,7 +4240,7 @@
if (pdata->regulator[i].ondemand)
continue;
if (regulator_count_voltages(
- sdm660_cdc->supplies[i].consumer) <= 0)
+ sdm660_cdc->supplies[i].consumer) <= 0)
continue;
ret = regulator_set_voltage(
@@ -4216,7 +4273,7 @@
if (pdata->regulator[i].ondemand)
continue;
if (regulator_count_voltages(
- sdm660_cdc->supplies[i].consumer) <= 0)
+ sdm660_cdc->supplies[i].consumer) <= 0)
continue;
regulator_set_voltage(sdm660_cdc->supplies[i].consumer, 0,
pdata->regulator[i].max_uv);
@@ -4317,6 +4374,28 @@
if (regulator_count_voltages(
sdm660_cdc->supplies[i].consumer) <= 0)
continue;
+ if (pdata->regulator[i].ondemand) {
+ ret = regulator_set_voltage(
+ sdm660_cdc->supplies[i].consumer,
+ 0, pdata->regulator[i].max_uv);
+ if (ret) {
+ dev_err(sdm660_cdc->dev,
+ "Setting regulator voltage failed for regulator %s err = %d\n",
+ sdm660_cdc->supplies[i].supply, ret);
+ goto err_supplies;
+ }
+ ret = regulator_set_load(
+ sdm660_cdc->supplies[i].consumer, 0);
+ if (ret < 0) {
+ dev_err(sdm660_cdc->dev,
+ "Setting regulator optimum mode failed for regulator %s err = %d\n",
+ sdm660_cdc->supplies[i].supply, ret);
+ goto err_supplies;
+ } else {
+ ret = 0;
+ continue;
+ }
+ }
ret = regulator_set_voltage(sdm660_cdc->supplies[i].consumer,
pdata->regulator[i].min_uv,
pdata->regulator[i].max_uv);
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
index 0c9e9a6..9563565 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.h
@@ -144,6 +144,9 @@
struct on_demand_supply {
struct regulator *supply;
atomic_t ref;
+ int min_uv;
+ int max_uv;
+ int optimum_ua;
};
struct wcd_imped_i_ref {
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 098958e..222c65a 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -4086,7 +4086,6 @@
dev_err(rtd->card->dev,
"%s lpaif_tert_muxsel_virt_addr is NULL\n",
__func__);
- auxpcm_intf_conf[index].ref_cnt++;
}
}
mutex_unlock(&auxpcm_intf_conf[index].lock);
@@ -4575,11 +4574,9 @@
mutex_lock(&mi2s_intf_conf[index].lock);
if (--mi2s_intf_conf[index].ref_cnt == 0) {
ret = msm_mi2s_set_sclk(substream, false);
- if (ret < 0) {
+ if (ret < 0)
pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
__func__, index, ret);
- mi2s_intf_conf[index].ref_cnt++;
- }
}
mutex_unlock(&mi2s_intf_conf[index].lock);
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 9eb0acb..c885265 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -3444,21 +3444,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -3471,28 +3468,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
@@ -3503,21 +3497,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -3530,28 +3521,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 83e1501..3a6cbe6 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -2243,21 +2243,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -2270,28 +2267,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
index f668e95..7ef1ca8 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
@@ -559,21 +559,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -586,28 +583,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
@@ -618,21 +612,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -645,28 +636,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
index 9b7c6fb..325d642 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
@@ -842,26 +842,21 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
-
- ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
- if (ret < 0)
- pr_err("%s: msm_pcm_playback_app_type_cfg_ctl_put failed, err %d\n",
- __func__, ret);
-
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+ ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
+ be_id, &cfg_data);
+ if (ret < 0)
+ pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
return ret;
}
@@ -870,29 +865,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
- pr_err("%s: msm_pcm_playback_app_type_cfg_ctl_get failed, err: %d\n",
- __func__, ret);
+ pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
-
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
@@ -903,26 +894,21 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
-
- ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
- if (ret < 0)
- pr_err("%s: msm_pcm_capture_app_type_cfg_ctl_put failed, err: %d\n",
- __func__, ret);
-
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+ ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
+ be_id, &cfg_data);
+ if (ret < 0)
+ pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
return ret;
}
@@ -932,28 +918,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
- pr_err("%s: msm_pcm_capture_app_type_cfg_ctl_get failed, err: %d\n",
- __func__, ret);
+ pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index c42cb05..74e99d3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -1556,21 +1556,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -1583,28 +1580,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_RX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
@@ -1615,21 +1609,18 @@
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
int be_id = ucontrol->value.integer.value[3];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate = 48000;
- app_type = ucontrol->value.integer.value[0];
- acdb_dev_id = ucontrol->value.integer.value[1];
+ cfg_data.app_type = ucontrol->value.integer.value[0];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[1];
if (ucontrol->value.integer.value[2] != 0)
- sample_rate = ucontrol->value.integer.value[2];
+ cfg_data.sample_rate = ucontrol->value.integer.value[2];
pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
- be_id, app_type,
- acdb_dev_id, sample_rate);
+ be_id, &cfg_data);
if (ret < 0)
pr_err("%s: msm_pcm_routing_reg_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -1642,28 +1633,25 @@
{
u64 fe_id = kcontrol->private_value;
int session_type = SESSION_TYPE_TX;
- int be_id = ucontrol->value.integer.value[3];
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
int ret = 0;
- int app_type;
- int acdb_dev_id;
- int sample_rate;
ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
- be_id, &app_type,
- &acdb_dev_id,
- &sample_rate);
+ &be_id, &cfg_data);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
goto done;
}
- ucontrol->value.integer.value[0] = app_type;
- ucontrol->value.integer.value[1] = acdb_dev_id;
- ucontrol->value.integer.value[2] = sample_rate;
+ ucontrol->value.integer.value[0] = cfg_data.app_type;
+ ucontrol->value.integer.value[1] = cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[2] = cfg_data.sample_rate;
+ ucontrol->value.integer.value[3] = be_id;
pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fe_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
done:
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 84cc554..019cbae 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -81,6 +81,12 @@
static bool is_ds2_on;
static bool swap_ch;
+#define WEIGHT_0_DB 0x4000
+/* all the FEs which can support channel mixer */
+static struct msm_pcm_channel_mixer channel_mixer[MSM_FRONTEND_DAI_MM_SIZE];
+/* input BE for each FE */
+static int channel_input[MSM_FRONTEND_DAI_MM_SIZE][ADM_MAX_CHANNELS];
+
enum {
MADNONE,
MADAUDIO,
@@ -677,6 +683,8 @@
static struct msm_pcm_stream_app_type_cfg
fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MAX][2][MSM_BACKEND_DAI_MAX];
+static int last_be_id_configured[MSM_FRONTEND_DAI_MAX][MAX_SESSION_TYPES];
+
/* The caller of this should aqcuire routing lock */
void msm_pcm_routing_get_bedai_info(int be_idx,
struct msm_pcm_routing_bdai_data *be_dai)
@@ -743,15 +751,22 @@
return rc;
}
-int msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int session_type,
- int be_id, int app_type,
- int acdb_dev_id, int sample_rate)
+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)
{
int ret = 0;
+ if (cfg_data == NULL) {
+ pr_err("%s: Received NULL pointer for cfg_data\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
pr_debug("%s: fedai_id %d, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
__func__, fedai_id, session_type, be_id,
- app_type, acdb_dev_id, sample_rate);
+ cfg_data->app_type, cfg_data->acdb_dev_id,
+ cfg_data->sample_rate);
if (!is_mm_lsm_fe_id(fedai_id)) {
pr_err("%s: Invalid machine driver ID %d\n",
@@ -773,15 +788,18 @@
goto done;
}
- fe_dai_app_type_cfg[fedai_id][session_type][be_id].app_type = app_type;
- fe_dai_app_type_cfg[fedai_id][session_type][be_id].acdb_dev_id =
- acdb_dev_id;
- fe_dai_app_type_cfg[fedai_id][session_type][be_id].sample_rate =
- sample_rate;
+ fe_dai_app_type_cfg[fedai_id][session_type][be_id] = *cfg_data;
+
+ /*
+ * Store the BE ID of the configuration information set as the latest so
+ * the get mixer control knows what to return.
+ */
+ last_be_id_configured[fedai_id][session_type] = be_id;
done:
return ret;
}
+EXPORT_SYMBOL(msm_pcm_routing_reg_stream_app_type_cfg);
/**
* msm_pcm_routing_get_stream_app_type_cfg
@@ -793,55 +811,48 @@
* fedai_id - Passed value, front end ID for which app type config is wanted
* session_type - Passed value, session type for which app type config
* is wanted
- * be_id - Passed value, back end device id for which app type config is wanted
- * app_type - Returned value, app type used by app type config
- * acdb_dev_id - Returned value, ACDB device ID used by app type config
- * sample_rate - Returned value, sample rate used by app type config
+ * be_id - Returned value, back end device id the app type config data is for
+ * cfg_data - Returned value, configuration data used by app type config
*/
-int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type,
- int be_id, int *app_type,
- int *acdb_dev_id, int *sample_rate)
+int msm_pcm_routing_get_stream_app_type_cfg(
+ int fedai_id, int session_type, int *bedai_id,
+ struct msm_pcm_stream_app_type_cfg *cfg_data)
{
+ int be_id;
int ret = 0;
- if (app_type == NULL) {
- pr_err("%s: NULL pointer sent for app_type\n", __func__);
+ if (bedai_id == NULL) {
+ pr_err("%s: Received NULL pointer for backend ID\n", __func__);
ret = -EINVAL;
goto done;
- } else if (acdb_dev_id == NULL) {
- pr_err("%s: NULL pointer sent for acdb_dev_id\n", __func__);
- ret = -EINVAL;
- goto done;
- } else if (sample_rate == NULL) {
- pr_err("%s: NULL pointer sent for sample rate\n", __func__);
+ } else if (cfg_data == NULL) {
+ pr_err("%s: NULL pointer sent for cfg_data\n", __func__);
ret = -EINVAL;
goto done;
} else if (!is_mm_lsm_fe_id(fedai_id)) {
- pr_err("%s: Invalid FE ID %d\n",
- __func__, fedai_id);
+ pr_err("%s: Invalid FE ID %d\n", __func__, fedai_id);
ret = -EINVAL;
goto done;
} else if (session_type != SESSION_TYPE_RX &&
session_type != SESSION_TYPE_TX) {
- pr_err("%s: Invalid session type %d\n",
- __func__, session_type);
+ pr_err("%s: Invalid session type %d\n", __func__, session_type);
ret = -EINVAL;
goto done;
- } else if (be_id < 0 || be_id >= MSM_BACKEND_DAI_MAX) {
- pr_err("%s: Received out of bounds be_id %d\n",
- __func__, be_id);
- return -EINVAL;
}
- *app_type = fe_dai_app_type_cfg[fedai_id][session_type][be_id].app_type;
- *acdb_dev_id =
- fe_dai_app_type_cfg[fedai_id][session_type][be_id].acdb_dev_id;
- *sample_rate =
- fe_dai_app_type_cfg[fedai_id][session_type][be_id].sample_rate;
+ be_id = last_be_id_configured[fedai_id][session_type];
+ if (be_id < 0 || be_id >= MSM_BACKEND_DAI_MAX) {
+ pr_err("%s: Invalid BE ID %d\n", __func__, be_id);
+ ret = -EINVAL;
+ goto done;
+ }
+ *bedai_id = be_id;
+ *cfg_data = fe_dai_app_type_cfg[fedai_id][session_type][be_id];
pr_debug("%s: fedai_id %d, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
- __func__, fedai_id, session_type, be_id,
- *app_type, *acdb_dev_id, *sample_rate);
+ __func__, fedai_id, session_type, *bedai_id,
+ cfg_data->app_type, cfg_data->acdb_dev_id,
+ cfg_data->sample_rate);
done:
return ret;
}
@@ -1257,6 +1268,62 @@
return session_id;
}
+static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode,
+ int dspst_id, int stream_type)
+{
+ int copp_idx = 0;
+ int sess_type = 0;
+ int i = 0, j = 0, be_id;
+ int ret = 0;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return 0;
+ }
+
+ if (!(channel_mixer[fe_id].enable)) {
+ pr_debug("%s: channel mixer not enabled for FE %d\n",
+ __func__, fe_id);
+ return 0;
+ }
+
+ if (stream_type == SNDRV_PCM_STREAM_PLAYBACK)
+ sess_type = SESSION_TYPE_RX;
+ else
+ sess_type = SESSION_TYPE_TX;
+
+ for (i = 0; i < ADM_MAX_CHANNELS && channel_input[fe_id][i] > 0;
+ ++i) {
+ be_id = channel_input[fe_id][i] - 1;
+ channel_mixer[fe_id].input_channels[i] =
+ msm_bedais[be_id].channel;
+
+ if ((msm_bedais[be_id].active) &&
+ test_bit(fe_id,
+ &msm_bedais[be_id].fe_sessions[0])) {
+ unsigned long copp =
+ session_copp_map[fe_id][sess_type][be_id];
+ for (j = 0; j < MAX_COPPS_PER_PORT; j++) {
+ if (test_bit(j, &copp)) {
+ copp_idx = j;
+ break;
+ }
+ }
+
+ pr_debug("%s: fe %d, be %d, channel %d, copp %d\n",
+ __func__,
+ fe_id, be_id, msm_bedais[be_id].channel,
+ copp_idx);
+ ret = adm_programable_channel_mixer(
+ msm_bedais[be_id].port_id,
+ copp_idx, dspst_id, sess_type,
+ channel_mixer + fe_id, i);
+ }
+ }
+
+ return ret;
+}
+
int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
int dspst_id, int stream_type)
{
@@ -1265,6 +1332,7 @@
u32 channels, sample_rate;
uint16_t bits_per_sample = 16;
uint32_t passthr_mode = LEGACY_PCM;
+ int ret = 0;
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
/* bad ID assigned in machine driver */
@@ -1388,8 +1456,11 @@
adm_matrix_map(path_type, payload, perf_mode, passthr_mode);
msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode);
}
+
+ ret = msm_pcm_routing_channel_mixer(fedai_id, perf_mode,
+ dspst_id, stream_type);
mutex_unlock(&routing_lock);
- return 0;
+ return ret;
}
int msm_pcm_routing_reg_phy_stream_v2(int fedai_id, int perf_mode,
@@ -2624,6 +2695,649 @@
return 1;
}
+static int msm_pcm_get_channel_rule_index(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0;
+
+ fe_id = ((struct soc_mixer_control *)
+ kcontrol->private_value)->shift;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = channel_mixer[fe_id].rule;
+
+ return 0;
+}
+
+static int msm_pcm_put_channel_rule_index(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0;
+
+ fe_id = ((struct soc_mixer_control *)
+ kcontrol->private_value)->shift;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ channel_mixer[fe_id].rule = ucontrol->value.integer.value[0];
+
+ return 1;
+}
+
+static int msm_pcm_get_out_chs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0;
+
+ fe_id = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] =
+ channel_mixer[fe_id].output_channel;
+ return 0;
+}
+
+static int msm_pcm_put_out_chs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0;
+
+ fe_id = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: fe_id is %d, output channels = %d\n", __func__,
+ fe_id,
+ (unsigned int)(ucontrol->value.integer.value[0]));
+ channel_mixer[fe_id].output_channel =
+ (unsigned int)(ucontrol->value.integer.value[0]);
+
+ return 1;
+}
+
+static const char *const ch_mixer[] = {"Disable", "Enable"};
+
+/* If new backend is added, need update this array */
+static const char *const be_name[] = {
+"ZERO", "PRI_I2S_RX", "PRI_I2S_TX", "SLIM_0_RX",
+"SLIM_0_TX", "HDMI_RX", "INT_BT_SCO_RX", "INT_BT_SCO_TX",
+"INT_FM_RX", "INT_FM_TX", "AFE_PCM_RX", "AFE_PCM_TX",
+"AUXPCM_RX", "AUXPCM_TX", "VOICE_PLAYBACK_TX", "VOICE2_PLAYBACK_TX",
+"INCALL_RECORD_RX", "INCALL_RECORD_TX", "MI2S_RX", "MI2S_TX",
+"SEC_I2S_RX", "SLIM_1_RX", "SLIM_1_TX", "SLIM_2_RX",
+"SLIM_2_TX", "SLIM_3_RX", "SLIM_3_TX", "SLIM_4_RX",
+"SLIM_4_TX", "SLIM_5_RX", "SLIM_5_TX", "SLIM_6_RX",
+"SLIM_6_TX", "SLIM_7_RX", "SLIM_7_TX", "SLIM_8_RX",
+"SLIM_8_TX", "EXTPROC_RX", "EXTPROC_TX", "EXPROC_EC_TX",
+"QUAT_MI2S_RX", "QUAT_MI2S_TX", "SECOND_MI2S_RX", "SECOND_MI2S_TX",
+"PRI_MI2S_RX", "PRI_MI2S_TX", "TERT_MI2S_RX", "TERT_MI2S_TX",
+"AUDIO_I2S_RX", "SEC_AUXPCM_RX", "SEC_AUXPCM_TX", "SPDIF_RX",
+"SECOND_MI2S_RX_SD1", "QUIN_MI2S_RX", "QUIN_MI2S_TX", "SENARY_MI2S_TX",
+"PRI_TDM_RX_0", "PRI_TDM_TX_0", "PRI_TDM_RX_1", "PRI_TDM_TX_1",
+"PRI_TDM_RX_2", "PRI_TDM_TX_2", "PRI_TDM_RX_3", "PRI_TDM_TX_3",
+"PRI_TDM_RX_4", "PRI_TDM_TX_4", "PRI_TDM_RX_5", "PRI_TDM_TX_5",
+"PRI_TDM_RX_6", "PRI_TDM_TX_6", "PRI_TDM_RX_7", "PRI_TDM_TX_7",
+"SEC_TDM_RX_0", "SEC_TDM_TX_0", "SEC_TDM_RX_1", "SEC_TDM_TX_1",
+"SEC_TDM_RX_2", "SEC_TDM_TX_2", "SEC_TDM_RX_3", "SEC_TDM_TX_3",
+"SEC_TDM_RX_4", "SEC_TDM_TX_4", "SEC_TDM_RX_5", "SEC_TDM_TX_5",
+"SEC_TDM_RX_6", "SEC_TDM_TX_6", "SEC_TDM_RX_7", "SEC_TDM_TX_7",
+"TERT_TDM_RX_0", "TERT_TDM_TX_0", "TERT_TDM_RX_1", "TERT_TDM_TX_1",
+"TERT_TDM_RX_2", "TERT_TDM_TX_2", "TERT_TDM_RX_3", "TERT_TDM_TX_3",
+"TERT_TDM_RX_4", "TERT_TDM_TX_4", "TERT_TDM_RX_5", "TERT_TDM_TX_5",
+"TERT_TDM_RX_6", "TERT_TDM_TX_6", "TERT_TDM_RX_7", "TERT_TDM_TX_7",
+"QUAT_TDM_RX_0", "QUAT_TDM_TX_0", "QUAT_TDM_RX_1", "QUAT_TDM_TX_1",
+"QUAT_TDM_RX_2", "QUAT_TDM_TX_2", "QUAT_TDM_RX_3", "QUAT_TDM_TX_3",
+"QUAT_TDM_RX_4", "QUAT_TDM_TX_4", "QUAT_TDM_RX_5", "QUAT_TDM_TX_5",
+"QUAT_TDM_RX_6", "QUAT_TDM_TX_6", "QUAT_TDM_RX_7", "QUAT_TDM_TX_7",
+"INT_BT_A2DP_RX", "USB_RX", "USB_TX", "DISPLAY_PORT_RX",
+"TERT_AUXPCM_RX", "TERT_AUXPCM_TX", "QUAT_AUXPCM_RX", "QUAT_AUXPCM_TX",
+"INT0_MI2S_RX", "INT0_MI2S_TX", "INT1_MI2S_RX", "INT1_MI2S_TX",
+"INT2_MI2S_RX", "INT2_MI2S_TX", "INT3_MI2S_RX", "INT3_MI2S_TX",
+"INT4_MI2S_RX", "INT4_MI2S_TX", "INT5_MI2S_RX", "INT5_MI2S_TX",
+"INT6_MI2S_RX", "INT6_MI2S_TX"
+};
+
+static SOC_ENUM_SINGLE_DECL(mm1_channel_mux,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, ch_mixer);
+static SOC_ENUM_SINGLE_DECL(mm2_channel_mux,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA2, ch_mixer);
+static SOC_ENUM_SINGLE_DECL(mm3_channel_mux,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA3, ch_mixer);
+static SOC_ENUM_SINGLE_DECL(mm4_channel_mux,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA4, ch_mixer);
+
+static SOC_ENUM_DOUBLE_DECL(mm1_ch1_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 0, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch2_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch3_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 2, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch4_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 3, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch5_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 4, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch6_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 5, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch7_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 6, be_name);
+static SOC_ENUM_DOUBLE_DECL(mm1_ch8_enum,
+ SND_SOC_NOPM, MSM_FRONTEND_DAI_MULTIMEDIA1, 7, be_name);
+
+static int msm_pcm_get_ctl_enum_info(struct snd_ctl_elem_info *uinfo,
+ unsigned int channels,
+ unsigned int items, const char *const names[])
+{
+ if (uinfo->value.enumerated.item >= items)
+ uinfo->value.enumerated.item = items - 1;
+
+ WARN(strlen(names[uinfo->value.enumerated.item]) >=
+ sizeof(uinfo->value.enumerated.name),
+ "ALSA: too long item name '%s'\n",
+ names[uinfo->value.enumerated.item]);
+ strlcpy(uinfo->value.enumerated.name,
+ names[uinfo->value.enumerated.item],
+ sizeof(uinfo->value.enumerated.name));
+ return 0;
+}
+
+static int msm_pcm_channel_mixer_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+
+ uinfo->value.enumerated.items = ARRAY_SIZE(ch_mixer);
+ msm_pcm_get_ctl_enum_info(uinfo, 1, e->items, e->texts);
+
+ return 0;
+}
+static int msm_pcm_channel_mixer_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0;
+
+ fe_id = ((struct soc_enum *)
+ kcontrol->private_value)->shift_l;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: FE %d %s\n", __func__,
+ fe_id,
+ channel_mixer[fe_id].enable ? "Enabled" : "Disabled");
+ ucontrol->value.enumerated.item[0] = channel_mixer[fe_id].enable;
+ return 0;
+}
+
+static int msm_pcm_channel_mixer_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0;
+
+ fe_id = ((struct soc_enum *)
+ kcontrol->private_value)->shift_l;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ channel_mixer[fe_id].enable = ucontrol->value.enumerated.item[0];
+ pr_debug("%s: %s FE %d\n", __func__,
+ channel_mixer[fe_id].enable ? "Enable" : "Disable",
+ fe_id);
+ return 0;
+}
+
+static int msm_pcm_channel_input_be_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+
+ uinfo->value.enumerated.items = ARRAY_SIZE(be_name);
+ msm_pcm_get_ctl_enum_info(uinfo, 1, e->items, e->texts);
+
+ return 0;
+}
+
+static int msm_pcm_channel_input_be_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ u16 fe_id = 0, in_ch = 0;
+
+ fe_id = e->shift_l;
+ in_ch = e->shift_r;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+ if (in_ch >= ADM_MAX_CHANNELS) {
+ pr_err("%s: invalid input channel %d\n", __func__, in_ch);
+ return -EINVAL;
+ }
+
+ channel_input[fe_id][in_ch] = ucontrol->value.enumerated.item[0];
+ return 1;
+}
+
+static int msm_pcm_channel_input_be_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ u16 fe_id = 0, in_ch = 0;
+
+ fe_id = e->shift_l;
+ in_ch = e->shift_r;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+ if (in_ch >= ADM_MAX_CHANNELS) {
+ pr_err("%s: invalid input channel %d\n", __func__, in_ch);
+ return -EINVAL;
+ }
+
+ ucontrol->value.enumerated.item[0] = channel_input[fe_id][in_ch];
+ return 1;
+}
+
+
+static int msm_pcm_channel_weight_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = ADM_MAX_CHANNELS;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = WEIGHT_0_DB;
+
+ return 0;
+}
+
+static int msm_pcm_channel_weight_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0, out_ch = 0;
+ int i, weight;
+
+ fe_id = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ out_ch = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->rshift;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+ if (out_ch >= ADM_MAX_CHANNELS) {
+ pr_err("%s: invalid input channel %d\n", __func__, out_ch);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: FE_ID: %d, channel weight %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld\n",
+ __func__, fe_id,
+ ucontrol->value.integer.value[0],
+ ucontrol->value.integer.value[1],
+ ucontrol->value.integer.value[2],
+ ucontrol->value.integer.value[3],
+ ucontrol->value.integer.value[4],
+ ucontrol->value.integer.value[5],
+ ucontrol->value.integer.value[6],
+ ucontrol->value.integer.value[7]);
+
+ for (i = 0; i < ADM_MAX_CHANNELS; ++i) {
+ weight = ucontrol->value.integer.value[i];
+ channel_mixer[fe_id].channel_weight[out_ch][i] = weight;
+ pr_debug("%s: FE_ID %d, output %d input %d weight %d\n",
+ __func__, fe_id, out_ch, i,
+ channel_mixer[fe_id].channel_weight[out_ch][i]);
+ }
+
+ return 0;
+}
+
+static int msm_pcm_channel_weight_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u16 fe_id = 0, out_ch = 0;
+ int i;
+
+ fe_id = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ out_ch = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->rshift;
+ if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) {
+ pr_err("%s: invalid FE %d\n", __func__, fe_id);
+ return -EINVAL;
+ }
+ if (out_ch >= ADM_MAX_CHANNELS) {
+ pr_err("%s: invalid input channel %d\n", __func__, out_ch);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ADM_MAX_CHANNELS; ++i)
+ ucontrol->value.integer.value[i] =
+ channel_mixer[fe_id].channel_weight[out_ch][i];
+
+ pr_debug("%s: FE_ID: %d, weight %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld",
+ __func__, fe_id,
+ ucontrol->value.integer.value[0],
+ ucontrol->value.integer.value[1],
+ ucontrol->value.integer.value[2],
+ ucontrol->value.integer.value[3],
+ ucontrol->value.integer.value[4],
+ ucontrol->value.integer.value[5],
+ ucontrol->value.integer.value[6],
+ ucontrol->value.integer.value[7]);
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new channel_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1 Channel Rule", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 8, 0,
+ msm_pcm_get_channel_rule_index,
+ msm_pcm_put_channel_rule_index),
+ SOC_SINGLE_EXT("MultiMedia2 Channel Rule", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 8, 0,
+ msm_pcm_get_channel_rule_index,
+ msm_pcm_put_channel_rule_index),
+ SOC_SINGLE_EXT("MultiMedia3 Channel Rule", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 8, 0,
+ msm_pcm_get_channel_rule_index,
+ msm_pcm_put_channel_rule_index),
+ SOC_SINGLE_EXT("MultiMedia4 Channel Rule", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 8, 0,
+ msm_pcm_get_channel_rule_index,
+ msm_pcm_put_channel_rule_index),
+ SOC_SINGLE_EXT("MultiMedia5 Channel Rule", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 8, 0,
+ msm_pcm_get_channel_rule_index,
+ msm_pcm_put_channel_rule_index),
+ SOC_SINGLE_EXT("MultiMedia6 Channel Rule", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 8, 0,
+ msm_pcm_get_channel_rule_index,
+ msm_pcm_put_channel_rule_index),
+
+ SOC_SINGLE_EXT("MultiMedia1 Channels", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 8, 0,
+ msm_pcm_get_out_chs,
+ msm_pcm_put_out_chs),
+ SOC_SINGLE_EXT("MultiMedia2 Channels", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 8, 0,
+ msm_pcm_get_out_chs,
+ msm_pcm_put_out_chs),
+ SOC_SINGLE_EXT("MultiMedia3 Channels", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 8, 0,
+ msm_pcm_get_out_chs,
+ msm_pcm_put_out_chs),
+ SOC_SINGLE_EXT("MultiMedia4 Channels", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 8, 0,
+ msm_pcm_get_out_chs,
+ msm_pcm_put_out_chs),
+ SOC_SINGLE_EXT("MultiMedia5 Channels", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 8, 0,
+ msm_pcm_get_out_chs,
+ msm_pcm_put_out_chs),
+ SOC_SINGLE_EXT("MultiMedia6 Channels", SND_SOC_NOPM,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 8, 0,
+ msm_pcm_get_out_chs,
+ msm_pcm_put_out_chs),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel Mixer",
+ .info = msm_pcm_channel_mixer_info,
+ .get = msm_pcm_channel_mixer_get,
+ .put = msm_pcm_channel_mixer_put,
+ .private_value = (unsigned long)&(mm1_channel_mux)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia2 Channel Mixer",
+ .info = msm_pcm_channel_mixer_info,
+ .get = msm_pcm_channel_mixer_get,
+ .put = msm_pcm_channel_mixer_put,
+ .private_value = (unsigned long)&(mm2_channel_mux)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia3 Channel Mixer",
+ .info = msm_pcm_channel_mixer_info,
+ .get = msm_pcm_channel_mixer_get,
+ .put = msm_pcm_channel_mixer_put,
+ .private_value = (unsigned long)&(mm3_channel_mux)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia4 Channel Mixer",
+ .info = msm_pcm_channel_mixer_info,
+ .get = msm_pcm_channel_mixer_get,
+ .put = msm_pcm_channel_mixer_put,
+ .private_value = (unsigned long)&(mm4_channel_mux)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel1",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 0,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel2",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 1, }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel3",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 2,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel4",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 3,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel5",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 4,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel6",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 5,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel7",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 6,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Output Channel8",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ { .shift = MSM_FRONTEND_DAI_MULTIMEDIA1, .rshift = 7,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia2 Output Channel1",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ {.shift = MSM_FRONTEND_DAI_MULTIMEDIA2, .rshift = 0,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia2 Output Channel2",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ {.shift = MSM_FRONTEND_DAI_MULTIMEDIA2, .rshift = 1,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia2 Output Channel3",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ {.shift = MSM_FRONTEND_DAI_MULTIMEDIA2, .rshift = 2,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia3 Output Channel1",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ {.shift = MSM_FRONTEND_DAI_MULTIMEDIA3, .rshift = 0,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia3 Output Channel2",
+ .info = msm_pcm_channel_weight_info,
+ .get = msm_pcm_channel_weight_get,
+ .put = msm_pcm_channel_weight_put,
+ .private_value = (unsigned long)&(struct soc_multi_mixer_control)
+ {.shift = MSM_FRONTEND_DAI_MULTIMEDIA3, .rshift = 1,}
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel1",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch1_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel2",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch2_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel3",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch3_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel4",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch4_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel5",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch5_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel6",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch6_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel7",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch7_enum)
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .name = "MultiMedia1 Channel8",
+ .info = msm_pcm_channel_input_be_info,
+ .get = msm_pcm_channel_input_be_get,
+ .put = msm_pcm_channel_input_be_put,
+ .private_value = (unsigned long)&(mm1_ch8_enum)
+ },
+};
static int msm_ec_ref_ch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -14825,6 +15539,9 @@
snd_soc_add_platform_controls(platform, ec_ref_param_controls,
ARRAY_SIZE(ec_ref_param_controls));
+ snd_soc_add_platform_controls(platform, channel_mixer_controls,
+ ARRAY_SIZE(channel_mixer_controls));
+
msm_qti_pp_add_controls(platform);
msm_dts_srs_tm_add_controls(platform);
@@ -14979,6 +15696,7 @@
(routing_cb)msm_pcm_get_dev_acdb_id_by_port_id);
memset(&be_dai_name_table, 0, sizeof(be_dai_name_table));
+ memset(&last_be_id_configured, 0, sizeof(last_be_id_configured));
return platform_driver_register(&msm_routing_pcm_driver);
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 234d57c..19e7260 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -385,6 +385,7 @@
#define INVALID_SESSION -1
#define SESSION_TYPE_RX 0
#define SESSION_TYPE_TX 1
+#define MAX_SESSION_TYPES 2
#define INT_RX_VOL_MAX_STEPS 0x2000
#define INT_RX_VOL_GAIN 0x2000
@@ -476,10 +477,10 @@
void msm_pcm_routing_acquire_lock(void);
void msm_pcm_routing_release_lock(void);
-int msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int session_type,
- int be_id, int app_type,
- int acdb_dev_id, int sample_rate);
-int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type,
- int be_id, int *app_type,
- int *acdb_dev_id, int *sample_rate);
+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);
+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);
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index d636c5a..1590605 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -530,6 +530,267 @@
return ret;
}
+static int adm_populate_channel_weight(u16 *ptr,
+ struct msm_pcm_channel_mixer *ch_mixer,
+ int channel_index)
+{
+ u16 i, j, start_index = 0;
+
+ if (channel_index > ch_mixer->output_channel) {
+ pr_err("%s: channel index %d is larger than output_channel %d\n",
+ __func__, channel_index, ch_mixer->output_channel);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ch_mixer->output_channel; i++) {
+ pr_debug("%s: weight for output %d:", __func__, i);
+ for (j = 0; j < ADM_MAX_CHANNELS; j++)
+ pr_debug(" %d",
+ ch_mixer->channel_weight[i][j]);
+ pr_debug("\n");
+ }
+
+ for (i = 0; i < channel_index; ++i)
+ start_index += ch_mixer->input_channels[i];
+
+ for (i = 0; i < ch_mixer->output_channel; ++i) {
+ for (j = start_index;
+ j < start_index +
+ ch_mixer->input_channels[channel_index]; j++) {
+ *ptr = ch_mixer->channel_weight[i][j];
+ pr_debug("%s: ptr[%d][%d] = %d\n",
+ __func__, i, j, *ptr);
+ ptr++;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * adm_programable_channel_mixer
+ *
+ * Receives port_id, copp_idx, session_id, session_type, ch_mixer
+ * and channel_index to send ADM command to mix COPP data.
+ *
+ * port_id - Passed value, port_id for which backend is wanted
+ * copp_idx - Passed value, copp_idx for which COPP is wanted
+ * session_id - Passed value, session_id for which session is needed
+ * 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
+ */
+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)
+{
+ 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;
+
+ pr_debug("%s: port_id = %d\n", __func__, port_id);
+ port_id = afe_convert_virtual_to_portid(port_id);
+ port_idx = adm_validate_and_get_port_index(port_id);
+ if (port_idx < 0) {
+ pr_err("%s: Invalid port_id %#x\n", __func__, port_id);
+ return -EINVAL;
+ }
+ /*
+ * First 8 bytes are 4 bytes as rule number, 2 bytes as output
+ * channel and 2 bytes as input channel.
+ * 2 * ch_mixer->output_channel means output channel mapping.
+ * 2 * ch_mixer->input_channels[channel_index]) means input
+ * channel mapping.
+ * 2 * ch_mixer->input_channels[channel_index] *
+ * ch_mixer->output_channel) means the channel mixer weighting
+ * coefficients.
+ * param_size needs to be a multiple of 4 bytes.
+ */
+
+ param_size = 2 * (4 + ch_mixer->output_channel +
+ ch_mixer->input_channels[channel_index] +
+ ch_mixer->input_channels[channel_index] *
+ ch_mixer->output_channel);
+ roundup(param_size, 4);
+
+ sz = sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5) +
+ sizeof(struct default_chmixer_param_id_coeff) +
+ sizeof(struct adm_param_data_v5) + param_size;
+ pr_debug("%s: sz = %d\n", __func__, sz);
+ adm_params = kzalloc(sz, GFP_KERNEL);
+ if (!adm_params)
+ return -ENOMEM;
+
+ adm_params->payload_addr_lsw = 0;
+ adm_params->payload_addr_msw = 0;
+ adm_params->mem_map_handle = 0;
+ adm_params->direction = session_type;
+ adm_params->sessionid = session_id;
+ pr_debug("%s: copp_id = %d, session id %d\n", __func__,
+ atomic_read(&this_adm.copp.id[port_idx][copp_idx]),
+ session_id);
+ adm_params->deviceid = atomic_read(
+ &this_adm.copp.id[port_idx][copp_idx]);
+ adm_params->reserved = 0;
+
+ data_v5.module_id = MTMX_MODULE_ID_DEFAULT_CHMIXER;
+ data_v5.param_id = DEFAULT_CHMIXER_PARAM_ID_COEFF;
+ data_v5.reserved = 0;
+ data_v5.param_size = param_size;
+ adm_params->payload_size =
+ sizeof(struct default_chmixer_param_id_coeff) +
+ sizeof(struct adm_param_data_v5) + data_v5.param_size;
+ adm_pspd_params = (u16 *)((u8 *)adm_params +
+ sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5));
+ memcpy(adm_pspd_params, &data_v5, sizeof(data_v5));
+
+ adm_pspd_params = (u16 *)((u8 *)adm_params +
+ sizeof(struct adm_cmd_set_pspd_mtmx_strtr_params_v5)
+ + sizeof(data_v5));
+
+ adm_pspd_params[0] = ch_mixer->rule;
+ adm_pspd_params[2] = ch_mixer->output_channel;
+ 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;
+ }
+
+ 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;
+ }
+
+ index = index + ch_mixer->input_channels[channel_index];
+ ret = adm_populate_channel_weight(&adm_pspd_params[index],
+ ch_mixer, channel_index);
+ if (!ret) {
+ pr_err("%s: fail to get channel weight with error %d\n",
+ __func__, ret);
+ goto fail_cmd;
+ }
+
+ adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ adm_params->hdr.src_svc = APR_SVC_ADM;
+ adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+ adm_params->hdr.src_port = port_id;
+ adm_params->hdr.dest_svc = APR_SVC_ADM;
+ adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+ adm_params->hdr.dest_port =
+ atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
+ adm_params->hdr.token = port_idx << 16 | copp_idx;
+ adm_params->hdr.opcode = ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5;
+ adm_params->hdr.pkt_size = sz;
+ adm_params->payload_addr_lsw = 0;
+ adm_params->payload_addr_msw = 0;
+ adm_params->mem_map_handle = 0;
+ adm_params->reserved = 0;
+
+ ptr = (u16 *)adm_params;
+ for (index = 0; index < (sz / 2); index++)
+ pr_debug("%s: adm_params[%d] = 0x%x\n",
+ __func__, index, (unsigned int)ptr[index]);
+
+ atomic_set(&this_adm.copp.stat[port_idx][copp_idx], 0);
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+ if (ret < 0) {
+ pr_err("%s: Set params failed port %d rc %d\n", __func__,
+ port_id, ret);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+ ret = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx],
+ atomic_read(
+ &this_adm.copp.stat[port_idx][copp_idx]) >= 0,
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: set params timed out port = %d\n",
+ __func__, port_id);
+ ret = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ ret = 0;
+fail_cmd:
+ kfree(adm_params);
+
+ return ret;
+}
+
int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx,
unsigned int session_id, char *params,
uint32_t params_length)