소스 검색

Merge b561c6e89089563a83ef6474f4df54b19e81d9bc on remote branch

Change-Id: Icefb797aa191950a8f177f43f4e2f921de834855
Linux Build Service Account 1 년 전
부모
커밋
2de148a8ec

+ 7 - 1
Makefile

@@ -4,12 +4,18 @@ KBUILD_OPTIONS += CONFIG_SND_SOC_SA7255=m
 KBUILD_OPTIONS += MODNAME=audio_dlkm
 endif
 
+ifeq ($(AUTO_GVM), yes)
+KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y
+KBUILD_OPTIONS += CONFIG_SND_SOC_GVM=y
+KBUILD_OPTIONS += MODNAME=audio_dlkm
+endif
+
 M=$(PWD)
 AUDIO_ROOT=$(KERNEL_SRC)/$(M)
 
 KBUILD_OPTIONS+=  AUDIO_ROOT=$(AUDIO_ROOT)
 
-all: modules
+all: clean modules
 
 clean:
 	$(MAKE) -C $(KERNEL_SRC) M=$(M) clean

+ 3 - 1
asoc/codecs/lpass-cdc/lpass-cdc-rx-macro.c

@@ -1890,7 +1890,9 @@ static int lpass_cdc_rx_macro_config_compander(struct snd_soc_component *compone
 		return 0;
 
 	comp = interp_n;
-	if (!rx_priv->comp_enabled[comp] && rx_priv->is_pcm_enabled)
+	if (!rx_priv->comp_enabled[comp])
+		return 0;
+	if (rx_priv->is_pcm_enabled)
 		return 0;
 
 	if (rx_priv->is_ear_mode_on && interp_n == INTERP_HPHL)

+ 9 - 6
asoc/codecs/lpass-cdc/lpass-cdc-wsa-macro.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -1343,19 +1343,22 @@ static int lpass_cdc_wsa_macro_enable_mix_path(struct snd_soc_dapm_widget *w,
 
 	if (!(strcmp(w->name, "WSA_RX0 MIX INP"))) {
 		gain_reg = LPASS_CDC_WSA_RX0_RX_VOL_MIX_CTL;
+		reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL +
+			(LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET *  w->shift);
+		mix_reg = LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL +
+			LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift;
 	} else if (!(strcmp(w->name, "WSA_RX1 MIX INP"))) {
 		gain_reg = LPASS_CDC_WSA_RX1_RX_VOL_MIX_CTL;
+		reg = LPASS_CDC_WSA_RX1_RX_PATH_CTL +
+			(LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET *  w->shift);
+		mix_reg = LPASS_CDC_WSA_RX1_RX_PATH_MIX_CTL +
+			LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift;
 	} else {
 		dev_err_ratelimited(component->dev, "%s: No gain register avail for %s\n",
 			__func__, w->name);
 		return 0;
 	}
 
-	reg = LPASS_CDC_WSA_RX0_RX_PATH_CTL +
-			(LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET *  w->shift);
-	mix_reg = LPASS_CDC_WSA_RX0_RX_PATH_MIX_CTL +
-			LPASS_CDC_WSA_MACRO_RX_PATH_OFFSET * w->shift;
-
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		snd_soc_component_update_bits(component, mix_reg, 0x40, 0x40);

+ 196 - 117
asoc/codecs/wcd9378/wcd9378.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -162,8 +162,6 @@ enum {
 	ADC_MODE_HIFI,
 	ADC_MODE_NORMAL,
 	ADC_MODE_LP,
-	ADC_MODE_ULP1,
-	ADC_MODE_ULP2,
 };
 
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
@@ -210,8 +208,6 @@ static int wcd9378_handle_post_irq(void *data)
 	wcd9378->tx_swr_dev->slave_irq_pending =
 			((sts1 || sts2 || !sts3) ? true : false);
 
-	pr_debug("%s: sts1: 0x%0x, sts2: 0x%0x, sts3: 0x%0x\n", __func__, sts1, sts2, sts3);
-
 	return IRQ_HANDLED;
 }
 
@@ -904,33 +900,6 @@ static int wcd9378_get_clk_rate(int mode)
 	return rate;
 }
 
-static int wcd9378_set_swr_clk_rate(struct snd_soc_component *component,
-					int rate, int bank)
-{
-	u8 mask = (bank ? 0xF0 : 0x0F);
-	u8 val = 0;
-
-	switch (rate) {
-	case SWR_CLK_RATE_2P4MHZ:
-		val = (bank ? 0x30 : 0x03);
-		break;
-	case SWR_CLK_RATE_4P8MHZ:
-		val = (bank ? 0x10 : 0x01);
-		break;
-	case SWR_CLK_RATE_9P6MHZ:
-	default:
-		val = 0x00;
-		break;
-	}
-	dev_dbg(component->dev,
-		"%s: rate: 0x%0x\n", __func__, val);
-
-	snd_soc_component_update_bits(component, WCD9378_SWR_TX_CLK_RATE,
-				      mask, val);
-
-	return 0;
-}
-
 static int wcd9378_get_adc_mode_val(int mode)
 {
 	int ret = 0;
@@ -980,12 +949,10 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 		}
 
 		rate = wcd9378_get_clk_rate(wcd9378->tx_mode[w->shift - ADC1]);
