瀏覽代碼

asoc: codecs: support for cps soundwire port

Implement backend for CPS soundwire port in Bolero.

Change-Id: Ibbd38d067e46be1a71723de04a83bc83f0ec2925
Signed-off-by: Vangala, Amarnath <[email protected]>
Vangala, Amarnath 3 年之前
父節點
當前提交
9a5deb8cc6
共有 4 個文件被更改,包括 287 次插入0 次删除
  1. 128 0
      asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c
  2. 116 0
      asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c
  3. 27 0
      asoc/kalama.c
  4. 16 0
      asoc/msm_dailink.h

+ 128 - 0
asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c

@@ -42,6 +42,9 @@
 		SNDRV_PCM_FMTBIT_S24_LE |\
 		SNDRV_PCM_FMTBIT_S24_3LE)
 
+#define LPASS_CDC_WSA_MACRO_CPS_RATES (48000)
+#define LPASS_CDC_WSA_MACRO_CPS_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
 #define NUM_INTERPOLATORS 2
 
 #define LPASS_CDC_WSA_MACRO_MUX_INP_SHFT 0x3
@@ -231,6 +234,7 @@ enum {
 	LPASS_CDC_WSA_MACRO_AIF_MIX1_PB,
 	LPASS_CDC_WSA_MACRO_AIF_VI,
 	LPASS_CDC_WSA_MACRO_AIF_ECHO,
+	LPASS_CDC_WSA_MACRO_AIF_CPS,
 	LPASS_CDC_WSA_MACRO_MAX_DAIS,
 };
 
@@ -501,6 +505,20 @@ static struct snd_soc_dai_driver lpass_cdc_wsa_macro_dai[] = {
 		},
 		.ops = &lpass_cdc_wsa_macro_dai_ops,
 	},
