Browse Source

Merge 82e12e19d8d7e6a714d9737f5bd54af440e9b489 on remote branch

Change-Id: Iccea92b474452e9f35ee5a1c8394ffe9c93bf212
Linux Build Service Account 4 years ago
parent
commit
e2aefd5566
58 changed files with 1785 additions and 770 deletions
  1. 25 40
      asoc/codecs/bolero/bolero-cdc.c
  2. 9 17
      asoc/codecs/bolero/bolero-cdc.h
  3. 34 2
      asoc/codecs/bolero/rx-macro.c
  4. 41 58
      asoc/codecs/bolero/tx-macro.c
  5. 4 114
      asoc/codecs/bolero/va-macro.c
  6. 14 4
      asoc/codecs/bolero/wsa-macro.c
  7. 2 2
      asoc/codecs/rouleur/rouleur-mbhc.c
  8. 4 1
      asoc/codecs/rouleur/rouleur.c
  9. 47 48
      asoc/codecs/swr-dmic.c
  10. 6 1
      asoc/codecs/swr-haptics.c
  11. 19 0
      asoc/codecs/wcd-mbhc-v2.c
  12. 2 0
      asoc/codecs/wcd937x/internal.h
  13. 56 1
      asoc/codecs/wcd937x/wcd937x.c
  14. 3 0
      asoc/codecs/wcd938x/internal.h
  15. 11 2
      asoc/codecs/wcd938x/wcd938x-slave.c
  16. 151 71
      asoc/codecs/wcd938x/wcd938x.c
  17. 9 0
      asoc/codecs/wcd938x/wcd938x.h
  18. 3 2
      asoc/codecs/wsa881x.c
  19. 6 1
      asoc/codecs/wsa883x/wsa883x.c
  20. 18 21
      asoc/kona.c
  21. 103 30
      asoc/lahaina.c
  22. 152 125
      asoc/msm-compress-q6-v2.c
  23. 4 0
      asoc/msm-compress-q6-v2.h
  24. 17 15
      asoc/msm-dai-fe.c
  25. 4 2
      asoc/msm-dai-q6-v2.c
  26. 23 11
      asoc/msm-lsm-client.c
  27. 2 2
      asoc/msm-pcm-afe-v2.c
  28. 3 3
      asoc/msm-pcm-dtmf-v2.c
  29. 6 6
      asoc/msm-pcm-host-voice-v2.c
  30. 43 22
      asoc/msm-pcm-loopback-v2.c
  31. 17 7
      asoc/msm-pcm-q6-noirq.c
  32. 73 26
      asoc/msm-pcm-q6-v2.c
  33. 38 10
      asoc/msm-pcm-routing-v2.c
  34. 1 0
      asoc/msm-pcm-routing-v2.h
  35. 5 5
      asoc/msm-pcm-voip-v2.c
  36. 5 5
      asoc/msm-qti-pp-config.c
  37. 11 0
      asoc/msm_dailink.h
  38. 58 22
      dsp/adsp-loader.c
  39. 12 0
      dsp/audio_notifier.c
  40. 2 2
      dsp/digital-cdc-rsc-mgr.c
  41. 43 7
      dsp/q6adm.c
  42. 210 35
      dsp/q6afe.c
  43. 4 0
      dsp/q6asm.c
  44. 136 2
      dsp/q6core.c
  45. 2 0
      dsp/q6voice.c
  46. 1 0
      include/asoc/wcd-mbhc-v2.h
  47. 28 1
      include/dsp/apr_audio-v2.h
  48. 2 1
      include/dsp/q6adm-v2.h
  49. 121 0
      include/dsp/q6core.h
  50. 10 1
      include/ipc/apr.h
  51. 5 1
      include/uapi/audio/linux/msm_audio_calibration.h
  52. 90 0
      include/uapi/audio/sound/audio_compressed_formats.h
  53. 35 3
      ipc/apr.c
  54. 3 3
      ipc/apr_tal_rpmsg.c
  55. 3 0
      soc/pinctrl-lpi.c
  56. 46 34
      soc/swr-mstr-ctrl.c
  57. 1 4
      soc/swr-mstr-ctrl.h
  58. 2 0
      soc/swrm_registers.h

+ 25 - 40
asoc/codecs/bolero/bolero-cdc.c

@@ -600,6 +600,28 @@ int bolero_dmic_clk_enable(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL(bolero_dmic_clk_enable);
 
+bool bolero_is_va_macro_registered(struct device *dev)
+{
+	struct bolero_priv *priv;
+
+	if (!dev) {
+		pr_err("%s: dev is null\n", __func__);
+		return false;
+	}
+	if (!bolero_is_valid_child_dev(dev)) {
+		dev_err(dev, "%s: child device calling is not added yet\n",
+			__func__);
+		return false;
+	}
+	priv = dev_get_drvdata(dev->parent);
+	if (!priv) {
+		dev_err(dev, "%s: priv is null\n", __func__);
+		return false;
+	}
+	return priv->macros_supported[VA_MACRO];
+}
+EXPORT_SYMBOL(bolero_is_va_macro_registered);
+
 /**
  * bolero_register_macro - Registers macro to bolero
  *
@@ -644,7 +666,6 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
 				bolero_mclk_mux_tbl[macro_id][MCLK_MUX0];
 	if (macro_id == TX_MACRO) {
 		priv->macro_params[macro_id].reg_wake_irq = ops->reg_wake_irq;
-		priv->macro_params[macro_id].clk_switch = ops->clk_switch;
 		priv->macro_params[macro_id].reg_evt_listener =
 							ops->reg_evt_listener;
 		priv->macro_params[macro_id].clk_enable = ops->clk_enable;
@@ -661,7 +682,7 @@ int bolero_register_macro(struct device *dev, u16 macro_id,
 	priv->num_macros_registered++;
 	priv->macros_supported[macro_id] = true;
 
-	dev_dbg(dev, "%s: register macro successful:%d\n", macro_id);
+	dev_info(dev, "%s: register macro successful:%d\n", __func__, macro_id);
 
 	if (priv->num_macros_registered == priv->num_macros) {
 		ret = bolero_copy_dais_from_macro(priv);
@@ -719,7 +740,6 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id)
 	priv->macro_params[macro_id].dev = NULL;
 	if (macro_id == TX_MACRO) {
 		priv->macro_params[macro_id].reg_wake_irq = NULL;
-		priv->macro_params[macro_id].clk_switch = NULL;
 		priv->macro_params[macro_id].reg_evt_listener = NULL;
 		priv->macro_params[macro_id].clk_enable = NULL;
 	}
@@ -1016,40 +1036,6 @@ int bolero_register_wake_irq(struct snd_soc_component *component,
 }
 EXPORT_SYMBOL(bolero_register_wake_irq);
 
-/**
- * bolero_tx_clk_switch - Switch tx macro clock
- *
- * @component: pointer to codec component instance.
- *
- * @clk_src: 0 for TX_RCG and 1 for VA_RCG
- *
- * Returns 0 on success or -EINVAL on error.
- */
-int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src)
-{
-	struct bolero_priv *priv = NULL;
-	int ret = 0;
-
-	if (!component)
-		return -EINVAL;
-
-	priv = snd_soc_component_get_drvdata(component);
-	if (!priv)
-		return -EINVAL;
-
-	if (!bolero_is_valid_codec_dev(priv->dev)) {
-		dev_err(component->dev, "%s: invalid codec\n", __func__);
-		return -EINVAL;
-	}
-
-	if (priv->macro_params[TX_MACRO].clk_switch)
-		ret = priv->macro_params[TX_MACRO].clk_switch(component,
-							      clk_src);
-
-	return ret;
-}
-EXPORT_SYMBOL(bolero_tx_clk_switch);
-
 /**
  * bolero_tx_mclk_enable - Enable/Disable TX Macro mclk
  *
@@ -1094,7 +1080,7 @@ EXPORT_SYMBOL(bolero_tx_mclk_enable);
  * Returns 0 on success or -EINVAL on error.
  */
 int bolero_register_event_listener(struct snd_soc_component *component,
-				   bool enable, bool is_dmic_sva)
+				   bool enable)
 {
 	struct bolero_priv *priv = NULL;
 	int ret = 0;
@@ -1113,8 +1099,7 @@ int bolero_register_event_listener(struct snd_soc_component *component,
 
 	if (priv->macro_params[TX_MACRO].reg_evt_listener)
 		ret = priv->macro_params[TX_MACRO].reg_evt_listener(component,
-								    enable,
-								    is_dmic_sva);
+								    enable);
 
 	return ret;
 }

+ 9 - 17
asoc/codecs/bolero/bolero-cdc.h

@@ -37,11 +37,6 @@ enum {
 	BOLERO_ADC_MAX
 };
 
-enum {
-	CLK_SRC_TX_RCG = 0,
-	CLK_SRC_VA_RCG,
-};
-
 enum {
 	BOLERO_MACRO_EVT_RX_MUTE = 1, /* for RX mute/unmute */
 	BOLERO_MACRO_EVT_IMPED_TRUE, /* for imped true */
@@ -76,9 +71,7 @@ struct macro_ops {
 	int (*set_port_map)(struct snd_soc_component *component, u32 uc,
 			    u32 size, void *data);
 	int (*clk_div_get)(struct snd_soc_component *component);
-	int (*clk_switch)(struct snd_soc_component *component, int clk_src);
-	int (*reg_evt_listener)(struct snd_soc_component *component,
-			bool en, bool is_dmic_sva);
+	int (*reg_evt_listener)(struct snd_soc_component *component, bool en);
 	int (*clk_enable)(struct snd_soc_component *c, bool en);
 	char __iomem *io_base;
 	u16 clk_id_req;
@@ -90,6 +83,7 @@ typedef int (*rsc_clk_cb_t)(struct device *dev, u16 event);
 #if IS_ENABLED(CONFIG_SND_SOC_BOLERO)
 int bolero_register_res_clk(struct device *dev, rsc_clk_cb_t cb);
 void bolero_unregister_res_clk(struct device *dev);
+bool bolero_is_va_macro_registered(struct device *dev);
 int bolero_register_macro(struct device *dev, u16 macro_id,
 			  struct macro_ops *ops);
 void bolero_unregister_macro(struct device *dev, u16 macro_id);
@@ -103,9 +97,8 @@ void bolero_clear_amic_tx_hold(struct device *dev, u16 adc_n);
 int bolero_runtime_resume(struct device *dev);
 int bolero_runtime_suspend(struct device *dev);
 int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data);
-int bolero_tx_clk_switch(struct snd_soc_component *component, int clk_src);
 int bolero_register_event_listener(struct snd_soc_component *component,
-				   bool enable, bool is_dmic_sva);
+				   bool enable);
 void bolero_wsa_pa_on(struct device *dev);
 bool bolero_check_core_votes(struct device *dev);
 int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable);
@@ -121,6 +114,11 @@ static inline void bolero_unregister_res_clk(struct device *dev)
 {
 }
 
+static bool bolero_is_va_macro_registered(struct device *dev)
+{
+	return false;
+}
+
 static inline int bolero_register_macro(struct device *dev,
 					u16 macro_id,
 					struct macro_ops *ops)
@@ -171,15 +169,9 @@ static inline int bolero_set_port_map(struct snd_soc_component *component,
 	return 0;
 }
 
-static inline int bolero_tx_clk_switch(struct snd_soc_component *component,
-					int clk_src)
-{
-	return 0;
-}
-
 static inline int bolero_register_event_listener(
 					struct snd_soc_component *component,
-					bool enable, bool is_dmic_sva)
+					bool enable)
 {
 	return 0;
 }

+ 34 - 2
asoc/codecs/bolero/rx-macro.c

@@ -378,7 +378,6 @@ struct rx_swr_ctrl_platform_data {
 							  void *data),
 			  void *swrm_handle,
 			  int action);
-	int (*pinctrl_setup)(void *handle, bool enable);
 };
 
 enum {
@@ -388,6 +387,7 @@ enum {
 	RX_MACRO_AIF3_PB,
 	RX_MACRO_AIF4_PB,
 	RX_MACRO_AIF_ECHO,
+	RX_MACRO_AIF5_PB,
 	RX_MACRO_AIF6_PB,
 	RX_MACRO_MAX_DAIS,
 };
@@ -720,6 +720,20 @@ static struct snd_soc_dai_driver rx_macro_dai[] = {
 		},
 		.ops = &rx_macro_dai_ops,
 	},
+	{
+		.name = "rx_macro_rx5",
+		.id = RX_MACRO_AIF5_PB,
+		.playback = {
+			.stream_name = "RX_MACRO_AIF5 Playback",
+			.rates = RX_MACRO_RATES | RX_MACRO_FRAC_RATES,
+			.formats = RX_MACRO_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.ops = &rx_macro_dai_ops,
+	},
 	{
 		.name = "rx_macro_rx6",
 		.id = RX_MACRO_AIF6_PB,
@@ -1139,6 +1153,13 @@ static int rx_macro_get_channel_map(struct snd_soc_dai *dai,
 			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d active_mask: 0x%x\n",
 			__func__, dai->id, *rx_slot, *rx_num, rx_priv->active_ch_mask[dai->id]);
 		break;
+	case RX_MACRO_AIF5_PB:
+		*rx_slot = 0x1;
+		*rx_num = 0x01;
+		dev_dbg(rx_priv->dev,
+			"%s: dai->id:%d, ch_mask:0x%x, active_ch_cnt:%d\n",
+			__func__, dai->id, *rx_slot, *rx_num);
+		break;
 	case RX_MACRO_AIF6_PB:
 		*rx_slot = 0x1;
 		*rx_num = 0x01;
@@ -3192,6 +3213,9 @@ static const struct snd_soc_dapm_widget rx_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_AIF_OUT("RX AIF_ECHO", "RX_AIF_ECHO Capture", 0,
 		SND_SOC_NOPM, 0, 0),
 
+	SND_SOC_DAPM_AIF_IN("RX AIF5 PB", "RX_MACRO_AIF5 Playback", 0,
+		SND_SOC_NOPM, 0, 0),
+
 	SND_SOC_DAPM_AIF_IN("RX AIF6 PB", "RX_MACRO_AIF6 Playback", 0,
 		SND_SOC_NOPM, 0, 0),
 
@@ -3862,6 +3886,7 @@ static int rx_macro_init(struct snd_soc_component *component)
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF4 Playback");
+	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF5 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF6 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "HPHL_OUT");
 	snd_soc_dapm_ignore_suspend(dapm, "HPHR_OUT");
@@ -4029,6 +4054,12 @@ static int rx_macro_probe(struct platform_device *pdev)
 	u32 is_used_rx_swr_gpio = 1;
 	const char *is_used_rx_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
+	if (!bolero_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
 	rx_priv = devm_kzalloc(&pdev->dev, sizeof(struct rx_macro_priv),
 			    GFP_KERNEL);
 	if (!rx_priv)
@@ -4080,6 +4111,8 @@ static int rx_macro_probe(struct platform_device *pdev)
 			__func__);
 		return -EPROBE_DEFER;
 	}
+	msm_cdc_pinctrl_set_wakeup_capable(
+				rx_priv->rx_swr_gpio_p, false);
 
 	rx_io_base = devm_ioremap(&pdev->dev, rx_base_addr,
 				  RX_MACRO_MAX_OFFSET);
@@ -4105,7 +4138,6 @@ static int rx_macro_probe(struct platform_device *pdev)
 	rx_priv->swr_plat_data.clk = rx_swrm_clock;
 	rx_priv->swr_plat_data.core_vote = rx_macro_core_vote;
 	rx_priv->swr_plat_data.handle_irq = NULL;
-	rx_priv->swr_plat_data.pinctrl_setup = NULL;
 
 	ret = of_property_read_u8_array(pdev->dev.of_node,
 				"qcom,rx-bcl-pmic-params", bcl_pmic_params,

+ 41 - 58
asoc/codecs/bolero/tx-macro.c

@@ -81,7 +81,6 @@ struct tx_macro_swr_ctrl_platform_data {
 							  void *data),
 			  void *swrm_handle,
 			  int action);
-	int (*pinctrl_setup)(void *handle, bool enable);
 };
 
 enum {
@@ -177,6 +176,7 @@ struct tx_macro_priv {
 	int bcs_ch;
 	bool bcs_clk_en;
 	bool hs_slow_insert_complete;
+	int amic_sample_rate;
 };
 
 static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -501,6 +501,29 @@ static void tx_macro_tx_hpf_corner_freq_callback(struct work_struct *work)
 				hpf_cut_off_freq << 5);
 		snd_soc_component_update_bits(component, hpf_gate_reg,
 						0x03, 0x02);
+		/* Add delay between toggle hpf gate based on sample rate */
+		switch(tx_priv->amic_sample_rate) {
+		case 8000:
+			usleep_range(125, 130);
+			break;
+		case 16000:
+			usleep_range(62, 65);
+			break;
+		case 32000:
+			usleep_range(31, 32);
+			break;
+		case 48000:
+			usleep_range(20, 21);
+			break;
+		case 96000:
+			usleep_range(10, 11);
+			break;
+		case 192000:
+			usleep_range(5, 6);
+			break;
+		default:
+			usleep_range(125, 130);
+		}
 		snd_soc_component_update_bits(component, hpf_gate_reg,
 						0x03, 0x01);
 	} else {
@@ -936,6 +959,7 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 	u16 dec_cfg_reg = 0;
 	u16 hpf_gate_reg = 0;
 	u16 tx_gain_ctl_reg = 0;
+	u16 tx_fs_reg = 0;
 	u8 hpf_cut_off_freq = 0;
 	u16 adc_mux_reg = 0;
 	int hpf_delay = TX_MACRO_DMIC_HPF_DELAY_MS;
@@ -961,6 +985,11 @@ static int tx_macro_enable_dec(struct snd_soc_dapm_widget *w,
 				TX_MACRO_TX_PATH_OFFSET * decimator;
 	adc_mux_reg = BOLERO_CDC_TX_INP_MUX_ADC_MUX0_CFG1 +
 			TX_MACRO_ADC_MUX_CFG_OFFSET * decimator;
+	tx_fs_reg = BOLERO_CDC_TX0_TX_PATH_CTL +
+				TX_MACRO_TX_PATH_OFFSET * decimator;
+
+	tx_priv->amic_sample_rate = (snd_soc_component_read32(component,
+				     tx_fs_reg) & 0x0F);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
@@ -2497,30 +2526,12 @@ static const struct snd_kcontrol_new tx_macro_snd_controls[] = {
 		       tx_macro_get_bcs, tx_macro_set_bcs),
 };
 
-static int tx_macro_pinctrl_setup(void *handle, bool enable)
-{
-	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
-
-	if (tx_priv == NULL) {
-		pr_err("%s: tx priv data is NULL\n", __func__);
-		return -EINVAL;
-	}
-	if (enable)
-		msm_cdc_pinctrl_set_wakeup_capable(
-			tx_priv->tx_swr_gpio_p, true);
-	else
-		msm_cdc_pinctrl_set_wakeup_capable(
-			tx_priv->tx_swr_gpio_p, false);
-	return 0;
-}
-
 static int tx_macro_register_event_listener(struct snd_soc_component *component,
-					    bool enable, bool is_dmic_sva)
+					    bool enable)
 {
 	struct device *tx_dev = NULL;
 	struct tx_macro_priv *tx_priv = NULL;
 	int ret = 0;
-	u32 dmic_sva = is_dmic_sva;
 
 	if (!component)
 		return -EINVAL;
@@ -2542,17 +2553,15 @@ static int tx_macro_register_event_listener(struct snd_soc_component *component,
 		if (enable) {
 			ret = swrm_wcd_notify(
 				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-				SWR_REGISTER_WAKEUP, &dmic_sva);
+				SWR_REGISTER_WAKEUP, NULL);
 			msm_cdc_pinctrl_set_wakeup_capable(
-				tx_priv->tx_swr_gpio_p, false);
+					tx_priv->tx_swr_gpio_p, false);
 		} else {
-			/* while teardown we can reset the flag */
-			dmic_sva = 0;
 			msm_cdc_pinctrl_set_wakeup_capable(
-				tx_priv->tx_swr_gpio_p, true);
+					tx_priv->tx_swr_gpio_p, true);
 			ret = swrm_wcd_notify(
 				tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-				SWR_DEREGISTER_WAKEUP, &dmic_sva);
+				SWR_DEREGISTER_WAKEUP, NULL);
 		}
 	}
 
@@ -2746,36 +2755,6 @@ static int tx_macro_clk_div_get(struct snd_soc_component *component)
 	return tx_priv->dmic_clk_div;
 }
 
-static int tx_macro_clk_switch(struct snd_soc_component *component, int clk_src)
-{
-	struct device *tx_dev = NULL;
-	struct tx_macro_priv *tx_priv = NULL;
-	int ret = 0;
-
-	if (!component)
-		return -EINVAL;
-
-	tx_dev = bolero_get_device_ptr(component->dev, TX_MACRO);
-	if (!tx_dev) {
-		dev_err(component->dev,
-			"%s: null device for macro!\n", __func__);
-		return -EINVAL;
-	}
-	tx_priv = dev_get_drvdata(tx_dev);
-	if (!tx_priv) {
-		dev_err(component->dev,
-			"%s: priv is null for macro!\n", __func__);
-		return -EINVAL;
-	}
-	if (tx_priv->swr_ctrl_data) {
-		ret = swrm_wcd_notify(
-			tx_priv->swr_ctrl_data[0].tx_swr_pdev,
-			SWR_REQ_CLK_SWITCH, &clk_src);
-	}
-
-	return ret;
-}
-
 static int tx_macro_core_vote(void *handle, bool enable)
 {
 	struct tx_macro_priv *tx_priv = (struct tx_macro_priv *) handle;
@@ -3257,7 +3236,6 @@ static void tx_macro_init_ops(struct macro_ops *ops,
 	ops->reg_wake_irq = tx_macro_reg_wake_irq;
 	ops->set_port_map = tx_macro_set_port_map;
 	ops->clk_div_get = tx_macro_clk_div_get;
-	ops->clk_switch = tx_macro_clk_switch;
 	ops->reg_evt_listener = tx_macro_register_event_listener;
 	ops->clk_enable = __tx_macro_mclk_enable;
 }
@@ -3273,6 +3251,12 @@ static int tx_macro_probe(struct platform_device *pdev)
 	u32 is_used_tx_swr_gpio = 1;
 	const char *is_used_tx_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
+	if (!bolero_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
 	tx_priv = devm_kzalloc(&pdev->dev, sizeof(struct tx_macro_priv),
 			    GFP_KERNEL);
 	if (!tx_priv)
@@ -3343,7 +3327,6 @@ static int tx_macro_probe(struct platform_device *pdev)
 		tx_priv->swr_plat_data.clk = tx_macro_swrm_clock;
 		tx_priv->swr_plat_data.core_vote = tx_macro_core_vote;
 		tx_priv->swr_plat_data.handle_irq = NULL;
-		tx_priv->swr_plat_data.pinctrl_setup = tx_macro_pinctrl_setup;
 		mutex_init(&tx_priv->swr_clk_lock);
 	}
 	tx_priv->is_used_tx_swr_gpio = is_used_tx_swr_gpio;

+ 4 - 114
asoc/codecs/bolero/va-macro.c

@@ -130,7 +130,6 @@ struct va_macro_swr_ctrl_platform_data {
 							  void *data),
 			  void *swrm_handle,
 			  int action);
