From 166ccaeb1e87085b7c02122cd80e93ac1113d82a Mon Sep 17 00:00:00 2001 From: Chaithanya Krishna Bacharaju Date: Thu, 25 Apr 2019 10:39:52 +0530 Subject: [PATCH] asoc: Add control to set AFE Tx loopback port AFE TX loopback is used to capture playback data from RX port and use it for echo reference. Add new control to configure Rx port to read data from in this case. Existing control was re-using EC Ref rx port control and can lead to far end configuration in undesired cases. Extend existing MultiMedia1 Output Channel control to support 10channels. Change-Id: I98f11d315e97d761ac2c8f8bf3ef387568c85082 Signed-off-by: Chaithanya Krishna Bacharaju --- asoc/msm-pcm-routing-v2.c | 500 ++++++++++++++++++++++---------------- 1 file changed, 286 insertions(+), 214 deletions(-) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index d5bad0fd66..f3795be852 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -82,6 +82,8 @@ static bool swap_ch; static int aanc_level; static int num_app_cfg_types; static int msm_ec_ref_port_id; +static int afe_loopback_tx_port_index; +static int afe_loopback_tx_port_id = -1; #define WEIGHT_0_DB 0x4000 /* all the FEs which can support channel mixer */ @@ -857,7 +859,20 @@ static int msm_pcm_routing_get_lsm_app_type_idx(int app_type) static int get_port_id(int port_id) { - return (port_id == AFE_LOOPBACK_TX ? msm_ec_ref_port_id : port_id); + int ret = port_id; + + if (port_id == AFE_LOOPBACK_TX) { + /* + * Return afe_loopback_tx_port_id if set. Else return + * msm_ec_ref_port_id to maintain backward compatibility. + */ + if (afe_loopback_tx_port_id != -1) + ret = afe_loopback_tx_port_id; + else + ret = msm_ec_ref_port_id; + } + + return ret; } static bool is_mm_lsm_fe_id(int fe_id) @@ -3611,7 +3626,7 @@ static const struct snd_kcontrol_new channel_mixer_controls[] = { msm_pcm_put_channel_rule_index), SOC_SINGLE_EXT("MultiMedia1 Channels", SND_SOC_NOPM, - MSM_FRONTEND_DAI_MULTIMEDIA1, 8, 0, + MSM_FRONTEND_DAI_MULTIMEDIA1, 10, 0, msm_pcm_get_out_chs, msm_pcm_put_out_chs), SOC_SINGLE_EXT("MultiMedia2 Channels", SND_SOC_NOPM, @@ -3753,6 +3768,26 @@ static const struct snd_kcontrol_new channel_mixer_controls[] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .name = "MultiMedia1 Output Channel9", + .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 = 8,} + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .name = "MultiMedia1 Output Channel10", + .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 = 9,} + }, + { + .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, @@ -4030,6 +4065,191 @@ static int msm_ec_ref_rate_put(struct snd_kcontrol *kcontrol, return 0; } +static int get_ec_ref_port_id(int value, int *index) +{ + int port_id; + + switch (value) { + case 0: + *index = 0; + port_id = AFE_PORT_INVALID; + break; + case 1: + *index = 1; + port_id = SLIMBUS_0_RX; + break; + case 2: + *index = 2; + port_id = AFE_PORT_ID_PRIMARY_MI2S_RX; + break; + case 3: + *index = 3; + port_id = AFE_PORT_ID_PRIMARY_MI2S_TX; + break; + case 4: + *index = 4; + port_id = AFE_PORT_ID_SECONDARY_MI2S_TX; + break; + case 5: + *index = 5; + port_id = AFE_PORT_ID_TERTIARY_MI2S_TX; + break; + case 6: + *index = 6; + port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + break; + case 7: + *index = 7; + port_id = AFE_PORT_ID_SECONDARY_MI2S_RX; + break; + case 9: + *index = 9; + port_id = SLIMBUS_5_RX; + break; + case 10: + *index = 10; + port_id = SLIMBUS_1_TX; + break; + case 11: + *index = 11; + port_id = AFE_PORT_ID_QUATERNARY_TDM_TX_1; + break; + case 12: + *index = 12; + port_id = AFE_PORT_ID_QUATERNARY_TDM_RX; + break; + case 13: + *index = 13; + port_id = AFE_PORT_ID_QUATERNARY_TDM_RX_1; + break; + case 14: + *index = 14; + port_id = AFE_PORT_ID_QUATERNARY_TDM_RX_2; + break; + case 15: + *index = 15; + port_id = SLIMBUS_6_RX; + break; + case 16: + *index = 16; + port_id = AFE_PORT_ID_TERTIARY_MI2S_RX; + break; + case 17: + *index = 17; + port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX; + break; + case 18: + *index = 18; + port_id = AFE_PORT_ID_TERTIARY_TDM_TX; + break; + case 19: + *index = 19; + port_id = AFE_PORT_ID_USB_RX; + break; + case 20: + *index = 20; + port_id = AFE_PORT_ID_INT0_MI2S_RX; + break; + case 21: + *index = 21; + port_id = AFE_PORT_ID_INT4_MI2S_RX; + break; + case 22: + *index = 22; + port_id = AFE_PORT_ID_INT3_MI2S_TX; + break; + case 23: + *index = 23; + port_id = AFE_PORT_ID_HDMI_OVER_DP_RX; + break; + case 24: + *index = 24; + port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_0; + break; + case 25: + *index = 25; + port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_1; + break; + case 26: + *index = 26; + port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_0; + break; + case 27: + *index = 27; + port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_1; + break; + case 28: + *index = 28; + port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_2; + break; + case 29: + *index = 29; + port_id = SLIMBUS_7_RX; + break; + case 30: + *index = 30; + port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_0; + break; + case 31: + *index = 31; + port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_1; + break; + case 32: + *index = 32; + port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_2; + break; + case 33: + *index = 33; + port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_3; + break; + case 34: + *index = 34; + port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_0; + break; + case 35: + *index = 35; + port_id = AFE_PORT_ID_TERTIARY_TDM_RX_2; + break; + case 36: + *index = 36; + port_id = AFE_PORT_ID_SECONDARY_TDM_TX; + break; + default: + *index = 0; /* NONE */ + pr_err("%s: Invalid value %d\n", __func__, value); + port_id = AFE_PORT_INVALID; + break; + } + + return port_id; +} + +static int msm_routing_afe_lb_tx_port_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: port index = %d", __func__, afe_loopback_tx_port_index); + mutex_lock(&routing_lock); + ucontrol->value.integer.value[0] = afe_loopback_tx_port_index; + mutex_unlock(&routing_lock); + + return 0; +} + +static int msm_routing_afe_lb_tx_port_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value = ucontrol->value.integer.value[0]; + + mutex_lock(&routing_lock); + afe_loopback_tx_port_id = get_ec_ref_port_id(value, + &afe_loopback_tx_port_index); + pr_debug("%s: afe_loopback_tx_port_index = %d\n", + __func__, afe_loopback_tx_port_index); + mutex_unlock(&routing_lock); + + return 0; +} + static const char *const ec_ref_rate_text[] = {"0", "8000", "16000", "32000", "44100", "48000", "96000", "192000", "384000"}; @@ -4039,218 +4259,6 @@ static const struct soc_enum msm_route_ec_ref_params_enum[] = { SOC_ENUM_SINGLE_EXT(9, ec_ref_rate_text), }; -static const struct snd_kcontrol_new ec_ref_param_controls[] = { - SOC_ENUM_EXT("EC Reference Channels", msm_route_ec_ref_params_enum[0], - msm_ec_ref_ch_get, msm_ec_ref_ch_put), - SOC_ENUM_EXT("EC Reference Bit Format", msm_route_ec_ref_params_enum[1], - msm_ec_ref_bit_format_get, msm_ec_ref_bit_format_put), - SOC_ENUM_EXT("EC Reference SampleRate", msm_route_ec_ref_params_enum[2], - msm_ec_ref_rate_get, msm_ec_ref_rate_put), - SOC_ENUM_EXT("EC Reference Downmixed Channels", msm_route_ec_ref_params_enum[0], - msm_ec_ref_ch_downmixed_get, msm_ec_ref_ch_downmixed_put), - SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch1", SND_SOC_NOPM, 0, - 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, - NULL, msm_ec_ref_chmixer_weights_put), - SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch2", SND_SOC_NOPM, 1, - 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, - NULL, msm_ec_ref_chmixer_weights_put), - SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch3", SND_SOC_NOPM, 2, - 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, - NULL, msm_ec_ref_chmixer_weights_put), - SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch4", SND_SOC_NOPM, 3, - 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, - NULL, msm_ec_ref_chmixer_weights_put), - SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch5", SND_SOC_NOPM, 4, - 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, - NULL, msm_ec_ref_chmixer_weights_put), - SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch6", SND_SOC_NOPM, 5, - 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, - NULL, msm_ec_ref_chmixer_weights_put), -}; - -static int msm_routing_ec_ref_rx_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - pr_debug("%s: ec_ref_rx = %d", __func__, msm_route_ec_ref_rx); - mutex_lock(&routing_lock); - ucontrol->value.integer.value[0] = msm_route_ec_ref_rx; - mutex_unlock(&routing_lock); - return 0; -} - -static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - int ec_ref_port_id; - struct snd_soc_dapm_widget *widget = - snd_soc_dapm_kcontrol_widget(kcontrol); - struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; - struct snd_soc_dapm_update *update = NULL; - - - mutex_lock(&routing_lock); - switch (ucontrol->value.integer.value[0]) { - case 0: - msm_route_ec_ref_rx = 0; - ec_ref_port_id = AFE_PORT_INVALID; - break; - case 1: - msm_route_ec_ref_rx = 1; - ec_ref_port_id = SLIMBUS_0_RX; - break; - case 2: - msm_route_ec_ref_rx = 2; - ec_ref_port_id = AFE_PORT_ID_PRIMARY_MI2S_RX; - break; - case 3: - msm_route_ec_ref_rx = 3; - ec_ref_port_id = AFE_PORT_ID_PRIMARY_MI2S_TX; - break; - case 4: - msm_route_ec_ref_rx = 4; - ec_ref_port_id = AFE_PORT_ID_SECONDARY_MI2S_TX; - break; - case 5: - msm_route_ec_ref_rx = 5; - ec_ref_port_id = AFE_PORT_ID_TERTIARY_MI2S_TX; - break; - case 6: - msm_route_ec_ref_rx = 6; - ec_ref_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; - break; - case 7: - msm_route_ec_ref_rx = 7; - ec_ref_port_id = AFE_PORT_ID_SECONDARY_MI2S_RX; - break; - case 9: - msm_route_ec_ref_rx = 9; - ec_ref_port_id = SLIMBUS_5_RX; - break; - case 10: - msm_route_ec_ref_rx = 10; - ec_ref_port_id = SLIMBUS_1_TX; - break; - case 11: - msm_route_ec_ref_rx = 11; - ec_ref_port_id = AFE_PORT_ID_QUATERNARY_TDM_TX_1; - break; - case 12: - msm_route_ec_ref_rx = 12; - ec_ref_port_id = AFE_PORT_ID_QUATERNARY_TDM_RX; - break; - case 13: - msm_route_ec_ref_rx = 13; - ec_ref_port_id = AFE_PORT_ID_QUATERNARY_TDM_RX_1; - break; - case 14: - msm_route_ec_ref_rx = 14; - ec_ref_port_id = AFE_PORT_ID_QUATERNARY_TDM_RX_2; - break; - case 15: - msm_route_ec_ref_rx = 15; - ec_ref_port_id = SLIMBUS_6_RX; - break; - case 16: - msm_route_ec_ref_rx = 16; - ec_ref_port_id = AFE_PORT_ID_TERTIARY_MI2S_RX; - break; - case 17: - msm_route_ec_ref_rx = 17; - ec_ref_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX; - break; - case 18: - msm_route_ec_ref_rx = 18; - ec_ref_port_id = AFE_PORT_ID_TERTIARY_TDM_TX; - break; - case 19: - msm_route_ec_ref_rx = 19; - ec_ref_port_id = AFE_PORT_ID_USB_RX; - break; - case 20: - msm_route_ec_ref_rx = 20; - ec_ref_port_id = AFE_PORT_ID_INT0_MI2S_RX; - break; - case 21: - msm_route_ec_ref_rx = 21; - ec_ref_port_id = AFE_PORT_ID_INT4_MI2S_RX; - break; - case 22: - msm_route_ec_ref_rx = 22; - ec_ref_port_id = AFE_PORT_ID_INT3_MI2S_TX; - break; - case 23: - 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_WSA_CODEC_DMA_RX_0; - break; - case 25: - msm_route_ec_ref_rx = 25; - ec_ref_port_id = AFE_PORT_ID_WSA_CODEC_DMA_RX_1; - break; - case 26: - msm_route_ec_ref_rx = 26; - ec_ref_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_0; - break; - case 27: - msm_route_ec_ref_rx = 27; - ec_ref_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_1; - break; - case 28: - msm_route_ec_ref_rx = 28; - ec_ref_port_id = AFE_PORT_ID_WSA_CODEC_DMA_TX_2; - break; - case 29: - msm_route_ec_ref_rx = 29; - ec_ref_port_id = SLIMBUS_7_RX; - break; - case 30: - msm_route_ec_ref_rx = 30; - ec_ref_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_0; - break; - case 31: - msm_route_ec_ref_rx = 31; - ec_ref_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_1; - break; - case 32: - msm_route_ec_ref_rx = 32; - ec_ref_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_2; - break; - case 33: - msm_route_ec_ref_rx = 33; - ec_ref_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_3; - break; - case 34: - msm_route_ec_ref_rx = 34; - ec_ref_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_0; - break; - case 35: - msm_route_ec_ref_rx = 35; - ec_ref_port_id = AFE_PORT_ID_TERTIARY_TDM_RX_2; - break; - case 36: - msm_route_ec_ref_rx = 36; - ec_ref_port_id = AFE_PORT_ID_SECONDARY_TDM_TX; - break; - default: - msm_route_ec_ref_rx = 0; /* NONE */ - pr_err("%s EC ref rx %ld not valid\n", - __func__, ucontrol->value.integer.value[0]); - ec_ref_port_id = AFE_PORT_INVALID; - break; - } - msm_ec_ref_port_id = ec_ref_port_id; - adm_ec_ref_rx_id(ec_ref_port_id); - pr_debug("%s: msm_route_ec_ref_rx = %d\n", - __func__, msm_route_ec_ref_rx); - mutex_unlock(&routing_lock); - snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, - msm_route_ec_ref_rx, e, update); - return 0; -} - static const char *const ec_ref_rx[] = { "None", "SLIM_RX", "I2S_RX", "PRI_MI2S_TX", "SEC_MI2S_TX", "TERT_MI2S_TX", "QUAT_MI2S_TX", "SEC_I2S_RX", "PROXY_RX", @@ -4268,6 +4276,70 @@ static const struct soc_enum msm_route_ec_ref_rx_enum[] = { SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ec_ref_rx), ec_ref_rx), }; +static const struct snd_kcontrol_new ec_ref_param_controls[] = { + SOC_ENUM_EXT("EC Reference Channels", msm_route_ec_ref_params_enum[0], + msm_ec_ref_ch_get, msm_ec_ref_ch_put), + SOC_ENUM_EXT("EC Reference Bit Format", msm_route_ec_ref_params_enum[1], + msm_ec_ref_bit_format_get, msm_ec_ref_bit_format_put), + SOC_ENUM_EXT("EC Reference SampleRate", msm_route_ec_ref_params_enum[2], + msm_ec_ref_rate_get, msm_ec_ref_rate_put), + SOC_ENUM_EXT("EC Reference Downmixed Channels", + msm_route_ec_ref_params_enum[0], + msm_ec_ref_ch_downmixed_get, msm_ec_ref_ch_downmixed_put), + SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch1", SND_SOC_NOPM, + 0, 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, NULL, + msm_ec_ref_chmixer_weights_put), + SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch2", SND_SOC_NOPM, + 1, 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, NULL, + msm_ec_ref_chmixer_weights_put), + SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch3", SND_SOC_NOPM, + 2, 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, NULL, + msm_ec_ref_chmixer_weights_put), + SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch4", SND_SOC_NOPM, + 3, 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, NULL, + msm_ec_ref_chmixer_weights_put), + SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch5", SND_SOC_NOPM, + 4, 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, NULL, + msm_ec_ref_chmixer_weights_put), + SOC_SINGLE_MULTI_EXT("EC Reference ChMixer Weights Ch6", SND_SOC_NOPM, + 5, 16384, 0, PCM_FORMAT_MAX_NUM_CHANNEL_V8, NULL, + msm_ec_ref_chmixer_weights_put), + SOC_ENUM_EXT("AFE_LOOPBACK_TX Port", msm_route_ec_ref_rx_enum[0], + msm_routing_afe_lb_tx_port_get, msm_routing_afe_lb_tx_port_put), +}; + +static int msm_routing_ec_ref_rx_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("%s: ec_ref_rx = %d", __func__, msm_route_ec_ref_rx); + mutex_lock(&routing_lock); + ucontrol->value.integer.value[0] = msm_route_ec_ref_rx; + mutex_unlock(&routing_lock); + + return 0; +} + +static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int value = ucontrol->value.integer.value[0]; + struct snd_soc_dapm_widget *widget = + snd_soc_dapm_kcontrol_widget(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + struct snd_soc_dapm_update *update = NULL; + + mutex_lock(&routing_lock); + msm_ec_ref_port_id = get_ec_ref_port_id(value, &msm_route_ec_ref_rx); + adm_ec_ref_rx_id(msm_ec_ref_port_id); + pr_debug("%s: msm_route_ec_ref_rx = %d\n", + __func__, msm_route_ec_ref_rx); + mutex_unlock(&routing_lock); + + snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, + msm_route_ec_ref_rx, e, update); + return 0; +} + static const struct snd_kcontrol_new ext_ec_ref_mux_ul1 = SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL1 MUX Mux", msm_route_ec_ref_rx_enum[0],