-
 		if (w->shift == ADC2 && !((snd_soc_component_read(component,
 				WCD9378_TX_NEW_TX_CH12_MUX) &
 				WCD9378_TX_NEW_TX_CH12_MUX_CH2_SEL_MASK) == 0x10)) {
 			if (!wcd9378->bcs_dis) {
-				dev_err(component->dev, "%s: mbhc connect port enter\n", __func__);
 				wcd9378_tx_connect_port(component, MBHC,
 					SWR_CLK_RATE_4P8MHZ, true);
 				set_bit(AMIC2_BCS_ENABLE, &wcd9378->status_mask);
@@ -1004,7 +971,6 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 					MICB_ENABLE, true);
 		switch (w->shift) {
 		case ADC1:
-			dev_dbg(component->dev, "%s ADC1 enter\n", __func__);
 			/*SMP MIC0 IT11 USAGE SET*/
 			snd_soc_component_update_bits(component, WCD9378_IT11_USAGE,
 						WCD9378_IT11_USAGE_IT11_USAGE_MASK, mode_val);
@@ -1020,7 +986,6 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 			break;
 		case ADC2:
 			if (wcd9378->sjmic_support) {
-				dev_dbg(component->dev, "%s SJ ADC2 enter\n", __func__);
 				/*SMP JACK IT31 USAGE SET*/
 				snd_soc_component_update_bits(component,
 						WCD9378_IT31_USAGE,
@@ -1030,7 +995,6 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 						WCD9378_PDE34_REQ_PS,
 						WCD9378_PDE34_REQ_PS_PDE34_REQ_PS_MASK, 0x00);
 			} else {
-				dev_dbg(component->dev, "%s SM1 ADC2 enter\n", __func__);
 				/*SMP MIC1 IT11 USAGE SET*/
 				snd_soc_component_update_bits(component,
 						WCD9378_SMP_MIC_CTRL1_IT11_USAGE,
@@ -1049,7 +1013,6 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 			}
 			break;
 		case ADC3:
-			dev_dbg(component->dev, "%s SM2 ADC3 enter\n", __func__);
 			/*SMP MIC2 IT11 USAGE SET*/
 			snd_soc_component_update_bits(component,
 						WCD9378_SMP_MIC_CTRL2_IT11_USAGE,
@@ -1069,47 +1032,30 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 		}
 		/*default delay 800us*/
 		usleep_range(800, 810);
-		/****ADC START*****/
-		wcd9378_set_swr_clk_rate(component, rate, bank);
 
 		wcd9378_swr_slave_clk_set(wcd9378->dev, bank, TX_PATH, true);
-
 		ret = swr_slvdev_datapath_control(wcd9378->tx_swr_dev,
 				wcd9378->tx_swr_dev->dev_num,
 				true);
-
-		/* Copy clk settings to active bank */
-		wcd9378_set_swr_clk_rate(component, rate, !bank);
-
 		wcd9378_swr_slave_clk_set(wcd9378->dev, !bank, TX_PATH, true);
-		/****ADC END*****/
 
 		switch (w->shift) {
 		case ADC1:
 			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH2,
 						WCD9378_ANA_TX_CH2_HPF1_INIT_MASK, 0x00);
-			break;
-		case ADC2:
-			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH2,
-						WCD9378_ANA_TX_CH2_HPF2_INIT_MASK, 0x00);
-			break;
-		case ADC3:
-			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH3_HPF,
-						WCD9378_ANA_TX_CH3_HPF_HPF3_INIT_MASK, 0x00);
-			break;
-		};
 