-	int (*pinctrl_setup)(void *handle, bool enable);
 };
 
 struct va_macro_priv {
@@ -381,7 +380,6 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
 	int ret = 0;
 	struct device *va_dev = NULL;
 	struct va_macro_priv *va_priv = NULL;
-	int clk_src = 0;
 
 	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
 		return -EINVAL;
@@ -394,30 +392,12 @@ static int va_macro_swr_pwr_event_v2(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (va_priv->swr_ctrl_data) {
-			clk_src = CLK_SRC_VA_RCG;
-			ret = swrm_wcd_notify(
-				va_priv->swr_ctrl_data[0].va_swr_pdev,
-				SWR_REQ_CLK_SWITCH, &clk_src);
-			if (ret)
-				dev_dbg(va_dev, "%s: clock switch failed\n",
-					__func__);
-		}
 		msm_cdc_pinctrl_set_wakeup_capable(
 				va_priv->va_swr_gpio_p, false);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		msm_cdc_pinctrl_set_wakeup_capable(
 				va_priv->va_swr_gpio_p, true);
-		if (va_priv->swr_ctrl_data) {
-			clk_src = CLK_SRC_TX_RCG;
-			ret = swrm_wcd_notify(
-				va_priv->swr_ctrl_data[0].va_swr_pdev,
-				SWR_REQ_CLK_SWITCH, &clk_src);
-			if (ret)
-				dev_dbg(va_dev, "%s: clock switch failed\n",
-					__func__);
-		}
 		break;
 	default:
 		dev_err(va_priv->dev,
@@ -455,22 +435,16 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
 					"%s: lpass audio hw enable failed\n",
 					__func__);
 		}
-		if (!ret)
-			if (bolero_tx_clk_switch(component, CLK_SRC_VA_RCG))
-				dev_dbg(va_dev, "%s: clock switch failed\n",
-					__func__);
 		if (va_priv->lpi_enable) {
-			bolero_register_event_listener(component, true, false);
+			bolero_register_event_listener(component, true);
 			va_priv->register_event_listener = true;
 		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		if (va_priv->register_event_listener) {
 			va_priv->register_event_listener = false;
-			bolero_register_event_listener(component, false, false);
+			bolero_register_event_listener(component, false);
 		}
-		if (bolero_tx_clk_switch(component, CLK_SRC_TX_RCG))
-			dev_dbg(va_dev, "%s: clock switch failed\n",__func__);
 		if (va_priv->lpass_audio_hw_vote)
 			digital_cdc_rsc_mgr_hw_vote_disable(
 				va_priv->lpass_audio_hw_vote);
@@ -483,45 +457,6 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
 	return ret;
 }
 
-static int va_macro_swr_intr_event(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 ret = 0;
-	struct device *va_dev = NULL;
-	struct va_macro_priv *va_priv = NULL;
-
-	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
-		return -EINVAL;
-
-	dev_dbg(va_dev, "%s: event = %d, lpi_enable = %d\n",
-		__func__, event, va_priv->lpi_enable);
-
-	if (!va_priv->lpi_enable)
-		return ret;
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		if (va_priv->lpi_enable) {
-			bolero_register_event_listener(component, true, true);
-			va_priv->register_event_listener = true;
-		}
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		if (va_priv->register_event_listener) {
-			va_priv->register_event_listener = false;
-			bolero_register_event_listener(component, false, true);
-		}
-		break;
-	default:
-		dev_err(va_priv->dev,
-			"%s: invalid DAPM event %d\n", __func__, event);
-		ret = -EINVAL;
-	}
-	return ret;
-}
-
 static int va_macro_tx_swr_clk_event_v2(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -549,7 +484,6 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
 	int ret = 0;
 	struct device *va_dev = NULL;
 	struct va_macro_priv *va_priv = NULL;
-	int clk_src = 0;
 
 	if (!va_macro_get_data(component, &va_dev, &va_priv, __func__))
 		return -EINVAL;
@@ -570,27 +504,10 @@ static int va_macro_mclk_event(struct snd_soc_dapm_widget *w,
 			ret = bolero_tx_mclk_enable(component, 1);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (va_priv->lpi_enable) {
-			if (va_priv->version == BOLERO_VERSION_2_1) {
-				if (va_priv->swr_ctrl_data) {
-					clk_src = CLK_SRC_TX_RCG;
-					ret = swrm_wcd_notify(
-					va_priv->swr_ctrl_data[0].va_swr_pdev,
-					SWR_REQ_CLK_SWITCH, &clk_src);
-					if (ret)
-						dev_dbg(va_dev,
-					"%s: clock switch failed\n",
-						__func__);
-				}
-			} else if (bolero_tx_clk_switch(component,
-					CLK_SRC_TX_RCG)) {
-				dev_dbg(va_dev, "%s: clock switch failed\n",
-					__func__);
-			}
+		if (va_priv->lpi_enable)
 			va_macro_mclk_enable(va_priv, 0, true);
-		} else {
+		else
 			bolero_tx_mclk_enable(component, 0);
-		}
 
 		if (va_priv->tx_clk_status > 0) {
 			bolero_clk_rsc_request_clock(va_priv->dev,
@@ -2029,10 +1946,6 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets_v3[] = {
 	SND_SOC_DAPM_SUPPLY_S("VA_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
 			      va_macro_swr_pwr_event,
 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0,
-			      va_macro_swr_intr_event,
-			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = {
@@ -2177,10 +2090,6 @@ static const struct snd_soc_dapm_widget va_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY_S("VA_MCLK", -1, SND_SOC_NOPM, 0, 0,
 			      va_macro_mclk_event,
 			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
-	SND_SOC_DAPM_SUPPLY_S("VA_SWR_INTR", 0, SND_SOC_NOPM, 0, 0,
-			      va_macro_swr_intr_event,
-			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_widget va_macro_wod_dapm_widgets[] = {
@@ -2327,15 +2236,6 @@ static const struct snd_soc_dapm_route va_audio_map_v3[] = {
 	{"VA SMIC MUX3", "SWR_MIC9", "VA SWR_INPUT"},
 	{"VA SMIC MUX3", "SWR_MIC10", "VA SWR_INPUT"},
 	{"VA SMIC MUX3", "SWR_MIC11", "VA SWR_INPUT"},
-
-	{"VA DMIC0", NULL, "VA_SWR_INTR"},
-	{"VA DMIC1", NULL, "VA_SWR_INTR"},
-	{"VA DMIC2", NULL, "VA_SWR_INTR"},
-	{"VA DMIC3", NULL, "VA_SWR_INTR"},
-	{"VA DMIC4", NULL, "VA_SWR_INTR"},
-	{"VA DMIC5", NULL, "VA_SWR_INTR"},
-	{"VA DMIC6", NULL, "VA_SWR_INTR"},
-	{"VA DMIC7", NULL, "VA_SWR_INTR"},
 };
 
 static const struct snd_soc_dapm_route va_audio_map_v2[] = {
@@ -2572,15 +2472,6 @@ static const struct snd_soc_dapm_route va_audio_map[] = {
 	{"VA SMIC MUX7", "SWR_DMIC6", "VA SWR_MIC6"},
 	{"VA SMIC MUX7", "SWR_DMIC7", "VA SWR_MIC7"},
 
-	{"VA DMIC0", NULL, "VA_SWR_INTR"},
-	{"VA DMIC1", NULL, "VA_SWR_INTR"},
-	{"VA DMIC2", NULL, "VA_SWR_INTR"},
-	{"VA DMIC3", NULL, "VA_SWR_INTR"},
-	{"VA DMIC4", NULL, "VA_SWR_INTR"},
-	{"VA DMIC5", NULL, "VA_SWR_INTR"},
-	{"VA DMIC6", NULL, "VA_SWR_INTR"},
-	{"VA DMIC7", NULL, "VA_SWR_INTR"},
-
 	{"VA SWR_ADC0", NULL, "VA_SWR_PWR"},
 	{"VA SWR_ADC1", NULL, "VA_SWR_PWR"},
 	{"VA SWR_ADC2", NULL, "VA_SWR_PWR"},
@@ -3230,7 +3121,6 @@ static int va_macro_probe(struct platform_device *pdev)
 		va_priv->swr_plat_data.clk = va_macro_swrm_clock;
 		va_priv->swr_plat_data.core_vote = va_macro_core_vote;
 		va_priv->swr_plat_data.handle_irq = NULL;
-		va_priv->swr_plat_data.pinctrl_setup = NULL;
 		mutex_init(&va_priv->swr_clk_lock);
 	}
 	va_priv->is_used_va_swr_gpio = is_used_va_swr_gpio;

+ 14 - 4
asoc/codecs/bolero/wsa-macro.c

@@ -166,7 +166,6 @@ struct wsa_macro_swr_ctrl_platform_data {
 							  void *data),
 			  void *swrm_handle,
 			  int action);
-	int (*pinctrl_setup)(void *handle, bool enable);
 };
 
 struct wsa_macro_bcl_pmic_params {
@@ -2009,10 +2008,12 @@ static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
 	int value = ucontrol->value.integer.value[0];
 	int wsa_rx_shift = ((struct soc_multi_mixer_control *)
 			kcontrol->private_value)->shift;
+	int ret = 0;
 
 	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
 		return -EINVAL;
 
+	pm_runtime_get_sync(wsa_priv->dev);
 	switch (wsa_rx_shift) {
 	case 0:
 		snd_soc_component_update_bits(component,
@@ -2037,13 +2038,16 @@ static int wsa_macro_set_rx_mute_status(struct snd_kcontrol *kcontrol,
 	default:
 		pr_err("%s: invalid argument rx_shift = %d\n", __func__,
 			wsa_rx_shift);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
+	pm_runtime_mark_last_busy(wsa_priv->dev);
+	pm_runtime_put_autosuspend(wsa_priv->dev);
 
 	dev_dbg(component->dev, "%s: WSA Digital Mute RX %d Enable %d\n",
 		__func__, wsa_rx_shift, value);
 	wsa_priv->wsa_digital_mute_status[wsa_rx_shift] = value;
-	return 0;
+
+	return ret;
 }
 
 static int wsa_macro_get_compander(struct snd_kcontrol *kcontrol,
@@ -3140,6 +3144,12 @@ static int wsa_macro_probe(struct platform_device *pdev)
 	u32 is_used_wsa_swr_gpio = 1;
 	const char *is_used_wsa_swr_gpio_dt = "qcom,is-used-swr-gpio";
 
+	if (!bolero_is_va_macro_registered(&pdev->dev)) {
+		dev_err(&pdev->dev,
+			"%s: va-macro not registered yet, defer\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
 	wsa_priv = devm_kzalloc(&pdev->dev, sizeof(struct wsa_macro_priv),
 				GFP_KERNEL);
 	if (!wsa_priv)
@@ -3197,7 +3207,6 @@ static int wsa_macro_probe(struct platform_device *pdev)
 	wsa_priv->swr_plat_data.clk = wsa_swrm_clock;
 	wsa_priv->swr_plat_data.core_vote = wsa_macro_core_vote;
 	wsa_priv->swr_plat_data.handle_irq = NULL;
-	wsa_priv->swr_plat_data.pinctrl_setup = NULL;
 
 	ret = of_property_read_u32(pdev->dev.of_node, "qcom,default-clk-id",
 				   &default_clk_id);
@@ -3226,6 +3235,7 @@ static int wsa_macro_probe(struct platform_device *pdev)
 	wsa_macro_init_ops(&ops, wsa_io_base);
 	ops.clk_id_req = wsa_priv->default_clk_id;
 	ops.default_clk_id = wsa_priv->default_clk_id;
+
 	ret = bolero_register_macro(&pdev->dev, WSA_MACRO, &ops);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "%s: register macro failed\n", __func__);

+ 2 - 2
asoc/codecs/rouleur/rouleur-mbhc.c

@@ -33,8 +33,8 @@
 #define ROULEUR_ZDET_C3                 4500
 
 /* Cross connection thresholds in mV */
-#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 200
-#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 200
+#define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 350
+#define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 350
 
 static struct wcd_mbhc_register
 	wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {

+ 4 - 1
asoc/codecs/rouleur/rouleur.c

@@ -783,6 +783,9 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
 		ret = swr_slvdev_datapath_control(rouleur->rx_swr_dev,
 			    rouleur->rx_swr_dev->dev_num,
 			    true);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x00);
 		usleep_range(5000, 5100);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_PDM_WD_CTL0,
@@ -1400,6 +1403,7 @@ static int rouleur_event_notify(struct notifier_block *block,
 		rouleur_init_reg(component);
 		regcache_mark_dirty(rouleur->regmap);
 		regcache_sync(rouleur->regmap);
+		rouleur->dev_up = true;
 		/* Initialize MBHC module */
 		mbhc = &rouleur->mbhc->wcd_mbhc;
 		ret = rouleur_mbhc_post_ssr_init(rouleur->mbhc, component);
@@ -1412,7 +1416,6 @@ static int rouleur_event_notify(struct notifier_block *block,
 				mdelay(500);
 		}
 		rouleur->mbhc->wcd_mbhc.deinit_in_progress = false;
-		rouleur->dev_up = true;
 		break;
 	default:
 		dev_err(component->dev, "%s: invalid event %d\n", __func__,

+ 47 - 48
asoc/codecs/swr-dmic.c

@@ -30,6 +30,9 @@
 #include "wcd938x/wcd938x.h"
 #include "swr-dmic.h"
 
+#define NUM_ATTEMPTS 5
+#define SWRS_SCP_CONTROL    0x44
+
 static int swr_master_channel_map[] = {
 	ZERO,
 	SWRM_TX1_CH1,
@@ -64,6 +67,7 @@ struct swr_dmic_priv {
 	int is_en_supply;
 	int port_type;
 	u8 tx_master_port_map[SWR_DMIC_MAX_PORTS];
+	struct notifier_block nblock;
 };
 
 const char *codec_name_list[] = {
@@ -243,38 +247,6 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
 	return ret;
 }
 
-static int swr_dmic_enable_supply(struct snd_soc_dapm_widget *w,
-			       struct snd_kcontrol *kcontrol,
-			       int event)
-{
-	struct snd_soc_component *component =
-			snd_soc_dapm_to_component(w->dapm);
-	struct swr_dmic_priv *swr_dmic =
-			snd_soc_component_get_drvdata(component);
-	int ret = 0;
-
-	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
-		w->name, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		ret = swr_dmic_up(swr_dmic->swr_slave);
-		break;
-	case SND_SOC_DAPM_POST_PMU:
-		ret = swr_dmic_reset(swr_dmic->swr_slave);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		ret = swr_dmic_down(swr_dmic->swr_slave);
-		break;
-	}
-
-	if (ret)
-		dev_dbg(component->dev, "%s wname: %s event: %d ret : %d\n",
-			__func__, w->name, event, ret);
-
-	return ret;
-}
-
 static const char * const tx_master_port_text[] = {
 	"ZERO", "SWRM_TX1_CH1", "SWRM_TX1_CH2", "SWRM_TX1_CH3", "SWRM_TX1_CH4",
 	"SWRM_TX2_CH1", "SWRM_TX2_CH2", "SWRM_TX2_CH3", "SWRM_TX2_CH4",
@@ -304,10 +276,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
 
 	SND_SOC_DAPM_INPUT("SWR_DMIC"),
 
-	SND_SOC_DAPM_SUPPLY_S("SMIC_SUPPLY", 1, SND_SOC_NOPM, 0, 0,
-				swr_dmic_enable_supply,
-				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
-				SND_SOC_DAPM_POST_PMD),
 	SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0,
 				swr_dmic_port_enable,
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -315,7 +283,6 @@ static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route swr_dmic_audio_map[] = {
-	{"SWR_DMIC", NULL, "SMIC_SUPPLY"},
 	{"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"},
 	{"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"},
 	{"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"},
@@ -391,6 +358,8 @@ static int enable_wcd_codec_supply(struct swr_dmic_priv *swr_dmic, bool enable)
 		pr_err("%s: component is NULL\n", __func__);
 		return -EINVAL;
 	}
+	dev_dbg(component->dev, "%s: supply %d micbias: %d enable: %d\n",
+		__func__, swr_dmic->is_en_supply, micb_num, enable);
 
 	if (enable)
 		rc = wcd938x_codec_force_enable_micbias_v2(component,
@@ -439,6 +408,29 @@ static struct snd_soc_dai_driver swr_dmic_dai[] = {
 	},
 };
 
+static int swr_dmic_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data)
+{
+	u16 event = (val & 0xffff);
+	int ret = 0;
+	struct swr_dmic_priv *swr_dmic = container_of(block,
+					struct swr_dmic_priv,
+					nblock);
+	switch (event) {
+	case WCD938X_EVT_SSR_DOWN:
+		ret = swr_dmic_down(swr_dmic->swr_slave);
+		break;
+	case WCD938X_EVT_SSR_UP:
+		ret = swr_dmic_up(swr_dmic->swr_slave);
+		if (!ret)
+			ret = swr_dmic_reset(swr_dmic->swr_slave);
+		break;
+	}
+
+	return ret;
+}
+
 static int swr_dmic_probe(struct swr_device *pdev)
 {
 	int ret = 0;
@@ -450,6 +442,7 @@ static int swr_dmic_probe(struct swr_device *pdev)
 	const char *swr_dmic_name_prefix_of = NULL;
 	const char *swr_dmic_codec_name_of = NULL;
 	struct snd_soc_component *component = NULL;
+	int num_retry = NUM_ATTEMPTS;
 
 	swr_dmic = devm_kzalloc(&pdev->dev, sizeof(struct swr_dmic_priv),
 			    GFP_KERNEL);
@@ -512,13 +505,18 @@ static int swr_dmic_probe(struct swr_device *pdev)
 	 * as per HW requirement.
 	 */
 	usleep_range(5000, 5010);
-	ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum);
+	do {
+		/* Add delay for soundwire enumeration */
+		usleep_range(100, 110);
+		ret = swr_get_logical_dev_num(pdev, pdev->addr, &swr_devnum);
+	} while (ret && --num_retry);
+
 	if (ret) {
-		dev_dbg(&pdev->dev,
-			"%s get devnum %d for dev addr %lx failed\n",
+		dev_info(&pdev->dev,
+			"%s get devnum %d for dev addr %llx failed\n",
 			__func__, swr_devnum, pdev->addr);
 		ret = -EPROBE_DEFER;
-		goto err;
+		goto dev_err;
 	}
 	pdev->dev_num = swr_devnum;
 
@@ -588,10 +586,9 @@ static int swr_dmic_probe(struct swr_device *pdev)
 			strlen(swr_dmic_name_prefix_of) + 1);
 	component->name_prefix = prefix_name;
 
-	if (swr_dmic->is_en_supply == 1) {
-		enable_wcd_codec_supply(swr_dmic, false);
-		--swr_dmic->is_en_supply;
-	}
+	swr_dmic->nblock.notifier_call = swr_dmic_event_notify;
+	wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component,
+					&swr_dmic->nblock, true);
 
 	return 0;
 
@@ -616,7 +613,10 @@ static int swr_dmic_remove(struct swr_device *pdev)
 		dev_err(&pdev->dev, "%s: swr_dmic is NULL\n", __func__);
 		return -EINVAL;
 	}
-
+	if (swr_dmic->is_en_supply == 1) {
+		enable_wcd_codec_supply(swr_dmic, false);
+		--swr_dmic->is_en_supply;
+	}
 	snd_soc_unregister_component(&pdev->dev);
 	swr_set_dev_data(pdev, NULL);
 	return 0;
@@ -670,7 +670,7 @@ done:
 static int swr_dmic_reset(struct swr_device *pdev)
 {
 	struct swr_dmic_priv *swr_dmic;
-	u8 retry = 5;
+	u8 retry = NUM_ATTEMPTS;
 	u8 devnum = 0;
 
 	swr_dmic = swr_get_dev_data(pdev);
@@ -735,7 +735,6 @@ static struct swr_driver swr_dmic_driver = {
 	.probe = swr_dmic_probe,
 	.remove = swr_dmic_remove,
 	.id_table = swr_dmic_id,
-	.device_down = swr_dmic_down,
 };
 
 static int __init swr_dmic_init(void)

+ 6 - 1
asoc/codecs/swr-haptics.c

@@ -314,6 +314,7 @@ static int swr_haptics_probe(struct swr_device *sdev)
 	struct swr_haptics_dev *swr_hap;
 	int rc;
 	u8 devnum;
+	int retry = 5;
 
 	swr_hap = devm_kzalloc(&sdev->dev,
 			sizeof(struct swr_haptics_dev), GFP_KERNEL);
@@ -346,8 +347,12 @@ static int swr_haptics_probe(struct swr_device *sdev)
 				__func__, rc);
 		goto clean;
 	}
+	do {
+		/* Add delay for soundwire enumeration */
+		usleep_range(500, 510);
+		rc = swr_get_logical_dev_num(sdev, sdev->addr, &devnum);
+	} while (rc && --retry);
 
-	rc = swr_get_logical_dev_num(sdev, sdev->addr, &devnum);
 	if (rc) {
 		dev_err(swr_hap->dev, "%s: failed to get devnum for swr-haptics, rc=%d\n",
 				__func__, rc);

+ 19 - 0
asoc/codecs/wcd-mbhc-v2.c

@@ -1621,6 +1621,8 @@ static int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc)
 static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb,
 					   unsigned long mode, void *ptr)
 {
+	unsigned int l_det_en = 0;
+	unsigned int detection_type = 0;
 	struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, fsa_nb);
 
 	if (!mbhc)
@@ -1633,6 +1635,23 @@ static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb,
 			mbhc->mbhc_cb->clk_setup(mbhc->component, true);
 		/* insertion detected, enable L_DET_EN */
 		WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
+	} else {
+		WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type);
+		WCD_MBHC_REG_READ(WCD_MBHC_L_DET_EN, l_det_en);
+		/* If both l_det_en and detection type are set, it means device was
+		 * unplugged during SSR and detection interrupt was not handled.
+		 * So trigger device disconnect */
+		if (detection_type && l_det_en) {
+			/* Set the detection type appropriately */
+			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE,
+						 !detection_type);
+			/* Set current plug type to the state before SSR */
+			mbhc->current_plug = mbhc->plug_before_ssr;
+
+			wcd_mbhc_swch_irq_handler(mbhc);
+			mbhc->mbhc_cb->lock_sleep(mbhc, false);
+			mbhc->plug_before_ssr = MBHC_PLUG_TYPE_NONE;
+		}
 	}
 	return 0;
 }

+ 2 - 0
asoc/codecs/wcd937x/internal.h

@@ -17,6 +17,7 @@
 #define  WCD_VOUT_CTL_TO_MICB(v)  (1000 + v * 50)
 #define MAX_PORT 8
 #define MAX_CH_PER_PORT 8
+#define MAX_TX_PWR_CH 2
 
 #define WCD937X_MAX_SLAVE_PORT_TYPES 10
 extern struct regmap_config wcd937x_regmap_config;
@@ -91,6 +92,7 @@ struct wcd937x_priv {
 	struct mutex ana_tx_clk_lock;
 	u8 tx_master_ch_map[WCD937X_MAX_SLAVE_CH_TYPES];
 	bool usbc_hs_status;
+	u32 tx_ch_pwr[MAX_TX_PWR_CH];
 };
 
 struct wcd937x_micbias_setting {

+ 56 - 1
asoc/codecs/wcd937x/wcd937x.c

@@ -1777,6 +1777,48 @@ static int wcd937x_rx_hph_mode_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int wcd937x_tx_ch_pwr_level_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
+
+	if (strnstr(kcontrol->id.name, "CH1", sizeof(kcontrol->id.name)))
+		ucontrol->value.integer.value[0] = wcd937x->tx_ch_pwr[0];
+	else if (strnstr(kcontrol->id.name, "CH3", sizeof(kcontrol->id.name)))
+		ucontrol->value.integer.value[0] = wcd937x->tx_ch_pwr[1];
+
+	return 0;
+}
+
+static int wcd937x_tx_ch_pwr_level_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+				snd_soc_kcontrol_component(kcontrol);
+	struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
+	u32 pwr_level = ucontrol->value.enumerated.item[0];
+
+	dev_dbg(component->dev, "%s: tx ch pwr_level: %d\n",
+		__func__, pwr_level);
+
+	if (strnstr(kcontrol->id.name, "CH1",
+				sizeof(kcontrol->id.name))) {
+		snd_soc_component_update_bits(component,
+				WCD937X_ANA_TX_CH1, 0x60,
+				pwr_level << 0x5);
+		wcd937x->tx_ch_pwr[0] = pwr_level;
+	} else if (strnstr(kcontrol->id.name, "CH3",
+			sizeof(kcontrol->id.name))) {
+		snd_soc_component_update_bits(component,
+				WCD937X_ANA_TX_CH3, 0x60,
+				pwr_level << 0x5);
+		wcd937x->tx_ch_pwr[1] = pwr_level;
+	}
+	return 0;
+}
+
 static int wcd937x_ear_pa_gain_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -2001,6 +2043,10 @@ static int wcd937x_tx_master_ch_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static const char * const wcd937x_tx_ch_pwr_level_text[] = {
+	"L0", "L1", "L2", "L3",
+};
+
 static const char * const wcd937x_ear_pa_gain_text[] = {
 	"G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB", "G_0_DB",
 	"G_M1P5_DB", "G_M3_DB", "G_M4P5_DB",
@@ -2016,6 +2062,9 @@ static const struct soc_enum rx_hph_mode_mux_enum =
 static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_ear_pa_gain_enum,
 				wcd937x_ear_pa_gain_text);
 
+static SOC_ENUM_SINGLE_EXT_DECL(wcd937x_tx_ch_pwr_level_enum,
+				wcd937x_tx_ch_pwr_level_text);
+
 static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
 	SOC_ENUM_EXT("EAR PA GAIN", wcd937x_ear_pa_gain_enum,
 		wcd937x_ear_pa_gain_get, wcd937x_ear_pa_gain_put),
@@ -2054,6 +2103,10 @@ static const struct snd_kcontrol_new wcd937x_snd_controls[] = {
 			wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put),
 	SOC_ENUM_EXT("DMIC5 ChMap", tx_master_ch_enum,
 			wcd937x_tx_master_ch_get, wcd937x_tx_master_ch_put),
+	SOC_ENUM_EXT("TX CH1 PWR", wcd937x_tx_ch_pwr_level_enum,
+		wcd937x_tx_ch_pwr_level_get, wcd937x_tx_ch_pwr_level_put),
+	SOC_ENUM_EXT("TX CH3 PWR", wcd937x_tx_ch_pwr_level_enum,
+		wcd937x_tx_ch_pwr_level_get, wcd937x_tx_ch_pwr_level_put),
 };
 
 static const struct snd_kcontrol_new adc1_switch[] = {
@@ -3114,7 +3167,9 @@ static int wcd937x_bind(struct device *dev)
 		dev_err(dev, "%s: bad micbias pdata\n", __func__);
 		goto err_irq;
 	}
-
+	/* default L1 power setting */
+	wcd937x->tx_ch_pwr[0] = 1;
+	wcd937x->tx_ch_pwr[1] = 1;
 	mutex_init(&wcd937x->micb_lock);
 	mutex_init(&wcd937x->ana_tx_clk_lock);
 	/* Request for watchdog interrupt */

+ 3 - 0
asoc/codecs/wcd938x/internal.h

@@ -106,6 +106,9 @@ struct wcd938x_priv {
 	bool dev_up;
 	u8 tx_master_ch_map[WCD938X_MAX_SLAVE_CH_TYPES];
 	bool usbc_hs_status;
+	/* wcd to swr dmic notification */
+	bool notify_swr_dmic;
+	struct blocking_notifier_head notifier;
 };
 
 struct wcd938x_micbias_setting {

+ 11 - 2
asoc/codecs/wcd938x/wcd938x-slave.c

@@ -24,6 +24,8 @@
 #define SWR_SLV_MAX_DEVICES     2
 #endif /* CONFIG_DEBUG_FS */
 
+#define SWR_MAX_RETRY    5
+
 struct wcd938x_slave_priv {
 	struct swr_device *swr_slave;
 #ifdef CONFIG_DEBUG_FS
@@ -278,17 +280,24 @@ static int wcd938x_slave_bind(struct device *dev,
 	int ret = 0;
 	uint8_t devnum = 0;
 	struct swr_device *pdev = to_swr_device(dev);
+	int retry = SWR_MAX_RETRY;
 
 	if (!pdev) {
 		pr_err("%s: invalid swr device handle\n", __func__);
 		return -EINVAL;
 	}
 
-	ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
+	do {
+		/* Add delay for soundwire enumeration */
+		usleep_range(100, 110);
+		ret = swr_get_logical_dev_num(pdev, pdev->addr, &devnum);
+	} while (ret && --retry);
+
 	if (ret) {
 		dev_dbg(&pdev->dev,
-			"%s get devnum %d for dev addr %lx failed\n",
+			"%s get devnum %d for dev addr %llx failed\n",
 			__func__, devnum, pdev->addr);
+		ret = -EPROBE_DEFER;
 		return ret;
 	}
 	pdev->dev_num = devnum;

+ 151 - 71
asoc/codecs/wcd938x/wcd938x.c

@@ -73,6 +73,10 @@ enum {
 	HPH_PA_DELAY,
 	AMIC2_BCS_ENABLE,
 	WCD_SUPPLIES_LPM_MODE,
+	WCD_ADC1_MODE,
+	WCD_ADC2_MODE,
+	WCD_ADC3_MODE,
+	WCD_ADC4_MODE,
 };
 
 enum {
@@ -1541,13 +1545,17 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
-			if (test_bit(WCD_ADC1, &wcd938x->status_mask))
+			if (test_bit(WCD_ADC1, &wcd938x->status_mask) ||
+				test_bit(WCD_ADC1_MODE, &wcd938x->status_mask))
 				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC1]];
-			if (test_bit(WCD_ADC2, &wcd938x->status_mask))
+			if (test_bit(WCD_ADC2, &wcd938x->status_mask) ||
+				test_bit(WCD_ADC2_MODE, &wcd938x->status_mask))
 				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC2]];
-			if (test_bit(WCD_ADC3, &wcd938x->status_mask))
+			if (test_bit(WCD_ADC3, &wcd938x->status_mask) ||
+				test_bit(WCD_ADC3_MODE, &wcd938x->status_mask))
 				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC3]];
-			if (test_bit(WCD_ADC4, &wcd938x->status_mask))
+			if (test_bit(WCD_ADC4, &wcd938x->status_mask) ||
+				test_bit(WCD_ADC4_MODE, &wcd938x->status_mask))
 				mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];
 
 			if (mode != 0) {
@@ -1594,6 +1602,14 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
 
 		if (strnstr(w->name, "ADC", sizeof("ADC")))
 			wcd938x_set_swr_clk_rate(component, rate, bank);
+		if (strnstr(w->name, "ADC1", sizeof("ADC1")))
+			clear_bit(WCD_ADC1_MODE, &wcd938x->status_mask);
+		else if (strnstr(w->name, "ADC2", sizeof("ADC2")))
+			clear_bit(WCD_ADC2_MODE, &wcd938x->status_mask);
+		else if (strnstr(w->name, "ADC3", sizeof("ADC3")))
+			clear_bit(WCD_ADC3_MODE, &wcd938x->status_mask);
+		else if (strnstr(w->name, "ADC4", sizeof("ADC4")))
+			clear_bit(WCD_ADC4_MODE, &wcd938x->status_mask);
 		break;
 	};
 
@@ -1634,57 +1650,6 @@ static int wcd938x_get_adc_mode(int val)
 	return ret;
 }
 
-static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
-				    struct snd_kcontrol *kcontrol,
-				    int event){
-	struct snd_soc_component *component =
-					snd_soc_dapm_to_component(w->dapm);
-	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
-	int clk_rate = 0, ret = 0;
-
-	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
-		w->name, event);
-
-	switch (event) {
-	case SND_SOC_DAPM_PRE_PMU:
-		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
-		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
-		set_bit(w->shift, &wcd938x->status_mask);
-		clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]);
-		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
-				 wcd938x->tx_swr_dev->dev_num,
-				 true);
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
-				wcd938x->tx_swr_dev->dev_num,
-				false);
-		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00);
-		clear_bit(w->shift, &wcd938x->status_mask);
-		break;
-	};
-
-	return ret;
-}
-
-void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
-					    bool bcs_disable)
-{
-	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
-
-	if (wcd938x->update_wcd_event) {
-		if (bcs_disable)
-			wcd938x->update_wcd_event(wcd938x->handle,
-						WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
-		else
-			wcd938x->update_wcd_event(wcd938x->handle,
-						WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
-	}
-}
-
 int wcd938x_tx_channel_config(struct snd_soc_component *component,
 			      int channel, int mode)
 {
@@ -1725,14 +1690,14 @@ int wcd938x_tx_channel_config(struct snd_soc_component *component,
 	return ret;
 }
 
-static int wcd938x_enable_req(struct snd_soc_dapm_widget *w,
-			      struct snd_kcontrol *kcontrol, int event)
-{
+static int wcd938x_codec_enable_adc(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 mode;
-	int ret = 0;
 	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+	int clk_rate = 0, ret = 0;
+	int mode;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
@@ -1740,9 +1705,14 @@ static int wcd938x_enable_req(struct snd_soc_dapm_widget *w,
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02);
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
 		snd_soc_component_update_bits(component,
-				WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00);
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
+		set_bit(w->shift, &wcd938x->status_mask);
+		clk_rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift]);
+		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
+				 wcd938x->tx_swr_dev->dev_num,
+				 true);
 		ret = wcd938x_tx_channel_config(component, w->shift, 1);
 		mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);
 		if (mode < 0) {
@@ -1818,6 +1788,51 @@ static int wcd938x_enable_req(struct snd_soc_dapm_widget *w,
 		default:
 			break;
 		}
+		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
+				wcd938x->tx_swr_dev->dev_num,
+				false);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x00);
+		clear_bit(w->shift, &wcd938x->status_mask);
+		break;
+	};
+
+	return ret;
+}
+
+void wcd938x_disable_bcs_before_slow_insert(struct snd_soc_component *component,
+					    bool bcs_disable)
+{
+	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+	if (wcd938x->update_wcd_event) {
+		if (bcs_disable)
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 0);
+		else
+			wcd938x->update_wcd_event(wcd938x->handle,
+						WCD_BOLERO_EVT_BCS_CLK_OFF, 1);
+	}
+}
+
+static int wcd938x_enable_req(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 ret = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_REQ_CTL, 0x02, 0x02);
+		snd_soc_component_update_bits(component,
+				WCD938X_DIGITAL_CDC_REQ_CTL, 0x01, 0x00);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
 		snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
 		break;