+	{
+		.name = "wsa_macro_cpsfeedback",
+		.id = LPASS_CDC_WSA_MACRO_AIF_CPS,
+		.capture = {
+			.stream_name = "WSA_AIF_CPS Capture",
+			.rates = LPASS_CDC_WSA_MACRO_CPS_RATES,
+			.formats = LPASS_CDC_WSA_MACRO_CPS_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 48000,
+			.channels_min = 1,
+			.channels_max = 2,
+		},
+		.ops = &lpass_cdc_wsa_macro_dai_ops,
+	},
 };
 
 static bool lpass_cdc_wsa_macro_get_data(struct snd_soc_component *component,
@@ -770,6 +788,9 @@ static int lpass_cdc_wsa_macro_hw_params(struct snd_pcm_substream *substream,
 		case 24:
 			wsa_priv->bit_width[dai->id] = 24;
 			break;
+		case 32:
+			wsa_priv->bit_width[dai->id] = 32;
+			break;
 		default:
 			dev_err_ratelimited(component->dev, "%s: Invalid format 0x%x\n",
 				__func__, params_width(params));
@@ -799,6 +820,7 @@ static int lpass_cdc_wsa_macro_get_channel_map(struct snd_soc_dai *dai,
 
 	switch (dai->id) {
 	case LPASS_CDC_WSA_MACRO_AIF_VI:
+	case LPASS_CDC_WSA_MACRO_AIF_CPS:
 		*tx_slot = wsa_priv->active_ch_mask[dai->id];
 		*tx_num = wsa_priv->active_ch_cnt[dai->id];
 		break;
@@ -2714,6 +2736,94 @@ static const struct snd_kcontrol_new aif_vi_mixer[] = {
 			lpass_cdc_wsa_macro_vi_feed_mixer_put),
 };
 
+static int lpass_cdc_wsa_macro_cps_feed_mixer_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget =
+		snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(widget->dapm);
+	struct soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa_macro_cps_feed_mixer_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget =
+		snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(widget->dapm);
+	struct soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa_dev = NULL;
+	struct lpass_cdc_wsa_macro_priv *wsa_priv = NULL;
+
+	if (!lpass_cdc_wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
+		return -EINVAL;
+
+	if (enable) {
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 &&
+			!test_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			set_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]++;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 &&
+			!test_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			set_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]++;
+		}
+	} else {
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX0 &&
+			test_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			clear_bit(LPASS_CDC_WSA_MACRO_TX0,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]--;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA_MACRO_TX1 &&
+			test_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id])) {
+			clear_bit(LPASS_CDC_WSA_MACRO_TX1,
+				&wsa_priv->active_ch_mask[dai_id]);
+			wsa_priv->active_ch_cnt[dai_id]--;
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_cps_mixer[] = {
+	SOC_SINGLE_EXT("WSA_SPKR_CPS_1", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX0, 1, 0,
+			lpass_cdc_wsa_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa_macro_cps_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA_SPKR_CPS_2", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_TX1, 1, 0,
+			lpass_cdc_wsa_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa_macro_cps_feed_mixer_put),
+};
+
 static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_IN("WSA AIF1 PB", "WSA_AIF1 Playback", 0,
 		SND_SOC_NOPM, 0, 0),
@@ -2729,8 +2839,16 @@ static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("WSA AIF_ECHO", "WSA_AIF_ECHO Capture", 0,
 		SND_SOC_NOPM, 0, 0),
 
+	SND_SOC_DAPM_AIF_OUT("WSA AIF_CPS", "WSA_AIF_CPS Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_AIF_OUT("WSA AIF_CPS", "WSA_AIF_CPS Capture", 0,
+		SND_SOC_NOPM, 0, 0),
+
 	SND_SOC_DAPM_MIXER("WSA_AIF_VI Mixer", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_VI,
 		0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
+	SND_SOC_DAPM_MIXER("WSA_AIF_CPS Mixer", SND_SOC_NOPM, LPASS_CDC_WSA_MACRO_AIF_CPS,
+		0, aif_cps_mixer, ARRAY_SIZE(aif_cps_mixer)),
 	SND_SOC_DAPM_MUX_E("WSA RX_MIX EC0_MUX", SND_SOC_NOPM,
 			LPASS_CDC_WSA_MACRO_EC0_MUX, 0,
 			&rx_mix_ec0_mux, lpass_cdc_wsa_macro_enable_echo,
@@ -2833,6 +2951,8 @@ static const struct snd_soc_dapm_widget lpass_cdc_wsa_macro_dapm_widgets[] = {
 
 	SND_SOC_DAPM_INPUT("VIINPUT_WSA"),
 
+	SND_SOC_DAPM_INPUT("CPSINPUT_WSA"),
+
 	SND_SOC_DAPM_OUTPUT("WSA_SPK1 OUT"),
 	SND_SOC_DAPM_OUTPUT("WSA_SPK2 OUT"),
 
@@ -2847,6 +2967,12 @@ static const struct snd_soc_dapm_route wsa_audio_map[] = {
 	{"WSA AIF_VI", NULL, "WSA_AIF_VI Mixer"},
 	{"WSA AIF_VI", NULL, "WSA_MCLK"},
 
+	/* CPS Feedback */
+	{"WSA_AIF_CPS Mixer", "WSA_SPKR_CPS_1", "CPSINPUT_WSA"},
+	{"WSA_AIF_CPS Mixer", "WSA_SPKR_CPS_2", "CPSINPUT_WSA"},
+	{"WSA AIF_CPS", NULL, "WSA_AIF_CPS Mixer"},
+	{"WSA AIF_CPS", NULL, "WSA_MCLK"},
+
 	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
 	{"WSA RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA_RX INT0 SEC MIX"},
 	{"WSA RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA_RX INT1 SEC MIX"},
@@ -3401,9 +3527,11 @@ static int lpass_cdc_wsa_macro_init(struct snd_soc_component *component)
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_MIX1 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_VI Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_ECHO Capture");
+	snd_soc_dapm_ignore_suspend(dapm, "WSA_AIF_CPS Capture");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK1 OUT");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_SPK2 OUT");
 	snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_WSA");
+	snd_soc_dapm_ignore_suspend(dapm, "CPSINPUT_WSA");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA SRC0_INP");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC0_INP");
 	snd_soc_dapm_ignore_suspend(dapm, "WSA_TX DEC1_INP");

+ 116 - 0
asoc/codecs/lpass-cdc/lpass-cdc-wsa2-macro.c

@@ -41,6 +41,9 @@
 		SNDRV_PCM_FMTBIT_S24_LE |\
 		SNDRV_PCM_FMTBIT_S24_3LE)
 
+#define LPASS_CDC_WSA2_MACRO_CPS_RATES (SNDRV_PCM_RATE_48000)
+#define LPASS_CDC_WSA2_MACRO_CPS_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+
 #define NUM_INTERPOLATORS 2
 
 #define LPASS_CDC_WSA2_MACRO_MUX_INP_SHFT 0x3
@@ -226,6 +229,7 @@ enum {
 	LPASS_CDC_WSA2_MACRO_AIF_MIX1_PB,
 	LPASS_CDC_WSA2_MACRO_AIF_VI,
 	LPASS_CDC_WSA2_MACRO_AIF_ECHO,
+	LPASS_CDC_WSA2_MACRO_AIF_CPS,
 	LPASS_CDC_WSA2_MACRO_MAX_DAIS,
 };
 
@@ -487,6 +491,20 @@ static struct snd_soc_dai_driver lpass_cdc_wsa2_macro_dai[] = {
 		},
 		.ops = &lpass_cdc_wsa2_macro_dai_ops,
 	},
+        {
+                .name = "wsa2_macro_cpsfeedback",
+                .id = LPASS_CDC_WSA2_MACRO_AIF_CPS,
+                .capture = {
+                        .stream_name = "WSA2_AIF_CPS Capture",
+                        .rates = LPASS_CDC_WSA2_MACRO_CPS_RATES,
+                        .formats = LPASS_CDC_WSA2_MACRO_CPS_FORMATS,
+                        .rate_max = 48000,
+                        .rate_min = 48000,
+                        .channels_min = 1,
+                        .channels_max = 2,
+                },
+                .ops = &lpass_cdc_wsa2_macro_dai_ops,
+        },
 };
 
 static bool lpass_cdc_wsa2_macro_get_data(struct snd_soc_component *component,
@@ -758,6 +776,7 @@ static int lpass_cdc_wsa2_macro_get_channel_map(struct snd_soc_dai *dai,
 
 	switch (dai->id) {
 	case LPASS_CDC_WSA2_MACRO_AIF_VI:
+	case LPASS_CDC_WSA2_MACRO_AIF_CPS:
 		*tx_slot = wsa2_priv->active_ch_mask[dai->id];
 		*tx_num = wsa2_priv->active_ch_cnt[dai->id];
 		break;
@@ -2448,6 +2467,93 @@ static const struct snd_kcontrol_new aif_vi_mixer[] = {
 			lpass_cdc_wsa2_macro_vi_feed_mixer_put),
 };
 
+static int lpass_cdc_wsa2_macro_cps_feed_mixer_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget =
+		snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(widget->dapm);
+	struct soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 dai_id = widget->shift;
+	u32 spk_tx_id = mixer->shift;
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (test_bit(spk_tx_id, &wsa2_priv->active_ch_mask[dai_id]))
+		ucontrol->value.integer.value[0] = 1;
+	else
+		ucontrol->value.integer.value[0] = 0;
+
+	return 0;
+}
+
+static int lpass_cdc_wsa2_macro_cps_feed_mixer_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_dapm_widget *widget =
+		snd_soc_dapm_kcontrol_widget(kcontrol);
+	struct snd_soc_component *component =
+				snd_soc_dapm_to_component(widget->dapm);
+	struct soc_multi_mixer_control *mixer =
+		((struct soc_multi_mixer_control *)kcontrol->private_value);
+	u32 spk_tx_id = mixer->shift;
+	u32 enable = ucontrol->value.integer.value[0];
+	struct device *wsa2_dev = NULL;
+	struct lpass_cdc_wsa2_macro_priv *wsa2_priv = NULL;
+
+	if (!lpass_cdc_wsa2_macro_get_data(component, &wsa2_dev, &wsa2_priv, __func__))
+		return -EINVAL;
+
+	if (enable) {
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX0 &&
+			!test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			set_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]++;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX1 &&
+			!test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			set_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]++;
+		}
+	} else {
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX0 &&
+			test_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			clear_bit(LPASS_CDC_WSA2_MACRO_TX0,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]--;
+		}
+		if (spk_tx_id == LPASS_CDC_WSA2_MACRO_TX1 &&
+			test_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS])) {
+			clear_bit(LPASS_CDC_WSA2_MACRO_TX1,
+				&wsa2_priv->active_ch_mask[LPASS_CDC_WSA2_MACRO_AIF_CPS]);
+			wsa2_priv->active_ch_cnt[LPASS_CDC_WSA2_MACRO_AIF_CPS]--;
+		}
+	}
+	snd_soc_dapm_mixer_update_power(widget->dapm, kcontrol, enable, NULL);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new aif_cps_mixer[] = {
+	SOC_SINGLE_EXT("WSA2_SPKR_CPS_1", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_TX0, 1, 0,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_put),
+	SOC_SINGLE_EXT("WSA2_SPKR_CPS_2", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_TX1, 1, 0,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_get,
+			lpass_cdc_wsa2_macro_cps_feed_mixer_put),
+};
+
 static const struct snd_soc_dapm_widget lpass_cdc_wsa2_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_IN("WSA2 AIF1 PB", "WSA2_AIF1 Playback", 0,
 		SND_SOC_NOPM, 0, 0),