-		if (w->shift == ADC1) {
 			act_ps = snd_soc_component_read(component, WCD9378_PDE11_ACT_PS);
 			if (act_ps)
-				pr_err("%s: tx0 sequencer didnot power on, act_ps: 0x%0x\n",
+				dev_dbg(component->dev, "%s: tx0 sequencer didnot power on, act_ps: 0x%0x\n",
 								__func__, act_ps);
 			else
-				pr_err("%s: tx0 sequencer power on successful, act_ps: 0x%0x\n",
+				dev_dbg(component->dev, "%s: tx0 sequencer power on successful, act_ps: 0x%0x\n",
 								__func__, act_ps);
-		}
+			break;
+		case ADC2:
+			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH2,
+						WCD9378_ANA_TX_CH2_HPF2_INIT_MASK, 0x00);
 
-		if (w->shift == ADC2) {
 			if (wcd9378->sjmic_support)
 				act_ps = snd_soc_component_read(component,
 							WCD9378_PDE34_ACT_PS);
@@ -1118,15 +1064,28 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 							WCD9378_SMP_MIC_CTRL1_PDE11_ACT_PS);
 
 			if (act_ps)
-				pr_err("%s: tx1 sequencer didnot power on, act_ps: 0x%0x\n",
+				dev_dbg(component->dev, "%s: tx1 sequencer didnot power on, act_ps: 0x%0x\n",
 									__func__, act_ps);
 			else
-				pr_err("%s: tx1 sequencer power on successful, act_ps: 0x%0x\n",
+				dev_dbg(component->dev, "%s: tx1 sequencer power on successful, act_ps: 0x%0x\n",
 									__func__, act_ps);
-		}
+			break;
+		case ADC3:
+			snd_soc_component_update_bits(component, WCD9378_ANA_TX_CH3_HPF,
+						WCD9378_ANA_TX_CH3_HPF_HPF3_INIT_MASK, 0x00);
+
+			act_ps = snd_soc_component_read(component,
+						WCD9378_SMP_MIC_CTRL2_PDE11_ACT_PS);
+			if (act_ps)
+				dev_dbg(component->dev, "%s: tx2 sequencer didnot power on, act_ps: 0x%0x\n",
+								__func__, act_ps);
+			else
+				dev_dbg(component->dev, "%s: tx2 sequencer power on successful, act_ps: 0x%0x\n",
+								__func__, act_ps);
+			break;
+		};
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		/****ADC START****/
 		wcd9378_tx_connect_port(component, w->shift, 0, false);
 		if (w->shift == ADC2 &&
 			test_bit(AMIC2_BCS_ENABLE, &wcd9378->status_mask)) {
@@ -1135,8 +1094,6 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 			clear_bit(AMIC2_BCS_ENABLE, &wcd9378->status_mask);
 		}
 
-		/****ADC END****/
-
 		switch (w->shift) {
 		case ADC1:
 			/*Normal TXFE Startup*/
@@ -1176,19 +1133,12 @@ static int wcd9378_tx_sequencer_enable(struct snd_soc_dapm_widget *w,
 		/*default delay 800us*/
 		usleep_range(800, 810);
 
-		rate = wcd9378_get_clk_rate(wcd9378->tx_mode[w->shift - ADC1]);
-
-		wcd9378_set_swr_clk_rate(component, rate, bank);
-
 		wcd9378_swr_slave_clk_set(wcd9378->dev, !bank, TX_PATH, false);
-
 		ret = swr_slvdev_datapath_control(wcd9378->tx_swr_dev,
 				wcd9378->tx_swr_dev->dev_num,
 				false);
 		wcd9378_swr_slave_clk_set(wcd9378->dev, bank, TX_PATH, false);
 
-		wcd9378_set_swr_clk_rate(component, rate, !bank);
-
 		if (wcd9378->va_amic_en)
 			wcd9378_micbias_control(component, w->shift,
 						MICB_PULLUP_DISABLE, true);
@@ -1227,6 +1177,112 @@ static int wcd9378_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
 	return ret;
 }
 
+static int wcd9378_tx_num_get(struct snd_soc_component *component,
+				int micb_num)
+{
+	int sm_num = 0;
+	struct wcd9378_priv *wcd9378 =
+			snd_soc_component_get_drvdata(component);
+
+	for (sm_num = SIM_MIC0; sm_num <= SIM_MIC2; sm_num++) {
+		if (wcd9378->micb_sel[sm_num] == micb_num) {
+			if (sm_num == SIM_MIC0)
+				return ADC1;
+			else if (sm_num == SIM_MIC1)
+				return ADC2;
+			else if (sm_num == SIM_MIC2)
+				return ADC3;
+			else
+				return -EINVAL;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int wcd9378_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+					struct snd_kcontrol *kcontrol,
+					int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num = 0, tx_num = 0;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "MIC BIAS1", sizeof("MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else if (strnstr(w->name, "MIC BIAS2", sizeof("MIC BIAS2")))
+		micb_num = MIC_BIAS_2;
+	else if (strnstr(w->name, "MIC BIAS3", sizeof("MIC BIAS3")))
+		micb_num = MIC_BIAS_3;
+	else
+		return -EINVAL;
+
+	tx_num = wcd9378_tx_num_get(component, micb_num);
+	if (tx_num < 0)
+		pr_err("%s: SM MB SEL should be set properly\n", __func__);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd9378_micbias_control(component, tx_num,
+				MICB_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd9378_micbias_control(component, tx_num,
+				MICB_DISABLE, true);
+		break;
+	};
+
+	return 0;
+}
+
+static int wcd9378_codec_enable_micbias_pullup(struct snd_soc_dapm_widget *w,
+					struct snd_kcontrol *kcontrol,
+					int event)
+{
+	struct snd_soc_component *component =
+			snd_soc_dapm_to_component(w->dapm);
+	int micb_num = 0, tx_num = 0;
+
+	dev_dbg(component->dev, "%s: wname: %s, event: %d\n",
+		__func__, w->name, event);
+
+	if (strnstr(w->name, "VA MIC BIAS1", sizeof("VA MIC BIAS1")))
+		micb_num = MIC_BIAS_1;
+	else if (strnstr(w->name, "VA MIC BIAS2", sizeof("VA MIC BIAS2")))
+		micb_num = MIC_BIAS_2;
+	else if (strnstr(w->name, "VA MIC BIAS3", sizeof("VA MIC BIAS3")))
+		micb_num = MIC_BIAS_3;
+	else
+		return -EINVAL;
+
+	tx_num = wcd9378_tx_num_get(component, micb_num);
+	if (tx_num < 0)
+		pr_err("%s: SM MB SEL should be set properly\n", __func__);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd9378_micbias_control(component, tx_num,
+				MICB_PULLUP_ENABLE, true);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(1000, 1100);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd9378_micbias_control(component, tx_num,
+				MICB_PULLUP_ENABLE, true);
+		break;
+	};
+
+	return 0;
+}
+
+
 /*
  * wcd9378_soc_get_mbhc: get wcd9378_mbhc handle of corresponding component
  * @component: handle to snd_soc_component *
@@ -1282,15 +1338,6 @@ static int wcd9378_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
 						(WCD_RX1 << 0x10));
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (wcd9378->update_wcd_event)
-			wcd9378->update_wcd_event(wcd9378->handle,
-						SLV_BOLERO_EVT_RX_MUTE,
-						(WCD_RX1 << 0x10 | 0x1));
-
-		if (wcd9378->update_wcd_event && wcd9378->comp1_enable)
-			wcd9378->update_wcd_event(wcd9378->handle,
-					SLV_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
-					(WCD_RX1 << 0x10));
 		/*HPHL DISABLE*/
 		snd_soc_component_update_bits(component, WCD9378_CDC_HPH_GAIN_CTL,
 			WCD9378_CDC_HPH_GAIN_CTL_HPHL_RX_EN_MASK, 0x00);
@@ -1391,12 +1438,11 @@ static int wcd9378_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 
 		act_ps = snd_soc_component_read(component, WCD9378_PDE47_ACT_PS);
 		if (act_ps)
-			pr_err("%s: hph sequencer didnot power on, act_ps: 0x%0x\n",
+			dev_dbg(component->dev, "%s: hph sequencer didnot power on, act_ps: 0x%0x\n",
 							__func__, act_ps);
 		else
-			pr_err("%s: hph sequencer power on successful, act_ps: 0x%0x\n",
+			dev_dbg(component->dev, "%s: hph sequencer power on successful, act_ps: 0x%0x\n",
 							__func__, act_ps);
-
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		if (wcd9378->update_wcd_event)
@@ -1409,17 +1455,9 @@ static int wcd9378_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 					SLV_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
 					(WCD_RX1 << 0x10));
 
-		if (!wcd9378->comp1_enable)
-			/*PA delay is 24250us*/
-			usleep_range(24300, 24310);
-		else
-			/*COMP delay is 11250us*/
-			usleep_range(11300, 11310);
-
 		blocking_notifier_call_chain(&wcd9378->mbhc->notifier,
 					WCD_EVENT_POST_HPHL_PA_OFF,
 					&wcd9378->mbhc->wcd_mbhc);
-
 		break;
 	default:
 		break;
@@ -1436,6 +1474,7 @@ static int wcd9378_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 			snd_soc_dapm_to_component(w->dapm);
 	struct wcd9378_priv *wcd9378 = snd_soc_component_get_drvdata(component);
 	int ret;
+	int act_ps = 0;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
@@ -1453,6 +1492,14 @@ static int wcd9378_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 			wcd9378->update_wcd_event(wcd9378->handle,
 						SLV_BOLERO_EVT_RX_MUTE,
 						(WCD_RX2 << 0x10));
+
+		act_ps = snd_soc_component_read(component, WCD9378_PDE47_ACT_PS);
+		if (act_ps)
+			dev_dbg(component->dev, "%s: hph sequencer didnot power on, act_ps: 0x%0x\n",
+							__func__, act_ps);
+		else
+			dev_dbg(component->dev, "%s: hph sequencer power on successful, act_ps: 0x%0x\n",
+							__func__, act_ps);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		if (wcd9378->update_wcd_event)
@@ -1465,17 +1512,9 @@ static int wcd9378_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 					SLV_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
 					(WCD_RX2 << 0x10));
 
-		if (!wcd9378->comp2_enable)
-			/*PA delay is 24250us*/
-			usleep_range(24300, 24310);
-		else
-			/*COMP delay is 11250us*/
-			usleep_range(11300, 11310);
-
 		blocking_notifier_call_chain(&wcd9378->mbhc->notifier,
 					WCD_EVENT_POST_HPHR_PA_OFF,
 					&wcd9378->mbhc->wcd_mbhc);
-
 		break;
 	default:
 		break;
@@ -1494,6 +1533,7 @@ static int wcd9378_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
 	struct wcd9378_priv *wcd9378 = snd_soc_component_get_drvdata(component);
 	int ret = 0;
 	int bank = 0;
+	int act_ps = 0;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
@@ -1528,6 +1568,14 @@ static int wcd9378_codec_enable_aux_pa(struct snd_soc_dapm_widget *w,
 							SLV_BOLERO_EVT_RX_MUTE,
 							(WCD_RX3 << 0x10));
 		}
+
+		act_ps = snd_soc_component_read(component, WCD9378_PDE23_ACT_PS);
+		if (act_ps)
+			dev_dbg(component->dev, "%s: sa sequencer didnot power on, act_ps: 0x%0x\n",
+							__func__, act_ps);
+		else
+			dev_dbg(component->dev, "%s: sa sequencer power on successful, act_ps: 0x%0x\n",
+							__func__, act_ps);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		if (wcd9378->aux_rx_path & AUX_RX_PATH_RX1) {
@@ -1591,10 +1639,10 @@ static int wcd9378_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
 
 		act_ps = snd_soc_component_read(component, WCD9378_PDE23_ACT_PS);
 		if (act_ps)
-			pr_err("%s: sa sequencer didnot power on, act_ps: 0x%0x\n",
+			dev_dbg(component->dev, "%s: sa sequencer didnot power on, act_ps: 0x%0x\n",
 							__func__, act_ps);
 		else
-			pr_err("%s: sa sequencer power on successful, act_ps: 0x%0x\n",
+			dev_dbg(component->dev, "%s: sa sequencer power on successful, act_ps: 0x%0x\n",
 							__func__, act_ps);
 
 		break;
@@ -1669,6 +1717,7 @@ static int wcd9378_swr_slave_clk_set(struct device *dev, int bank, int path, boo
 {
 	u16 clk_scale_reg = 0;
 	u8 clk_rst = 0x00, scale_rst = 0x00;
+	u8 swr_base_clk = 0, swr_clk_scale = 0;
 	struct wcd9378_priv *wcd9378 = NULL;
 	struct swr_device *swr_dev = NULL;
 
@@ -1676,23 +1725,24 @@ static int wcd9378_swr_slave_clk_set(struct device *dev, int bank, int path, boo
 	if (!wcd9378)
 		return -EINVAL;
 
-	if (path == RX_PATH)
+	if (path == RX_PATH) {
 		swr_dev = wcd9378->rx_swr_dev;
-	else
+		swr_base_clk = wcd9378->swr_base_clk;
+		swr_clk_scale = wcd9378->swr_clk_scale;
+	} else {
 		swr_dev = wcd9378->tx_swr_dev;
+		swr_base_clk = SWR_BASECLK_19P2MHZ;
+		swr_clk_scale = SWR_CLKSCALE_DIV2;
+	}
 
 	clk_scale_reg = (bank ? SWRS_SCP_BUSCLOCK_SCALE_BANK1 :
 				SWRS_SCP_BUSCLOCK_SCALE_BANK0);
 
 	if (enable) {
-		pr_debug("%s: bank: %d	base_clk: 0x%0x, clk_scale_reg: 0x%0x, swr_clk_scale: 0x%0x\n",
-				__func__, bank, wcd9378->swr_base_clk,
-				clk_scale_reg, wcd9378->swr_clk_scale);
-
 		swr_write(swr_dev, swr_dev->dev_num,
-				SWRS_SCP_BASE_CLK_BASE, &wcd9378->swr_base_clk);
+				SWRS_SCP_BASE_CLK_BASE, &swr_base_clk);
 		swr_write(swr_dev, swr_dev->dev_num,
-				clk_scale_reg, &wcd9378->swr_clk_scale);
+				clk_scale_reg, &swr_clk_scale);
 	} else {
 		swr_write(swr_dev, swr_dev->dev_num,
 				SWRS_SCP_BASE_CLK_BASE, &clk_rst);
@@ -1777,6 +1827,12 @@ static int wcd9378_hph_sequencer_enable(struct snd_soc_dapm_widget *w,
 		snd_soc_component_update_bits(component, WCD9378_PDE47_REQ_PS,
 				WCD9378_PDE47_REQ_PS_PDE47_REQ_PS_MASK, 0x03);
 
+		if (!wcd9378->comp1_enable || !wcd9378->comp2_enable)
+			/*PA delay is 24250us*/
+			usleep_range(24300, 24310);
+		else
+			/*COMP delay is 11250us*/
+			usleep_range(11300, 11310);
 		break;
 	default:
 		break;
@@ -1887,8 +1943,6 @@ static int wcd9378_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
 
 			wcd9378_rx_connect_port(component, LO, true);
 		}
-
-		set_bit(WCD_AUX_EN, &wcd9378->status_mask);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		if (aux_rx1) {
@@ -1898,8 +1952,6 @@ static int wcd9378_codec_aux_dac_event(struct snd_soc_dapm_widget *w,
 					WCD9378_CDC_AUX_GAIN_CTL_AUX_EN_MASK, 0x00);
 			wcd9378_rx_connect_port(component, LO, true);
 		}
-
-		clear_bit(WCD_AUX_EN, &wcd9378->status_mask);
 		break;
 	};
 	return 0;
@@ -2184,7 +2236,6 @@ int wcd9378_swr_dmic_register_notifier(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL_GPL(wcd9378_swr_dmic_register_notifier);
 
-/*TBD: NEED TO CHECK AND UPDATE*/
 static int wcd9378_event_notify(struct notifier_block *block,
 				unsigned long val,
 				void *data)
@@ -3500,6 +3551,34 @@ static const struct snd_soc_dapm_widget wcd9378_dapm_widgets[] = {
 				wcd9378_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
 
+	/* micbias widgets*/
+	SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, 0, 0,
+				wcd9378_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, 0, 0,
+				wcd9378_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, 0, 0,
+				wcd9378_codec_enable_micbias,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
+	/* micbias pull up widgets*/
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+				wcd9378_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, 0, 0,
+				wcd9378_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, 0, 0,
+				wcd9378_codec_enable_micbias_pullup,
+				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+				SND_SOC_DAPM_POST_PMD),
+
 	/* rx mixer widgets*/
 	SND_SOC_DAPM_MUX("EAR_MUX", SND_SOC_NOPM, 0, 0, &ear_mux),
 	SND_SOC_DAPM_MUX("AUX_MUX", SND_SOC_NOPM, 0, 0, &aux_mux),

+ 8 - 4
asoc/codecs/wcd937x/wcd937x.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -3170,7 +3170,7 @@ static int wcd937x_reset(struct device *dev)
 	if (rc) {
 		dev_err(dev, "%s: wcd sleep state request fail!\n",
 				__func__);
-		return rc;
+		return -EPROBE_DEFER;
 	}
 	/* 20ms sleep required after pulling the reset gpio to LOW */
 	usleep_range(20, 30);
@@ -3179,7 +3179,7 @@ static int wcd937x_reset(struct device *dev)
 	if (rc) {
 		dev_err(dev, "%s: wcd active state request fail!\n",
 				__func__);
-		return rc;
+		return -EPROBE_DEFER;
 	}
 	/* 20ms sleep required after pulling the reset gpio to HIGH */
 	usleep_range(20, 30);
@@ -3403,7 +3403,11 @@ static int wcd937x_bind(struct device *dev)
 		goto err_bind_all;
 	}
 
-	wcd937x_reset(dev);
+	ret = wcd937x_reset(dev);
+	if (ret == -EPROBE_DEFER) {
+		dev_err(dev, "%s: wcd reset failed!\n", __func__);
+		goto err_bind_all;
+	}
 	/*
 	 * Add 5msec delay to provide sufficient time for
 	 * soundwire auto enumeration of slave devices as

+ 8 - 4
asoc/codecs/wcd938x/wcd938x.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -4181,7 +4181,7 @@ static int wcd938x_reset(struct device *dev)
 	if (rc) {
 		dev_err_ratelimited(dev, "%s: wcd sleep state request fail!\n",
 				__func__);
-		return rc;
+		return -EPROBE_DEFER;
 	}
 	/* 20us sleep required after pulling the reset gpio to LOW */
 	usleep_range(20, 30);
@@ -4190,7 +4190,7 @@ static int wcd938x_reset(struct device *dev)
 	if (rc) {
 		dev_err_ratelimited(dev, "%s: wcd active state request fail!\n",
 				__func__);
-		return rc;
+		return -EPROBE_DEFER;
 	}
 	/* 20us sleep required after pulling the reset gpio to HIGH */
 	usleep_range(20, 30);
@@ -4619,7 +4619,11 @@ static int wcd938x_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_lock_init;
 
-	wcd938x_reset(dev);
+	ret =  wcd938x_reset(dev);
+	if (ret == -EPROBE_DEFER) {
+		dev_err(dev, "%s: wcd reset failed!\n", __func__);
+		goto err_lock_init;
+	}
 
 	wcd938x->wakeup = wcd938x_wakeup;
 

+ 8 - 4
asoc/codecs/wcd939x/wcd939x.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -4706,7 +4706,7 @@ static int wcd939x_reset(struct device *dev)
 	if (rc) {
 		dev_err_ratelimited(dev, "%s: wcd sleep state request fail!\n",
 				__func__);
-		return rc;
+		return -EPROBE_DEFER;
 	}
 	/* 20us sleep required after pulling the reset gpio to LOW */
 	usleep_range(20, 30);
@@ -4715,7 +4715,7 @@ static int wcd939x_reset(struct device *dev)
 	if (rc) {
 		dev_err_ratelimited(dev, "%s: wcd active state request fail!\n",
 				__func__);
-		return rc;
+		return -EPROBE_DEFER;
 	}
 	/* 20us sleep required after pulling the reset gpio to HIGH */
 	usleep_range(20, 30);
@@ -5497,7 +5497,11 @@ static int wcd939x_probe(struct platform_device *pdev)
 	if (ret)
 		goto err_lock_init;
 
-	wcd939x_reset(dev);
+	ret = wcd939x_reset(dev);
+	if (ret == -EPROBE_DEFER) {
+		dev_err(dev, "%s: wcd reset failed!\n", __func__);
+		goto err_lock_init;
+	}
 
 	wcd939x->wakeup = wcd939x_wakeup;
 

+ 133 - 1
asoc/gvm_auto_spf_dummy.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/clk.h>
@@ -195,6 +195,7 @@ struct msm_asoc_mach_data {
 	struct snd_soc_codec *codec;
 	struct work_struct adsp_power_up_work;
 	struct tdm_conf tdm_intf_conf[TDM_INTERFACE_MAX];
+	struct snd_pcm_hardware hw_params;
 };
 
 static const char *const pin_states[] = {"sleep", "i2s-active",
@@ -225,12 +226,31 @@ static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
 	SND_SOC_DAPM_MIC("Digital Mic7", NULL),
 };
 
+static int tdm_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	if (!dai_link->no_pcm)
+		ret = snd_soc_set_runtime_hwparams(substream, &pdata->hw_params);
+
+	return ret;
+}
+
+static const struct snd_soc_ops tdm_be_ops = {
+	.startup = tdm_snd_startup,
+};
+
 static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	/* BackEnd DAI Links */
 	{
 	.name = "PRI_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -241,6 +261,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "PRI_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -251,6 +272,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "SEC_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF-RX-SECONDARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -261,6 +283,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "SEC_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF-TX-SECONDARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -271,6 +294,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "TERT_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF-RX-TERTIARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -281,6 +305,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "TERT_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF-TX-TERTIARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -291,6 +316,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "QUAT_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_RXTX-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -301,6 +327,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "QUAT_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_RXTX-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -311,6 +338,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "QUIN_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_VA-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -321,6 +349,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "QUIN_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_VA-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -331,6 +360,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "SEN_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_WSA-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -341,6 +371,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "SEN_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_WSA-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -351,6 +382,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "SEP_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_AUD-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -361,6 +393,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "SEP_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_AUD-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -371,6 +404,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "OCT_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_WSA2-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -381,6 +415,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "OCT_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_WSA2-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -391,6 +426,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF0_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_SDR-RX-PRIMARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -401,6 +437,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF0_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_SDR-TX-PRIMARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -411,6 +448,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF1_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_SDR-RX-SECONDARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -421,6 +459,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF1_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_SDR-TX-SECONDARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -431,6 +470,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF2_TDM_RX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_SDR-RX-TERTIARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -441,6 +481,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF2_TDM_TX_0_DUMMY",
 	.stream_name = "TDM-LPAIF_SDR-TX-TERTIARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -451,6 +492,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF3_TDM_RX_0",
 	.stream_name = "TDM-LPAIF_SDR-RX-QUATERNARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -461,6 +503,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF3_TDM_TX_0",
 	.stream_name = "TDM-LPAIF_SDR-TX-QUATERNARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -471,6 +514,7 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF4_TDM_RX_0",
 	.stream_name = "TDM-LPAIF_SDR-RX-QUINARY",
 	.dpcm_playback = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
@@ -481,12 +525,23 @@ static struct snd_soc_dai_link msm_gvm_auto_dai_links[] = {
 	.name = "HS_IF4_TDM_TX_0",
 	.stream_name = "TDM-LPAIF_SDR-TX-QUINARY",
 	.dpcm_capture = 1,
+	.ops = &tdm_be_ops,
 	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 				SND_SOC_DPCM_TRIGGER_POST},
 	.ignore_suspend = 1,
 	.ignore_pmdown_time = 1,
 	SND_SOC_DAILINK_REG(hs_if4_tdm_tx_0_dummy),
 	},
+	{
+	.name = "PCM_DUMMY-TX-0",
+	.stream_name = "PCM_DUMMY-TX-0",
+	.dpcm_capture = 1,
+	.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+	.ignore_suspend = 1,
+	.ignore_pmdown_time = 1,
+	SND_SOC_DAILINK_REG(pcm_dummy_tx0),
+	},
 };
 
 int snd_card_notify_user(snd_card_status_t card_status)
@@ -760,6 +815,75 @@ err:
 	return -EINVAL;
 }
 
+static int msm_get_hwparams(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct msm_asoc_mach_data *pdata = NULL;
+	u32 pcm_info = 0;
+	u32 buffer_bytes_max = 0;
+	u32 periods_bytes[2] = {0};
+	u32 periods_count[2] = {0};
+	int ret = 0;
+
+	card = platform_get_drvdata(pdev);
+	if (!card) {
+		pr_err("%s: card is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+	pdata = snd_soc_card_get_drvdata(card);
+	if (!pdata) {
+		pr_err("%s: pdata is NULL\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,hw_pcm_info",
+			&pcm_info);
+	if (ret) {
+		pr_err("%s: read pcm info failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node,
+			"qcom,hw_buffer_size_max",
+			&buffer_bytes_max);
+	if (ret) {
+		pr_err("%s: read buffer size max failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,hw_period_byte_size",
+			periods_bytes, 2);
+	if (ret) {
+		pr_err("%s: read period byte size failed\n",
+			__func__);
+		return ret;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,hw_period_count_size",
+			periods_count, 2);
+	if (ret) {
+		pr_err("%s: read period count size failed\n",
+			__func__);
+		return ret;
+	}
+
+	pdata->hw_params.info = pcm_info;
+	pdata->hw_params.buffer_bytes_max = buffer_bytes_max;
+	pdata->hw_params.period_bytes_min = periods_bytes[0];
+	pdata->hw_params.period_bytes_max = periods_bytes[1];
+	pdata->hw_params.periods_min = periods_count[0];
+	pdata->hw_params.periods_max = periods_count[1];
+
+	return ret;
+}
+
 static int msm_asoc_machine_probe(struct platform_device *pdev)
 {
 	struct snd_soc_card *card;
@@ -819,6 +943,14 @@ static int msm_asoc_machine_probe(struct platform_device *pdev)
 
 	pr_debug("%s: DRIVER Audio Ready\n", __func__);
 
+	ret = msm_get_hwparams(pdev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"%s: hwparams get failed with %d\n",
+			__func__, ret);
+		return ret;
+	}
+
 	spdev = pdev;
 	ret = msm_audio_ssr_register(&virt_sndcard_ctl);
 	if (ret)

+ 24 - 8
asoc/msm_common.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/gpio.h>
@@ -94,6 +94,7 @@ static const struct snd_pcm_hardware dummy_dma_hardware = {
 #define MAX_CPU_CLUSTER 4 /* Silver, Gold, T, Prime */
 
 static int qos_vote_status;
+static uint8_t cpu_vote_mask;
 static bool lpi_pcm_logging_enable;
 static bool vote_against_sleep_enable;
 static unsigned int vote_against_sleep_cnt;
@@ -648,11 +649,13 @@ static void msm_audio_add_qos_request(void)
 			    &msm_audio_req[cpu],
 			    DEV_PM_QOS_RESUME_LATENCY,
 			    PM_QOS_CPU_LATENCY_DEFAULT_VALUE);
-		if (ret < 0)
+		if (ret < 0) {
 			pr_err("%s error (%d) adding resume latency to cpu %d.\n",
                                                 __func__, ret, cpu);
-		pr_debug("%s set cpu affinity to logical core %d.\n", __func__, cpu);
-
+		} else {
+			cpu_vote_mask |= (1 << cpu);
+			pr_debug("%s set cpu affinity to logical core %d.\n", __func__, cpu);
+		}
 		/* Limit the request to 2 silver cpu cores. */
 		if (++num_req == 2)
 			break;
@@ -663,14 +666,21 @@ static void msm_audio_remove_qos_request(void)
 {
 	int cpu = 0;
 	int ret = 0;
+	uint8_t cpu_bit = 0;
 	cpumask_t *cluster_cpu_mask = NULL;
 
 	cluster_cpu_mask = topology_core_cpumask(cluster_first_cpu[0]);
 
 	if (msm_audio_req) {
 		for_each_cpu(cpu, cluster_cpu_mask) {
-			ret = dev_pm_qos_remove_request(
-				    &msm_audio_req[cpu]);
+			cpu_bit = 1 << cpu;
+			if (cpu_bit & cpu_vote_mask) {
+				ret = dev_pm_qos_remove_request(
+					    &msm_audio_req[cpu]);
+				cpu_vote_mask &= ~cpu_bit;
+			} else
+				pr_debug("%s: core %d not voted.\n",
+								__func__, cpu);
 			if (ret < 0)
 				pr_err("%s error (%d) removing request from cpu %d.\n",
                                                 __func__, ret, cpu);
@@ -957,6 +967,7 @@ void msm_common_get_backend_name(const char *stream_name, char **backend_name)
 static void msm_audio_update_qos_request(u32 latency)
 {
 	int cpu = 0;
+	uint8_t cpu_bit = 0;
 	int ret = -1;
 	int num_req = 0;
 	cpumask_t *cluster_cpu_mask = NULL;
@@ -965,8 +976,13 @@ static void msm_audio_update_qos_request(u32 latency)
 
 	if (msm_audio_req) {
 		for_each_cpu(cpu, cluster_cpu_mask) {
-			ret = dev_pm_qos_update_request(
-					&msm_audio_req[cpu], latency);
+			cpu_bit = 1 << cpu;
+			if (cpu_bit & cpu_vote_mask)
+				ret = dev_pm_qos_update_request(
+						&msm_audio_req[cpu], latency);
+			else
+				pr_debug("%s: core %d not voted.\n",
+								__func__, cpu);
 			if (1 == ret ) {
 				pr_debug("%s: updated latency of core %d to %u.\n",
 								__func__, cpu, latency);

+ 5 - 0
dsp/Kbuild

@@ -24,6 +24,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
 	endif
+	ifdef CONFIG_SND_SOC_GVM
+		include $(AUDIO_ROOT)/config/gvmauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
 	ifdef CONFIG_SND_SOC_SA7255
 		include $(AUDIO_ROOT)/config/sa7255auto.conf
 		export

+ 5 - 5
dsp/audio_notifier.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2016-2017, 2020-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -247,8 +247,10 @@ static int audio_notifier_dereg_service(int service, int domain)
 		__func__, service_data[service][domain].name,
 		service_data[service][domain].handle);
 
+	mutex_lock(&notifier_mutex);
 	service_data[service][domain].state = AUDIO_NOTIFIER_SERVICE_DOWN;
 	service_data[service][domain].handle = NULL;
+	mutex_unlock(&notifier_mutex);
 done:
 	return ret;
 }
@@ -473,16 +475,16 @@ static int audio_notifier_service_cb(unsigned long opcode,
 		__func__, service_data[service][domain].name, notifier_opcode);
 
 	mutex_lock(&notifier_mutex);
-
 	service_data[service][domain].state = notifier_opcode;
+
 	ret = srcu_notifier_call_chain(&service_data[service][domain].
 		client_nb_list, notifier_opcode, &data);
+	mutex_unlock(&notifier_mutex);
 	if (ret < 0)
 		pr_err_ratelimited("%s: srcu_notifier_call_chain returned %d, service %s, \
 			opcode 0x%lx\n", __func__, ret, service_data[service][domain].name,
 			notifier_opcode);
 
-	mutex_unlock(&notifier_mutex);
 
 	return NOTIFY_OK;
 }
@@ -520,7 +522,6 @@ int audio_notifier_deregister(char *client_name)
 		ret = -EINVAL;
 		goto done;
 	}
-	mutex_lock(&notifier_mutex);
 	list_for_each_safe(ptr, next, &client_list) {
 		client_data = list_entry(ptr, struct client_data, list);
 		if (!strcmp(client_name, client_data->client_name)) {
@@ -537,7 +538,6 @@ int audio_notifier_deregister(char *client_name)
 			kfree(client_data);
 		}
 	}
-	mutex_unlock(&notifier_mutex);
 done:
 	return ret;
 }

+ 5 - 0
ipc/Kbuild

@@ -25,6 +25,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
 	endif
+	ifdef CONFIG_SND_SOC_GVM
+		include $(AUDIO_ROOT)/config/gvmauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
 	ifdef CONFIG_SND_SOC_SA7255
 		include $(AUDIO_ROOT)/config/sa7255auto.conf
 		export

+ 5 - 0
soc/Kbuild

@@ -24,6 +24,11 @@ ifeq ($(CONFIG_SND_SOC_AUTO), y)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
 	endif
+	ifdef CONFIG_SND_SOC_GVM
+		include $(AUDIO_ROOT)/config/gvmauto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
+	endif
 	ifdef CONFIG_SND_SOC_SA7255
 		include $(AUDIO_ROOT)/config/sa7255auto.conf
 		export

+ 9 - 1
soc/swr-mstr-ctrl.c

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/irq.h>
@@ -2281,6 +2281,14 @@ handle_irq:
 			/* Wait 3.5ms to clear */
 			usleep_range(3500, 3505);
 			break;
+		case SWRM_INTERRUPT_STATUS_DOUT_RATE_MISMATCH:
+			dev_err(swrm->dev,
+				"%s: SWR Port Channel rate mismatch\n", __func__);
+			swrm->intr_mask &=
+				~SWRM_INTERRUPT_STATUS_DOUT_RATE_MISMATCH;
+			swr_master_write(swrm,
+				SWRM_INTERRUPT_EN(swrm->ee_val), swrm->intr_mask);
+			break;
 		default:
 			dev_err_ratelimited(swrm->dev,
 					"%s: SWR unknown interrupt value: %d\n",