@@ -1992,15 +2007,16 @@ static int wcd938x_get_logical_addr(struct swr_device *swr_dev)
 	int num_retry = NUM_ATTEMPTS;
 
 	do {
+		/* retry after 1ms */
+		usleep_range(1000, 1010);
 		ret = swr_get_logical_dev_num(swr_dev, swr_dev->addr, &devnum);
-		if (ret) {
-			dev_err(&swr_dev->dev,
-				"%s get devnum %d for dev addr %lx failed\n",
-				__func__, devnum, swr_dev->addr);
-			/* retry after 1ms */
-			usleep_range(1000, 1010);
-		}
 	} while (ret && --num_retry);
+
+	if (ret)
+		dev_err(&swr_dev->dev,
+			"%s get devnum %d for dev addr %llx failed\n",
+			__func__, devnum, swr_dev->addr);
+
 	swr_dev->dev_num = devnum;
 	return 0;
 }
@@ -2016,6 +2032,27 @@ static bool get_usbc_hs_status(struct snd_soc_component *component,
 	return false;
 }
 
+int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *component,
+					struct notifier_block *nblock,
+					bool enable)
+{
+	struct wcd938x_priv *wcd938x_priv;
+	if(NULL == component) {
+		pr_err("%s: wcd938x component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wcd938x_priv = snd_soc_component_get_drvdata(component);
+	wcd938x_priv->notify_swr_dmic = enable;
+	if (enable)
+		return blocking_notifier_chain_register(&wcd938x_priv->notifier,
+							nblock);
+	else
+		return blocking_notifier_chain_unregister(
+				&wcd938x_priv->notifier, nblock);
+}
+EXPORT_SYMBOL(wcd938x_swr_dmic_register_notifier);
+
 static int wcd938x_event_notify(struct notifier_block *block,
 				unsigned long val,
 				void *data)
@@ -2031,21 +2068,25 @@ static int wcd938x_event_notify(struct notifier_block *block,
 		if (test_bit(WCD_ADC1, &wcd938x->status_mask)) {
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_TX_CH2, 0x40, 0x00);
+			set_bit(WCD_ADC1_MODE, &wcd938x->status_mask);
 			clear_bit(WCD_ADC1, &wcd938x->status_mask);
 		}
 		if (test_bit(WCD_ADC2, &wcd938x->status_mask)) {
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_TX_CH2, 0x20, 0x00);
+			set_bit(WCD_ADC2_MODE, &wcd938x->status_mask);
 			clear_bit(WCD_ADC2, &wcd938x->status_mask);
 		}
 		if (test_bit(WCD_ADC3, &wcd938x->status_mask)) {
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_TX_CH4, 0x40, 0x00);
+			set_bit(WCD_ADC3_MODE, &wcd938x->status_mask);
 			clear_bit(WCD_ADC3, &wcd938x->status_mask);
 		}
 		if (test_bit(WCD_ADC4, &wcd938x->status_mask)) {
 			snd_soc_component_update_bits(component,
 					WCD938X_ANA_TX_CH4, 0x20, 0x00);
+			set_bit(WCD_ADC4_MODE, &wcd938x->status_mask);
 			clear_bit(WCD_ADC4, &wcd938x->status_mask);
 		}
 		break;