@@ -2465,6 +2571,8 @@ static const struct snd_soc_dapm_widget lpass_cdc_wsa2_macro_dapm_widgets[] = {
 
 	SND_SOC_DAPM_MIXER("WSA2_AIF_VI Mixer", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_AIF_VI,
 		0, aif_vi_mixer, ARRAY_SIZE(aif_vi_mixer)),
+	SND_SOC_DAPM_MIXER("WSA2_AIF_CPS Mixer", SND_SOC_NOPM, LPASS_CDC_WSA2_MACRO_AIF_CPS,
+		0, aif_cps_mixer, ARRAY_SIZE(aif_cps_mixer)),
 	SND_SOC_DAPM_MUX_E("WSA2 RX_MIX EC0_MUX", SND_SOC_NOPM,
 			LPASS_CDC_WSA2_MACRO_EC0_MUX, 0,
 			&rx_mix_ec0_mux, lpass_cdc_wsa2_macro_enable_echo,
@@ -2567,6 +2675,8 @@ static const struct snd_soc_dapm_widget lpass_cdc_wsa2_macro_dapm_widgets[] = {
 
 	SND_SOC_DAPM_INPUT("VIINPUT_WSA2"),
 
+	SND_SOC_DAPM_INPUT("CPSINPUT_WSA2"),
+
 	SND_SOC_DAPM_OUTPUT("WSA2_SPK1 OUT"),
 	SND_SOC_DAPM_OUTPUT("WSA2_SPK2 OUT"),
 
@@ -2581,6 +2691,12 @@ static const struct snd_soc_dapm_route wsa2_audio_map[] = {
 	{"WSA2 AIF_VI", NULL, "WSA2_AIF_VI Mixer"},
 	{"WSA2 AIF_VI", NULL, "WSA2_MCLK"},
 
+	/* VI Feedback */
+	{"WSA2_AIF_CPS Mixer", "WSA2_SPKR_CPS_1", "CPSINPUT_WSA2"},
+	{"WSA2_AIF_CPS Mixer", "WSA2_SPKR_CPS_2", "CPSINPUT_WSA2"},
+	{"WSA2 AIF_CPS", NULL, "WSA2_AIF_CPS Mixer"},
+	{"WSA2 AIF_CPS", NULL, "WSA2_MCLK"},
+
 	{"WSA2 RX_MIX EC0_MUX", "RX_MIX_TX0", "WSA2_RX INT0 SEC MIX"},
 	{"WSA2 RX_MIX EC1_MUX", "RX_MIX_TX0", "WSA2_RX INT0 SEC MIX"},
 	{"WSA2 RX_MIX EC0_MUX", "RX_MIX_TX1", "WSA2_RX INT1 SEC MIX"},

+ 27 - 0
asoc/kalama.c

@@ -584,6 +584,15 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = {
 		/* .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, */
 		SND_SOC_DAILINK_REG(vi_feedback),
 	},
+	{
+		.name = LPASS_BE_WSA_CDC_DMA_TX_2,
+		.stream_name = LPASS_BE_WSA_CDC_DMA_TX_2,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		/* .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, */
+		SND_SOC_DAILINK_REG(cps_feedback),
+	},
 	{
 		.name = LPASS_BE_WSA_CDC_DMA_RX_0_VIRT,
 		.stream_name = LPASS_BE_WSA_CDC_DMA_RX_0_VIRT,
@@ -641,6 +650,15 @@ static struct snd_soc_dai_link msm_wsa2_cdc_dma_be_dai_links[] = {
 		/* .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, */
 		SND_SOC_DAILINK_REG(wsa2_vi_feedback),
 	},
+	{
+		.name = LPASS_BE_WSA2_CDC_DMA_TX_2,
+		.stream_name = LPASS_BE_WSA2_CDC_DMA_TX_2,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		/* .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, */
+		SND_SOC_DAILINK_REG(wsa2_cps_feedback),
+	},
 };
 
 static struct snd_soc_dai_link msm_wsa_wsa2_cdc_dma_be_dai_links[] = {
@@ -687,6 +705,15 @@ static struct snd_soc_dai_link msm_wsa_wsa2_cdc_dma_be_dai_links[] = {
 		/* .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, */
 		SND_SOC_DAILINK_REG(wsa_wsa2_vi_feedback),
 	},
+	{
+		.name = LPASS_BE_WSA_CDC_DMA_TX_2,
+		.stream_name = LPASS_BE_WSA_CDC_DMA_TX_2,
+		.capture_only = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_common_be_ops,
+		/* .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, */
+		SND_SOC_DAILINK_REG(wsa_wsa2_cps_feedback),
+	},
 };
 
 static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {

+ 16 - 0
asoc/msm_dailink.h

@@ -362,6 +362,22 @@ SND_SOC_DAILINK_DEFS(wsa_wsa2_vi_feedback,
 			   COMP_CODEC("lpass-cdc", "wsa2_macro_vifeedback")),
 	DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
 
+SND_SOC_DAILINK_DEFS(cps_feedback,
+	DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("lpass-cdc", "wsa_macro_cpsfeedback")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
+
+SND_SOC_DAILINK_DEFS(wsa2_cps_feedback,
+	DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("lpass-cdc", "wsa2_macro_cpsfeedback")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
+
+SND_SOC_DAILINK_DEFS(wsa_wsa2_cps_feedback,
+	DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("lpass-cdc", "wsa_macro_cpsfeedback"),
+			   COMP_CODEC("lpass-cdc", "wsa2_macro_cpsfeedback")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
+
 SND_SOC_DAILINK_DEFS(tavil_i2s_rx1,
 	DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
 	DAILINK_COMP_ARRAY(COMP_CODEC("tavil_codec", "tavil_i2s_rx1")),