@@ -2059,7 +2100,13 @@ static int wcd938x_event_notify(struct notifier_block *block,
 		break;
 	case BOLERO_WCD_EVT_SSR_DOWN:
 		wcd938x->dev_up = false;
+		if(wcd938x->notify_swr_dmic)
+			blocking_notifier_call_chain(&wcd938x->notifier,
+						     WCD938X_EVT_SSR_DOWN,
+						     NULL);
 		wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true;
+		wcd938x->mbhc->wcd_mbhc.plug_before_ssr =
+					wcd938x->mbhc->wcd_mbhc.current_plug;
 		mbhc = &wcd938x->mbhc->wcd_mbhc;
 		wcd938x->usbc_hs_status = get_usbc_hs_status(component,
 						mbhc->mbhc_cfg);
@@ -2090,6 +2137,10 @@ static int wcd938x_event_notify(struct notifier_block *block,
 		}
 		wcd938x->mbhc->wcd_mbhc.deinit_in_progress = false;
 		wcd938x->dev_up = true;
+		if(wcd938x->notify_swr_dmic)
+			blocking_notifier_call_chain(&wcd938x->notifier,
+						     WCD938X_EVT_SSR_UP,
+						     NULL);
 		break;
 	case BOLERO_WCD_EVT_CLK_NOTIFY:
 		snd_soc_component_update_bits(component,
@@ -2273,6 +2324,9 @@ static int wcd938x_enable_micbias(struct wcd938x_priv *wcd938x,
 		return -EINVAL;
 	};
 
+	pr_debug("%s: req: %d micb_num: %d  micb_ref: %d pullup_ref: %d\n",
+		__func__, req, micb_num, wcd938x->micb_ref[micb_index],
+		wcd938x->pullup_ref[micb_index]);
 	mutex_lock(&wcd938x->micb_lock);
 
 	switch (req) {
@@ -2337,6 +2391,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
 					int event, int micb_num)
 {
 	struct wcd938x_priv *wcd938x_priv = NULL;
+	int ret = 0;
+	int micb_index = micb_num - 1;
 
 	if(NULL == component) {
 		pr_err("%s: wcd938x component is NULL\n", __func__);
@@ -2353,6 +2409,15 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
 
 	wcd938x_priv = snd_soc_component_get_drvdata(component);
 
+	if (!wcd938x_priv->dev_up) {
+		if ((wcd938x_priv->pullup_ref[micb_index] > 0) &&
+			(event == SND_SOC_DAPM_POST_PMD)) {
+			wcd938x_priv->pullup_ref[micb_index]--;
+			ret = -ENODEV;
+			goto done;
+		}
+	}
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		wcd938x_wakeup(wcd938x_priv, true);
@@ -2366,7 +2431,8 @@ int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *component,
 		break;
 	}
 
-	return 0;
+done:
+	return ret;
 }
 EXPORT_SYMBOL(wcd938x_codec_force_enable_micbias_v2);
 
@@ -3051,9 +3117,17 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("AMIC5"),
 	SND_SOC_DAPM_INPUT("AMIC6"),
 	SND_SOC_DAPM_INPUT("AMIC7"),
+
 	SND_SOC_DAPM_INPUT("IN1_HPHL"),
 	SND_SOC_DAPM_INPUT("IN2_HPHR"),
 	SND_SOC_DAPM_INPUT("IN3_AUX"),
+	/*
+	 * These dummy widgets are null connected to WCD938x dapm input and
+	 * output widgets which are not actual path endpoints. This ensures
+	 * dapm doesnt set these dapm input and output widgets as endpoints.
+	 */
+	SND_SOC_DAPM_INPUT("WCD_TX_DUMMY"),
+	SND_SOC_DAPM_OUTPUT("WCD_RX_DUMMY"),
 
 	/*tx widgets*/
 	SND_SOC_DAPM_ADC_E("ADC1", NULL, SND_SOC_NOPM, 0, 0,
@@ -3290,6 +3364,7 @@ static const struct snd_soc_dapm_widget wcd938x_dapm_widgets[] = {
 
 static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
 
+	{"WCD_TX_DUMMY", NULL, "WCD_TX_OUTPUT"},
 	{"WCD_TX_OUTPUT", NULL, "ADC1_MIXER"},
 	{"ADC1_MIXER", "Switch", "ADC1 REQ"},
 	{"ADC1 REQ", NULL, "ADC1"},
@@ -3344,6 +3419,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
 	{"WCD_TX_OUTPUT", NULL, "DMIC8_MIXER"},
 	{"DMIC8_MIXER", "Switch", "DMIC8"},
 
+	{"IN1_HPHL", NULL, "WCD_RX_DUMMY"},
 	{"IN1_HPHL", NULL, "VDD_BUCK"},
 	{"IN1_HPHL", NULL, "CLS_H_PORT"},
 	{"RX1", NULL, "IN1_HPHL"},
@@ -3352,6 +3428,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
 	{"HPHL PGA", NULL, "HPHL_RDAC"},
 	{"HPHL", NULL, "HPHL PGA"},
 
+	{"IN2_HPHR", NULL, "WCD_RX_DUMMY"},
 	{"IN2_HPHR", NULL, "VDD_BUCK"},
 	{"IN2_HPHR", NULL, "CLS_H_PORT"},
 	{"RX2", NULL, "IN2_HPHR"},
@@ -3360,6 +3437,7 @@ static const struct snd_soc_dapm_route wcd938x_audio_map[] = {
 	{"HPHR PGA", NULL, "HPHR_RDAC"},
 	{"HPHR", NULL, "HPHR PGA"},
 
+	{"IN3_AUX", NULL, "WCD_RX_DUMMY"},
 	{"IN3_AUX", NULL, "VDD_BUCK"},
 	{"IN3_AUX", NULL, "CLS_H_PORT"},
 	{"RX3", NULL, "IN3_AUX"},
@@ -3652,6 +3730,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
 	snd_soc_dapm_ignore_suspend(dapm, "AUX");
 	snd_soc_dapm_ignore_suspend(dapm, "HPHL");
 	snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+	snd_soc_dapm_ignore_suspend(dapm, "WCD_TX_DUMMY");
+	snd_soc_dapm_ignore_suspend(dapm, "WCD_RX_DUMMY");
 	snd_soc_dapm_sync(dapm);
 
 	wcd_cls_h_init(&wcd938x->clsh_info);
@@ -3691,7 +3771,6 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
 			return ret;
 		}
 	}
-	wcd938x->dev_up = true;
 	return ret;
 
 err_hwdep:
@@ -4051,6 +4130,7 @@ static int wcd938x_bind(struct device *dev)
 				__func__);
 		goto err_irq;
 	}
+	wcd938x->dev_up = true;
 
 	return ret;
 err_irq:

+ 9 - 0
asoc/codecs/wcd938x/wcd938x.h

@@ -17,6 +17,12 @@ enum {
 	WCD9385 = 5,
 };
 
+/* from WCD to SWR DMIC events */
+enum {
+	WCD938X_EVT_SSR_DOWN,
+	WCD938X_EVT_SSR_UP,
+};
+
 struct swr_slave_ch_map {
 	u8 ch_type;
 	u8 index;
@@ -62,6 +68,9 @@ int wcd938x_info_create_codec_entry(struct snd_info_entry *codec_root,
 int wcd938x_get_codec_variant(struct snd_soc_component *component);
 int wcd938x_codec_force_enable_micbias_v2(struct snd_soc_component *wcd938x,
 					int event, int micb_num);
+int wcd938x_swr_dmic_register_notifier(struct snd_soc_component *wcd938x,
+                                        struct notifier_block *nblock,
+                                        bool enable);
 
 static inline int wcd938x_slave_get_master_ch_val(int ch)
 {

+ 3 - 2
asoc/codecs/wsa881x.c

@@ -1083,6 +1083,9 @@ static int wsa881x_spkr_pa_event(struct snd_soc_dapm_widget *w,
 					      0x80, 0x00);
 		if (wsa881x->visense_enable) {
 			wsa881x_visense_adc_ctrl(component, DISABLE);
+			snd_soc_component_update_bits(component,
+						WSA881X_ADC_EN_SEL_IBAIS,
+						0x07, 0x00);
 			wsa881x_visense_txfe_ctrl(component, DISABLE,
 						0x00, 0x01, 0x01);
 		}
@@ -1614,8 +1617,6 @@ static int wsa881x_swr_down(struct swr_device *pdev)
 	else
 		wsa881x->state = WSA881X_DEV_DOWN;
 
-	if (delayed_work_pending(&wsa881x->ocp_ctl_work))
-		cancel_delayed_work_sync(&wsa881x->ocp_ctl_work);
 	return ret;
 }
 

+ 6 - 1
asoc/codecs/wsa883x/wsa883x.c

@@ -620,9 +620,14 @@ static int wsa_get_temp(struct snd_kcontrol *kcontrol,
 {
 	struct snd_soc_component *component =
 			snd_soc_kcontrol_component(kcontrol);
+	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
 	int temp = 0;
 
-	wsa883x_get_temperature(component, &temp);
+	if (test_bit(SPKR_STATUS, &wsa883x->status_mask))
+		temp = wsa883x->curr_temp;
+	else
+		wsa883x_get_temperature(component, &temp);
+
 	ucontrol->value.integer.value[0] = temp;
 
 	return 0;

+ 18 - 21
asoc/kona.c

@@ -5444,6 +5444,7 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_component *aux_comp;
 	struct platform_device *pdev = NULL;
 	int i = 0;
+	bool is_wcd937x_used = false;
 	char *data = NULL;
 	struct msm_asoc_mach_data *pdata =
 				snd_soc_card_get_drvdata(rtd->card);
@@ -5545,33 +5546,29 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 			if (data != NULL) {
 				if (!strncmp(data, "wcd937x",
 						sizeof("wcd937x"))) {
-					bolero_set_port_map(component,
-						ARRAY_SIZE(sm_port_map_wcd937x),
-						sm_port_map_wcd937x);
-					break;
-				} else if (!strncmp( data, "wcd938x",
-							sizeof("wcd938x"))) {
-					if (pdata->lito_v2_enabled) {
-						/*
-						 * Enable tx data line3 for
-						 * saipan version v2 and
-						 * write corresponding
-						 * lpi register.
-						 */
-						bolero_set_port_map(component,
-							ARRAY_SIZE(sm_port_map_v2),
-							sm_port_map_v2);
-					} else {
-						bolero_set_port_map(component,
-							ARRAY_SIZE(sm_port_map),
-							sm_port_map);
-					}
+					is_wcd937x_used = true;
 					break;
 				}
 			}
 		}
 	}
 
+	if (is_wcd937x_used) {
+		bolero_set_port_map(component,
+				    ARRAY_SIZE(sm_port_map_wcd937x),
+				    sm_port_map_wcd937x);
+	} else if (pdata->lito_v2_enabled) {
+		/*
+		 * Enable tx data line3 for saipan version v2 and
+		 * write corresponding lpi register.
+		 */
+		bolero_set_port_map(component, ARRAY_SIZE(sm_port_map_v2),
+				    sm_port_map_v2);
+	} else {
+		bolero_set_port_map(component, ARRAY_SIZE(sm_port_map),
+				    sm_port_map);
+	}
+
 	card = rtd->card->snd_card;
 	if (!pdata->codec_root) {
 		entry = msm_snd_info_create_subdir(card->module, "codecs",

+ 103 - 30
asoc/lahaina.c

@@ -4569,6 +4569,7 @@ static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1:
 	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2:
 	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3:
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5:
 	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6:
 		idx = msm_cdc_dma_get_idx_from_beid(dai_link->id);
 		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
@@ -5999,6 +6000,19 @@ static struct snd_soc_dai_link msm_bolero_fe_dai_links[] = {
 	},
 };
 
+static struct snd_soc_dai_link msm_bolero_fe_stub_dai_links[] = {
+	{/* hw:x,33 */
+		.name = LPASS_BE_WSA_CDC_DMA_TX_0,
+		.stream_name = "WSA CDC DMA0 Capture",
+		.id = MSM_BACKEND_DAI_WSA_CDC_DMA_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(wsa_cdcdma0_capture_stub),
+	},
+};
+
 static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
 	{/* hw:x,34 */
 		.name = MSM_DAILINK_NAME(ASM Loopback),
@@ -6847,6 +6861,7 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
 		.ignore_suspend = 1,
 		.ops = &msm_cdc_dma_be_ops,
 		SND_SOC_DAILINK_REG(rx_dma_rx1),
+		.init = &msm_int_audrx_init,
 	},
 	{
 		.name = LPASS_BE_RX_CDC_DMA_RX_2,
@@ -6878,6 +6893,21 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
 		.ops = &msm_cdc_dma_be_ops,
 		SND_SOC_DAILINK_REG(rx_dma_rx3),
 	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_5,
+		.stream_name = "RX CDC DMA5 Playback",
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.dynamic_be = 1,
+#endif /* CONFIG_AUDIO_QGKI */
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_RX_CDC_DMA_RX_5,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(rx_dma_rx5),
+	},
 	{
 		.name = LPASS_BE_RX_CDC_DMA_RX_6,
 		.stream_name = "RX CDC DMA6 Playback",
@@ -7225,6 +7255,45 @@ static const struct of_device_id lahaina_asoc_machine_of_match[]  = {
 	{},
 };
 
+static int msm_snd_card_late_probe(struct snd_soc_card *card)
+{
+	struct snd_soc_component *component = NULL;
+	const char *be_dl_name = LPASS_BE_RX_CDC_DMA_RX_0;
+	struct snd_soc_pcm_runtime *rtd;
+	int ret = 0;
+	void *mbhc_calibration;
+
+	rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+	if (!rtd) {
+		dev_err(card->dev,
+			"%s: snd_soc_get_pcm_runtime for %s failed!\n",
+			__func__, be_dl_name);
+		return -EINVAL;
+	}
+
+	component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME);
+	if (!component) {
+		pr_err("%s component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	mbhc_calibration = def_wcd_mbhc_cal();
+	if (!mbhc_calibration)
+		return -ENOMEM;
+	wcd_mbhc_cfg.calibration = mbhc_calibration;
+	ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
+	if (ret) {
+		dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
+			__func__, ret);
+		goto err_hs_detect;
+	}
+	return 0;
+
+err_hs_detect:
+	kfree(mbhc_calibration);
+	return ret;
+}
+
 static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
 {
 	struct snd_soc_card *card = NULL;
@@ -7238,6 +7307,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
 	u32 val = 0;
 	u32 wcn_btfm_intf = 0;
 	const struct of_device_id *match;
+	u32 wsa_max_devs = 0;
 
 	match = of_match_node(lahaina_asoc_machine_of_match, dev->of_node);
 	if (!match) {
@@ -7254,12 +7324,27 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
 		       sizeof(msm_common_dai_links));
 		total_links += ARRAY_SIZE(msm_common_dai_links);
 
-		memcpy(msm_lahaina_dai_links + total_links,
-		       msm_bolero_fe_dai_links,
-		       sizeof(msm_bolero_fe_dai_links));
-		total_links +=
-			ARRAY_SIZE(msm_bolero_fe_dai_links);
-
+		rc = of_property_read_u32(dev->of_node,
+				"qcom,wsa-max-devs", &wsa_max_devs);
+		if (rc) {
+			dev_info(dev,
+				"%s: wsa-max-devs property missing in DT %s, ret = %d\n",
+				 __func__, dev->of_node->full_name, rc);
+			wsa_max_devs = 0;
+		}
+		if (!wsa_max_devs) {
+			memcpy(msm_lahaina_dai_links + total_links,
+				msm_bolero_fe_stub_dai_links,
+				sizeof(msm_bolero_fe_stub_dai_links));
+			total_links +=
+				ARRAY_SIZE(msm_bolero_fe_stub_dai_links);
+		} else {
+			memcpy(msm_lahaina_dai_links + total_links,
+				msm_bolero_fe_dai_links,
+				sizeof(msm_bolero_fe_dai_links));
+			total_links +=
+				ARRAY_SIZE(msm_bolero_fe_dai_links);
+		}
 		memcpy(msm_lahaina_dai_links + total_links,
 		       msm_common_misc_fe_dai_links,
 		       sizeof(msm_common_misc_fe_dai_links));
@@ -7276,12 +7361,13 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
 		total_links +=
 			ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links);
 
-		memcpy(msm_lahaina_dai_links + total_links,
-		       msm_wsa_cdc_dma_be_dai_links,
-		       sizeof(msm_wsa_cdc_dma_be_dai_links));
-		total_links +=
-			ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links);
-
+		if (wsa_max_devs) {
+			memcpy(msm_lahaina_dai_links + total_links,
+				msm_wsa_cdc_dma_be_dai_links,
+				sizeof(msm_wsa_cdc_dma_be_dai_links));
+			total_links +=
+				ARRAY_SIZE(msm_wsa_cdc_dma_be_dai_links);
+		}
 		memcpy(msm_lahaina_dai_links + total_links,
 		       msm_va_cdc_dma_be_dai_links,
 		       sizeof(msm_va_cdc_dma_be_dai_links));
@@ -7386,6 +7472,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
 	if (card) {
 		card->dai_link = dailink;
 		card->num_links = total_links;
+		card->late_probe = msm_snd_card_late_probe;
 	}
 
 	return card;
@@ -7410,6 +7497,9 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 				snd_soc_card_get_drvdata(rtd->card);
 	int ret = 0;
 
+	if (codec_reg_done) {
+		return 0;
+	}
         if (pdata->wsa_max_devs > 0) {
 		component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1");
 		if (!component) {
@@ -7532,7 +7622,6 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_soc_dapm_context *dapm = NULL;
 	int ret = 0;
 	int codec_variant = -1;
-	void *mbhc_calibration;
 	struct snd_info_entry *entry;
 	struct snd_card *card = NULL;
 	struct msm_asoc_mach_data *pdata;
@@ -7562,8 +7651,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 		if (!entry) {
 			dev_dbg(component->dev, "%s: Cannot create codecs module entry\n",
 				 __func__);
-			ret = 0;
-			goto mbhc_cfg_cal;
+			 return 0;
 		}
 		pdata->codec_root = entry;
 	}
@@ -7586,22 +7674,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 		return ret;
 	}
 
-mbhc_cfg_cal:
-	mbhc_calibration = def_wcd_mbhc_cal();
-	if (!mbhc_calibration)
-		return -ENOMEM;
-	wcd_mbhc_cfg.calibration = mbhc_calibration;
-	ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
-	if (ret) {
-		dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
-			__func__, ret);
-		goto err_hs_detect;
-	}
 	return 0;
-
-err_hs_detect:
-	kfree(mbhc_calibration);
-	return ret;
 }
 
 static void msm_i2s_auxpcm_init(struct platform_device *pdev)

+ 152 - 125
asoc/msm-compress-q6-v2.c

@@ -21,6 +21,7 @@
 #include <sound/control.h>
 #include <sound/pcm_params.h>
 #include <audio/sound/audio_effects.h>
+#include <audio/sound/audio_compressed_formats.h>
 #include <asm/dma.h>
 #include <linux/dma-mapping.h>
 #include <audio/linux/msm_audio.h>
@@ -81,6 +82,8 @@ const DECLARE_TLV_DB_LINEAR(msm_compr_vol_gain, 0,
 #define COMPRESSED_PERF_MODE_FLAG 0
 #endif
 
+#define DSD_BLOCK_SIZE_4 4
+
 struct msm_compr_gapless_state {
 	bool set_next_stream_id;
 	int32_t stream_opened[MAX_NUMBER_OF_STREAMS];
@@ -189,7 +192,7 @@ struct msm_compr_audio {
 
 const u32 compr_codecs[] = {
 	SND_AUDIOCODEC_AC3, SND_AUDIOCODEC_EAC3, SND_AUDIOCODEC_DTS,
-	SND_AUDIOCODEC_DSD, SND_AUDIOCODEC_TRUEHD, SND_AUDIOCODEC_IEC61937};
+	SND_AUDIOCODEC_TRUEHD, SND_AUDIOCODEC_IEC61937};
 
 struct query_audio_effect {
 	uint32_t mod_id;
@@ -1099,24 +1102,62 @@ static void populate_codec_list(struct msm_compr_audio *prtd)
 			COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
 	prtd->compr_cap.max_fragments =
 			COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
-	prtd->compr_cap.num_codecs = 17;
+	prtd->compr_cap.num_codecs = 10;
 	prtd->compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
 	prtd->compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
 	prtd->compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
 	prtd->compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
 	prtd->compr_cap.codecs[4] = SND_AUDIOCODEC_MP2;
 	prtd->compr_cap.codecs[5] = SND_AUDIOCODEC_PCM;
-	prtd->compr_cap.codecs[6] = SND_AUDIOCODEC_WMA;
-	prtd->compr_cap.codecs[7] = SND_AUDIOCODEC_WMA_PRO;
-	prtd->compr_cap.codecs[8] = SND_AUDIOCODEC_FLAC;
-	prtd->compr_cap.codecs[9] = SND_AUDIOCODEC_VORBIS;
-	prtd->compr_cap.codecs[10] = SND_AUDIOCODEC_ALAC;
-	prtd->compr_cap.codecs[11] = SND_AUDIOCODEC_APE;
-	prtd->compr_cap.codecs[12] = SND_AUDIOCODEC_DTS;
-	prtd->compr_cap.codecs[13] = SND_AUDIOCODEC_DSD;
-	prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX;
-	prtd->compr_cap.codecs[15] = SND_AUDIOCODEC_TRUEHD;
-	prtd->compr_cap.codecs[16] = SND_AUDIOCODEC_IEC61937;
+	prtd->compr_cap.codecs[6] = SND_AUDIOCODEC_DTS;
+	prtd->compr_cap.codecs[7] = SND_AUDIOCODEC_TRUEHD;
+	prtd->compr_cap.codecs[8] = SND_AUDIOCODEC_IEC61937;
+	prtd->compr_cap.codecs[9] = SND_AUDIOCODEC_BESPOKE;
+}
+
+static int msm_compr_get_decoder_format(struct msm_compr_audio *prtd,
+	int *frame_sz, bool *is_format_gapless)
+{
+	int ret = 0;
+	__s32 *gdec;
+
+	pr_debug("%s: generic format = %x", __func__,
+		prtd->codec_param.codec.options.generic.reserved[0]);
+
+	switch(prtd->codec_param.codec.options.generic.reserved[0]) {
+	case AUDIO_COMP_FORMAT_ALAC:
+		ret = FORMAT_ALAC;
+		break;
+	case AUDIO_COMP_FORMAT_APE:
+		ret = FORMAT_APE;
+		break;
+	case AUDIO_COMP_FORMAT_APTX:
+		ret = FORMAT_APTX;
+		break;
+	case AUDIO_COMP_FORMAT_DSD:
+		ret = FORMAT_DSD;
+		break;
+	case AUDIO_COMP_FORMAT_FLAC:
+		ret = FORMAT_FLAC;
+		*is_format_gapless = true;
+		gdec = &(prtd->codec_param.codec.options.generic.reserved[1]);
+		*frame_sz = ((struct snd_generic_dec_flac *)gdec)->min_blk_size;
+		break;
+	case AUDIO_COMP_FORMAT_VORBIS:
+		ret = FORMAT_VORBIS;
+		break;
+	case AUDIO_COMP_FORMAT_WMA:
+		ret = FORMAT_WMA_V9;
+		break;
+	case AUDIO_COMP_FORMAT_WMA_PRO:
+		ret = FORMAT_WMA_V10PRO;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
 }
 
 static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
@@ -1145,6 +1186,7 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 	bool use_default_chmap = true;
 	char *chmap = NULL;
 	uint16_t sample_word_size;
+	__s32 *gdec;
 
 	pr_debug("%s: use_gapless_codec_options %d\n",
 			__func__, use_gapless_codec_options);
@@ -1260,12 +1302,17 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 		wma_cfg.format_tag = prtd->codec_param.codec.format;
 		wma_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
 		wma_cfg.sample_rate = prtd->sample_rate;
-		wma_cfg.avg_bytes_per_sec = codec_options->wma_dec.avg_bit_rate/8;
-		wma_cfg.block_align = codec_options->wma_dec.super_block_align;
+		gdec = &(codec_options->generic.reserved[1]);
+		wma_cfg.avg_bytes_per_sec =
+			((struct snd_generic_dec_wma *)gdec)->avg_bit_rate/8;
+		wma_cfg.block_align =
+			((struct snd_generic_dec_wma *)gdec)->super_block_align;
 		wma_cfg.valid_bits_per_sample =
-			codec_options->wma_dec.bits_per_sample;
-		wma_cfg.ch_mask = codec_options->wma_dec.channelmask;
-		wma_cfg.encode_opt = codec_options->wma_dec.encodeopt;
+			((struct snd_generic_dec_wma *)gdec)->bits_per_sample;
+		wma_cfg.ch_mask =
+			((struct snd_generic_dec_wma *)gdec)->channelmask;
+		wma_cfg.encode_opt =
+			((struct snd_generic_dec_wma *)gdec)->encodeopt;
 		ret = q6asm_media_format_block_wma(prtd->audio_client,
 					&wma_cfg, stream_id);
 		if (ret < 0)
@@ -1277,14 +1324,21 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 		wma_pro_cfg.format_tag = prtd->codec_param.codec.format;
 		wma_pro_cfg.ch_cfg = prtd->codec_param.codec.ch_in;
 		wma_pro_cfg.sample_rate = prtd->sample_rate;
-		wma_cfg.avg_bytes_per_sec = codec_options->wma_dec.avg_bit_rate/8;
-		wma_pro_cfg.block_align = codec_options->wma_dec.super_block_align;
+		gdec = &(codec_options->generic.reserved[1]);
+		wma_cfg.avg_bytes_per_sec =
+			((struct snd_generic_dec_wma *)gdec)->avg_bit_rate/8;
+		wma_pro_cfg.block_align =
+			((struct snd_generic_dec_wma *)gdec)->super_block_align;
 		wma_pro_cfg.valid_bits_per_sample =
-			codec_options->wma_dec.bits_per_sample;
-		wma_pro_cfg.ch_mask = codec_options->wma_dec.channelmask;
-		wma_pro_cfg.encode_opt = codec_options->wma_dec.encodeopt;
-		wma_pro_cfg.adv_encode_opt = codec_options->wma_dec.encodeopt1;
-		wma_pro_cfg.adv_encode_opt2 = codec_options->wma_dec.encodeopt2;
+			((struct snd_generic_dec_wma *)gdec)->bits_per_sample;
+		wma_pro_cfg.ch_mask =
+			((struct snd_generic_dec_wma *)gdec)->channelmask;
+		wma_pro_cfg.encode_opt =
+			((struct snd_generic_dec_wma *)gdec)->encodeopt;
+		wma_pro_cfg.adv_encode_opt =
+			((struct snd_generic_dec_wma *)gdec)->encodeopt1;
+		wma_pro_cfg.adv_encode_opt2 =
+			((struct snd_generic_dec_wma *)gdec)->encodeopt2;
 		ret = q6asm_media_format_block_wmapro(prtd->audio_client,
 				&wma_pro_cfg, stream_id);
 		if (ret < 0)
@@ -1299,53 +1353,59 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 		flac_cfg.ch_cfg = prtd->num_channels;
 		flac_cfg.sample_rate = prtd->sample_rate;
 		flac_cfg.stream_info_present = 1;
-		flac_cfg.sample_size = codec_options->flac_dec.sample_size;
-		flac_cfg.min_blk_size = codec_options->flac_dec.min_blk_size;
-		flac_cfg.max_blk_size = codec_options->flac_dec.max_blk_size;
+		gdec = &(codec_options->generic.reserved[1]);
+		flac_cfg.sample_size =
+			((struct snd_generic_dec_flac *)gdec)->sample_size;
+		flac_cfg.min_blk_size =
+			((struct snd_generic_dec_flac *)gdec)->min_blk_size;
+		flac_cfg.max_blk_size =
+			((struct snd_generic_dec_flac *)gdec)->max_blk_size;
 		flac_cfg.max_frame_size =
-			codec_options->flac_dec.max_frame_size;
+			((struct snd_generic_dec_flac *)gdec)->max_frame_size;
 		flac_cfg.min_frame_size =
-			codec_options->flac_dec.min_frame_size;
-
+			((struct snd_generic_dec_flac *)gdec)->min_frame_size;
 		ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
 							&flac_cfg, stream_id);
 		if (ret < 0)
 			pr_err("%s: CMD Format block failed ret %d\n",
 				__func__, ret);
-
 		break;
 	case FORMAT_VORBIS:
 		pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
 		memset(&vorbis_cfg, 0x0, sizeof(struct asm_vorbis_cfg));
+		gdec = &(codec_options->generic.reserved[1]);
 		vorbis_cfg.bit_stream_fmt =
-			codec_options->vorbis_dec.bit_stream_fmt;
-
+			((struct snd_generic_dec_vorbis *)gdec)->bit_stream_fmt;
 		ret = q6asm_stream_media_format_block_vorbis(
 					prtd->audio_client, &vorbis_cfg,
 					stream_id);
 		if (ret < 0)
 			pr_err("%s: CMD Format block failed ret %d\n",
 					__func__, ret);
-
 		break;
 	case FORMAT_ALAC:
 		pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
 		memset(&alac_cfg, 0x0, sizeof(struct asm_alac_cfg));
 		alac_cfg.num_channels = prtd->num_channels;
 		alac_cfg.sample_rate = prtd->sample_rate;
-		alac_cfg.frame_length = codec_options->alac.frame_length;
+		gdec = &(codec_options->generic.reserved[1]);
+		alac_cfg.frame_length =
+			((struct snd_generic_dec_alac *)gdec)->frame_length;
 		alac_cfg.compatible_version =
-			codec_options->alac.compatible_version;
-		alac_cfg.bit_depth = codec_options->alac.bit_depth;
-		alac_cfg.pb = codec_options->alac.pb;
-		alac_cfg.mb = codec_options->alac.mb;
-		alac_cfg.kb = codec_options->alac.kb;
-		alac_cfg.max_run = codec_options->alac.max_run;
-		alac_cfg.max_frame_bytes = codec_options->alac.max_frame_bytes;
-		alac_cfg.avg_bit_rate = codec_options->alac.avg_bit_rate;
+		((struct snd_generic_dec_alac *)gdec)->compatible_version;
+		alac_cfg.bit_depth =
+			((struct snd_generic_dec_alac *)gdec)->bit_depth;
+		alac_cfg.pb = ((struct snd_generic_dec_alac *)gdec)->pb;
+		alac_cfg.mb = ((struct snd_generic_dec_alac *)gdec)->mb;
+		alac_cfg.kb = ((struct snd_generic_dec_alac *)gdec)->kb;
+		alac_cfg.max_run =
+			((struct snd_generic_dec_alac *)gdec)->max_run;
+		alac_cfg.max_frame_bytes =
+			((struct snd_generic_dec_alac *)gdec)->max_frame_bytes;
+		alac_cfg.avg_bit_rate =
+			((struct snd_generic_dec_alac *)gdec)->avg_bit_rate;
 		alac_cfg.channel_layout_tag =
-			codec_options->alac.channel_layout_tag;
-
+		((struct snd_generic_dec_alac *)gdec)->channel_layout_tag;
 		ret = q6asm_media_format_block_alac(prtd->audio_client,
 							&alac_cfg, stream_id);
 		if (ret < 0)
@@ -1357,22 +1417,25 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 		memset(&ape_cfg, 0x0, sizeof(struct asm_ape_cfg));
 		ape_cfg.num_channels = prtd->num_channels;
 		ape_cfg.sample_rate = prtd->sample_rate;
+		gdec = &(codec_options->generic.reserved[1]);
 		ape_cfg.compatible_version =
-			codec_options->ape.compatible_version;
+		((struct snd_generic_dec_ape *)gdec)->compatible_version;
 		ape_cfg.compression_level =
-			codec_options->ape.compression_level;
-		ape_cfg.format_flags = codec_options->ape.format_flags;
-		ape_cfg.blocks_per_frame = codec_options->ape.blocks_per_frame;
+		((struct snd_generic_dec_ape *)gdec)->compression_level;
+		ape_cfg.format_flags =
+		((struct snd_generic_dec_ape *)gdec)->format_flags;
+		ape_cfg.blocks_per_frame =
+		((struct snd_generic_dec_ape *)gdec)->blocks_per_frame;
 		ape_cfg.final_frame_blocks =
-			codec_options->ape.final_frame_blocks;
-		ape_cfg.total_frames = codec_options->ape.total_frames;
-		ape_cfg.bits_per_sample = codec_options->ape.bits_per_sample;
+		((struct snd_generic_dec_ape *)gdec)->final_frame_blocks;
+		ape_cfg.total_frames =
+		((struct snd_generic_dec_ape *)gdec)->total_frames;
+		ape_cfg.bits_per_sample =
+		((struct snd_generic_dec_ape *)gdec)->bits_per_sample;
 		ape_cfg.seek_table_present =
-			codec_options->ape.seek_table_present;
-
+		((struct snd_generic_dec_ape *)gdec)->seek_table_present;
 		ret = q6asm_media_format_block_ape(prtd->audio_client,
 							&ape_cfg, stream_id);
-
 		if (ret < 0)
 			pr_err("%s: CMD Format block failed ret %d\n",
 					__func__, ret);
@@ -1389,6 +1452,12 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 		dsd_cfg.num_version = 0;
 		dsd_cfg.is_bitwise_big_endian = 1;
 		dsd_cfg.dsd_channel_block_size = 1;
+		gdec = &(codec_options->generic.reserved[1]);
+		if (((struct snd_generic_dec_dsd *)gdec)->blk_size ==
+							DSD_BLOCK_SIZE_4)
+			dsd_cfg.dsd_channel_block_size =
+				((struct snd_generic_dec_dsd *)gdec)->blk_size;
+
 		ret = q6asm_media_format_block_dsd(prtd->audio_client,
 						   &dsd_cfg, stream_id);
 		if (ret < 0)
@@ -1416,9 +1485,13 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 							prtd->sample_rate,
 							stream_id);
 		if (ret >= 0) {
-			aptx_cfg.nap = codec_options->aptx_dec.nap;
-			aptx_cfg.uap = codec_options->aptx_dec.uap;
-			aptx_cfg.lap = codec_options->aptx_dec.lap;
+			gdec = &(codec_options->generic.reserved[1]);
+			aptx_cfg.nap =
+				((struct snd_generic_dec_aptx *)gdec)->nap;
+			aptx_cfg.uap =
+				((struct snd_generic_dec_aptx *)gdec)->uap;
+			aptx_cfg.lap =
+				((struct snd_generic_dec_aptx *)gdec)->lap;
 			q6asm_set_aptx_dec_bt_addr(prtd->audio_client,
 							&aptx_cfg);
 		} else {
@@ -1437,9 +1510,10 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream,
 	case FORMAT_AMR_WB_PLUS:
 		pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
 		memset(&amrwbplus_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
+		gdec = &(codec_options->generic.reserved[1]);
 		amrwbplus_cfg.amr_frame_fmt =
-			codec_options->amrwbplus.bit_stream_fmt;
-		ret =  q6asm_media_format_block_amrwbplus(
+		((struct snd_generic_dec_amrwb_plus *)gdec)->bit_stream_fmt;
+		ret = q6asm_media_format_block_amrwbplus(
 				prtd->audio_client,
 				&amrwbplus_cfg);
 		if (ret < 0)
@@ -2328,48 +2402,6 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
 		break;
 	}
 
-	case SND_AUDIOCODEC_WMA: {
-		pr_debug("SND_AUDIOCODEC_WMA\n");
-		prtd->codec = FORMAT_WMA_V9;
-		break;
-	}
-
-	case SND_AUDIOCODEC_WMA_PRO: {
-		pr_debug("SND_AUDIOCODEC_WMA_PRO\n");
-		prtd->codec = FORMAT_WMA_V10PRO;
-		break;
-	}
-
-	case SND_AUDIOCODEC_FLAC: {
-		pr_debug("%s: SND_AUDIOCODEC_FLAC\n", __func__);
-		prtd->codec = FORMAT_FLAC;
-		/*
-		 * DSP bufferring is based on blk size,
-		 * consider mininum buffering to rule out any false wait
-		 */
-		frame_sz =
-			prtd->codec_param.codec.options.flac_dec.min_blk_size;
-		is_format_gapless = true;
-		break;
-	}
-
-	case SND_AUDIOCODEC_VORBIS: {
-		pr_debug("%s: SND_AUDIOCODEC_VORBIS\n", __func__);
-		prtd->codec = FORMAT_VORBIS;
-		break;
-	}
-
-	case SND_AUDIOCODEC_ALAC: {
-		pr_debug("%s: SND_AUDIOCODEC_ALAC\n", __func__);
-		prtd->codec = FORMAT_ALAC;
-		break;
-	}
-
-	case SND_AUDIOCODEC_APE: {
-		pr_debug("%s: SND_AUDIOCODEC_APE\n", __func__);
-		prtd->codec = FORMAT_APE;
-		break;
-	}
 
 	case SND_AUDIOCODEC_DTS: {
 		pr_debug("%s: SND_AUDIOCODEC_DTS\n", __func__);
@@ -2377,12 +2409,6 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
 		break;
 	}
 
-	case SND_AUDIOCODEC_DSD: {
-		pr_debug("%s: SND_AUDIOCODEC_DSD\n", __func__);
-		prtd->codec = FORMAT_DSD;
-		break;
-	}
-
 	case SND_AUDIOCODEC_TRUEHD: {
 		pr_debug("%s: SND_AUDIOCODEC_TRUEHD\n", __func__);
 		prtd->codec = FORMAT_TRUEHD;
@@ -2395,15 +2421,13 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream,
 		break;
 	}
 
-	case SND_AUDIOCODEC_APTX: {
-		pr_debug("%s: SND_AUDIOCODEC_APTX\n", __func__);
-		prtd->codec = FORMAT_APTX;
-		break;
-	}
-
 	case SND_AUDIOCODEC_BESPOKE: {
 		pr_debug("%s: SND_AUDIOCODEC_BESPOKE\n", __func__);
-		prtd->codec = FORMAT_BESPOKE;
+		ret = msm_compr_get_decoder_format(prtd, &frame_sz,
+						&is_format_gapless);
+		if (ret < 0)
+			return ret;
+		prtd->codec = ret;
 		break;
 	}
 
@@ -3343,15 +3367,10 @@ static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream,
 		break;
 	case SND_AUDIOCODEC_AC3:
 	case SND_AUDIOCODEC_EAC3:
-	case SND_AUDIOCODEC_FLAC:
-	case SND_AUDIOCODEC_VORBIS:
-	case SND_AUDIOCODEC_ALAC:
-	case SND_AUDIOCODEC_APE:
 	case SND_AUDIOCODEC_DTS:
-	case SND_AUDIOCODEC_DSD:
 	case SND_AUDIOCODEC_TRUEHD:
 	case SND_AUDIOCODEC_IEC61937:
-	case SND_AUDIOCODEC_APTX:
+	case SND_AUDIOCODEC_BESPOKE:
 		break;
 	default:
 		pr_err("%s: Unsupported audio codec %d\n",
@@ -5614,9 +5633,17 @@ fail:
 	return ret;
 }
 
-static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
+int msm_compr_new(struct snd_soc_pcm_runtime *rtd, int num)
 {
-	int rc;
+	int rc = 0;
+
+	if (rtd == NULL) {
+		pr_err("%s: RTD is NULL\n", __func__);
+		return 0;
+	}
+	rc = snd_soc_new_compress(rtd, num);
+	if (rc)
+		pr_err("%s: Fail to create pcm for compress\n", __func__);
 
 	rc = msm_compr_add_volume_control(rtd);
 	if (rc)
@@ -5670,6 +5697,7 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
 			__func__);
 	return 0;
 }
+EXPORT_SYMBOL(msm_compr_new);
 
 static struct snd_compr_ops msm_compr_ops = {
 	.open			= msm_compr_open,
@@ -5692,7 +5720,6 @@ static struct snd_soc_component_driver msm_soc_component = {
 	.name		= DRV_NAME,
 	.probe		= msm_compr_probe,
 	.compr_ops	= &msm_compr_ops,
-	.pcm_new	= msm_compr_new,
 };
 
 static int msm_compr_dev_probe(struct platform_device *pdev)

+ 4 - 0
asoc/msm-compress-q6-v2.h

@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+*/
+int msm_compr_new(struct snd_soc_pcm_runtime *rtd, int num);

+ 17 - 15
asoc/msm-dai-fe.c

@@ -12,6 +12,8 @@
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
+#include "msm-compress-q6-v2.h"
+
 static struct snd_soc_dai_ops msm_fe_dai_ops = {};
 
 /* Conventional and unconventional sample rate supported */
@@ -222,7 +224,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia4",
 		.probe = fe_dai_probe,
 	},
@@ -308,7 +310,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia7",
 		.probe = fe_dai_probe,
 	},
@@ -2401,7 +2403,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia11",
 		.probe = fe_dai_probe,
 	},
@@ -2421,7 +2423,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia12",
 		.probe = fe_dai_probe,
 	},
@@ -2441,7 +2443,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia13",
 		.probe = fe_dai_probe,
 	},
@@ -2461,7 +2463,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia14",
 		.probe = fe_dai_probe,
 	},
@@ -2481,7 +2483,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia15",
 		.probe = fe_dai_probe,
 	},
@@ -2583,7 +2585,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max =     192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia17",
 		.probe = fe_dai_probe,
 	},
@@ -2602,7 +2604,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max =     192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia18",
 		.probe = fe_dai_probe,
 	},
@@ -2621,7 +2623,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max =     192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia19",
 		.probe = fe_dai_probe,
 	},
@@ -2839,7 +2841,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 384000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia26",
 		.probe = fe_dai_probe,
 	},
@@ -2858,7 +2860,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max = 192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia27",
 		.probe = fe_dai_probe,
 	},
@@ -2877,7 +2879,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 		.rate_max =     192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia28",
 		.probe = fe_dai_probe,
 	},
@@ -2896,7 +2898,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max =     192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia29",
 		.probe = fe_dai_probe,
 	},
@@ -2915,7 +2917,7 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
 			.rate_max =     192000,
 		},
 		.ops = &msm_fe_Multimedia_dai_ops,
-		.compress_new = snd_soc_new_compress,
+		.compress_new = msm_compr_new,
 		.name = "MultiMedia30",
 		.probe = fe_dai_probe,
 	},

+ 4 - 2
asoc/msm-dai-q6-v2.c

@@ -331,7 +331,8 @@ static const char *const mi2s_format[] = {
 	"NA6",
 	"NA7",
 	"NA8",
-	"DSD_DOP_W_MARKER"
+	"DSD_DOP_W_MARKER",
+	"NATIVE_DSD_DATA"
 };
 
 static const char *const mi2s_vi_feed_mono[] = {
@@ -340,7 +341,7 @@ static const char *const mi2s_vi_feed_mono[] = {
 };
 
 static const struct soc_enum mi2s_config_enum[] = {
-	SOC_ENUM_SINGLE_EXT(10, mi2s_format),
+	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_format), mi2s_format),
 	SOC_ENUM_SINGLE_EXT(2, mi2s_vi_feed_mono),
 };
 
@@ -5895,6 +5896,7 @@ static int msm_dai_q6_mi2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBS_CFS:
+	case SND_SOC_DAIFMT_CBM_CFS:
 		mi2s_dai_data->rx_dai.mi2s_dai_data.port_config.i2s.ws_src = 1;
 		mi2s_dai_data->tx_dai.mi2s_dai_data.port_config.i2s.ws_src = 1;
 		break;

+ 23 - 11
asoc/msm-lsm-client.c

@@ -881,8 +881,16 @@ static int msm_lsm_dereg_model(struct snd_pcm_substream *substream,
 		}
 
 		if (sm->model_id == p_info->model_id) {
-			rc = q6lsm_set_one_param(client, p_info, NULL,
-						 LSM_DEREG_MULTI_SND_MODEL);
+			if (p_info->param_size != sizeof(p_info->model_id)) {
+				rc = -EINVAL;
+				pr_err("%s: %s failed, p_info->param_size is invalid: %d\n",
+				       __func__,  "LSM_DEREG_MULTI_SND_MODEL",
+				       p_info->param_size);
+			} else {
+				rc = q6lsm_set_one_param(client, p_info, NULL,
+							 LSM_DEREG_MULTI_SND_MODEL);
+			}
+
 			if (rc)
 				dev_err(rtd->dev,
 					"%s: Failed to deregister snd_model %d, err = %d\n",
@@ -1252,7 +1260,7 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
 			 unsigned int cmd, void *arg)
 {
 	struct snd_soc_pcm_runtime *rtd;
-	unsigned long flags;
+	unsigned long flags = 0;
 	int ret;
 	struct snd_lsm_sound_model_v2 snd_model_v2;
 	struct snd_lsm_session_data session_data;
@@ -2404,10 +2412,13 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
 	case SNDRV_LSM_SET_MODULE_PARAMS_V2: {
 		struct snd_lsm_module_params p_data;
 		struct lsm_params_info *temp_ptr_info = NULL;
+		struct lsm_params_info_v2 info_v2;
 		struct lsm_params_info_v2 *ptr_info_v2 = NULL, *temp_ptr_info_v2 = NULL;
 		size_t p_size = 0, count;
 		u8 *params;
 
+		memset(&info_v2, 0, sizeof(info_v2));
+
 		if (!prtd->lsm_client->use_topology) {
 			dev_err(rtd->dev,
 				"%s: %s: not supported if not using topology\n",
@@ -2472,16 +2483,17 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
 		for (count = 0; count < p_data.num_params; count++) {
 			if (cmd == SNDRV_LSM_SET_MODULE_PARAMS) {
 				/* convert to V2 param info struct from legacy param info */
-				ptr_info_v2->module_id = temp_ptr_info->module_id;
-				ptr_info_v2->param_id = temp_ptr_info->param_id;
-				ptr_info_v2->param_size = temp_ptr_info->param_size;
-				ptr_info_v2->param_data = temp_ptr_info->param_data;
-				ptr_info_v2->param_type = temp_ptr_info->param_type;
+				info_v2.module_id = temp_ptr_info->module_id;
+				info_v2.param_id = temp_ptr_info->param_id;
+				info_v2.param_size = temp_ptr_info->param_size;
+				info_v2.param_data = temp_ptr_info->param_data;
+				info_v2.param_type = temp_ptr_info->param_type;
 
-				ptr_info_v2->instance_id = INSTANCE_ID_0;
-				ptr_info_v2->stage_idx = LSM_STAGE_INDEX_FIRST;
-				ptr_info_v2->model_id = 0;
+				info_v2.instance_id = INSTANCE_ID_0;
+				info_v2.stage_idx = LSM_STAGE_INDEX_FIRST;
+				info_v2.model_id = 0;
 
+				ptr_info_v2 = &info_v2;
 				temp_ptr_info++;
 			} else {
 				if (LSM_REG_MULTI_SND_MODEL != temp_ptr_info_v2->param_type ||

+ 2 - 2
asoc/msm-pcm-afe-v2.c

@@ -161,7 +161,7 @@ static void pcm_afe_process_tx_pkt(uint32_t opcode,
 		 void *priv)
 {
 	struct pcm_afe_info *prtd = priv;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	struct snd_pcm_substream *substream = NULL;
 	struct snd_pcm_runtime *runtime = NULL;
 	uint16_t event;
@@ -255,7 +255,7 @@ static void pcm_afe_process_rx_pkt(uint32_t opcode,
 		 void *priv)
 {
 	struct pcm_afe_info *prtd = priv;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	struct snd_pcm_substream *substream = NULL;
 	struct snd_pcm_runtime *runtime = NULL;
 	struct snd_soc_pcm_runtime *rtd = NULL;

+ 3 - 3
asoc/msm-pcm-dtmf-v2.c

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2013-2014, 2017-2019 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2017-2020 The Linux Foundation. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -224,7 +224,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
 	struct dtmf_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct dtmf_drv_info *prtd = runtime->private_data;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	ret = wait_event_interruptible_timeout(prtd->out_wait,
 				(!list_empty(&prtd->out_queue)),
@@ -324,7 +324,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_pcm_substream *c_substream;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct dtmf_drv_info *prtd = runtime->private_data;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	pr_debug("%s() DTMF\n", __func__);
 

+ 6 - 6
asoc/msm-pcm-host-voice-v2.c

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -678,7 +678,7 @@ static void hpcm_copy_capture_data_to_queue(struct dai_data *dai_data,
 					    uint32_t len)
 {
 	struct hpcm_buf_node *buf_node = NULL;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	if (dai_data->substream == NULL)
 		return;
@@ -987,7 +987,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_dma_buffer *dma_buf;
 	struct snd_pcm_runtime *runtime;
 	struct hpcm_drv *prtd;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	struct dai_data *dai_data = NULL;
 	struct tap_point *tp = NULL;
 	struct tappnt_mxr_data *tmd = NULL;
@@ -1077,7 +1077,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct hpcm_drv *prtd = runtime->private_data;
 	struct dai_data *dai_data = hpcm_get_dai_data(substream->pcm->id, prtd);
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	if (dai_data == NULL) {
 		pr_err("%s, dai_data is null\n", __func__);
@@ -1129,7 +1129,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct hpcm_drv *prtd = runtime->private_data;
 	struct dai_data *dai_data = hpcm_get_dai_data(substream->pcm->id, prtd);
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	if (dai_data == NULL) {
 		pr_err("%s, dai_data is null\n", __func__);
@@ -1455,7 +1455,7 @@ static struct snd_soc_component_driver msm_soc_component = {
 static int msm_pcm_probe(struct platform_device *pdev)
 {
 
-	pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+	pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
 	return snd_soc_register_component(&pdev->dev, &msm_soc_component,
 					  NULL, 0);
 }

+ 43 - 22
asoc/msm-pcm-loopback-v2.c

@@ -552,13 +552,15 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
 		goto exit;
 	}
 	mutex_lock(&loopback_session_lock);
-	prtd = substream->runtime->private_data;
-	if (!prtd) {
-		rc = -ENODEV;
-		mutex_unlock(&loopback_session_lock);
-		goto exit;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (!prtd) {
+			rc = -ENODEV;
+			mutex_unlock(&loopback_session_lock);
+			goto exit;
+		}
+		rc = pcm_loopback_set_volume(prtd, volume);
 	}
-	rc = pcm_loopback_set_volume(prtd, volume);
 	mutex_unlock(&loopback_session_lock);
 exit:
 	return rc;
@@ -584,13 +586,15 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
 		goto exit;
 	}
 	mutex_lock(&loopback_session_lock);
-	prtd = substream->runtime->private_data;
-	if (!prtd) {
-		rc = -ENODEV;
-		mutex_unlock(&loopback_session_lock);
-		goto exit;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (!prtd) {
+			rc = -ENODEV;
+			mutex_unlock(&loopback_session_lock);
+			goto exit;
+		}
+		ucontrol->value.integer.value[0] = prtd->volume;
 	}
-	ucontrol->value.integer.value[0] = prtd->volume;
 	mutex_unlock(&loopback_session_lock);
 exit:
 	return rc;
@@ -623,16 +627,19 @@ static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
 	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};
+	struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000, 0};
 	int ret = 0;
 
 	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)
 		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",
+	if (ucontrol->value.integer.value[4] != 0)
+		cfg_data.copp_token = ucontrol->value.integer.value[4];
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 	ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
 						      be_id, &cfg_data);
 	if (ret < 0)
@@ -663,9 +670,12 @@ static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
 	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",
+	ucontrol->value.integer.value[4] = cfg_data.copp_token;
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
+
 done:
 	return ret;
 }
@@ -676,16 +686,19 @@ static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
 	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};
+	struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000, 0};
 	int ret = 0;
 
 	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)
 		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",
+	if (ucontrol->value.integer.value[4] != 0)
+		cfg_data.copp_token = ucontrol->value.integer.value[4];
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 	ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
 						      be_id, &cfg_data);
 	if (ret < 0)
@@ -716,9 +729,11 @@ static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
 	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",
+	ucontrol->value.integer.value[4] = cfg_data.copp_token;
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 done:
 	return ret;
 }
@@ -888,6 +903,12 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
 			chmixer_pspd);
 
 	mutex_lock(&loopback_session_lock);
+	if (substream->ref_count <= 0) {
+		pr_err_ratelimited("%s: substream ref_count:%d invalid\n",
+				__func__, substream->ref_count);
+		mutex_unlock(&loopback_session_lock);
+		return -EINVAL;
+	}
 	if (chmixer_pspd->enable && substream->runtime) {
 		prtd = substream->runtime->private_data;
 		if (!prtd) {

+ 17 - 7
asoc/msm-pcm-q6-noirq.c

@@ -732,6 +732,12 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
 		pr_err("%s: vol is NULL\n", __func__);
 		return -ENODEV;
 	}
+
+	if (!vol->pcm) {
+		pr_err("%s: vol->pcm is NULL\n", __func__);
+		return -ENODEV;
+	}
+
 	substream = vol->pcm->streams[vol->stream].substream;
 	if (!substream) {
 		pr_err("%s substream not found\n", __func__);
@@ -756,9 +762,11 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
 		return -ENODEV;
 	}
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
-	if (prtd)
-		ucontrol->value.integer.value[0] = prtd->volume;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (prtd)
+			ucontrol->value.integer.value[0] = prtd->volume;
+	}
 	mutex_unlock(&pdata->lock);
 	return 0;
 }
@@ -801,10 +809,12 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
 	}
 
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
-	if (prtd) {
-		rc = msm_pcm_set_volume(prtd, volume);
-		prtd->volume = volume;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (prtd) {
+			rc = msm_pcm_set_volume(prtd, volume);
+			prtd->volume = volume;
+		}
 	}
 	mutex_unlock(&pdata->lock);
 	return rc;

+ 73 - 26
asoc/msm-pcm-q6-v2.c

@@ -1330,7 +1330,12 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
 		ret = -EINVAL;
 		goto done;
 	}
-
+	if (substream->ref_count <= 0) {
+		pr_err_ratelimited("%s substream ref_count:%d invalid\n",
+				__func__, substream->ref_count);
+		ret = -EINVAL;
+		goto done;
+	}
 	prtd = substream->runtime->private_data;
 	if (prtd == NULL) {
 		pr_err("%s prtd is null.\n", __func__);
@@ -1530,6 +1535,12 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
 		pr_err("%s: vol is NULL\n", __func__);
 		return -ENODEV;
 	}
+
+	if (!vol->pcm) {
+		pr_err("%s: vol->pcm is NULL\n", __func__);
+		return -ENODEV;
+	}
+
 	substream = vol->pcm->streams[vol->stream].substream;
 	if (!substream) {
 		pr_err("%s substream not found\n", __func__);
@@ -1555,9 +1566,11 @@ static int msm_pcm_volume_ctl_get(struct snd_kcontrol *kcontrol,
 	}
 
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
-	if (prtd)
-		ucontrol->value.integer.value[0] = prtd->volume;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (prtd)
+			ucontrol->value.integer.value[0] = prtd->volume;
+	}
 	mutex_unlock(&pdata->lock);
 	return 0;
 }
@@ -1601,10 +1614,12 @@ static int msm_pcm_volume_ctl_put(struct snd_kcontrol *kcontrol,
 	}
 
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
-	if (prtd) {
-		rc = msm_pcm_set_volume(prtd, volume);
-		prtd->volume = volume;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (prtd) {
+			rc = msm_pcm_set_volume(prtd, volume);
+			prtd->volume = volume;
+		}
 	}
 	mutex_unlock(&pdata->lock);
 	return rc;
@@ -1672,9 +1687,11 @@ static int msm_pcm_compress_ctl_get(struct snd_kcontrol *kcontrol,
 		return 0;
 	}
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
-	if (prtd)
-		ucontrol->value.integer.value[0] = prtd->compress_enable;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (prtd)
+			ucontrol->value.integer.value[0] = prtd->compress_enable;
+	}
 	mutex_unlock(&pdata->lock);
 	return 0;
 }
@@ -1704,11 +1721,13 @@ static int msm_pcm_compress_ctl_put(struct snd_kcontrol *kcontrol,
 		return 0;
 	}
 	mutex_lock(&pdata->lock);
-	prtd = substream->runtime->private_data;
-	if (prtd) {
-		pr_debug("%s: setting compress flag to 0x%x\n",
-		__func__, compress);
-		prtd->compress_enable = compress;
+	if (substream->ref_count > 0) {
+		prtd = substream->runtime->private_data;
+		if (prtd) {
+			pr_debug("%s: setting compress flag to 0x%x\n",
+			__func__, compress);
+			prtd->compress_enable = compress;
+		}
 	}
 	mutex_unlock(&pdata->lock);
 	return rc;
@@ -1818,6 +1837,12 @@ static int msm_pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
 		return 0;
 
 	mutex_lock(&pdata->lock);
+	if (substream->ref_count <= 0) {
+		pr_err_ratelimited("%s: substream ref_count:%d invalid\n",
+				__func__, substream->ref_count);
+		mutex_unlock(&pdata->lock);
+		return -EINVAL;
+	}
 	prtd = substream->runtime ? substream->runtime->private_data : NULL;
 	if (prtd) {
 		prtd->set_channel_map = true;
@@ -1885,6 +1910,12 @@ static int msm_pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
 		return 0; /* no channels set */
 
 	mutex_lock(&pdata->lock);
+	if (substream->ref_count <= 0) {
+		pr_err_ratelimited("%s: substream ref_count:%d invalid\n",
+				__func__, substream->ref_count);
+		mutex_unlock(&pdata->lock);
+		return -EINVAL;
+	}
 	prtd = substream->runtime ? substream->runtime->private_data : NULL;
 
 	if (prtd && prtd->set_channel_map == true) {
@@ -1936,16 +1967,19 @@ static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
 	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};
+	struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000, 0};
 	int ret = 0;
 
 	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)
 		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",
+	if (ucontrol->value.integer.value[4] != 0)
+		cfg_data.copp_token = ucontrol->value.integer.value[4];
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 	ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
 						      be_id, &cfg_data);
 	if (ret < 0)
@@ -1976,9 +2010,11 @@ static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
 	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",
+	ucontrol->value.integer.value[4] = cfg_data.copp_token;
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 done:
 	return ret;
 }
@@ -1989,16 +2025,19 @@ static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
 	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};
+	struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000, 0};
 	int ret = 0;
 
 	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)
 		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",
+	if (ucontrol->value.integer.value[4] != 0)
+		cfg_data.copp_token = ucontrol->value.integer.value[4];
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 	ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
 						      be_id, &cfg_data);
 	if (ret < 0)
@@ -2029,9 +2068,11 @@ static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
 	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",
+	ucontrol->value.integer.value[4] = cfg_data.copp_token;
+	pr_debug("%s: fe_id- %llu session_type- %d be_id- %d app_type- %d acdb_dev_id- %d sample_rate- %d copp_token %d\n",
 		__func__, fe_id, session_type, be_id,
-		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+		cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate,
+		cfg_data.copp_token);
 done:
 	return ret;
 }
@@ -2174,6 +2215,12 @@ static int msm_pcm_channel_mixer_cfg_ctl_put(struct snd_kcontrol *kcontrol,
 	}
 
 	mutex_lock(&pdata->lock);
+	if (substream->ref_count <= 0) {
+		pr_err_ratelimited("%s: substream ref_count:%d invalid\n",
+				__func__, substream->ref_count);
+		mutex_unlock(&pdata->lock);
+		return -EINVAL;
+	}
 	prtd = substream->runtime ? substream->runtime->private_data : NULL;
 	if (chmixer_pspd->enable && prtd) {
 		if (session_type == SESSION_TYPE_RX &&

+ 38 - 10
asoc/msm-pcm-routing-v2.c

@@ -1250,10 +1250,10 @@ int msm_pcm_routing_reg_stream_app_type_cfg(
 		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",
+	pr_debug("%s: fedai_id %d, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d copp_token %d\n",
 		__func__, fedai_id, session_type, be_id,
 		cfg_data->app_type, cfg_data->acdb_dev_id,
-		cfg_data->sample_rate);
+		cfg_data->sample_rate, cfg_data->copp_token);
 
 	if (!is_mm_lsm_fe_id(fedai_id)) {
 		pr_err("%s: Invalid machine driver ID %d\n",
@@ -1336,10 +1336,10 @@ int msm_pcm_routing_get_stream_app_type_cfg(
 
 	*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",
+	pr_debug("%s: fedai_id %d, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d copp_token %d\n",
 		__func__, fedai_id, session_type, *bedai_id,
 		cfg_data->app_type, cfg_data->acdb_dev_id,
-		cfg_data->sample_rate);
+		cfg_data->sample_rate, cfg_data->copp_token);
 done:
 	return ret;
 }
@@ -1626,6 +1626,7 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
 	u32 channels, sample_rate;
 	u16 bit_width = 16, be_bit_width;
 	bool is_lsm;
+	uint32_t copp_token = 0;
 
 	pr_debug("%s:fe_id[%d] perf_mode[%d] id[%d] stream_type[%d] passt[%d]",
 		 __func__, fe_id, perf_mode, dspst_id,
@@ -1710,6 +1711,8 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
 			fe_dai_app_type_cfg[fe_id][session_type][i].sample_rate;
 				bit_width =
 					app_type_cfg[app_type_idx].bit_width;
+				copp_token =
+			fe_dai_app_type_cfg[fe_id][session_type][i].copp_token;
 			} else {
 				sample_rate = msm_bedais[i].sample_rate;
 			}
@@ -1739,7 +1742,7 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
 				adm_open(port_id, path_type, sample_rate,
 					 channels, topology, perf_mode,
 					 bit_width, app_type, acdb_dev_id,
-					 session_type);
+					 session_type, passthr_mode, copp_token);
 			if ((copp_idx < 0) ||
 				(copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s:adm open failed coppid:%d\n",
@@ -2014,6 +2017,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
 	uint16_t bits_per_sample = 16, be_bit_width;
 	uint32_t passthr_mode = LEGACY_PCM;
 	int ret = 0;
+	uint32_t copp_token = 0;
 
 	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
 		/* bad ID assigned in machine driver */
@@ -2070,6 +2074,9 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
 					.sample_rate;
 				bits_per_sample =
 					app_type_cfg[app_type_idx].bit_width;
+				copp_token =
+				fe_dai_app_type_cfg[fedai_id][session_type][i]
+					.copp_token;
 			} else
 				sample_rate = msm_bedais[i].sample_rate;
 
@@ -2091,7 +2098,7 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
 					    sample_rate, channels, topology,
 					    perf_mode, bits_per_sample,
 					    app_type, acdb_dev_id,
-					    session_type);
+					    session_type, passthr_mode, copp_token);
 			if ((copp_idx < 0) ||
 				(copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s: adm open failed copp_idx:%d\n",
@@ -2254,6 +2261,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 	struct msm_pcm_routing_fdai_data *fdai;
 	uint32_t passthr_mode;
 	bool is_lsm;
+	uint32_t copp_token = 0;
 
 	pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
 
@@ -2352,6 +2360,9 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 					.sample_rate;
 				bits_per_sample =
 					app_type_cfg[app_type_idx].bit_width;
+				copp_token =
+				fe_dai_app_type_cfg[val][session_type][reg]
+					.copp_token;
 			} else
 				sample_rate = msm_bedais[reg].sample_rate;
 
@@ -2372,7 +2383,7 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 					    sample_rate, channels, topology,
 					    fdai->perf_mode, bits_per_sample,
 					    app_type, acdb_dev_id,
-					    session_type);
+					    session_type, passthr_mode, copp_token);
 			if ((copp_idx < 0) ||
 			    (copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s: adm open failed\n", __func__);
@@ -9106,6 +9117,10 @@ static const struct snd_kcontrol_new usb_audio_rx_mixer_controls[] = {
 	MSM_BACKEND_DAI_USB_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia31", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_USB_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA31, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
@@ -9201,6 +9216,10 @@ static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
 	MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA30, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia31", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_INT_BT_SCO_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA31, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_bt_a2dp_rx_mixer_controls[] = {
@@ -9272,6 +9291,10 @@ static const struct snd_kcontrol_new int_bt_a2dp_rx_mixer_controls[] = {
 	MSM_BACKEND_DAI_INT_BT_A2DP_RX,
 	MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer,
 	msm_routing_put_audio_mixer),
+	SOC_DOUBLE_EXT("MultiMedia31", SND_SOC_NOPM,
+	MSM_BACKEND_DAI_INT_BT_A2DP_RX,
+	MSM_FRONTEND_DAI_MULTIMEDIA31, 1, 0, msm_routing_get_audio_mixer,
+	msm_routing_put_audio_mixer),
 };
 
 static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -26108,6 +26131,7 @@ static const struct snd_soc_dapm_route intercon[] = {
 	{"SLIMBUS_7_RX Audio Mixer", "MultiMedia15", "MM_DL15"},
 	{"SLIMBUS_7_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
 	{"SLIMBUS_7_RX Audio Mixer", "MultiMedia26", "MM_DL26"},
+	{"SLIMBUS_7_RX Audio Mixer", "MultiMedia31", "MM_DL31"},
 	{"SLIMBUS_7_RX", NULL, "SLIMBUS_7_RX Audio Mixer"},
 
 	{"SLIMBUS_9_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -26146,6 +26170,7 @@ static const struct snd_soc_dapm_route intercon[] = {
 	{"USB_AUDIO_RX Audio Mixer", "MultiMedia15", "MM_DL15"},
 	{"USB_AUDIO_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
 	{"USB_AUDIO_RX Audio Mixer", "MultiMedia26", "MM_DL26"},
+	{"USB_AUDIO_RX Audio Mixer", "MultiMedia31", "MM_DL31"},
 	{"USB_AUDIO_RX", NULL, "USB_AUDIO_RX Audio Mixer"},
 
 	{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
@@ -27962,7 +27987,6 @@ static const struct snd_soc_dapm_route intercon[] = {
 	{"MM_UL20", NULL, "MultiMedia20 Mixer"},
 	{"MM_UL21", NULL, "MultiMedia21 Mixer"},
 	{"MM_UL22", NULL, "MultiMedia22 Mixer"},
-	{"MM_UL23", NULL, "MultiMedia23 Mixer"},
 	{"MM_UL24", NULL, "MultiMedia24 Mixer"},
 	{"MM_UL25", NULL, "MultiMedia25 Mixer"},
 	{"MM_UL27", NULL, "MultiMedia27 Mixer"},
@@ -30032,6 +30056,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
 	u32 session_id;
 	struct media_format_info voc_be_media_format;
 	bool is_lsm;
+	uint32_t copp_token = 0;
 
 	pr_debug("%s: substream->pcm->id:%s\n",
 		 __func__, substream->pcm->id);
@@ -30115,6 +30140,9 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
 							   [be_id].sample_rate;
 				bits_per_sample =
 					app_type_cfg[app_type_idx].bit_width;
+				copp_token =
+					fe_dai_app_type_cfg[i][session_type]
+							[be_id].copp_token;
 			} else
 				sample_rate = bedai->sample_rate;
 			/*
@@ -30147,7 +30175,7 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
 					    sample_rate, channels, topology,
 					    fdai->perf_mode, bits_per_sample,
 					    app_type, acdb_dev_id,
-					    session_type);
+					    session_type, fdai->passthr_mode, copp_token);
 			if ((copp_idx < 0) ||
 				(copp_idx >= MAX_COPPS_PER_PORT)) {
 				pr_err("%s: adm open failed\n", __func__);
@@ -30516,7 +30544,7 @@ static int msm_routing_put_pll_clk_drift(struct snd_kcontrol *kcontrol,
 	clk_drift = ucontrol->value.integer.value[1];
 	clk_reset = ucontrol->value.integer.value[2];
 
-	if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) {
+	if (be_idx < 0 || be_idx >= MSM_BACKEND_DAI_MAX) {
 		pr_err("%s: Invalid be id %d\n", __func__, be_idx);
 		return -EINVAL;
 	}

+ 1 - 0
asoc/msm-pcm-routing-v2.h

@@ -607,6 +607,7 @@ struct msm_pcm_stream_app_type_cfg {
 	int app_type;
 	int acdb_dev_id;
 	int sample_rate;
+	uint32_t copp_token;
 };
 
 /* dai_id: front-end ID,

+ 5 - 5
asoc/msm-pcm-voip-v2.c

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
  */
 
 #include <linux/init.h>
@@ -508,7 +508,7 @@ static void voip_process_dl_pkt(uint8_t *voc_pkt, void *private_data)
 {
 	struct voip_buf_node *buf_node = NULL;
 	struct voip_drv_info *prtd = private_data;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	uint32_t rate_type;
 	uint32_t frame_rate;
 	u32 pkt_len;
@@ -778,7 +778,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
 	struct voip_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	pr_debug("%s: fbytes=%lu\n", __func__, fbytes);
 
@@ -852,7 +852,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
 	struct voip_buf_node *buf_node = NULL;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct voip_drv_info *prtd = runtime->private_data;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 	int size;
 
 	pr_debug("%s: fbytes = %lu\n", __func__, fbytes);
@@ -941,7 +941,7 @@ static int msm_pcm_close(struct snd_pcm_substream *substream)
 	struct snd_pcm_substream *p_substream, *c_substream;
 	struct snd_pcm_runtime *runtime;
 	struct voip_drv_info *prtd;
-	unsigned long dsp_flags;
+	unsigned long dsp_flags = 0;
 
 	if (substream == NULL) {
 		pr_err("substream is NULL\n");

+ 5 - 5
asoc/msm-qti-pp-config.c

@@ -536,7 +536,7 @@ static int msm_qti_pp_get_rms_value_control(struct snd_kcontrol *kcontrol,
 			break;
 	}
 	if ((be_idx >= MSM_BACKEND_DAI_MAX) || !msm_bedai.active) {
-		pr_err("%s, back not active to query rms be_idx:%d\n",
+		pr_debug("%s, back not active to query rms be_idx:%d\n",
 			__func__, be_idx);
 		rc = -EINVAL;
 		goto get_rms_value_err;
@@ -1200,7 +1200,7 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
 	int ctl_len = 0, ret = 0;
 	struct dsp_stream_callback_list *new_event;
 	struct dsp_stream_callback_list *oldest_event;
-	unsigned long spin_flags;
+	unsigned long spin_flags = 0;
 	struct dsp_stream_callback_prtd *kctl_prtd = NULL;
 	struct msm_adsp_event_data *event_data = NULL;
 	const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
@@ -1269,11 +1269,11 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
 
 	spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
 	while (kctl_prtd->event_count >= DSP_STREAM_CALLBACK_QUEUE_SIZE) {
-		pr_info("%s: queue of size %d is full. delete oldest one.\n",
+		pr_debug("%s: queue of size %d is full. delete oldest one.\n",
 			__func__, DSP_STREAM_CALLBACK_QUEUE_SIZE);
 		oldest_event = list_first_entry(&kctl_prtd->event_queue,
 				struct dsp_stream_callback_list, list);
-		pr_info("%s: event deleted: type %d length %d\n",
+		pr_debug("%s: event deleted: type %d length %d\n",
 			__func__, oldest_event->event.event_type,
 			oldest_event->event.payload_len);
 		list_del(&oldest_event->list);
@@ -1309,7 +1309,7 @@ int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol,
 {
 	uint32_t payload_size = 0;
 	struct dsp_stream_callback_list *oldest_event;
-	unsigned long spin_flags;
+	unsigned long spin_flags = 0;
 	struct dsp_stream_callback_prtd *kctl_prtd = NULL;
 	int ret = 0;
 

+ 11 - 0
asoc/msm_dailink.h

@@ -176,6 +176,11 @@ SND_SOC_DAILINK_DEFS(wsa_cdcdma0_capture,
 	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "wsa_macro_vifeedback")),
 	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
 
+SND_SOC_DAILINK_DEFS(wsa_cdcdma0_capture_stub,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45057")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
 SND_SOC_DAILINK_DEFS(multimedia6,
 	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia6")),
 	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
@@ -523,6 +528,12 @@ SND_SOC_DAILINK_DEFS(rx_dma_rx3,
 			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc")),
 	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
 
+SND_SOC_DAILINK_DEFS(rx_dma_rx5,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45114")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx5"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
 SND_SOC_DAILINK_DEFS(rx_dma_rx6,
 	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45116")),
 	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx6"),

+ 58 - 22
dsp/adsp-loader.c

@@ -55,6 +55,51 @@ static struct work_struct adsp_ldr_work;
 static struct platform_device *adsp_private;
 static void adsp_loader_unload(struct platform_device *pdev);
 
+static int adsp_restart_subsys(void)
+{
+	struct subsys_device *adsp_dev = NULL;
+	struct platform_device *pdev = adsp_private;
+	struct adsp_loader_private *priv = NULL;
+	int rc = -EINVAL;
+
+	priv = platform_get_drvdata(pdev);
+	if (!priv)
+		return rc;
+
+	adsp_dev = (struct subsys_device *)priv->pil_h;
+	if (!adsp_dev)
+		return rc;
+
+	/* subsystem_restart_dev has worker queue to handle */
+	rc = subsystem_restart_dev(adsp_dev);
+	if (rc) {
+		dev_err(&pdev->dev, "subsystem_restart_dev failed\n");
+		return rc;
+	}
+	pr_debug("%s :: Restart Success %d\n", __func__, rc);
+	return rc;
+}
+
+static void adsp_load_state_notify_cb(enum apr_subsys_state state,
+						void *phandle)
+{
+	struct platform_device *pdev = adsp_private;
+	struct adsp_loader_private *priv = NULL;
+
+	priv = platform_get_drvdata(pdev);
+	if (!priv)
+		return;
+	if (phandle != adsp_private) {
+		pr_err("%s:callback is not for adsp-loader client\n", __func__);
+		return;
+	}
+	pr_debug("%s:: Received cb for ADSP restart\n", __func__);
+	if (state == APR_SUBSYS_UNKNOWN)
+		adsp_restart_subsys();
+	else
+		pr_debug("%s:Ignore restart request for ADSP", __func__);
+}
+
 static void adsp_load_fw(struct work_struct *adsp_ldr_work)
 {
 	struct platform_device *pdev = adsp_private;
@@ -63,6 +108,7 @@ static void adsp_load_fw(struct work_struct *adsp_ldr_work)
 	int rc = 0;
 	u32 adsp_state;
 	const char *img_name;
+	void *padsp_restart_cb = &adsp_load_state_notify_cb;
 
 	if (!pdev) {
 		dev_err(&pdev->dev, "%s: Platform device null\n", __func__);
@@ -119,7 +165,7 @@ static void adsp_load_fw(struct work_struct *adsp_ldr_work)
 		}
 
 		dev_dbg(&pdev->dev, "%s: Q6/MDSP image is loaded\n", __func__);
-		return;
+		goto success;
 	}
 
 load_adsp:
@@ -153,10 +199,13 @@ load_adsp:
 		}
 
 		dev_dbg(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__);
-		return;
+		apr_register_adsp_state_cb(padsp_restart_cb, adsp_private);
+		goto success;
 	}
 fail:
 	dev_err(&pdev->dev, "%s: Q6 image loading failed\n", __func__);
+success:
+	return;
 }
 
 static void adsp_loader_do(struct platform_device *pdev)
@@ -170,37 +219,24 @@ static ssize_t adsp_ssr_store(struct kobject *kobj,
 	size_t count)
 {
 	int ssr_command = 0;
-	struct subsys_device *adsp_dev = NULL;
 	struct platform_device *pdev = adsp_private;
 	struct adsp_loader_private *priv = NULL;
-	int rc;
+	int rc = -EINVAL;
 
 	dev_dbg(&pdev->dev, "%s: going to call adsp ssr\n ", __func__);
 
-	if (kstrtoint(buf, 10, &ssr_command) < 0)
-		return -EINVAL;
-
-	if (ssr_command != SSR_RESET_CMD)
-		return -EINVAL;
-
 	priv = platform_get_drvdata(pdev);
 	if (!priv)
-		return -EINVAL;
+		return rc;
 
-	adsp_dev = (struct subsys_device *)priv->pil_h;
-	if (!adsp_dev)
+	if (kstrtoint(buf, 10, &ssr_command) < 0)
 		return -EINVAL;
 
-	dev_err(&pdev->dev, "requesting for ADSP restart\n");
-
-	/* subsystem_restart_dev has worker queue to handle */
-	rc = subsystem_restart_dev(adsp_dev);
-	if (rc) {
-		dev_err(&pdev->dev, "subsystem_restart_dev failed\n");
-		return rc;
-	}
+	if (ssr_command != SSR_RESET_CMD)
+		return -EINVAL;
 
-	dev_dbg(&pdev->dev, "ADSP restarted\n");
+	adsp_restart_subsys();
+	dev_dbg(&pdev->dev, "%s :: ADSP restarted\n", __func__);
 	return count;
 }
 

+ 12 - 0
dsp/audio_notifier.c

@@ -606,6 +606,7 @@ static int __init audio_notifier_late_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_MSM_QDSP6_PDR
 static int __init audio_notifier_init(void)
 {
 	int ret;
@@ -624,6 +625,17 @@ static int __init audio_notifier_init(void)
 
 	return 0;
 }
+#else
+static int __init audio_notifier_init(void)
+{
+	audio_notifier_subsys_init();
+	audio_notifier_disable_service(AUDIO_NOTIFIER_PDR_SERVICE);
+
+	audio_notifier_late_init();
+
+	return 0;
+}
+#endif
 module_init(audio_notifier_init);
 
 static void __exit audio_notifier_exit(void)

+ 2 - 2
dsp/digital-cdc-rsc-mgr.c

@@ -87,13 +87,13 @@ void digital_cdc_rsc_mgr_hw_vote_reset(struct clk* vote_handle)
 }
 EXPORT_SYMBOL(digital_cdc_rsc_mgr_hw_vote_reset);
 
-void digital_cdc_rsc_mgr_init()
+void digital_cdc_rsc_mgr_init(void)
 {
 	mutex_init(&hw_vote_lock);
 	is_init_done = true;
 }
 
-void digital_cdc_rsc_mgr_exit()
+void digital_cdc_rsc_mgr_exit(void)
 {
 	mutex_destroy(&hw_vote_lock);
 	is_init_done = false;

+ 43 - 7
dsp/q6adm.c

@@ -67,6 +67,7 @@ struct adm_copp {
 	atomic_t adm_delay_stat[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	uint32_t adm_delay[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 	unsigned long adm_status[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
+	atomic_t token[AFE_MAX_PORTS][MAX_COPPS_PER_PORT];
 };
 
 struct source_tracking_data {
@@ -104,6 +105,7 @@ struct adm_ctl {
 						[PCM_FORMAT_MAX_NUM_CHANNEL_V8];
 	int ffecns_port_id;
 	int native_mode;
+	uint32_t copp_token;
 };
 
 static struct adm_ctl			this_adm;
@@ -280,15 +282,45 @@ static int adm_get_copp_id(int port_idx, int copp_idx)
 	return atomic_read(&this_adm.copp.id[port_idx][copp_idx]);
 }
 
+static int adm_get_idx_if_single_copp_exists(int port_idx,
+			int topology, int mode,
+			int rate, int bit_width,
+			uint32_t copp_token)
+{
+	int idx;
+
+	pr_debug("%s: copp_token %d\n", __func__, copp_token);
+
+	for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
+		if ((topology ==
+			atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
+			(mode ==
+			 atomic_read(&this_adm.copp.mode[port_idx][idx])) &&
+			(rate ==
+			 atomic_read(&this_adm.copp.rate[port_idx][idx])) &&
+			(bit_width ==
+			atomic_read(&this_adm.copp.bit_width[port_idx][idx])) &&
+			(copp_token ==
+			atomic_read(&this_adm.copp.token[port_idx][idx])))
+			return idx;
+	return -EINVAL;
+}
+
 static int adm_get_idx_if_copp_exists(int port_idx, int topology, int mode,
 				 int rate, int bit_width, int app_type,
-				 int session_type)
+				 int session_type, uint32_t copp_token)
 {
 	int idx;
 
 	pr_debug("%s: port_idx-%d, topology-0x%x, mode-%d, rate-%d, bit_width-%d\n",
 		 __func__, port_idx, topology, mode, rate, bit_width);
 
+	if (copp_token)
+		return adm_get_idx_if_single_copp_exists(port_idx,
+				topology, mode,
+				rate, bit_width,
+				copp_token);
+
 	for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++)
 		if ((topology ==
 			atomic_read(&this_adm.copp.topology[port_idx][idx])) &&
@@ -2991,7 +3023,7 @@ exit:
  */
 int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
 	     int perf_mode, uint16_t bit_width, int app_type, int acdb_id,
-	     int session_type)
+	     int session_type, uint32_t passthr_mode, uint32_t copp_token)
 {
 	struct adm_cmd_device_open_v5	open;
 	struct adm_cmd_device_open_v6	open_v6;
@@ -3094,7 +3126,7 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
 		copp_idx = adm_get_idx_if_copp_exists(port_idx, topology,
 						      perf_mode,
 						      rate, bit_width,
-						      app_type, session_type);
+						      app_type, session_type, copp_token);
 
 	if (copp_idx < 0) {
 		copp_idx = adm_get_next_available_copp(port_idx);
@@ -3120,6 +3152,8 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
 			   acdb_id);
 		atomic_set(&this_adm.copp.session_type[port_idx][copp_idx],
 			   session_type);
+		atomic_set(&this_adm.copp.token[port_idx][copp_idx],
+			   copp_token);
 		set_bit(ADM_STATUS_CALIBRATION_REQUIRED,
 		(void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
 		if ((path != ADM_PATH_COMPRESSED_RX) &&
@@ -3205,7 +3239,9 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
 			}
 
 			open_v8.topology_id = topology;
-			open_v8.reserved = 0;
+			open_v8.compressed_data_type = 0;
+			if (passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
+				open_v8.compressed_data_type = 1;
 
 			/* variable endpoint payload */
 			ep1_payload.dev_num_channel = channel_mode & 0x00FF;
@@ -3278,7 +3314,6 @@ int adm_open(int port_id, int path, int rate, int channel_mode, int topology,
 			if ((this_adm.num_ec_ref_rx_chans != 0)
 				&& (path != ADM_PATH_PLAYBACK)
 				&& (open_v8.endpoint_id_2 != 0xFFFF)) {
-				this_adm.num_ec_ref_rx_chans = 0;
 				memcpy(adm_params + sizeof(open_v8)
 						+ ep1_payload_size,
 						(void *)&ep2_payload,
@@ -3905,6 +3940,7 @@ int adm_close(int port_id, int perf_mode, int copp_idx)
 		atomic_set(&this_adm.copp.bit_width[port_idx][copp_idx], 0);
 		atomic_set(&this_adm.copp.app_type[port_idx][copp_idx], 0);
 		atomic_set(&this_adm.copp.session_type[port_idx][copp_idx], 0);
+		atomic_set(&this_adm.copp.token[port_idx][copp_idx], 0);
 
 		clear_bit(ADM_STATUS_CALIBRATION_REQUIRED,
 			(void *)&this_adm.copp.adm_status[port_idx][copp_idx]);
@@ -5358,7 +5394,7 @@ int adm_get_source_tracking(int port_id, int copp_idx,
 	 */
 	param_hdr.param_size =
 		sizeof(struct adm_param_fluence_sourcetracking_t) +
-		sizeof(union param_hdrs);
+		sizeof(struct param_hdr_v3);
 
 	/*
 	 * Retrieving parameters out of band, so no need to provide a buffer for
@@ -5387,7 +5423,7 @@ int adm_get_source_tracking(int port_id, int copp_idx,
 	source_tracking_params =
 		(struct adm_param_fluence_sourcetracking_t
 			 *) (this_adm.sourceTrackingData.memmap.kvaddr +
-			     sizeof(struct param_hdr_v1));
+			     sizeof(struct param_hdr_v3));
 	for (i = 0; i < MAX_SECTORS; i++) {
 		sourceTrackingData->vad[i] = source_tracking_params->vad[i];
 		pr_debug("%s: vad[%d] = %d\n",

+ 210 - 35
dsp/q6afe.c

@@ -24,6 +24,21 @@
 
 #define WAKELOCK_TIMEOUT	5000
 #define AFE_CLK_TOKEN	1024
+
+struct afe_avcs_payload_port_mapping {
+	u16 port_id;
+	struct avcs_load_unload_modules_payload *payload;
+} __packed;
+
+enum {
+	ENCODER_CASE,
+	DECODER_CASE,
+	/* Add new use case here */
+	MAX_ALLOWED_USE_CASES
+};
+
+static struct afe_avcs_payload_port_mapping *pm[MAX_ALLOWED_USE_CASES];
+
 enum {
 	AFE_COMMON_RX_CAL = 0,
 	AFE_COMMON_TX_CAL,
@@ -240,6 +255,124 @@ static bool proxy_afe_started = false;
 #define SIZEOF_CFG_CMD(y) \
 		(sizeof(struct apr_hdr) + sizeof(u16) + (sizeof(struct y)))
 
+static void q6afe_unload_avcs_modules(u16 port_id, int index)
+{
+	int ret = 0;
+
+	ret = q6core_avcs_load_unload_modules(pm[index]->payload,
+			AVCS_UNLOAD_MODULES);
+
+	if (ret < 0)
+		pr_err("%s: avcs module unload failed %d\n", __func__, ret);
+
+	kfree(pm[index]->payload);
+	pm[index]->payload = NULL;
+	kfree(pm[index]);
+	pm[index] = NULL;
+}
+
+static int q6afe_load_avcs_modules(int num_modules, u16 port_id,
+		 uint32_t use_case, u32 format_id)
+{
+	int i = 0;
+	int32_t ret = 0;
+	size_t payload_size = 0, port_struct_size = 0;
+	struct afe_avcs_payload_port_mapping payload_map;
+	struct avcs_load_unload_modules_sec_payload sec_payload;
+
+	if (num_modules <= 0) {
+		pr_err("%s: Invalid number of modules to load\n", __func__);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) {
+		if (pm[i] == NULL) {
+			port_struct_size = sizeof(payload_map);
+			pm[i] = kzalloc(port_struct_size, GFP_KERNEL);
+			if (!pm[i])
+				return -ENOMEM;
+
+			pm[i]->port_id = port_id;
+			payload_size = sizeof(uint32_t) + (sizeof(sec_payload)
+					* num_modules);
+			pm[i]->payload = kzalloc(payload_size, GFP_KERNEL);
+			if (!pm[i]->payload) {
+				kfree(pm[i]);
+				pm[i] = NULL;
+				return -ENOMEM;
+			}
+
+			/*
+			 * index 0 : packetizer/de-packetizer
+			 * index 1 : encoder/decoder
+			 */
+
+			pm[i]->payload->num_modules = num_modules;
+
+			/*
+			 * Remaining fields of payload
+			 * are initialized to zero
+			 */
+
+			if (use_case == ENCODER_CASE) {
+				pm[i]->payload->load_unload_info[0].module_type =
+						AMDB_MODULE_TYPE_PACKETIZER;
+				pm[i]->payload->load_unload_info[0].id1 =
+						AVS_MODULE_ID_PACKETIZER_COP;
+				pm[i]->payload->load_unload_info[1].module_type =
+						AMDB_MODULE_TYPE_ENCODER;
+				pm[i]->payload->load_unload_info[1].id1 =
+						format_id;
+			} else if (use_case == DECODER_CASE) {
+				pm[i]->payload->load_unload_info[0].module_type =
+						AMDB_MODULE_TYPE_DEPACKETIZER;
+				pm[i]->payload->load_unload_info[0].id1 =
+					AVS_MODULE_ID_DEPACKETIZER_COP_V1;
+
+				if (format_id == ENC_CODEC_TYPE_LDAC) {
+					pm[i]->payload->load_unload_info[0].id1 =
+						AVS_MODULE_ID_DEPACKETIZER_COP;
+					goto load_unload;
+				}
+
+				pm[i]->payload->load_unload_info[1].module_type =
+						AMDB_MODULE_TYPE_DECODER;
+				pm[i]->payload->load_unload_info[1].id1 =
+						format_id;
+
+			} else {
+				pr_err("%s:load usecase %d not supported\n",
+					 __func__, use_case);
+				ret = -EINVAL;
+				goto fail;
+			}
+
+load_unload:
+			ret = q6core_avcs_load_unload_modules(pm[i]->payload,
+						 AVCS_LOAD_MODULES);
+
+			if (ret < 0) {
+				pr_err("%s: load failed %d\n", __func__, ret);
+				goto fail;
+			}
+			return 0;
+		}
+
+	}
+
+	ret = -EINVAL;
+	if (i == MAX_ALLOWED_USE_CASES) {
+		pr_err("%s: Not enough ports available\n", __func__);
+		return ret;
+	}
+fail:
+	kfree(pm[i]->payload);
+	pm[i]->payload = NULL;
+	kfree(pm[i]);
+	pm[i] = NULL;
+	return ret;
+}
+
 static int afe_get_cal_hw_delay(int32_t path,
 				struct audio_cal_hw_delay_entry *entry);
 static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
@@ -2738,7 +2871,7 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port(
 		/* Skip cal_block if it is already marked stale */
 		if (cal_utils_is_cal_stale(cal_block))
 			continue;
-		pr_info("%s: port id: 0x%x, dev_acdb_id: %d\n", __func__,
+		pr_debug("%s: port id: 0x%x, dev_acdb_id: %d\n", __func__,
 			 port_id, this_afe.dev_acdb_id[afe_port_index]);
 		path = ((afe_get_port_type(port_id) ==
 			MSM_AFE_PORT_TYPE_TX)?(TX_DEVICE):(RX_DEVICE));
@@ -2748,14 +2881,14 @@ static struct cal_block_data *afe_find_cal_topo_id_by_port(
 			if (this_afe.dev_acdb_id[afe_port_index] > 0) {
 				if (afe_top->acdb_id ==
 				    this_afe.dev_acdb_id[afe_port_index]) {
-					pr_info("%s: top_id:%x acdb_id:%d afe_port_id:0x%x\n",
+					pr_debug("%s: top_id:%x acdb_id:%d afe_port_id:0x%x\n",
 						 __func__, afe_top->topology,
 						 afe_top->acdb_id,
 						 q6audio_get_port_id(port_id));
 					return cal_block;
 				}
 			} else {
-				pr_info("%s: top_id:%x acdb_id:%d afe_port:0x%x\n",
+				pr_debug("%s: top_id:%x acdb_id:%d afe_port:0x%x\n",
 				 __func__, afe_top->topology, afe_top->acdb_id,
 				 q6audio_get_port_id(port_id));
 				return cal_block;
@@ -2869,7 +3002,7 @@ static int afe_send_port_topology_id(u16 port_id)
 	this_afe.topology[index] = topology_id;
 	rtac_update_afe_topology(port_id);
 done:
-	pr_info("%s: AFE set topology id 0x%x  enable for port 0x%x ret %d\n",
+	pr_debug("%s: AFE set topology id 0x%x  enable for port 0x%x ret %d\n",
 			__func__, topology_id, port_id, ret);
 	return ret;
 
@@ -3186,7 +3319,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
 	struct audio_cal_info_afe *afe_cal_info = NULL;
 	int afe_port_index = q6audio_get_port_index(port_id);
 
-	pr_info("%s: cal_index %d port_id 0x%x port_index %d\n", __func__,
+	pr_debug("%s: cal_index %d port_id 0x%x port_index %d\n", __func__,
 		  cal_index, port_id, afe_port_index);
 	if (afe_port_index < 0) {
 		pr_err("%s: Error getting AFE port index %d\n",
@@ -3198,7 +3331,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
 			   &this_afe.cal_data[cal_index]->cal_blocks) {
 		cal_block = list_entry(ptr, struct cal_block_data, list);
 		afe_cal_info = cal_block->cal_info;
-		pr_info("%s: acdb_id %d dev_acdb_id %d sample_rate %d afe_sample_rates %d\n",
+		pr_debug("%s: acdb_id %d dev_acdb_id %d sample_rate %d afe_sample_rates %d\n",
 			__func__, afe_cal_info->acdb_id,
 			this_afe.dev_acdb_id[afe_port_index],
 			afe_cal_info->sample_rate,
@@ -3207,7 +3340,7 @@ static struct cal_block_data *afe_find_cal(int cal_index, int port_id)
 		     this_afe.dev_acdb_id[afe_port_index]) &&
 		    (afe_cal_info->sample_rate ==
 		     this_afe.afe_sample_rates[afe_port_index])) {
-			pr_info("%s: cal block is a match, size is %zd\n",
+			pr_debug("%s: cal block is a match, size is %zd\n",
 				 __func__, cal_block->cal_data.size);
 			goto exit;
 		}
@@ -3225,7 +3358,7 @@ static int send_afe_cal_type(int cal_index, int port_id)
 	int ret;
 	int afe_port_index = q6audio_get_port_index(port_id);
 
-	pr_info("%s: cal_index is %d\n", __func__, cal_index);
+	pr_debug("%s: cal_index is %d\n", __func__, cal_index);
 
 	if (this_afe.cal_data[cal_index] == NULL) {
 		pr_warn("%s: cal_index %d not allocated!\n",
@@ -3242,7 +3375,7 @@ static int send_afe_cal_type(int cal_index, int port_id)
 	}
 
 	mutex_lock(&this_afe.cal_data[cal_index]->lock);
-	pr_info("%s: dev_acdb_id[%d] is %d\n",
+	pr_debug("%s: dev_acdb_id[%d] is %d\n",
 			__func__, afe_port_index,
 			this_afe.dev_acdb_id[afe_port_index]);
 	if (((cal_index == AFE_COMMON_RX_CAL) ||
@@ -3260,7 +3393,7 @@ static int send_afe_cal_type(int cal_index, int port_id)
 		goto unlock;
 	}
 
-	pr_info("%s: Sending cal_index cal %d\n", __func__, cal_index);
+	pr_debug("%s: Sending cal_index cal %d\n", __func__, cal_index);
 
 	ret = remap_cal_data(cal_block, cal_index);
 	if (ret) {
@@ -5267,7 +5400,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
 		port_id = VIRTUAL_ID_TO_PORTID(port_id);
 	}
 
-	pr_info("%s: port id: 0x%x\n", __func__, port_id);
+	pr_debug("%s: port id: 0x%x\n", __func__, port_id);
 
 	index = q6audio_get_port_index(port_id);
 	if (index < 0 || index >= AFE_MAX_PORTS) {
@@ -5514,8 +5647,21 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	if ((codec_format != ASM_MEDIA_FMT_NONE) &&
 	    (cfg_type == AFE_PARAM_ID_SLIMBUS_CONFIG)) {
 		if (enc_cfg != NULL) {
-			pr_debug("%s: Found AFE encoder support for SLIMBUS format = %d\n",
+			pr_debug("%s: Found AFE encoder support  for SLIMBUS format = %d\n",
 						__func__, codec_format);
+
+			if ((q6core_get_avcs_api_version_per_service(
+				APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >=
+						AVCS_API_VERSION_V5)) {
+				ret = q6afe_load_avcs_modules(2, port_id,
+					ENCODER_CASE, codec_format);
+				if (ret < 0) {
+					pr_err("%s:encoder load for port 0x%x failed %d\n",
+						__func__, port_id, ret);
+					goto fail_cmd;
+				}
+			}
+
 			ret = q6afe_send_enc_config(port_id, enc_cfg,
 						    codec_format, *afe_config,
 						    afe_in_channels,
@@ -5529,7 +5675,28 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
 		}
 		if (dec_cfg != NULL) {
 			pr_debug("%s: Found AFE decoder support for SLIMBUS format = %d\n",
-				  __func__, codec_format);
+				__func__, codec_format);
+
+			if ((q6core_get_avcs_api_version_per_service(
+				APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >=
+				AVCS_API_VERSION_V5)) {
+				/*
+				 * LDAC and APTX_ADAPTIVE don't require loading decoder module
+				 * Only loading de-packetizer module.
+				 */
+				if (codec_format == ENC_CODEC_TYPE_LDAC ||
+					codec_format == ASM_MEDIA_FMT_APTX_ADAPTIVE)
+					ret = q6afe_load_avcs_modules(1, port_id,
+						DECODER_CASE, codec_format);
+				else
+					ret = q6afe_load_avcs_modules(2, port_id,
+						DECODER_CASE, codec_format);
+				if (ret < 0) {
+					pr_err("%s:decoder load for port 0x%x failed %d\n",
+						__func__, port_id, ret);
+					goto fail_cmd;
+				}
+			}
 			ret = q6afe_send_dec_config(port_id, *afe_config,
 						    dec_cfg, codec_format,
 						    afe_in_channels,
@@ -8341,6 +8508,7 @@ int afe_close(int port_id)
 	struct afe_port_cmd_device_stop stop;
 	enum afe_mad_type mad_type;
 	int ret = 0;
+	u16 i;
 	int index = 0;
 	uint16_t port_index;
 
@@ -8356,7 +8524,7 @@ int afe_close(int port_id)
 		ret = -EINVAL;
 		goto fail_cmd;
 	}
-	pr_info("%s: port_id = 0x%x\n", __func__, port_id);
+	pr_debug("%s: port_id = 0x%x\n", __func__, port_id);
 	if ((port_id == RT_PROXY_DAI_001_RX) ||
 			(port_id == RT_PROXY_DAI_002_TX)) {
 		pr_debug("%s: before decrementing pcm_afe_instance %d\n",
@@ -8463,6 +8631,15 @@ int afe_close(int port_id)
 		pr_err("%s: AFE close failed %d\n", __func__, ret);
 
 fail_cmd:
+	if ((q6core_get_avcs_api_version_per_service(
+		APRV2_IDS_SERVICE_ID_ADSP_CORE_V) >= AVCS_API_VERSION_V5)) {
+		for (i = 0; i < MAX_ALLOWED_USE_CASES; i++) {
+			if (pm[i] && pm[i]->port_id == port_id) {
+				q6afe_unload_avcs_modules(port_id, i);
+				break;
+			}
+		}
+	}
 	mutex_unlock(&this_afe.afe_cmd_lock);
 	return ret;
 }
@@ -9589,29 +9766,27 @@ int afe_spk_prot_feed_back_cfg(int src_port, int dst_port,
 		}
 		this_afe.v4_ch_map_cfg.num_channels = index;
 		this_afe.num_spkrs = index / 2;
-		pr_debug("%s no of channels: %d\n", __func__, index);
-		this_afe.vi_tx_port = src_port;
-		this_afe.vi_rx_port = dst_port;
-		ret = 0;
-	} else {
-		memset(&prot_config, 0, sizeof(prot_config));
-		prot_config.feedback_path_cfg.dst_portid =
+	}
+
+	index = 0;
+	memset(&prot_config, 0, sizeof(prot_config));
+	prot_config.feedback_path_cfg.dst_portid =
 		q6audio_get_port_id(dst_port);
-		if (l_ch) {
-			prot_config.feedback_path_cfg.chan_info[index++] = 1;
-			prot_config.feedback_path_cfg.chan_info[index++] = 2;
-		}
-		if (r_ch) {
-			prot_config.feedback_path_cfg.chan_info[index++] = 3;
-			prot_config.feedback_path_cfg.chan_info[index++] = 4;
-		}
-		prot_config.feedback_path_cfg.num_channels = index;
-		pr_debug("%s no of channels: %d\n", __func__, index);
-		prot_config.feedback_path_cfg.minor_version = 1;
-		ret = afe_spk_prot_prepare(src_port, dst_port,
-				AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config,
-				 sizeof(union afe_spkr_prot_config));
+	if (l_ch) {
+		prot_config.feedback_path_cfg.chan_info[index++] = 1;
+		prot_config.feedback_path_cfg.chan_info[index++] = 2;
 	}
+	if (r_ch) {
+		prot_config.feedback_path_cfg.chan_info[index++] = 3;
+		prot_config.feedback_path_cfg.chan_info[index++] = 4;
+	}
+
+	prot_config.feedback_path_cfg.num_channels = index;
+	pr_debug("%s no of channels: %d\n", __func__, index);
+	prot_config.feedback_path_cfg.minor_version = 1;
+	ret = afe_spk_prot_prepare(src_port, dst_port,
+			AFE_PARAM_ID_FEEDBACK_PATH_CFG, &prot_config,
+			 sizeof(union afe_spkr_prot_config));
 
 fail_cmd:
 	return ret;

+ 4 - 0
dsp/q6asm.c

@@ -3097,6 +3097,10 @@ int q6asm_open_read_compressed(struct audio_client *ac, uint32_t format,
 		open.mode_flags = 0x1;
 		open.frames_per_buf = 1;
 		pr_debug("%s: Flag 1 IEC61937 output\n", __func__);
+	} else if (format == FORMAT_DSD) {
+		open.mode_flags = ASM_DSD_FORMAT_FLAG;
+		open.frames_per_buf = 1;
+		pr_debug("%s: Flag 2 DSD output\n", __func__);
 	} else {
 		open.mode_flags = 0;
 		open.frames_per_buf = 1;

+ 136 - 2
dsp/q6core.c

@@ -61,9 +61,11 @@ struct q6core_str {
 	wait_queue_head_t cmd_req_wait;
 	wait_queue_head_t avcs_fwk_ver_req_wait;
 	wait_queue_head_t lpass_npa_rsc_wait;
+	wait_queue_head_t avcs_module_load_unload_wait;
 	u32 lpass_npa_rsc_rsp_rcvd;
 	u32 bus_bw_resp_received;
 	u32 mdf_map_resp_received;
+	u32 avcs_module_resp_received;
 	enum cmd_flags {
 		FLAG_NONE,
 		FLAG_CMDRSP_LICENSE_RESULT
@@ -87,6 +89,9 @@ struct q6core_str {
 
 static struct q6core_str q6core_lcl;
 
+/* Global payload used for AVCS_CMD_RSP_MODULES command */
+static struct avcs_load_unload_modules_payload *rsp_payload;
+
 struct generic_get_data_ {
 	int valid;
 	int size_in_ints;
@@ -343,6 +348,29 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
 			q6core_lcl.lpass_npa_rsc_rsp_rcvd = 1;
 			wake_up(&q6core_lcl.lpass_npa_rsc_wait);
 			break;
+		case AVCS_CMD_LOAD_MODULES:
+			pr_err("%s: Cmd = %s failed status[%s]\n",
+				__func__, "AVCS_CMD_LOAD__MODULES",
+				adsp_err_get_err_str(payload1[1]));
+			q6core_lcl.avcs_module_resp_received = 1;
+			q6core_lcl.adsp_status = -payload1[1];
+			wake_up(&q6core_lcl.avcs_module_load_unload_wait);
+			break;
+		case AVCS_CMD_UNLOAD_MODULES:
+			if (payload1[1] == ADSP_EOK) {
+				pr_debug("%s: Cmd = %s success status[%s]\n",
+					__func__, "AVCS_CMD_UNLOAD_MODULES",
+					"ADSP_EOK");
+			} else {
+				pr_err("%s: Cmd = %s failed status[%s]\n",
+					__func__, "AVCS_CMD_UNLOAD_MODULES",
+				adsp_err_get_err_str(payload1[1]));
+				q6core_lcl.adsp_status = -payload1[1];
+			}
+			q6core_lcl.avcs_module_resp_received = 1;
+			wake_up(&q6core_lcl.avcs_module_load_unload_wait);
+			break;
+
 		default:
 			pr_err("%s: Invalid cmd rsp[0x%x][0x%x] opcode %d\n",
 					__func__,
@@ -441,6 +469,13 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv)
 		q6core_lcl.avcs_fwk_ver_resp_received = 1;
 		wake_up(&q6core_lcl.avcs_fwk_ver_req_wait);
 		break;
+	case AVCS_CMD_RSP_LOAD_MODULES:
+		pr_debug("%s: Received AVCS_CMD_RSP_LOAD_MODULES\n",
+			 __func__);
+		memcpy(rsp_payload, data->payload, data->payload_size);
+		q6core_lcl.avcs_module_resp_received = 1;
+		wake_up(&q6core_lcl.avcs_module_load_unload_wait);
+		break;
 	default:
 		pr_err("%s: Message id from adsp core svc: 0x%x\n",
 			__func__, data->opcode);
@@ -821,7 +856,6 @@ int32_t core_get_license_status(uint32_t module_id)
 	get_lvr_cmd.hdr.opcode = AVCS_CMD_GET_LICENSE_VALIDATION_RESULT;
 	get_lvr_cmd.id = module_id;
 
-
 	ret = apr_send_pkt(q6core_lcl.core_handle_q, (uint32_t *) &get_lvr_cmd);
 	if (ret < 0) {
 		pr_err("%s: license_validation request failed, err %d\n",
@@ -894,6 +928,106 @@ uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
 }
 EXPORT_SYMBOL(core_set_dolby_manufacturer_id);
 
+int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload
+				 *payload, uint32_t preload_type)
+{
+	int ret = 0;
+	size_t packet_size = 0,  payload_size = 0;
+	struct avcs_cmd_dynamic_modules *mod = NULL;
+	int num_modules;
+
+	if (payload == NULL) {
+		pr_err("%s: payload is null\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&(q6core_lcl.cmd_lock));
+	num_modules = payload->num_modules;
+	ocm_core_open();
+
+	if (q6core_lcl.core_handle_q == NULL) {
+		pr_err("%s: apr registration for CORE failed\n", __func__);
+		mutex_unlock(&(q6core_lcl.cmd_lock));
+		return -ENODEV;
+	}
+
+	payload_size = (sizeof(struct avcs_load_unload_modules_sec_payload)
+			* num_modules) + sizeof(uint32_t);
+	packet_size = sizeof(struct avcs_cmd_dynamic_modules) +
+			payload_size - sizeof(uint32_t);
+	mod = kzalloc(packet_size, GFP_KERNEL);
+
+	if (!mod) {
+		mutex_unlock(&(q6core_lcl.cmd_lock));
+		return -ENOMEM;
+	}
+
+	rsp_payload = kzalloc(payload_size, GFP_KERNEL);
+	if (!rsp_payload) {
+		kfree(mod);
+		mutex_unlock(&(q6core_lcl.cmd_lock));
+		return -ENOMEM;
+	}
+
+	memcpy((uint8_t *)mod + sizeof(struct apr_hdr) +
+		sizeof(struct avcs_load_unload_modules_meminfo),
+		payload, payload_size);
+
+	mod->hdr.hdr_field =
+			APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	mod->hdr.pkt_size = packet_size;
+	mod->hdr.src_port = 0;
+	mod->hdr.dest_port = 0;
+	mod->hdr.token = 0;
+	mod->meminfo.data_payload_addr_lsw = 0;
+	mod->meminfo.data_payload_addr_msw = 0;
+	mod->meminfo.mem_map_handle = 0;
+	mod->meminfo.buffer_size = payload_size;
+
+	if (preload_type == AVCS_LOAD_MODULES)
+		mod->hdr.opcode =  AVCS_CMD_LOAD_MODULES;
+	else
+		mod->hdr.opcode =  AVCS_CMD_UNLOAD_MODULES;
+
+	q6core_lcl.adsp_status = 0;
+	q6core_lcl.avcs_module_resp_received = 0;
+	ret = apr_send_pkt(q6core_lcl.core_handle_q,
+		(uint32_t *)mod);
+
+	if (ret < 0) {
+		pr_err("%s: modules load/unload failed ret = %d\n",
+			__func__, ret);
+		goto done;
+	}
+
+	ret = wait_event_timeout(q6core_lcl.avcs_module_load_unload_wait,
+				(q6core_lcl.avcs_module_resp_received == 1),
+				msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s wait event timeout for avcs load/unload module\n",
+			__func__);
+		ret = -ETIMEDOUT;
+		goto done;
+	}
+
+	if (q6core_lcl.adsp_status < 0) {
+		pr_err("%s: modules load/unload failed %d\n", __func__,
+				q6core_lcl.adsp_status);
+		ret = q6core_lcl.adsp_status;
+		goto done;
+	} else {
+		if (mod->hdr.opcode == AVCS_CMD_LOAD_MODULES)
+			memcpy(payload, rsp_payload, payload_size);
+	}
+done:
+	kfree(mod);
+	kfree(rsp_payload);
+	mutex_unlock(&(q6core_lcl.cmd_lock));
+	return ret;
+}
+EXPORT_SYMBOL(q6core_avcs_load_unload_modules);
+
 int32_t q6core_load_unload_topo_modules(uint32_t topo_id,
 			bool preload_type)
 {
@@ -1871,7 +2005,6 @@ static int q6core_probe(struct platform_device *pdev)
 	if (rc < 0)
 		goto err;
 	q6core_lcl.avs_state = avs_state;
-
 	rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 	if (rc) {
 		dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
@@ -1926,6 +2059,7 @@ int __init core_init(void)
 	init_waitqueue_head(&q6core_lcl.avcs_fwk_ver_req_wait);
 	init_waitqueue_head(&q6core_lcl.mdf_map_resp_wait);
 	init_waitqueue_head(&q6core_lcl.lpass_npa_rsc_wait);
+	init_waitqueue_head(&q6core_lcl.avcs_module_load_unload_wait);
 	q6core_lcl.cmd_resp_received_flag = FLAG_NONE;
 	mutex_init(&q6core_lcl.cmd_lock);
 	mutex_init(&q6core_lcl.ver_lock);

+ 2 - 0
dsp/q6voice.c

@@ -515,6 +515,8 @@ static void voc_set_error_state(uint16_t reset_proc)
 		if (v != NULL) {
 			v->voc_state = VOC_ERROR;
 			v->rec_info.recording = 0;
+			v->music_info.playing = 0;
+			v->music_info.force = 0;
 		}
 	}
 }

+ 1 - 0
include/asoc/wcd-mbhc-v2.h

@@ -551,6 +551,7 @@ struct wcd_mbhc {
 	wait_queue_head_t wait_btn_press;
 	bool is_btn_press;
 	u8 current_plug;
+	u8 plug_before_ssr;
 	bool in_swch_irq_handler;
 	bool hphl_swh; /*track HPHL switch NC / NO */
 	bool gnd_swh; /*track GND switch NC / NO */

+ 28 - 1
include/dsp/apr_audio-v2.h

@@ -598,7 +598,7 @@ struct adm_cmd_device_open_v8 {
  * In all other use cases this should be set to 0xffff
  */
 
-	u16                  reserved;
+	u16 compressed_data_type;
 } __packed;
 
 /*
@@ -2557,6 +2557,7 @@ struct afe_port_data_cmd_rt_proxy_port_read_v2 {
 #define AFE_GENERIC_COMPRESSED           0x8
 #define AFE_LINEAR_PCM_DATA_PACKED_16BIT 0X6
 #define AFE_DSD_DOP_W_MARKER_DATA        0x9
+#define AFE_DSD_DATA                     0xA
 
 /* This param id is used to configure I2S interface */
 #define AFE_PARAM_ID_I2S_CONFIG	0x0001020D
@@ -4142,6 +4143,16 @@ struct afe_id_aptx_adaptive_enc_init
 #define AFE_MODULE_ID_DEPACKETIZER_COP        0x00013233
 #define AFE_MODULE_ID_DEPACKETIZER_COP_V1     0x000132E9
 
+/* Macros for dynamic loading of modules by AVCS */
+
+#define AVS_MODULE_ID_PACKETIZER_COP        0x0001322A
+
+#define AVS_MODULE_ID_PACKETIZER_COP_V1     0x000132E8
+
+#define AVS_MODULE_ID_DEPACKETIZER_COP      0x00013233
+
+#define AVS_MODULE_ID_DEPACKETIZER_COP_V1   0x000132E9
+
 /*
  * Depacketizer type parameter for the #AVS_MODULE_ID_DECODER module.
  * This parameter cannot be set runtime.
@@ -8957,6 +8968,13 @@ struct asm_data_cmd_remove_silence {
 /* Shift value for the IEC 61937 to 61937 pass-through capture. */
 #define ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG           0
 
+/* Bitmask for the DSD pass-through capture. */
+#define ASM_BIT_MASK_COMPRESSED_FORMAT_FLAG             (0x00000003UL)
+
+/* Shift value for the DSD pass-through capture. */
+#define ASM_SHIFT_DSD_COMPRESSED_FORMAT_FLAG            0
+
+#define ASM_DSD_FORMAT_FLAG                             2
 struct asm_stream_cmd_open_read_compressed {
 	struct apr_hdr hdr;
 	u32                    mode_flags;
@@ -8968,6 +8986,12 @@ struct asm_stream_cmd_open_read_compressed {
  * - Use #ASM_BIT_MASK_IEC_61937_PASS_THROUGH_FLAG to set the bitmask
  *   and #ASM_SHIFT_IEC_61937_PASS_THROUGH_FLAG to set the shift value
  *   for this bit.
+ * Supported values for bit 1: (DSD native pass-through mode)
+ * 0 -- non DSD operation
+ * 1 -- Pass-through transfer of the DSD format stream
+ * To set this bit, use #ASM_BIT_MASK_DSD_PASS_THROUGH_FLAG and
+ * use #ASM_SHIFT_DSD_PASS_THROUGH_FLAG to set the shift value for
+ * this bit
  * Supported values for bit 4:
  * - 0 -- Return data buffer contains all encoded frames only; it does
  *      not contain frame metadata.
@@ -8984,6 +9008,9 @@ struct asm_stream_cmd_open_read_compressed {
  * Supported values: should be greater than 0 for IEC to RAW compressed
  *                   unpack mode.
  *                   Value is don't care for IEC 61937 pass-through mode.
+ * @values
+ * - >0 -- For IEC 61937-to-RAW Compressed Unpack mode
+ * - 1  -- For IEC 61937 or DSD Pass-through mode
  */
 
 } __packed;

+ 2 - 1
include/dsp/q6adm-v2.h

@@ -119,7 +119,8 @@ int adm_pack_and_set_one_pp_param(int port_id, int copp_idx,
 
 int adm_open(int port, int path, int rate, int mode, int topology,
 			   int perf_mode, uint16_t bits_per_sample,
-			   int app_type, int acdbdev_id, int session_type);
+			   int app_type, int acdbdev_id, int session_type,
+			   uint32_t pass_thr, uint32_t copp_token);
 
 int adm_map_rtac_block(struct rtac_cal_block_data *cal_block);
 

+ 121 - 0
include/dsp/q6core.h

@@ -13,6 +13,7 @@
 #define AVCS_CMD_ADSP_EVENT_GET_STATE		0x0001290C
 #define AVCS_CMDRSP_ADSP_EVENT_GET_STATE	0x0001290D
 #define AVCS_API_VERSION_V4		4
+#define AVCS_API_VERSION_V5		5
 #define APRV2_IDS_SERVICE_ID_ADSP_CORE_V (0x3)
 
 bool q6core_is_adsp_ready(void);
@@ -198,6 +199,126 @@ struct avcs_cmd_load_unload_topo_modules {
 	uint32_t topology_id;
 } __packed;
 
+#define AVCS_LOAD_MODULES 1
+
+#define AVCS_UNLOAD_MODULES 0
+
+#define AVCS_CMD_LOAD_MODULES           0x00012989
+
+#define AVCS_CMD_UNLOAD_MODULES         0x0001298A
+
+#define AVCS_CMD_RSP_LOAD_MODULES       0x0001298B
+
+/*
+ * Module is generic, such as a preprocessor,
+ * postprocessor, or volume control
+ *  module.
+ */
+#define AMDB_MODULE_TYPE_GENERIC           0
+
+/** Module is a decoder. */
+#define AMDB_MODULE_TYPE_DECODER           1
+
+/** Module is an encoder. */
+#define AMDB_MODULE_TYPE_ENCODER           2
+
+/** Module is a converter. */
+#define AMDB_MODULE_TYPE_CONVERTER         3
+
+/** Module is a packetizer. */
+#define AMDB_MODULE_TYPE_PACKETIZER        4
+
+/** Module is a depacketizer. */
+#define AMDB_MODULE_TYPE_DEPACKETIZER      5
+
+
+struct avcs_load_unload_modules_sec_payload {
+	uint32_t       module_type;
+	/*
+	 * < Type of module.
+
+	 * @values
+	 * - #AMDB_MODULE_TYPE_GENERIC
+	 * - #AMDB_MODULE_TYPE_DECODER
+	 * - #AMDB_MODULE_TYPE_ENCODER
+	 * - #AMDB_MODULE_TYPE_CONVERTER
+	 * - #AMDB_MODULE_TYPE_PACKETIZER
+	 * - #AMDB_MODULE_TYPE_DEPACKETIZER
+	 */
+
+
+	uint32_t       id1;
+	/*
+	 * < One of the following types of IDs:
+	 * - Format ID for the encoder, decoder, and packetizer module types
+	 * - Module ID for the generic module type
+	 * - Source format ID for the converter module type
+	 */
+
+	uint32_t       id2;
+	/*
+	 * < Sink format ID for the converter module type.
+	 * Zero for other module types
+	 */
+
+	uint32_t handle_lsw;
+	/* < LSW of the Handle to the module loaded */
+
+	uint32_t handle_msw;
+	/* < MSW of the Handle to the module loaded. */
+} __packed;
+
+struct avcs_load_unload_modules_payload {
+	uint32_t num_modules;
+	/**< Number of modules being registered */
+
+	struct avcs_load_unload_modules_sec_payload load_unload_info[0];
+	/*
+	 * < Load/unload information for num_modules.
+	 * It will be of type avcs_load_unload_info_t[num_modules]
+	 */
+} __packed;
+
+struct avcs_load_unload_modules_meminfo {
+	uint32_t                  data_payload_addr_lsw;
+	/**< Lower 32 bits of the 64-bit data payload address. */
+
+	uint32_t                  data_payload_addr_msw;
+	/**< Upper 32 bits of the 64-bit data payload address. */
+
+	uint32_t                  mem_map_handle;
+	/*
+	 * < Unique identifier for an address. The aDSP returns this memory map
+	 * handle through the #AVCS_CMD_SHARED_MEM_MAP_REGIONS command.
+
+	 * @values @vertspace{-2}
+	 * - NULL -- Parameter data payloads are within the message payload
+	 * (in-band).
+	 * - Non-NULL -- Parameter data payloads begin at the address specified
+	 * in the data_payload_addr_lsw and data_payload_addr_msw fields
+	 * (out-of-band).
+
+	 * The client can choose in-band or out-of-band
+	 */
+
+	uint32_t                  buffer_size;
+	/*
+	 * < Actual size (in bytes) of the valid data
+	 * in the data payload address.
+	 */
+} __packed;
+
+struct avcs_cmd_dynamic_modules {
+	struct apr_hdr hdr;
+	struct avcs_load_unload_modules_meminfo meminfo;
+	struct avcs_load_unload_modules_payload payload;
+} __packed;
+
+
+int32_t q6core_avcs_load_unload_modules(struct avcs_load_unload_modules_payload *payload,
+				uint32_t preload_type);
+
+
 /* This command allows a remote client(HLOS) creates a client to LPASS NPA
  * resource node. Currently, this command supports only the NPA Sleep resource
  * "/island/core/drivers" node ID.

+ 10 - 1
include/ipc/apr.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2010-2017, 2019, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2017, 2019, 2020, The Linux Foundation. All rights reserved.
  */
 #ifndef __APR_H_
 #define __APR_H_
@@ -12,6 +12,7 @@ enum apr_subsys_state {
 	APR_SUBSYS_DOWN,
 	APR_SUBSYS_UP,
 	APR_SUBSYS_LOADED,
+	APR_SUBSYS_UNKNOWN,
 };
 
 struct apr_q6 {
@@ -19,6 +20,13 @@ struct apr_q6 {
 	atomic_t q6_state;
 	atomic_t modem_state;
 	struct mutex lock;
+/*
+ * ToDo - Multiple client support to be added.
+ * And checking for state UNKNOWN currently.
+ */
+	void (*state_notify_cb)(enum apr_subsys_state state,
+				void *client_handle);
+	void *client_handle;
 };
 
 struct apr_hdr {
@@ -186,4 +194,5 @@ const char *apr_get_lpass_subsys_name(void);
 uint16_t apr_get_reset_domain(uint16_t proc);
 int apr_start_rx_rt(void *handle);
 int apr_end_rx_rt(void *handle);
+void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle);
 #endif

+ 5 - 1
include/uapi/audio/linux/msm_audio_calibration.h

@@ -126,6 +126,7 @@ enum {
 #define TOPOLOGY_SPECIFIC_CHANNEL_INFO
 #define MSM_SPKR_PROT_SPV3
 #define MSM_SPKR_PROT_SPV4
+#define MSM_CMA_MEM_ALLOC
 
 enum {
 	VERSION_0_0,
@@ -156,7 +157,10 @@ struct audio_cal_data {
 	__s32		cal_size;
 	/* If mem_handle if shared memory is used*/
 	__s32		mem_handle;
-	/* size of virtual memory if shared memory not used */
+#ifdef MSM_CMA_MEM_ALLOC
+	/* cma allocation flag if cma heap memory is used */
+	__u32		cma_mem;
+#endif
 };
 
 

+ 90 - 0
include/uapi/audio/sound/audio_compressed_formats.h

@@ -0,0 +1,90 @@
+#ifndef __AUDIO_COMPRESSED_FORMATS_H
+#define __AUDIO_COMPRESSED_FORMATS_H
+
+#include <linux/types.h>
+
+#define AUDIO_COMP_FORMAT_ALAC 0x1
+#define AUDIO_COMP_FORMAT_APE 0x2
+#define AUDIO_COMP_FORMAT_APTX 0x3
+#define AUDIO_COMP_FORMAT_DSD 0x4
+#define AUDIO_COMP_FORMAT_FLAC 0x5
+#define AUDIO_COMP_FORMAT_VORBIS 0x6
+#define AUDIO_COMP_FORMAT_WMA 0x7
+#define AUDIO_COMP_FORMAT_WMA_PRO 0x8
+
+#define SND_COMPRESS_DEC_HDR
+struct snd_generic_dec_aac {
+	__u16 audio_obj_type;
+	__u16 pce_bits_size;
+} __attribute__((packed, aligned(4)));
+
+struct snd_generic_dec_flac {
+	__u16 sample_size;
+	__u16 min_blk_size;
+	__u16 max_blk_size;
+	__u16 min_frame_size;
+	__u16 max_frame_size;
+} __attribute__((packed, aligned(4)));
+
+struct snd_generic_dec_alac {
+	__u32 frame_length;
+	__u8 compatible_version;
+	__u8 bit_depth;
+	__u8 pb;
+	__u8 mb;
+	__u8 kb;
+	__u8 num_channels;
+	__u16 max_run;
+	__u32 max_frame_bytes;
+	__u32 avg_bit_rate;
+	__u32 sample_rate;
+	__u32 channel_layout_tag;
+} __attribute__((packed, aligned(4)));
+
+struct snd_generic_dec_ape {
+	__u16 compatible_version;
+	__u16 compression_level;
+	__u32 format_flags;
+	__u32 blocks_per_frame;
+	__u32 final_frame_blocks;
+	__u32 total_frames;
+	__u16 bits_per_sample;
+	__u16 num_channels;
+	__u32 sample_rate;
+	__u32 seek_table_present;
+} __attribute__((packed, aligned(4)));
+
+struct snd_generic_dec_wma {
+	__u32 super_block_align;
+	__u32 bits_per_sample;
+	__u32 channelmask;
+	__u32 encodeopt;
+	__u32 encodeopt1;
+	__u32 encodeopt2;
+	__u32 avg_bit_rate;
+} __attribute__((packed, aligned(4)));
+
+#define SND_DEC_WMA_EXTENTED_SUPPORT
+
+struct snd_generic_dec_aptx {
+	__u32 lap;
+	__u32 uap;
+	__u32 nap;
+} __attribute__((packed, aligned(4)));
+
+struct snd_generic_dec_vorbis {
+	__u32 bit_stream_fmt;
+} __attribute__((packed, aligned(4)));
+
+/** struct snd_generic_dec_dsd - codec for DSD format
+ * @blk_size - dsd channel block size
+ */
+struct snd_generic_dec_dsd {
+	__u32 blk_size;
+} __attribute__((packed, aligned(4)));
+
+struct snd_generic_dec_amrwb_plus {
+	__u32 bit_stream_fmt;
+} __attribute__((packed, aligned(4)));
+
+#endif

+ 35 - 3
ipc/apr.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2010-2014, 2016-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 2016-2020 The Linux Foundation. All rights reserved.
  */
 
 #include <linux/kernel.h>
@@ -32,9 +32,14 @@
 
 #define APR_PKT_IPC_LOG_PAGE_CNT 2
 
+static int apr_pkt_cnt_adsp_restart = 20;
+module_param(apr_pkt_cnt_adsp_restart, int, 0664);
+MODULE_PARM_DESC(apr_pkt_cnt_adsp_restart, "set apr pktcount for adsp restart feature");
+
 static struct apr_q6 q6;
 static struct apr_client client[APR_DEST_MAX][APR_CLIENT_MAX];
 static void *apr_pkt_ctx;
+static int apr_send_pkt_count;
 static wait_queue_head_t modem_wait;
 static bool is_modem_up;
 static char *subsys_name = NULL;
@@ -61,6 +66,8 @@ struct apr_private {
 
 static struct apr_private *apr_priv;
 static bool apr_cf_debug;
+static struct work_struct apr_cb_work;
+static void state_notify_cb(struct work_struct *work);
 
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *debugfs_apr_debug;
@@ -313,6 +320,7 @@ static void apr_adsp_up(void)
 		schedule_work(&apr_priv->add_chld_dev_work);
 	spin_unlock(&apr_priv->apr_lock);
 	snd_event_notify(apr_priv->dev, SND_EVENT_UP);
+	cancel_work_sync(&apr_cb_work);
 }
 
 int apr_load_adsp_image(void)
@@ -415,7 +423,7 @@ int apr_send_pkt(void *handle, uint32_t *buf)
 		w_len = rc;
 		if (w_len != hdr->pkt_size) {
 			pr_err("%s: Unable to write whole APR pkt successfully: %d\n",
-			       __func__, rc);
+				__func__, rc);
 			rc = -EINVAL;
 		}
 	} else {
@@ -426,6 +434,17 @@ int apr_send_pkt(void *handle, uint32_t *buf)
 					__func__);
 			rc = -ENETRESET;
 		}
+		if (rc == -EAGAIN || rc == -ETIMEDOUT) {
+			apr_send_pkt_count++;
+			pr_err("%s:: send pkt timedout apr_send_pkt_count %d\n",
+				__func__, apr_send_pkt_count);
+		}
+	}
+	if (apr_send_pkt_count == apr_pkt_cnt_adsp_restart) {
+		pr_debug("%s:: schedule work for adsp loader restart cb\n",
+				__func__);
+		schedule_work(&apr_cb_work);
+		apr_send_pkt_count = 0;
 	}
 	spin_unlock_irqrestore(&svc->w_lock, flags);
 
@@ -800,6 +819,19 @@ static void apr_reset_deregister(struct work_struct *work)
 	kfree(apr_reset);
 }
 
+static void state_notify_cb(struct work_struct *work)
+{
+	if (q6.state_notify_cb)
+		q6.state_notify_cb(APR_SUBSYS_UNKNOWN, q6.client_handle);
+}
+
+void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle)
+{
+	q6.state_notify_cb = adsp_cb;
+	q6.client_handle = client_handle;
+}
+EXPORT_SYMBOL(apr_register_adsp_state_cb);
+
 /**
  * apr_start_rx_rt - Clients call to vote for thread
  * priority upgrade whenever needed.
@@ -1212,7 +1244,7 @@ static int apr_probe(struct platform_device *pdev)
 			__func__, ret);
 		ret = 0;
 	}
-
+	INIT_WORK(&apr_cb_work, state_notify_cb);
 	return apr_debug_init();
 }
 

+ 3 - 3
ipc/apr_tal_rpmsg.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2017-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2020 The Linux Foundation. All rights reserved.
  */
 
 #include <linux/module.h>
@@ -36,7 +36,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
 			   struct apr_pkt_priv *pkt_priv, int len)
 {
 	int rc = 0, retries = 0;
-	unsigned long flags;
+	unsigned long flags = 0;
 	struct rpmsg_device *rpdev = NULL;
 
 	if (!apr_ch || len > APR_MAX_BUF ||
@@ -186,7 +186,7 @@ static int apr_tal_rpmsg_callback(struct rpmsg_device *rpdev,
 				  void *data, int len, void *priv, u32 addr)
 {
 	struct apr_svc_ch_dev *apr_ch = dev_get_drvdata(&rpdev->dev);
-	unsigned long flags;
+	unsigned long flags = 0;
 
 	if (!apr_ch || !data) {
 		pr_err("%s: Invalid apr_ch or ptr\n", __func__);

+ 3 - 0
soc/pinctrl-lpi.c

@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 #include <soc/snd_event.h>
 #include <dsp/digital-cdc-rsc-mgr.h>
 #include <linux/pm_runtime.h>
@@ -489,6 +490,8 @@ static int lpi_notifier_service_cb(struct notifier_block *this,
 
 		/* Reset HW votes after SSR */
 		if (!lpi_dev_up) {
+			/* Add 100ms sleep to ensure AVS is up after SSR */
+			msleep(100);
 			if (state->lpass_core_hw_vote)
 				digital_cdc_rsc_mgr_hw_vote_reset(
 					state->lpass_core_hw_vote);

+ 46 - 34
soc/swr-mstr-ctrl.c

@@ -41,7 +41,6 @@
 #define SWRM_DSD_PARAMS_PORT 4
 
 #define SWR_BROADCAST_CMD_ID            0x0F
-#define SWR_AUTO_SUSPEND_DELAY          1 /* delay in sec */
 #define SWR_DEV_ID_MASK			0xFFFFFFFFFFFF
 #define SWR_REG_VAL_PACK(data, dev, id, reg)	\
 			((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24))
@@ -82,7 +81,7 @@
 #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT    0x08
 
 /* pm runtime auto suspend timer in msecs */
-static int auto_suspend_timer = SWR_AUTO_SUSPEND_DELAY * 1000;
+static int auto_suspend_timer = 500;
 module_param(auto_suspend_timer, int, 0664);
 MODULE_PARM_DESC(auto_suspend_timer, "timer for auto suspend");
 
@@ -121,7 +120,7 @@ static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm);
 static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm);
 static u32 swr_master_read(struct swr_mstr_ctrl *swrm, unsigned int reg_addr);
 static void swr_master_write(struct swr_mstr_ctrl *swrm, u16 reg_addr, u32 val);
-
+static int swrm_runtime_resume(struct device *dev);
 
 static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq)
 {
@@ -647,6 +646,7 @@ static int swr_master_bulk_write(struct swr_mstr_ctrl *swrm, u32 *reg_addr,
 			usleep_range(50, 55);
 			swr_master_write(swrm, reg_addr[i], val[i]);
 		}
+		usleep_range(100, 110);
 		mutex_unlock(&swrm->iolock);
 	}
 	return 0;
@@ -901,6 +901,8 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
 	mutex_unlock(&swrm->devlock);
 
 	pm_runtime_get_sync(swrm->dev);
+	if (swrm->req_clk_switch)
+		swrm_runtime_resume(swrm->dev);
 	ret = swrm_cmd_fifo_rd_cmd(swrm, &val, dev_num, 0, reg_addr, len);
 
 	if (!ret)
@@ -934,6 +936,8 @@ static int swrm_write(struct swr_master *master, u8 dev_num, u16 reg_addr,
 	mutex_unlock(&swrm->devlock);
 
 	pm_runtime_get_sync(swrm->dev);
+	if (swrm->req_clk_switch)
+		swrm_runtime_resume(swrm->dev);
 	ret = swrm_cmd_fifo_wr_cmd(swrm, reg_val, dev_num, 0, reg_addr);
 
 	pm_runtime_put_autosuspend(swrm->dev);
@@ -1271,10 +1275,16 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
 								bank));
 
 			reg[len] = SWRM_CMD_FIFO_WR_CMD;
-			val[len++] = SWR_REG_VAL_PACK(mport->sinterval,
+			val[len++] = SWR_REG_VAL_PACK(mport->sinterval & 0xFF,
 					port_req->dev_num, 0x00,
 					SWRS_DP_SAMPLE_CONTROL_1_BANK(slv_id,
 								bank));
+
+			reg[len] = SWRM_CMD_FIFO_WR_CMD;
+			val[len++] = SWR_REG_VAL_PACK((mport->sinterval >> 8)& 0xFF,
+					port_req->dev_num, 0x00,
+					SWRS_DP_SAMPLE_CONTROL_2_BANK(slv_id,
+								bank));
 			/* Assumption: If different channels in the same port
 			 * on master is enabled for different slaves, then each
 			 * slave offset should be configured differently.
@@ -1925,16 +1935,22 @@ handle_irq:
 				swrm->intr_mask);
 			break;
 		case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
-			dev_dbg(swrm->dev, "%s: SWR read FIFO overflow\n",
-				__func__);
+			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
+			dev_err(swrm->dev,
+				"%s: SWR read FIFO overflow fifo status\n",
+				__func__, value);
 			break;
 		case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
-			dev_dbg(swrm->dev, "%s: SWR read FIFO underflow\n",
-				__func__);
+			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
+			dev_err(swrm->dev,
+				"%s: SWR read FIFO underflow fifo status\n",
+				__func__, value);
 			break;
 		case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
-			dev_dbg(swrm->dev, "%s: SWR write FIFO overflow\n",
-				__func__);
+			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
+			dev_err(swrm->dev,
+				"%s: SWR write FIFO overflow fifo status\n",
+				__func__, value);
 			swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
 			break;
 		case SWRM_INTERRUPT_STATUS_CMD_ERROR:
@@ -2471,8 +2487,6 @@ static int swrm_probe(struct platform_device *pdev)
 		ret = -EINVAL;
 		goto err_pdata_fail;
 	}
-	swrm->pinctrl_setup = pdata->pinctrl_setup;
-
 	if (of_property_read_u32(pdev->dev.of_node,
 			"qcom,swr-clock-stop-mode0",
 			&swrm->clk_stop_mode0_supp)) {
@@ -2665,6 +2679,8 @@ static int swrm_probe(struct platform_device *pdev)
 	 * controller will be up now
 	 */
 	swr_master_add_boarddevices(&swrm->master);
+	if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true))
+		dev_dbg(&pdev->dev, "%s: Audio HW Vote is failed\n", __func__);
 	mutex_lock(&swrm->mlock);
 	swrm_clk_request(swrm, true);
 	swrm->version = swr_master_read(swrm, SWRM_COMP_HW_VERSION);
@@ -2727,13 +2743,13 @@ err_mstr_fail:
 		swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
 				swrm, SWR_IRQ_FREE);
 	} else if (swrm->irq) {
-		free_irq(swrm->irq, swrm);
 		irqd_set_trigger_type(
 			irq_get_irq_data(swrm->irq),
 			IRQ_TYPE_NONE);
+		if (swrm->swr_irq_wakeup_capable)
+			irq_set_irq_wake(swrm->irq, 0);
+		free_irq(swrm->irq, swrm);
 	}
-	if (swrm->swr_irq_wakeup_capable)
-		irq_set_irq_wake(swrm->irq, 0);
 err_irq_fail:
 	mutex_destroy(&swrm->irq_lock);
 	mutex_destroy(&swrm->mlock);
@@ -2757,15 +2773,15 @@ static int swrm_remove(struct platform_device *pdev)
 		swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
 				swrm, SWR_IRQ_FREE);
 	} else if (swrm->irq) {
-		free_irq(swrm->irq, swrm);
 		irqd_set_trigger_type(
 			irq_get_irq_data(swrm->irq),
 			IRQ_TYPE_NONE);
+		if (swrm->swr_irq_wakeup_capable)
+			irq_set_irq_wake(swrm->irq, 0);
+		free_irq(swrm->irq, swrm);
 	} else if (swrm->wake_irq > 0) {
 		free_irq(swrm->wake_irq, swrm);
 	}
-	if (swrm->swr_irq_wakeup_capable)
-		irq_set_irq_wake(swrm->irq, 0);
 	cancel_work_sync(&swrm->wakeup_work);
 	pm_runtime_disable(&pdev->dev);
 	pm_runtime_set_suspended(&pdev->dev);
@@ -2820,11 +2836,9 @@ static int swrm_runtime_resume(struct device *dev)
 			__func__);
 		hw_core_err = true;
 	}
-	if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true)) {
+	if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, true))
 		dev_err(dev, "%s:lpass audio hw enable failed\n",
 			__func__);
-		swrm->aud_core_err = true;
-	}
 
 	if ((swrm->state == SWR_MSTR_DOWN) ||
 	    (swrm->state == SWR_MSTR_SSR && swrm->dev_up)) {
@@ -2842,9 +2856,6 @@ static int swrm_runtime_resume(struct device *dev)
 				    irq_get_irq_data(swrm->wake_irq)))
 					disable_irq_nosync(swrm->wake_irq);
 				mutex_unlock(&swrm->irq_lock);
-				if (swrm->dmic_sva && swrm->pinctrl_setup)
-					swrm->pinctrl_setup(swrm->handle,
-							    false);
 			}
 			if (swrm->ipc_wakeup)
 				msm_aud_evt_blocking_notifier_call_chain(
@@ -2918,8 +2929,6 @@ static int swrm_runtime_resume(struct device *dev)
 		swrm->state = SWR_MSTR_UP;
 	}
 exit:
-	if (ret && !swrm->aud_core_err)
-		swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
 	if (!hw_core_err)
 		swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
 	if (swrm_clk_req_err)
@@ -2928,6 +2937,8 @@ exit:
 	else
 		pm_runtime_set_autosuspend_delay(&pdev->dev,
 				auto_suspend_timer);
+	if (swrm->req_clk_switch)
+		swrm->req_clk_switch = false;
 	mutex_unlock(&swrm->reslock);
 
 	trace_printk("%s: pm_runtime: resume done, state:%d\n",
@@ -3027,8 +3038,6 @@ static int swrm_runtime_suspend(struct device *dev)
 
 		if (swrm->clk_stop_mode0_supp) {
 			if (swrm->wake_irq > 0) {
-				if (swrm->dmic_sva && swrm->pinctrl_setup)
-					swrm->pinctrl_setup(swrm->handle, true);
 				enable_irq(swrm->wake_irq);
 			} else if (swrm->ipc_wakeup) {
 				msm_aud_evt_blocking_notifier_call_chain(
@@ -3038,15 +3047,16 @@ static int swrm_runtime_suspend(struct device *dev)
 		}
 
 	}
+	if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false))
+		dev_dbg(dev, "%s:lpass audio hw enable failed\n",
+			__func__);
+
 	/* Retain  SSR state until resume */
 	if (current_state != SWR_MSTR_SSR)
 		swrm->state = SWR_MSTR_DOWN;
 exit:
-	if (!swrm->aud_core_err)
-		swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false);
 	if (!hw_core_err)
 		swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
-	swrm->aud_core_err = false;
 	mutex_unlock(&swrm->reslock);
 	trace_printk("%s: pm_runtime: suspend done state: %d\n",
 		__func__, swrm->state);
@@ -3217,8 +3227,12 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
 		}
 		mutex_lock(&swrm->mlock);
 		if (swrm->clk_src != *(int *)data) {
-			if (swrm->state == SWR_MSTR_UP)
+			if (swrm->state == SWR_MSTR_UP) {
+				swrm->req_clk_switch = true;
 				swrm_device_suspend(&pdev->dev);
+				if (swrm->state == SWR_MSTR_UP)
+					swrm->req_clk_switch = false;
+			}
 			swrm->clk_src = *(int *)data;
 		}
 		mutex_unlock(&swrm->mlock);
@@ -3378,12 +3392,10 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
 	case SWR_REGISTER_WAKEUP:
 		msm_aud_evt_blocking_notifier_call_chain(
 					SWR_WAKE_IRQ_REGISTER, (void *)swrm);
-		swrm->dmic_sva = *(u32 *)data;
 		break;
 	case SWR_DEREGISTER_WAKEUP:
 		msm_aud_evt_blocking_notifier_call_chain(
 					SWR_WAKE_IRQ_DEREGISTER, (void *)swrm);
-		swrm->dmic_sva = 0;
 		break;
 	case SWR_SET_PORT_MAP:
 		if (!data) {

+ 1 - 4
soc/swr-mstr-ctrl.h

@@ -115,7 +115,6 @@ struct swr_ctrl_platform_data {
 	int (*core_vote)(void *handle, bool enable);
 	int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq,
 			void *data), void *swr_handle, int type);
-	int (*pinctrl_setup)(void *handle, bool enable);
 };
 
 struct swr_mstr_ctrl {
@@ -149,7 +148,6 @@ struct swr_mstr_ctrl {
 	int (*core_vote)(void *handle, bool enable);
 	int (*reg_irq)(void *handle, irqreturn_t(*irq_handler)(int irq,
 			void *data), void *swr_handle, int type);
-	int (*pinctrl_setup)(void *handle, bool enable);
 	int irq;
 	int wake_irq;
 	int version;
@@ -175,10 +173,9 @@ struct swr_mstr_ctrl {
 	u32 clk_stop_mode0_supp;
 	struct work_struct wakeup_work;
 	u32 ipc_wakeup;
-	u32 dmic_sva;
 	bool dev_up;
 	bool ipc_wakeup_triggered;
-	bool aud_core_err;
+	bool req_clk_switch;
 	struct pm_qos_request pm_qos_req;
 	enum swrm_pm_state pm_state;
 	wait_queue_head_t pm_wq;

+ 2 - 0
soc/swrm_registers.h

@@ -232,6 +232,8 @@
 						 SWRS_DP_REG_OFFSET(n, m))
 #define SWRS_DP_SAMPLE_CONTROL_1_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x122 + \
 						 SWRS_DP_REG_OFFSET(n, m))
+#define SWRS_DP_SAMPLE_CONTROL_2_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x123 + \
+						 SWRS_DP_REG_OFFSET(n, m))
 #define SWRS_DP_OFFSET_CONTROL_1_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x124 + \
 						 SWRS_DP_REG_OFFSET(n, m))
 #define SWRS_DP_OFFSET_CONTROL_2_BANK(n, m)	(SWRS_BASE_ADDRESS + 0x125 + \