Browse Source

Merge commit '5efb3a4ee3959f20ed2b697663205ec9a6bd1e5c' into audio-kernel-5-4.lnx.1.0

Change-Id: I58fbdf6b91c33ab5d147efbe5f5706616052c7fe
Signed-off-by: Vidyakumar Athota <[email protected]>
Vidyakumar Athota 4 years ago
parent
commit
584244b6ac
53 changed files with 9168 additions and 309 deletions
  1. 7 0
      Makefile
  2. 17 9
      Makefile.am
  3. 8 0
      asoc/Kbuild
  4. 2 0
      asoc/codecs/bolero/bolero-cdc-regmap.c
  5. 28 3
      asoc/codecs/bolero/bolero-cdc.c
  6. 5 2
      asoc/codecs/bolero/bolero-cdc.h
  7. 4 0
      asoc/codecs/bolero/internal.h
  8. 61 0
      asoc/codecs/bolero/rx-macro.c
  9. 99 4
      asoc/codecs/bolero/tx-macro.c
  10. 19 1
      asoc/codecs/bolero/va-macro.c
  11. 7 4
      asoc/codecs/bolero/wsa-macro.c
  12. 46 0
      asoc/codecs/msm-cdc-supply.c
  13. 1 1
      asoc/codecs/msm_hdmi_codec_rx.c
  14. 9 0
      asoc/codecs/rouleur/internal.h
  15. 5 0
      asoc/codecs/rouleur/pm2250-spmi.h
  16. 34 0
      asoc/codecs/rouleur/pm2250_spmi.c
  17. 36 21
      asoc/codecs/rouleur/rouleur-mbhc.c
  18. 3 0
      asoc/codecs/rouleur/rouleur-registers.h
  19. 3 0
      asoc/codecs/rouleur/rouleur-regmap.c
  20. 3 0
      asoc/codecs/rouleur/rouleur-tables.c
  21. 210 16
      asoc/codecs/rouleur/rouleur.c
  22. 57 21
      asoc/codecs/swr-dmic.c
  23. 6 21
      asoc/codecs/swr-haptics.c
  24. 75 12
      asoc/codecs/wcd937x/wcd937x.c
  25. 9 7
      asoc/codecs/wcd937x/wcd937x.h
  26. 1 0
      asoc/codecs/wcd938x/internal.h
  27. 144 94
      asoc/codecs/wcd938x/wcd938x.c
  28. 124 10
      asoc/codecs/wsa881x-analog.c
  29. 2 0
      asoc/codecs/wsa881x.c
  30. 1 0
      asoc/codecs/wsa883x/internal.h
  31. 88 8
      asoc/codecs/wsa883x/wsa883x.c
  32. 5 0
      asoc/codecs/wsa883x/wsa883x.h
  33. 61 0
      asoc/holi-port-config.h
  34. 6813 0
      asoc/holi.c
  35. 24 2
      asoc/lahaina-port-config.h
  36. 2 1
      asoc/msm_dailink.h
  37. 471 0
      asoc/msm_holi_dailink.h
  38. 34 0
      config/holiauto.conf
  39. 38 0
      config/holiautoconf.h
  40. 1 1
      dsp/adsp-loader.c
  41. 104 8
      dsp/msm_audio_ion.c
  42. 5 0
      include/asoc/msm-cdc-supply.h
  43. 5 0
      include/dsp/apr_audio-v2.h
  44. 1 0
      include/dsp/audio_cal_utils.h
  45. 4 0
      include/dsp/msm_audio_ion.h
  46. 5 1
      include/uapi/audio/linux/msm_audio_calibration.h
  47. 90 0
      include/uapi/audio/sound/audio_compressed_formats.h
  48. 27 2
      include/uapi/audio/sound/lsm_params.h
  49. 241 59
      soc/swr-mstr-ctrl.c
  50. 4 0
      soc/swr-mstr-ctrl.h
  51. 4 1
      soc/swr-mstr-registers.h
  52. 113 0
      soc/swr-slave-port-config.h
  53. 2 0
      soc/swrm_registers.h

+ 7 - 0
Makefile

@@ -18,6 +18,9 @@ endif
 ifeq ($(CONFIG_ARCH_LAHAINA), y)
 include $(srctree)/techpack/audio/config/lahainaauto.conf
 endif
+ifeq ($(CONFIG_ARCH_HOLI), y)
+include $(srctree)/techpack/audio/config/holiauto.conf
+endif
 endif
 
 # Use USERINCLUDE when you must reference the UAPI directories only.
@@ -51,6 +54,10 @@ ifeq ($(CONFIG_ARCH_LAHAINA), y)
 LINUXINCLUDE    += \
                 -include $(srctree)/techpack/audio/config/lahainaautoconf.h
 endif
+ifeq ($(CONFIG_ARCH_HOLI), y)
+LINUXINCLUDE    += \
+                -include $(srctree)/techpack/audio/config/holiautoconf.h
+endif
 
 obj-y += soc/
 obj-y += dsp/

+ 17 - 9
Makefile.am

@@ -18,6 +18,8 @@ ifeq ($(TARGET_SUPPORT), sdmsteppe)
 KBUILD_OPTIONS += CONFIG_ARCH_SM6150=y
 endif
 
+subdir-ccflags-y += -I$(AUDIO_ROOT)/include/uapi/
+
 obj-m := ipc/
 obj-m += dsp/
 obj-m += soc/
@@ -50,6 +52,10 @@ KBUILD_OPTIONS += CONFIG_SND_SOC_SA6155=m
 endif
 endif
 
+define PROCESS_HEADERS
+	$(foreach name,$(1),$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(2)$(name) $(3)$(name)))
+endef
+
 all:
 	$(shell rm -fr $(shell pwd)/soc/core.h)
 	$(shell ln -s $(KERNEL_SRC)/drivers/pinctrl/core.h $(shell pwd)/soc/core.h)
@@ -61,15 +67,17 @@ all:
 	$(shell mkdir $(shell pwd)/sound)
 	$(shell mkdir $(shell pwd)/linux/mfd)
 	$(shell mkdir $(shell pwd)/linux/mfd/wcd9xxx)
-	$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(UAPI_OUT)/linux/ $(AUDIO_ROOT)/include/uapi/audio/linux/ $(notdir $(AUDIO_KERNEL_HEADERS_PATH1)))
-	$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(UAPI_OUT)/linux/mfd/wcd9xxx/ $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/ $(notdir $(AUDIO_KERNEL_HEADERS_PATH2)))
-	$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(UAPI_OUT)/sound/ $(AUDIO_ROOT)/include/uapi/audio/sound/ $(notdir $(AUDIO_KERNEL_HEADERS_PATH3)))
-	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/sound)
-	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/linux/mfd)
-	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/linux/mfd/wcd9xxx)
-	$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(KERNEL_BINARY_DIR)/usr/include/linux/ $(AUDIO_ROOT)/include/uapi/audio/linux/ $(notdir $(AUDIO_KERNEL_HEADERS_PATH1)))
-	$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(KERNEL_BINARY_DIR)/usr/include/linux/mfd/wcd9xxx/ $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/ $(notdir $(AUDIO_KERNEL_HEADERS_PATH2)))
-	$(shell cd $(KERNEL_BINARY_DIR) && $(KERNEL_SRC)/scripts/headers_install.sh $(KERNEL_BINARY_DIR)/usr/include/sound/ $(AUDIO_ROOT)/include/uapi/audio/sound/ $(notdir $(AUDIO_KERNEL_HEADERS_PATH3)))
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/, $(UAPI_OUT)/linux/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/, $(UAPI_OUT)/linux/mfd/wcd9xxx/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/sound/*.h)), $(AUDIO_ROOT)/include/uapi/audio/sound/, $(UAPI_OUT)/sound/)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/sound)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/linux)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/linux/mfd)
+	$(shell mkdir $(KERNEL_BINARY_DIR)/usr/include/audio/linux/mfd/wcd9xxx)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/, $(KERNEL_BINARY_DIR)/usr/include/audio/linux/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/*.h)), $(AUDIO_ROOT)/include/uapi/audio/linux/mfd/wcd9xxx/, $(KERNEL_BINARY_DIR)/usr/include/audio/linux/mfd/wcd9xxx/)
+	$(call PROCESS_HEADERS, $(notdir $(shell ls $(AUDIO_ROOT)/include/uapi/audio/sound/*.h)), $(AUDIO_ROOT)/include/uapi/audio/sound/, $(KERNEL_BINARY_DIR)/usr/include/audio/sound/)
 	$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
 
 modules_install:

+ 8 - 0
asoc/Kbuild

@@ -138,6 +138,11 @@ ifdef CONFIG_SND_SOC_LAHAINA
 	MACHINE_OBJS += lahaina.o
 endif
 
+# for HOLI sound card driver
+ifdef CONFIG_SND_SOC_HOLI
+	MACHINE_OBJS += holi.o
+endif
+
 ifdef CONFIG_SND_SOC_LITO
 	MACHINE_OBJS += kona.o
 endif
@@ -219,6 +224,9 @@ machine_dlkm-y := $(MACHINE_OBJS)
 obj-$(CONFIG_SND_SOC_LAHAINA) += machine_dlkm.o
 machine_dlkm-y := $(MACHINE_OBJS)
 
+obj-$(CONFIG_SND_SOC_HOLI) += machine_dlkm.o
+machine_dlkm-y := $(MACHINE_OBJS)
+
 obj-$(CONFIG_SND_SOC_LITO) += machine_dlkm.o
 machine_dlkm-y := $(MACHINE_OBJS)
 

+ 2 - 0
asoc/codecs/bolero/bolero-cdc-regmap.c

@@ -805,6 +805,8 @@ static bool bolero_is_volatile_register(struct device *dev,
 	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC1_CTL:
 	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC2_CTL:
 	case BOLERO_CDC_TX_TOP_CSR_SWR_DMIC3_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_MIC0_CTL:
+	case BOLERO_CDC_TX_TOP_CSR_SWR_MIC1_CTL:
 	case BOLERO_CDC_WSA_VBAT_BCL_VBAT_GAIN_MON_VAL:
 	case BOLERO_CDC_WSA_VBAT_BCL_VBAT_DECODE_ST:
 	case BOLERO_CDC_WSA_INTR_CTRL_PIN1_STATUS0:

+ 28 - 3
asoc/codecs/bolero/bolero-cdc.c

@@ -232,6 +232,27 @@ static int bolero_cdc_update_wcd_event(void *handle, u16 event, u32 data)
 				priv->component,
 				BOLERO_MACRO_EVT_BCS_CLK_OFF, data);
 		break;
+	case WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE:
+		/* Update PA Gain only for bolero version 2.1 */
+		if (priv->version == BOLERO_VERSION_2_1)
+			if (priv->macro_params[RX_MACRO].event_handler)
+				priv->macro_params[RX_MACRO].event_handler(
+					priv->component,
+					BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE,
+					data);
+		break;
+	case WCD_BOLERO_EVT_HPHL_HD2_ENABLE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_HPHL_HD2_ENABLE, data);
+		break;
+	case WCD_BOLERO_EVT_HPHR_HD2_ENABLE:
+		if (priv->macro_params[RX_MACRO].event_handler)
+			priv->macro_params[RX_MACRO].event_handler(
+				priv->component,
+				BOLERO_MACRO_EVT_HPHR_HD2_ENABLE, data);
+		break;
 	default:
 		dev_err(priv->dev, "%s: Invalid event %d trigger from wcd\n",
 			__func__, event);
@@ -755,7 +776,7 @@ void bolero_unregister_macro(struct device *dev, u16 macro_id)
 }
 EXPORT_SYMBOL(bolero_unregister_macro);
 
-void bolero_wsa_pa_on(struct device *dev)
+void bolero_wsa_pa_on(struct device *dev, bool adie_lb)
 {
 	struct bolero_priv *priv;
 
@@ -773,8 +794,12 @@ void bolero_wsa_pa_on(struct device *dev)
 		dev_err(dev, "%s: priv is null\n", __func__);
 		return;
 	}
-
-	bolero_cdc_notifier_call(priv, BOLERO_WCD_EVT_PA_ON_POST_FSCLK);
+	if (adie_lb)
+		bolero_cdc_notifier_call(priv,
+			BOLERO_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB);
+	else
+		bolero_cdc_notifier_call(priv,
+			BOLERO_WCD_EVT_PA_ON_POST_FSCLK);
 }
 EXPORT_SYMBOL(bolero_wsa_pa_on);
 

+ 5 - 2
asoc/codecs/bolero/bolero-cdc.h

@@ -50,6 +50,9 @@ enum {
 	BOLERO_MACRO_EVT_BCS_CLK_OFF,
 	BOLERO_MACRO_EVT_SSR_GFMUX_UP,
 	BOLERO_MACRO_EVT_PRE_SSR_UP,
+	BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE,
+	BOLERO_MACRO_EVT_HPHL_HD2_ENABLE, /* Enable HD2 cfg for HPHL */
+	BOLERO_MACRO_EVT_HPHR_HD2_ENABLE, /* Enable HD2 cfg for HPHR */
 };
 
 enum {
@@ -99,7 +102,7 @@ int bolero_runtime_suspend(struct device *dev);
 int bolero_set_port_map(struct snd_soc_component *component, u32 size, void *data);
 int bolero_register_event_listener(struct snd_soc_component *component,
 				   bool enable);
-void bolero_wsa_pa_on(struct device *dev);
+void bolero_wsa_pa_on(struct device *dev, bool adie_lb);
 bool bolero_check_core_votes(struct device *dev);
 int bolero_tx_mclk_enable(struct snd_soc_component *c, bool enable);
 int bolero_get_version(struct device *dev);
@@ -176,7 +179,7 @@ static inline int bolero_register_event_listener(
 	return 0;
 }
 
-static void bolero_wsa_pa_on(struct device *dev)
+static void bolero_wsa_pa_on(struct device *dev, bool adie_lb)
 {
 }
 

+ 4 - 0
asoc/codecs/bolero/internal.h

@@ -16,6 +16,7 @@ enum {
 	BOLERO_WCD_EVT_SSR_DOWN,
 	BOLERO_WCD_EVT_SSR_UP,
 	BOLERO_WCD_EVT_PA_ON_POST_FSCLK,
+	BOLERO_WCD_EVT_PA_ON_POST_FSCLK_ADIE_LB,
 };
 
 enum {
@@ -32,6 +33,9 @@ enum {
 	WCD_BOLERO_EVT_IMPED_FALSE,  /* for imped false */
 	WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
 	WCD_BOLERO_EVT_BCS_CLK_OFF,
+	WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE,
+	WCD_BOLERO_EVT_HPHL_HD2_ENABLE, /* to enable hd2 config for hphl */
+	WCD_BOLERO_EVT_HPHR_HD2_ENABLE, /* to enable hd2 config for hphr */
 };
 
 struct wcd_ctrl_platform_data {

+ 61 - 0
asoc/codecs/bolero/rx-macro.c

@@ -78,6 +78,11 @@ static const struct snd_kcontrol_new name##_mux = \
 #define RX_MACRO_EC_MIX_TX1_MASK 0x0f
 #define RX_MACRO_EC_MIX_TX2_MASK 0x0f
 
+#define RX_MACRO_GAIN_MAX_VAL 0x28
+#define RX_MACRO_GAIN_VAL_UNITY 0x0
+/* Define macros to increase PA Gain by half */
+#define RX_MACRO_MOD_GAIN (RX_MACRO_GAIN_VAL_UNITY + 6)
+
 #define COMP_MAX_COEFF 25
 
 struct wcd_imped_val {
@@ -454,6 +459,8 @@ struct rx_macro_priv {
 	struct rx_macro_bcl_pmic_params bcl_pmic_params;
 	u16 clk_id;
 	u16 default_clk_id;
+	int8_t rx0_gain_val;
+	int8_t rx1_gain_val;
 };
 
 static struct snd_soc_dai_driver rx_macro_dai[];
@@ -1460,6 +1467,56 @@ static int rx_macro_event_handler(struct snd_soc_component *component,
 	case BOLERO_MACRO_EVT_CLK_RESET:
 		bolero_rsc_clk_reset(rx_dev, RX_CORE_CLK);
 		break;
+	case BOLERO_MACRO_EVT_RX_PA_GAIN_UPDATE:
+		rx_priv->rx0_gain_val = snd_soc_component_read32(component,
+					BOLERO_CDC_RX_RX0_RX_VOL_CTL);
+		rx_priv->rx1_gain_val = snd_soc_component_read32(component,
+					BOLERO_CDC_RX_RX1_RX_VOL_CTL);
+		if (data) {
+			/* Reduce gain by half only if its greater than -6DB */
+			if ((rx_priv->rx0_gain_val >= RX_MACRO_GAIN_VAL_UNITY)
+			&& (rx_priv->rx0_gain_val <= RX_MACRO_GAIN_MAX_VAL))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx0_gain_val -
+					 RX_MACRO_MOD_GAIN));
+			if ((rx_priv->rx1_gain_val >= RX_MACRO_GAIN_VAL_UNITY)
+			&& (rx_priv->rx1_gain_val <= RX_MACRO_GAIN_MAX_VAL))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx1_gain_val -
+					 RX_MACRO_MOD_GAIN));
+		}
+		else {
+			/* Reset gain value to default */
+			if ((rx_priv->rx0_gain_val >=
+			    (RX_MACRO_GAIN_VAL_UNITY - RX_MACRO_MOD_GAIN)) &&
+			    (rx_priv->rx0_gain_val <= (RX_MACRO_GAIN_MAX_VAL -
+			    RX_MACRO_MOD_GAIN)))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX0_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx0_gain_val +
+					 RX_MACRO_MOD_GAIN));
+			if ((rx_priv->rx1_gain_val >=
+			    (RX_MACRO_GAIN_VAL_UNITY - RX_MACRO_MOD_GAIN)) &&
+			    (rx_priv->rx1_gain_val <= (RX_MACRO_GAIN_MAX_VAL -
+			    RX_MACRO_MOD_GAIN)))
+				snd_soc_component_update_bits(component,
+					BOLERO_CDC_RX_RX1_RX_VOL_CTL, 0xFF,
+					(rx_priv->rx1_gain_val +
+					 RX_MACRO_MOD_GAIN));
+		}
+		break;
+	case BOLERO_MACRO_EVT_HPHL_HD2_ENABLE:
+		/* Enable hd2 config for hphl*/
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX0_RX_PATH_CFG0, 0x04, data);
+		break;
+	case BOLERO_MACRO_EVT_HPHR_HD2_ENABLE:
+		/* Enable hd2 config for hphr*/
+		snd_soc_component_update_bits(component,
+				BOLERO_CDC_RX_RX1_RX_PATH_CFG0, 0x04, data);
+		break;
 	}
 done:
 	return ret;
@@ -3877,6 +3934,8 @@ static int rx_macro_init(struct snd_soc_component *component)
 		return ret;
 	}
 	rx_priv->dev_up = true;
+	rx_priv->rx0_gain_val = 0;
+	rx_priv->rx1_gain_val = 0;
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF1 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF2 Playback");
 	snd_soc_dapm_ignore_suspend(dapm, "RX_MACRO_AIF3 Playback");
@@ -4106,6 +4165,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);

+ 99 - 4
asoc/codecs/bolero/tx-macro.c

@@ -177,6 +177,8 @@ struct tx_macro_priv {
 	bool bcs_clk_en;
 	bool hs_slow_insert_complete;
 	int amic_sample_rate;
+	bool lpi_enable;
+	bool register_event_listener;
 };
 
 static bool tx_macro_get_data(struct snd_soc_component *component,
@@ -235,11 +237,11 @@ static int tx_macro_mclk_enable(struct tx_macro_priv *tx_priv,
 		}
 		bolero_clk_rsc_fs_gen_request(tx_priv->dev,
 					true);
+		regcache_mark_dirty(regmap);
+		regcache_sync_region(regmap,
+				TX_START_OFFSET,
+				TX_MAX_OFFSET);
 		if (tx_priv->tx_mclk_users == 0) {
-			regcache_mark_dirty(regmap);
-			regcache_sync_region(regmap,
-					TX_START_OFFSET,
-					TX_MAX_OFFSET);
 			/* 9.6MHz MCLK, set value 0x00 if other frequency */
 			regmap_update_bits(regmap,
 				BOLERO_CDC_TX_TOP_CSR_FREQ_MCLK, 0x01, 0x01);
@@ -330,6 +332,45 @@ static int tx_macro_tx_swr_clk_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static int tx_macro_swr_pwr_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 *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	dev_dbg(tx_dev, "%s: event = %d, lpi_enable = %d\n",
+		__func__, event, tx_priv->lpi_enable);
+
+	if (!tx_priv->lpi_enable)
+		return ret;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (tx_priv->lpi_enable) {
+			bolero_register_event_listener(component, true);
+			tx_priv->register_event_listener = true;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (tx_priv->register_event_listener) {
+			tx_priv->register_event_listener = false;
+			bolero_register_event_listener(component, false);
+		}
+		break;
+	default:
+		dev_err(tx_priv->dev,
+			"%s: invalid DAPM event %d\n", __func__, event);
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
 static int tx_macro_mclk_event(struct snd_soc_dapm_widget *w,
 			       struct snd_kcontrol *kcontrol, int event)
 {
@@ -784,6 +825,38 @@ static int tx_macro_dec_mode_put(struct snd_kcontrol *kcontrol,
 	return 0;
 }
 
+static int tx_macro_lpi_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	ucontrol->value.integer.value[0] = tx_priv->lpi_enable;
+
+	return 0;
+}
+
+static int tx_macro_lpi_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_component *component =
+			snd_soc_kcontrol_component(kcontrol);
+	struct device *tx_dev = NULL;
+	struct tx_macro_priv *tx_priv = NULL;
+
+	if (!tx_macro_get_data(component, &tx_dev, &tx_priv, __func__))
+		return -EINVAL;
+
+	tx_priv->lpi_enable = ucontrol->value.integer.value[0];
+
+	return 0;
+}
+
 static int tx_macro_bcs_ch_get(struct snd_kcontrol *kcontrol,
 				 struct snd_ctl_elem_value *ucontrol)
 {
@@ -1675,6 +1748,10 @@ static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_common[] = {
 
 	SND_SOC_DAPM_SUPPLY_S("TX_MCLK", 0, SND_SOC_NOPM, 0, 0,
 	tx_macro_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+	SND_SOC_DAPM_SUPPLY_S("TX_SWR_PWR", -1, SND_SOC_NOPM, 0, 0,
+			      tx_macro_swr_pwr_event,
+			      SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_widget tx_macro_dapm_widgets_v2[] = {
@@ -2144,6 +2221,19 @@ static const struct snd_soc_dapm_route tx_audio_map_v3[] = {
 	{"TX SMIC MUX5", NULL, "TX_SWR_CLK"},
 	{"TX SMIC MUX6", NULL, "TX_SWR_CLK"},
 	{"TX SMIC MUX7", NULL, "TX_SWR_CLK"},
+
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
+	{"TX SWR_INPUT", NULL, "TX_SWR_PWR"},
 };
 
 static const struct snd_soc_dapm_route tx_audio_map[] = {
@@ -2406,6 +2496,9 @@ static const struct snd_kcontrol_new tx_macro_snd_controls_common[] = {
 			  BOLERO_CDC_TX3_TX_VOL_CTL,
 			  -84, 40, digital_gain),
 
+	SOC_SINGLE_EXT("TX LPI Enable", 0, 0, 1, 0,
+		tx_macro_lpi_get, tx_macro_lpi_put),
+
 	SOC_ENUM_EXT("DEC0 MODE", dec_mode_mux_enum,
 			tx_macro_dec_mode_get, tx_macro_dec_mode_put),
 
@@ -2937,6 +3030,8 @@ static int tx_macro_init(struct snd_soc_component *component)
 			"%s: priv is null for macro!\n", __func__);
 		return -EINVAL;
 	}
+	tx_priv->lpi_enable = false;
+	tx_priv->register_event_listener = false;
 	tx_priv->version = bolero_get_version(tx_dev);
 	if (tx_priv->version >= BOLERO_VERSION_2_0) {
 		ret = snd_soc_dapm_new_controls(dapm,

+ 19 - 1
asoc/codecs/bolero/va-macro.c

@@ -173,6 +173,7 @@ struct va_macro_priv {
 	bool lpi_enable;
 	bool register_event_listener;
 	int dec_mode[VA_MACRO_NUM_DECIMATORS];
+	int disable_afe_wakeup_event_listener;
 };
 
 static bool va_macro_get_data(struct snd_soc_component *component,
@@ -435,7 +436,8 @@ static int va_macro_swr_pwr_event(struct snd_soc_dapm_widget *w,
 					"%s: lpass audio hw enable failed\n",
 					__func__);
 		}
-		if (va_priv->lpi_enable) {
+		if (va_priv->lpi_enable &&
+		    !va_priv->disable_afe_wakeup_event_listener) {
 			bolero_register_event_listener(component, true);
 			va_priv->register_event_listener = true;
 		}
@@ -2992,7 +2994,10 @@ static int va_macro_probe(struct platform_device *pdev)
 	u32 default_clk_id = 0;
 	struct clk *lpass_audio_hw_vote = NULL;
 	u32 is_used_va_swr_gpio = 0;
+	u32 disable_afe_wakeup_event_listener = 0;
 	const char *is_used_va_swr_gpio_dt = "qcom,is-used-swr-gpio";
+	const char *disable_afe_wakeup_event_listener_dt =
+			"qcom,disable-afe-wakeup-event-listener";
 
 	va_priv = devm_kzalloc(&pdev->dev, sizeof(struct va_macro_priv),
 			    GFP_KERNEL);
@@ -3034,6 +3039,19 @@ static int va_macro_probe(struct platform_device *pdev)
 			is_used_va_swr_gpio = 0;
 		}
 	}
+
+	if (of_find_property(pdev->dev.of_node,
+			     disable_afe_wakeup_event_listener_dt, NULL)) {
+		ret = of_property_read_u32(pdev->dev.of_node,
+					   disable_afe_wakeup_event_listener_dt,
+					   &disable_afe_wakeup_event_listener);
+		if (ret)
+			dev_dbg(&pdev->dev, "%s: error reading %s in dt\n",
+				__func__, disable_afe_wakeup_event_listener_dt);
+	}
+	va_priv->disable_afe_wakeup_event_listener =
+			disable_afe_wakeup_event_listener;
+
 	va_priv->va_swr_gpio_p = of_parse_phandle(pdev->dev.of_node,
 					"qcom,va-swr-gpios", 0);
 	if (!va_priv->va_swr_gpio_p && is_used_va_swr_gpio) {

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

@@ -843,6 +843,7 @@ static int wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute)
 	uint16_t j = 0, reg = 0, mix_reg = 0, dsm_reg = 0;
 	u16 int_mux_cfg0 = 0, int_mux_cfg1 = 0;
 	u8 int_mux_cfg0_val = 0, int_mux_cfg1_val = 0;
+	bool adie_lb = false;
 
 	if (mute)
 		return 0;
@@ -879,7 +880,7 @@ static int wsa_macro_digital_mute(struct snd_soc_dai *dai, int mute)
 			}
 		}
 	}
-	bolero_wsa_pa_on(wsa_dev);
+	bolero_wsa_pa_on(wsa_dev, adie_lb);
 		break;
 	default:
 		break;
@@ -1470,6 +1471,7 @@ static int wsa_macro_enable_main_path(struct snd_soc_dapm_widget *w,
 	u16 reg = 0;
 	struct device *wsa_dev = NULL;
 	struct wsa_macro_priv *wsa_priv = NULL;
+	bool adie_lb = false;
 
 	if (!wsa_macro_get_data(component, &wsa_dev, &wsa_priv, __func__))
 		return -EINVAL;
@@ -1480,9 +1482,10 @@ static int wsa_macro_enable_main_path(struct snd_soc_dapm_widget *w,
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		if (wsa_macro_adie_lb(component, w->shift)) {
+			adie_lb = true;
 			snd_soc_component_update_bits(component,
 						reg, 0x20, 0x20);
-			bolero_wsa_pa_on(wsa_dev);
+			bolero_wsa_pa_on(wsa_dev, adie_lb);
 		}
 		break;
 	default:
@@ -2561,10 +2564,10 @@ static const struct snd_soc_dapm_widget wsa_macro_dapm_widgets[] = {
 	SND_SOC_DAPM_MUX_E("WSA_RX1 MIX INP", SND_SOC_NOPM,
 		0, 0, &rx1_mix_mux, wsa_macro_enable_mix_path,
 		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
+	SND_SOC_DAPM_PGA_E("WSA_RX INT0 MIX", SND_SOC_NOPM,
 			0, 0, NULL, 0, wsa_macro_enable_main_path,
 			SND_SOC_DAPM_PRE_PMU),
-	SND_SOC_DAPM_MIXER_E("WSA_RX INT1 MIX", SND_SOC_NOPM,
+	SND_SOC_DAPM_PGA_E("WSA_RX INT1 MIX", SND_SOC_NOPM,
 			1, 0, NULL, 0, wsa_macro_enable_main_path,
 			SND_SOC_DAPM_PRE_PMU),
 	SND_SOC_DAPM_MIXER("WSA_RX INT0 SEC MIX", SND_SOC_NOPM, 0, 0, NULL, 0),

+ 46 - 0
asoc/codecs/msm-cdc-supply.c

@@ -173,6 +173,52 @@ bool msm_cdc_is_ondemand_supply(struct device *dev,
 }
 EXPORT_SYMBOL(msm_cdc_is_ondemand_supply);
 
+/*
+ * msm_cdc_set_supply_min_voltage:
+ *	Set min supply voltage for particular supply
+ *
+ * @dev: pointer to codec device
+ * @supplies: pointer to regulator bulk data
+ * @cdc_vreg: pointer to platform regulator data
+ * @num_supplies: number of supplies
+ * @supply_name: Supply name to change voltage for
+ * @vval_min: Min voltage to be set in uV
+ * @override_min_vol: True if override min voltage from default
+ * Return error code if unable to set voltage
+ */
+int msm_cdc_set_supply_min_voltage(struct device *dev,
+				    struct regulator_bulk_data *supplies,
+				    struct cdc_regulator *cdc_vreg,
+				    int num_supplies, char *supply_name,
+				    int vval_min, bool override_min_vol)
+{
+	int rc = 0, i;
+
+	if ((!supply_name) || (!supplies)) {
+		pr_err("%s: either dev or supplies or cdc_vreg is NULL\n",
+				__func__);
+		return -EINVAL;
+	}
+	/* input parameter validation */
+	rc = msm_cdc_check_supply_param(dev, cdc_vreg, num_supplies);
+	if (rc)
+		return rc;
+	for (i = 0; i < num_supplies; i++) {
+		if (!strcmp(cdc_vreg[i].name, supply_name)) {
+			if (override_min_vol)
+				regulator_set_voltage(supplies[i].consumer,
+					vval_min, cdc_vreg[i].max_uV);
+			else
+				regulator_set_voltage(supplies[i].consumer,
+				    cdc_vreg[i].min_uV, cdc_vreg[i].max_uV);
+			break;
+		}
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(msm_cdc_set_supply_min_voltage);
+
 /*
  * msm_cdc_disable_ondemand_supply:
  *	Disable codec ondemand supply

+ 1 - 1
asoc/codecs/msm_hdmi_codec_rx.c

@@ -224,7 +224,7 @@ static int msm_ext_disp_audio_type_get(struct snd_kcontrol *kcontrol,
 
 	if (!codec_data->ext_disp_ops.get_audio_edid_blk ||
 	    !codec_data->ext_disp_ops.get_intf_id || rc) {
-		dev_err(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
+		dev_err_ratelimited(component->dev, "%s: get_audio_edid_blk() or get_intf_id is NULL\n",
 			__func__);
 		rc = -EINVAL;
 		goto cable_err;

+ 9 - 0
asoc/codecs/rouleur/internal.h

@@ -85,6 +85,11 @@ struct rouleur_priv {
 	struct mutex main_bias_lock;
 	bool dev_up;
 	bool usbc_hs_status;
+	struct notifier_block psy_nb;
+	struct work_struct soc_eval_work;
+	bool low_soc;
+	int foundry_id_reg;
+	int foundry_id;
 };
 
 struct rouleur_micbias_setting {
@@ -102,6 +107,7 @@ struct rouleur_pdata {
 	struct cdc_regulator *regulator;
 	int num_supplies;
 	int reset_reg;
+	int foundry_id_reg;
 };
 
 struct wcd_ctrl_platform_data {
@@ -131,6 +137,9 @@ enum {
 	WCD_BOLERO_EVT_IMPED_FALSE,	/* for imped false */
 	WCD_BOLERO_EVT_RX_COMPANDER_SOFT_RST,
 	WCD_BOLERO_EVT_BCS_CLK_OFF,
+	WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE, /* To reduce PA gain for low SoC */
+	WCD_BOLERO_EVT_HPHL_HD2_ENABLE, /* to enable hd2 config for hphl */
+	WCD_BOLERO_EVT_HPHR_HD2_ENABLE, /* to enable hd2 config for hphr */
 };
 
 enum {

+ 5 - 0
asoc/codecs/rouleur/pm2250-spmi.h

@@ -7,11 +7,16 @@
 
 #ifdef CONFIG_PM2250_SPMI
 int pm2250_spmi_write(struct device *dev, int reg, int value);
+int pm2250_spmi_read(struct device *dev, int reg, int *value);
 #else
 int pm2250_spmi_write(struct device *dev, int reg, int value)
 {
 	return 0;
 }
+int pm2250_spmi_read(struct device *dev, int reg, int *value);
+{
+	return 0;
+}
 #endif	/* CONFIG_PM2250_SPMI */
 
 #endif

+ 34 - 0
asoc/codecs/rouleur/pm2250_spmi.c

@@ -25,6 +25,12 @@ static const struct of_device_id pm2250_id_table[] = {
 };
 MODULE_DEVICE_TABLE(of, pm2250_id_table);
 
+/**
+ * pm2250_spmi_write: Function to write to PMIC register
+ * @device: node for rouleur device
+ * @reg: PMIC register to write value
+ * @value: Value to be written to PMIC register
+ */
 int pm2250_spmi_write(struct device *dev, int reg, int value)
 {
 	int rc;
@@ -47,6 +53,34 @@ int pm2250_spmi_write(struct device *dev, int reg, int value)
 }
 EXPORT_SYMBOL(pm2250_spmi_write);
 
+/**
+ * pm2250_spmi_read: Function to read PMIC register
+ * @device: node for rouleur device
+ * @reg: PMIC register to read value
+ * @value: Pointer to value of reg to be read
+ */
+int pm2250_spmi_read(struct device *dev, int reg, int *value)
+{
+	int rc;
+	struct pm2250_spmi *spmi_dd;
+
+	if (!of_device_is_compatible(dev->of_node, "qcom,pm2250-spmi")) {
+		pr_err("%s: Device node is invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	spmi_dd = dev_get_drvdata(dev);
+	if (!spmi_dd)
+		return -EINVAL;
+
+	rc = regmap_read(spmi_dd->regmap, reg, value);
+	if (rc)
+		dev_err(dev, "%s: Read from PMIC register failed\n", __func__);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm2250_spmi_read);
+
 static int pm2250_spmi_probe(struct platform_device *pdev)
 {
 	struct pm2250_spmi *spmi_dd;

+ 36 - 21
asoc/codecs/rouleur/rouleur-mbhc.c

@@ -36,6 +36,8 @@
 #define ROULEUR_HPHL_CROSS_CONN_THRESHOLD 350
 #define ROULEUR_HPHR_CROSS_CONN_THRESHOLD 350
 
+#define IMPED_NUM_RETRY 5
+
 static struct wcd_mbhc_register
 	wcd_mbhc_registers[WCD_MBHC_REG_FUNC_MAX] = {
 	WCD_MBHC_REGISTER("WCD_MBHC_L_DET_EN",
@@ -515,6 +517,35 @@ z_right:
 	*zr = zdet;
 }
 
+static void rouleur_mbhc_impedance_fn(struct snd_soc_component *component,
+				      int32_t *z1L, int32_t *z1R,
+				      int32_t *zl, int32_t *zr)
+{
+	int i;
+	for (i = 0; i < IMPED_NUM_RETRY; i++) {
+		/* Start of left ch impedance calculation */
+		rouleur_mbhc_zdet_start(component, z1L, NULL);
+		if ((*z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
+		    (*z1L > ROULEUR_ZDET_VAL_100K))
+			*zl = ROULEUR_ZDET_FLOATING_IMPEDANCE;
+		else
+			*zl = *z1L/1000;
+
+		/* Start of right ch impedance calculation */
+		rouleur_mbhc_zdet_start(component, NULL, z1R);
+		if ((*z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
+		    (*z1R > ROULEUR_ZDET_VAL_100K))
+			*zr = ROULEUR_ZDET_FLOATING_IMPEDANCE;
+		else
+			*zr = *z1R/1000;
+	}
+
+	dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
+		__func__, *zl);
+	dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
+		__func__, *zr);
+}
+
 static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
 					  uint32_t *zr)
 {
@@ -564,27 +595,11 @@ static void rouleur_wcd_mbhc_calc_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
 	/* 1ms delay needed after disable surge protection */
 	usleep_range(1000, 1010);
 
-	/* Start of left ch impedance calculation */
-	rouleur_mbhc_zdet_start(component, &z1L, NULL);
-	if ((z1L == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
-		(z1L > ROULEUR_ZDET_VAL_100K))
-		*zl = ROULEUR_ZDET_FLOATING_IMPEDANCE;
-	else
-		*zl = z1L/1000;
-
-	dev_dbg(component->dev, "%s: impedance on HPH_L = %d(ohms)\n",
-		__func__, *zl);
-
-	/* Start of right ch impedance calculation */
-	rouleur_mbhc_zdet_start(component, NULL, &z1R);
-	if ((z1R == ROULEUR_ZDET_FLOATING_IMPEDANCE) ||
-		(z1R > ROULEUR_ZDET_VAL_100K))
-		*zr = ROULEUR_ZDET_FLOATING_IMPEDANCE;
-	else
-		*zr = z1R/1000;
-
-	dev_dbg(component->dev, "%s: impedance on HPH_R = %d(ohms)\n",
-		__func__, *zr);
+	/*
+	 * Call impedance detection routine multiple times
+	 * in order to avoid wrong impedance values.
+	 */
+	rouleur_mbhc_impedance_fn(component, &z1L, &z1R, zl, zr);
 
 	/* Mono/stereo detection */
 	if ((*zl == ROULEUR_ZDET_FLOATING_IMPEDANCE) &&

+ 3 - 0
asoc/codecs/rouleur/rouleur-registers.h

@@ -48,6 +48,7 @@ enum {
 #define ROULEUR_ANA_MBHC_CTL_CLK              (ROULEUR_ANA_BASE_ADDR+0x06D)
 #define ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT    (ROULEUR_ANA_BASE_ADDR+0x072)
 #define ROULEUR_ANA_NCP_EN                    (ROULEUR_ANA_BASE_ADDR+0x077)
+#define ROULEUR_ANA_NCP_VCTRL                 (ROULEUR_ANA_BASE_ADDR+0x07C)
 #define ROULEUR_ANA_HPHPA_CNP_CTL_1           (ROULEUR_ANA_BASE_ADDR+0x083)
 #define ROULEUR_ANA_HPHPA_CNP_CTL_2           (ROULEUR_ANA_BASE_ADDR+0x084)
 #define ROULEUR_ANA_HPHPA_PA_STATUS           (ROULEUR_ANA_BASE_ADDR+0x087)
@@ -58,6 +59,8 @@ enum {
 #define ROULEUR_SWR_HPHPA_HD2                 (ROULEUR_ANA_BASE_ADDR+0x090)
 #define ROULEUR_ANA_SURGE_EN                  (ROULEUR_ANA_BASE_ADDR+0x097)
 #define ROULEUR_ANA_COMBOPA_CTL               (ROULEUR_ANA_BASE_ADDR+0x09B)
+#define ROULEUR_ANA_COMBOPA_CTL_4             (ROULEUR_ANA_BASE_ADDR+0x09F)
+#define ROULEUR_ANA_COMBOPA_CTL_5             (ROULEUR_ANA_BASE_ADDR+0x0A0)
 #define ROULEUR_ANA_RXLDO_CTL                 (ROULEUR_ANA_BASE_ADDR+0x0B2)
 #define ROULEUR_ANA_MBIAS_EN                  (ROULEUR_ANA_BASE_ADDR+0x0B4)
 

+ 3 - 0
asoc/codecs/rouleur/rouleur-regmap.c

@@ -41,6 +41,7 @@ static const struct reg_default rouleur_defaults[] = {
 	{ ROULEUR_ANA_MBHC_CTL_CLK,               0x30 },
 	{ ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT,     0x00 },
 	{ ROULEUR_ANA_NCP_EN,                     0x00 },
+	{ ROULEUR_ANA_NCP_VCTRL,                  0xA7 },
 	{ ROULEUR_ANA_HPHPA_CNP_CTL_1,            0x54 },
 	{ ROULEUR_ANA_HPHPA_CNP_CTL_2,            0x2B },
 	{ ROULEUR_ANA_HPHPA_PA_STATUS,            0x00 },
@@ -51,6 +52,8 @@ static const struct reg_default rouleur_defaults[] = {
 	{ ROULEUR_ANA_HPHPA_SPARE_CTL,            0x02 },
 	{ ROULEUR_ANA_SURGE_EN,                   0x38 },
 	{ ROULEUR_ANA_COMBOPA_CTL,                0x35 },
+	{ ROULEUR_ANA_COMBOPA_CTL_4,              0x84 },
+	{ ROULEUR_ANA_COMBOPA_CTL_5,              0x05 },
 	{ ROULEUR_ANA_RXLDO_CTL,                  0x86 },
 	{ ROULEUR_ANA_MBIAS_EN,                   0x00 },
 	{ ROULEUR_DIG_SWR_CHIP_ID0,               0x00 },

+ 3 - 0
asoc/codecs/rouleur/rouleur-tables.c

@@ -36,6 +36,7 @@ const u8 rouleur_reg_access_analog[ROULEUR_REG(
 	[ROULEUR_REG(ROULEUR_ANA_MBHC_CTL_CLK)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_MBHC_ZDET_CALIB_RESULT)] = RD_REG,
 	[ROULEUR_REG(ROULEUR_ANA_NCP_EN)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_NCP_VCTRL)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_1)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_HPHPA_CNP_CTL_2)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_HPHPA_PA_STATUS)] = RD_REG,
@@ -46,6 +47,8 @@ const u8 rouleur_reg_access_analog[ROULEUR_REG(
 	[ROULEUR_REG(ROULEUR_SWR_HPHPA_HD2)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_SURGE_EN)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL_4)] = RD_WR_REG,
+	[ROULEUR_REG(ROULEUR_ANA_COMBOPA_CTL_5)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_RXLDO_CTL)] = RD_WR_REG,
 	[ROULEUR_REG(ROULEUR_ANA_MBIAS_EN)] = RD_WR_REG,
 };

+ 210 - 16
asoc/codecs/rouleur/rouleur.c

@@ -26,6 +26,7 @@
 #include <asoc/msm-cdc-pinctrl.h>
 #include <dt-bindings/sound/audio-codec-port-types.h>
 #include <asoc/msm-cdc-supply.h>
+#include <linux/power_supply.h>
 
 #define DRV_NAME "rouleur_codec"
 
@@ -35,6 +36,10 @@
 #define ROULEUR_VERSION_ENTRY_SIZE 32
 
 #define NUM_ATTEMPTS 5
+#define SOC_THRESHOLD_LEVEL 25
+#define LOW_SOC_MBIAS_REG_MIN_VOLTAGE 2850000
+
+#define FOUNDRY_ID_SEC 0x5
 
 enum {
 	CODEC_TX = 0,
@@ -361,6 +366,8 @@ static int rouleur_rx_clk_enable(struct snd_soc_component *component)
 				ROULEUR_ANA_HPHPA_FSM_CLK, 0x7F, 0x11);
 		snd_soc_component_update_bits(component,
 				ROULEUR_ANA_HPHPA_FSM_CLK, 0x80, 0x80);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_NCP_VCTRL, 0x07, 0x06);
 		snd_soc_component_update_bits(component,
 				ROULEUR_ANA_NCP_EN, 0x01, 0x01);
 		usleep_range(500, 510);
@@ -591,12 +598,12 @@ static int rouleur_codec_ear_lo_dac_event(struct snd_soc_dapm_widget *w,
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_CDC_RX0_CTL,
 				0x80, 0x00);
-		snd_soc_component_update_bits(component,
-				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
-				0x04, 0x04);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_CDC_RX_CLK_CTL,
 				0x01, 0x01);
+		snd_soc_component_update_bits(component,
+				ROULEUR_DIG_SWR_CDC_RX_GAIN_CTL,
+				0x04, 0x04);
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
@@ -635,7 +642,12 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 				    true);
 
 		set_bit(HPH_PA_DELAY, &rouleur->status_mask);
-		usleep_range(5000, 5100);
+		usleep_range(200, 210);
+		/* Enable HD2 Config for HPHR if foundry id is SEC */
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						WCD_BOLERO_EVT_HPHR_HD2_ENABLE,
+						0x04);
 		snd_soc_component_update_bits(component,
 			ROULEUR_DIG_SWR_PDM_WD_CTL1,
 			0x03, 0x03);
@@ -671,9 +683,8 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		/*
-		 * 7ms sleep is required after PA is disabled as per
-		 * HW requirement. If compander is disabled, then
-		 * 20ms delay is required.
+		 * 5ms sleep is required after PA is disabled as per
+		 * HW requirement.
 		 */
 		if (test_bit(HPH_PA_DELAY, &rouleur->status_mask)) {
 
@@ -681,6 +692,10 @@ static int rouleur_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 			clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
 		}
 
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						WCD_BOLERO_EVT_HPHR_HD2_ENABLE,
+						0x00);
 		blocking_notifier_call_chain(&rouleur->mbhc->notifier,
 					     WCD_EVENT_POST_HPHR_PA_OFF,
 					     &rouleur->mbhc->wcd_mbhc);
@@ -710,7 +725,11 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 				    rouleur->rx_swr_dev->dev_num,
 				    true);
 		set_bit(HPH_PA_DELAY, &rouleur->status_mask);
-		usleep_range(5000, 5100);
+		usleep_range(200, 210);
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x04);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_PDM_WD_CTL0,
 				0x03, 0x03);
@@ -754,6 +773,10 @@ static int rouleur_codec_enable_hphl_pa(struct snd_soc_dapm_widget *w,
 			clear_bit(HPH_PA_DELAY, &rouleur->status_mask);
 		}
 
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x00);
 		blocking_notifier_call_chain(&rouleur->mbhc->notifier,
 					     WCD_EVENT_POST_HPHL_PA_OFF,
 					     &rouleur->mbhc->wcd_mbhc);
@@ -783,18 +806,36 @@ 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);
-		usleep_range(5000, 5100);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_5,
+				0x04, 0x00);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x0F);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL,
+				0x40, 0x00);
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x04);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_PDM_WD_CTL0,
 				0x03, 0x03);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(5000, 5100);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x04);
 		if (rouleur->update_wcd_event)
 			rouleur->update_wcd_event(rouleur->handle,
 						WCD_BOLERO_EVT_RX_MUTE,
 						(WCD_RX1 << 0x10));
-			wcd_enable_irq(&rouleur->irq_info,
-					ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		wcd_enable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
 		wcd_disable_irq(&rouleur->irq_info,
@@ -806,6 +847,10 @@ static int rouleur_codec_enable_ear_pa(struct snd_soc_dapm_widget *w,
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		usleep_range(5000, 5100);
+		if (rouleur->foundry_id == FOUNDRY_ID_SEC)
+			rouleur->update_wcd_event(rouleur->handle,
+						WCD_BOLERO_EVT_HPHL_HD2_ENABLE,
+						0x00);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_PDM_WD_CTL0,
 				0x03, 0x00);
@@ -830,24 +875,35 @@ static int rouleur_codec_enable_lo_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_5,
+				0x04, 0x00);
+		usleep_range(1000, 1010);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x0F);
+		usleep_range(1000, 1010);
 		snd_soc_component_update_bits(component,
 				ROULEUR_ANA_COMBOPA_CTL,
 				0x40, 0x40);
-		usleep_range(5000, 5100);
 		snd_soc_component_update_bits(component,
 				ROULEUR_DIG_SWR_PDM_WD_CTL0,
 				0x03, 0x03);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
+		usleep_range(5000, 5100);
+		snd_soc_component_update_bits(component,
+				ROULEUR_ANA_COMBOPA_CTL_4,
+				0x0F, 0x04);
 		if (rouleur->update_wcd_event)
 			rouleur->update_wcd_event(rouleur->handle,
 						WCD_BOLERO_EVT_RX_MUTE,
 						(WCD_RX1 << 0x10));
-			wcd_enable_irq(&rouleur->irq_info,
-					ROULEUR_IRQ_HPHL_PDM_WD_INT);
+		wcd_enable_irq(&rouleur->irq_info,
+				ROULEUR_IRQ_HPHL_PDM_WD_INT);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-			wcd_disable_irq(&rouleur->irq_info,
+		wcd_disable_irq(&rouleur->irq_info,
 					ROULEUR_IRQ_HPHL_PDM_WD_INT);
 		if (rouleur->update_wcd_event)
 			rouleur->update_wcd_event(rouleur->handle,
@@ -1400,6 +1456,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 +1469,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__,
@@ -1974,6 +2030,126 @@ done:
 	return rc;
 }
 
+static int rouleur_battery_supply_cb(struct notifier_block *nb,
+			unsigned long event, void *data)
+{
+	struct power_supply *psy = data;
+	struct rouleur_priv *rouleur =
+		container_of(nb, struct rouleur_priv, psy_nb);
+
+	if (strcmp(psy->desc->name, "battery"))
+		return NOTIFY_OK;
+	queue_work(system_freezable_wq, &rouleur->soc_eval_work);
+
+	return NOTIFY_OK;
+}
+
+static int rouleur_read_battery_soc(struct rouleur_priv *rouleur, int *soc_val)
+{
+	static struct power_supply *batt_psy;
+	union power_supply_propval ret = {0,};
+	int err = 0;
+
+	*soc_val = 100;
+	if (!batt_psy)
+		batt_psy = power_supply_get_by_name("battery");
+	if (batt_psy) {
+		err = power_supply_get_property(batt_psy,
+				POWER_SUPPLY_PROP_CAPACITY, &ret);
+		if (err) {
+			pr_err("%s: battery SoC read error:%d\n",
+				__func__, err);
+			return err;
+		}
+		*soc_val = ret.intval;
+	}
+	pr_debug("%s: soc:%d\n", __func__, *soc_val);
+
+	return err;
+}
+
+static void rouleur_evaluate_soc(struct work_struct *work)
+{
+	struct rouleur_priv *rouleur =
+		container_of(work, struct rouleur_priv, soc_eval_work);
+	int soc_val = 0, ret = 0;
+	struct rouleur_pdata *pdata = NULL;
+
+	pdata = dev_get_platdata(rouleur->dev);
+	if (!pdata) {
+		dev_err(rouleur->dev, "%s: pdata is NULL\n", __func__);
+		return;
+	}
+
+	if (rouleur_read_battery_soc(rouleur, &soc_val) < 0) {
+		dev_err(rouleur->dev, "%s unable to read battery SoC\n",
+			__func__);
+		return;
+	}
+
+	if (soc_val < SOC_THRESHOLD_LEVEL) {
+		dev_dbg(rouleur->dev,
+			"%s battery SoC less than threshold soc_val = %d\n",
+			__func__, soc_val);
+		/* Reduce PA Gain by 6DB for low SoC */
+		if (rouleur->update_wcd_event)
+			rouleur->update_wcd_event(rouleur->handle,
+					WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE,
+					true);
+		rouleur->low_soc = true;
+		ret = msm_cdc_set_supply_min_voltage(rouleur->dev,
+						 rouleur->supplies,
+						 pdata->regulator,
+						 pdata->num_supplies,
+						 "cdc-vdd-mic-bias",
+						 LOW_SOC_MBIAS_REG_MIN_VOLTAGE,
+						 true);
+		if (ret < 0)
+			dev_err(rouleur->dev,
+				"%s unable to set mbias min voltage\n",
+				__func__);
+	} else {
+		if (rouleur->low_soc == true) {
+			/* Reset PA Gain to default for normal SoC */
+			if (rouleur->update_wcd_event)
+				rouleur->update_wcd_event(rouleur->handle,
+					WCD_BOLERO_EVT_RX_PA_GAIN_UPDATE,
+					false);
+			ret = msm_cdc_set_supply_min_voltage(rouleur->dev,
+						rouleur->supplies,
+						pdata->regulator,
+						pdata->num_supplies,
+						"cdc-vdd-mic-bias",
+						LOW_SOC_MBIAS_REG_MIN_VOLTAGE,
+						false);
+			if (ret < 0)
+				dev_err(rouleur->dev,
+					"%s unable to set mbias min voltage\n",
+					__func__);
+			rouleur->low_soc = false;
+		}
+	}
+}
+
+static void rouleur_get_foundry_id(struct rouleur_priv *rouleur)
+{
+	int ret;
+
+	if (rouleur->foundry_id_reg == 0) {
+		pr_debug("%s: foundry id not defined\n", __func__);
+		return;
+	}
+
+	ret = pm2250_spmi_read(rouleur->spmi_dev,
+				rouleur->foundry_id_reg, &rouleur->foundry_id);
+	if (ret == 0)
+		pr_debug("%s: rouleur foundry id = %x\n", rouleur->foundry_id,
+			 __func__);
+	else
+		pr_debug("%s: rouleur error in spmi read ret = %d\n",
+			 __func__, ret);
+}
+
 static int rouleur_soc_codec_probe(struct snd_soc_component *component)
 {
 	struct rouleur_priv *rouleur = snd_soc_component_get_drvdata(component);
@@ -2029,6 +2205,8 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
 	snd_soc_dapm_sync(dapm);
 
 	rouleur_init_reg(component);
+	/* Get rouleur foundry id */
+	rouleur_get_foundry_id(rouleur);
 
 	rouleur->version = ROULEUR_VERSION_1_0;
        /* Register event notifier */
@@ -2044,7 +2222,16 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
 			return ret;
 		}
 	}
+	rouleur->low_soc = false;
 	rouleur->dev_up = true;
+	/* Register notifier to change gain based on state of charge */
+	INIT_WORK(&rouleur->soc_eval_work, rouleur_evaluate_soc);
+	rouleur->psy_nb.notifier_call = rouleur_battery_supply_cb;
+	if (power_supply_reg_notifier(&rouleur->psy_nb) < 0)
+		dev_dbg(rouleur->dev,
+			"%s: could not register pwr supply notifier\n",
+			__func__);
+	queue_work(system_freezable_wq, &rouleur->soc_eval_work);
 done:
 	return ret;
 }
@@ -2278,6 +2465,12 @@ struct rouleur_pdata *rouleur_populate_dt_data(struct device *dev)
 	}
 	pdata->reset_reg = reg;
 
+	if (of_property_read_u32(dev->of_node, "qcom,foundry-id-reg", &reg))
+		dev_dbg(dev, "%s: Failed to obtain foundry id\n",
+			__func__);
+	else
+		pdata->foundry_id_reg = reg;
+
 	/* Parse power supplies */
 	msm_cdc_get_power_supplies(dev, &pdata->regulator,
 				   &pdata->num_supplies);
@@ -2353,6 +2546,7 @@ static int rouleur_bind(struct device *dev)
 
 	rouleur->spmi_dev = &pdev->dev;
 	rouleur->reset_reg = pdata->reset_reg;
+	rouleur->foundry_id_reg = pdata->foundry_id_reg;
 	ret = msm_cdc_init_supplies(dev, &rouleur->supplies,
 				    pdata->regulator, pdata->num_supplies);
 	if (!rouleur->supplies) {

+ 57 - 21
asoc/codecs/swr-dmic.c

@@ -33,6 +33,8 @@
 #define NUM_ATTEMPTS 5
 #define SWRS_SCP_CONTROL    0x44
 
+#define MAX_NAME_LEN 40
+
 static int swr_master_channel_map[] = {
 	ZERO,
 	SWRM_TX1_CH1,
@@ -94,6 +96,9 @@ const char *aif_name_list[] = {
 static int swr_dmic_reset(struct swr_device *pdev);
 static int swr_dmic_up(struct swr_device *pdev);
 static int swr_dmic_down(struct swr_device *pdev);
+static int swr_dmic_event_notify(struct notifier_block *block,
+				unsigned long val,
+				void *data);
 
 static inline int swr_dmic_tx_get_slave_port_type_idx(const char *wname,
 				      unsigned int *port_idx)
@@ -269,23 +274,41 @@ static const struct snd_kcontrol_new dmic_switch[] = {
 	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
 };
 
+static const struct snd_kcontrol_new va_dmic_switch[] = {
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0)
+};
+
 static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
 	SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM, 0, 0,
 			dmic_switch, ARRAY_SIZE(dmic_switch), dmic_swr_ctrl,
 			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_MIXER_E("SWR_DMIC_VA_MIXER", SND_SOC_NOPM, 0, 0,
+			va_dmic_switch, ARRAY_SIZE(va_dmic_switch), dmic_swr_ctrl,
+			SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_INPUT("SWR_DMIC"),
+	SND_SOC_DAPM_INPUT("VA_SWR_DMIC"),
 
 	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),
+
+	SND_SOC_DAPM_OUT_DRV_E("SMIC_VA_PORT_EN", SND_SOC_NOPM, 0, 0, NULL, 0,
+				swr_dmic_port_enable,
+				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+
 	SND_SOC_DAPM_OUTPUT("SWR_DMIC_OUTPUT"),
+	SND_SOC_DAPM_OUTPUT("SWR_DMIC_VA_OUTPUT"),
 };
 
 static const struct snd_soc_dapm_route swr_dmic_audio_map[] = {
 	{"SWR_DMIC_MIXER", "Switch", "SWR_DMIC"},
 	{"SMIC_PORT_EN", NULL, "SWR_DMIC_MIXER"},
 	{"SWR_DMIC_OUTPUT", NULL, "SMIC_PORT_EN"},
+	{"SWR_DMIC_VA_MIXER", "Switch", "VA_SWR_DMIC"},
+	{"SMIC_VA_PORT_EN", NULL, "SWR_DMIC_VA_MIXER"},
+	{"SWR_DMIC_VA_OUTPUT", NULL, "SMIC_VA_PORT_EN"},
 };
 
 static int swr_dmic_codec_probe(struct snd_soc_component *component)
@@ -294,36 +317,45 @@ static int swr_dmic_codec_probe(struct snd_soc_component *component)
 			snd_soc_component_get_drvdata(component);
 	struct snd_soc_dapm_context *dapm =
 			snd_soc_component_get_dapm(component);
-	char w_name[100];
+	char w_name[MAX_NAME_LEN];
 
 	if (!swr_dmic)
 		return -EINVAL;
 
 	swr_dmic->component = component;
-	snd_soc_dapm_ignore_suspend(dapm,
-				swr_dmic->dai_driver->capture.stream_name);
-	memset(w_name, 0, 100);
-	strlcpy(w_name, component->name_prefix, 100);
-	strlcat(w_name, " SWR_DMIC", 100);
+	if (!component->name_prefix) {
+		dev_err(component->dev, "%s: component prefix is NULL\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " ", sizeof(w_name));
+	strlcat(w_name, swr_dmic->dai_driver->capture.stream_name,
+				sizeof(w_name));
 	snd_soc_dapm_ignore_suspend(dapm, w_name);
 
-	memset(w_name, 0, 100);
-	strlcpy(w_name, component->name_prefix, 100);
-	strlcat(w_name, " SMIC_SUPPLY", 100);
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SWR_DMIC", sizeof(w_name));
 	snd_soc_dapm_ignore_suspend(dapm, w_name);
 
-	memset(w_name, 0, 100);
-	strlcpy(w_name, component->name_prefix, 100);
-	strlcat(w_name, " SMIC_PORT_EN", 100);
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SMIC_PORT_EN", sizeof(w_name));
 	snd_soc_dapm_ignore_suspend(dapm, w_name);
 
-	memset(w_name, 0, 100);
-	strlcpy(w_name, component->name_prefix, 100);
-	strlcat(w_name, " SWR_DMIC_OUTPUT", 100);
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SWR_DMIC_OUTPUT", sizeof(w_name));
 	snd_soc_dapm_ignore_suspend(dapm, w_name);
 
 	snd_soc_dapm_sync(dapm);
 
+	swr_dmic->nblock.notifier_call = swr_dmic_event_notify;
+	wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component,
+					&swr_dmic->nblock, true);
+
 	return 0;
 }
 
@@ -472,6 +504,8 @@ static int swr_dmic_probe(struct swr_device *pdev)
 		ret = enable_wcd_codec_supply(swr_dmic, true);
 		if (ret) {
 			ret = -EPROBE_DEFER;
+			swr_dmic->is_wcd_supply = false;
+			swr_dmic->wcd_handle = NULL;
 			goto err;
 		}
 		++swr_dmic->is_en_supply;
@@ -516,11 +550,17 @@ static int swr_dmic_probe(struct swr_device *pdev)
 			"%s get devnum %d for dev addr %llx failed\n",
 			__func__, swr_devnum, pdev->addr);
 		ret = -EPROBE_DEFER;
-		goto dev_err;
+
+		if (swr_dmic->is_en_supply == 1) {
+			enable_wcd_codec_supply(swr_dmic, false);
+			--swr_dmic->is_en_supply;
+		}
+		swr_dmic->is_wcd_supply = false;
+		swr_dmic->wcd_handle = NULL;
+		goto err;
 	}
 	pdev->dev_num = swr_devnum;
 
-
 	swr_dmic->driver = devm_kzalloc(&pdev->dev,
 			sizeof(struct snd_soc_component_driver), GFP_KERNEL);
 	if (!swr_dmic->driver) {
@@ -586,10 +626,6 @@ static int swr_dmic_probe(struct swr_device *pdev)
 			strlen(swr_dmic_name_prefix_of) + 1);
 	component->name_prefix = prefix_name;
 
-	swr_dmic->nblock.notifier_call = swr_dmic_event_notify;
-	wcd938x_swr_dmic_register_notifier(swr_dmic->supply_component,
-					&swr_dmic->nblock, true);
-
 	return 0;
 
 dev_err:

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

@@ -456,48 +456,33 @@ static int swr_haptics_device_down(struct swr_device *sdev)
 static int swr_haptics_suspend(struct device *dev)
 {
 	struct swr_haptics_dev *swr_hap;
-	int rc;
+	int rc = 0;
 
 	swr_hap = swr_get_dev_data(to_swr_device(dev));
 	if (!swr_hap) {
 		dev_err(dev, "%s: no data for swr_hap\n", __func__);
 		return -ENODEV;
 	}
+	trace_printk("%s: suspended\n", __func__);
 
-	/* Put SWR slave into reset */
-	rc = regulator_disable(swr_hap->vdd);
-	if (rc < 0) {
-		dev_err(swr_hap->dev, "%s: disable swr-slave failed, rc=%d\n",
-				__func__, rc);
-		return rc;
-	}
-
-	return 0;
+	return rc;
 }
 
 static int swr_haptics_resume(struct device *dev)
 {
 	struct swr_haptics_dev *swr_hap;
-	int rc;
+	int rc = 0;
 
 	swr_hap = swr_get_dev_data(to_swr_device(dev));
 	if (!swr_hap) {
 		dev_err(dev, "%s: no data for swr_hap\n", __func__);
 		return -ENODEV;
 	}
+	trace_printk("%s: resumed\n", __func__);
 
-	/* Take SWR slave out of reset */
-	rc = regulator_enable(swr_hap->vdd);
-	if (rc < 0) {
-		dev_err(swr_hap->dev, "%s: enable swr-slave failed, rc=%d\n",
-				__func__, rc);
-		return rc;
-	}
-
-	return 0;
+	return rc;
 }
 
-
 static const struct of_device_id swr_haptics_match_table[] = {
 	{ .compatible = "qcom,swr-haptics", },
 	{ .compatible = "qcom,pm8350b-swr-haptics", },

+ 75 - 12
asoc/codecs/wcd937x/wcd937x.c

@@ -26,8 +26,6 @@
 #include "wcd937x.h"
 #include "internal.h"
 
-#define DRV_NAME "wcd937x_codec"
-
 #define WCD9370_VARIANT 0
 #define WCD9375_VARIANT 5
 #define WCD937X_VARIANT_ENTRY_SIZE 32
@@ -40,6 +38,18 @@
 
 #define NUM_ATTEMPTS 5
 
+#define WCD937X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
+			SNDRV_PCM_RATE_384000)
+/* Fractional Rates */
+#define WCD937X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
+			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800)
+
+#define WCD937X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+		SNDRV_PCM_FMTBIT_S24_LE |\
+		SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
 enum {
 	CODEC_TX = 0,
 	CODEC_RX,
@@ -91,12 +101,39 @@ static struct regmap_irq_chip wcd937x_regmap_irq_chip = {
 	.mask_base = WCD937X_DIGITAL_INTR_MASK_0,
 	.ack_base = WCD937X_DIGITAL_INTR_CLEAR_0,
 	.use_ack = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
 	.clear_ack = 1,
+#endif
 	.type_base = WCD937X_DIGITAL_INTR_LEVEL_0,
 	.runtime_pm = false,
 	.handle_post_irq = wcd937x_handle_post_irq,
 	.irq_drv_data = NULL,
 };
+
+static struct snd_soc_dai_driver wcd937x_dai[] = {
+	{
+		.name = "wcd937x_cdc",
+		.playback = {
+			.stream_name = "WCD937X_AIF Playback",
+			.rates = WCD937X_RATES | WCD937X_FRAC_RATES,
+			.formats = WCD937X_FORMATS,
+			.rate_max = 384000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+		.capture = {
+			.stream_name = "WCD937X_AIF Capture",
+			.rates = WCD937X_RATES,
+			.formats = WCD937X_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 4,
+		},
+	},
+};
+
 static int wcd937x_handle_post_irq(void *data)
 {
 	struct wcd937x_priv *wcd937x = data;
@@ -278,7 +315,7 @@ static int wcd937x_tx_connect_port(struct snd_soc_component *component,
 	u8 ch_mask;
 	u32 ch_rate;
 	u8 ch_type = 0;
-	int slave_port_idx;
+	int slave_ch_idx;
 	u8 num_port = 1;
 	int ret = 0;
 
@@ -2195,6 +2232,14 @@ static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = {
 	SND_SOC_DAPM_INPUT("IN2_HPHR"),
 	SND_SOC_DAPM_INPUT("IN3_AUX"),
 
+	/*
+	 * These dummy widgets are null connected to WCD937x 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,
 				wcd937x_codec_enable_adc,
@@ -2224,15 +2269,15 @@ static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = {
 				SND_SOC_DAPM_POST_PMD),
 
 	/* micbias widgets*/
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS1", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_SUPPLY("MIC BIAS1", SND_SOC_NOPM, 0, 0,
 				wcd937x_codec_enable_micbias,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS2", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_SUPPLY("MIC BIAS2", SND_SOC_NOPM, 0, 0,
 				wcd937x_codec_enable_micbias,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("MIC BIAS3", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_SUPPLY("MIC BIAS3", SND_SOC_NOPM, 0, 0,
 				wcd937x_codec_enable_micbias,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
@@ -2316,15 +2361,15 @@ static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = {
 	SND_SOC_DAPM_OUTPUT("HPHR"),
 
 	/* micbias pull up widgets*/
-	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS1", SND_SOC_NOPM, 0, 0,
 				wcd937x_codec_enable_micbias_pullup,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS2", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS2", SND_SOC_NOPM, 0, 0,
 				wcd937x_codec_enable_micbias_pullup,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MICBIAS_E("VA MIC BIAS3", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_SUPPLY("VA MIC BIAS3", SND_SOC_NOPM, 0, 0,
 				wcd937x_codec_enable_micbias_pullup,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
 				SND_SOC_DAPM_POST_PMD),
@@ -2405,6 +2450,7 @@ static const struct snd_soc_dapm_widget wcd9375_dapm_widgets[] = {
 };
 
 static const struct snd_soc_dapm_route wcd937x_audio_map[] = {
+	{"WCD_TX_DUMMY", NULL, "WCD_TX_OUTPUT"},
 	{"WCD_TX_OUTPUT", NULL, "ADC1_MIXER"},
 	{"ADC1_MIXER", "Switch", "ADC1 REQ"},
 	{"ADC1 REQ", NULL, "ADC1"},
@@ -2417,6 +2463,7 @@ static const struct snd_soc_dapm_route wcd937x_audio_map[] = {
 	{"ADC2 MUX", "INP3", "AMIC3"},
 	{"ADC2 MUX", "INP2", "AMIC2"},
 
+	{"IN1_HPHL", NULL, "WCD_RX_DUMMY"},
 	{"IN1_HPHL", NULL, "VDD_BUCK"},
 	{"IN1_HPHL", NULL, "CLS_H_PORT"},
 	{"RX1", NULL, "IN1_HPHL"},
@@ -2425,6 +2472,7 @@ static const struct snd_soc_dapm_route wcd937x_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"},
@@ -2433,6 +2481,7 @@ static const struct snd_soc_dapm_route wcd937x_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"},
@@ -2451,6 +2500,7 @@ static const struct snd_soc_dapm_route wcd937x_audio_map[] = {
 
 static const struct snd_soc_dapm_route wcd9375_audio_map[] = {
 
+	{"WCD_TX_DUMMY", NULL, "WCD_TX_OUTPUT"},
 	{"WCD_TX_OUTPUT", NULL, "ADC3_MIXER"},
 	{"ADC3_OUTPUT", NULL, "ADC3_MIXER"},
 	{"ADC3_MIXER", "Switch", "ADC3 REQ"},
@@ -2576,19 +2626,25 @@ int wcd937x_info_create_codec_entry(struct snd_info_entry *codec_root,
 		return 0;
 	}
 	card = component->card;
-	priv->entry = snd_info_create_subdir(codec_root->module,
+	priv->entry = snd_info_create_module_entry(codec_root->module,
 					     "wcd937x", codec_root);
 	if (!priv->entry) {
 		dev_dbg(component->dev, "%s: failed to create wcd937x entry\n",
 			__func__);
 		return -ENOMEM;
 	}
+	priv->entry->mode = S_IFDIR | 0555;
+	if (snd_info_register(priv->entry) < 0) {
+		snd_info_free_entry(priv->entry);
+		return -ENOMEM;
+	}
 	version_entry = snd_info_create_card_entry(card->snd_card,
 						   "version",
 						   priv->entry);
 	if (!version_entry) {
 		dev_dbg(component->dev, "%s: failed to create wcd937x version entry\n",
 			__func__);
+		snd_info_free_entry(priv->entry);
 		return -ENOMEM;
 	}
 
@@ -2599,6 +2655,7 @@ int wcd937x_info_create_codec_entry(struct snd_info_entry *codec_root,
 
 	if (snd_info_register(version_entry) < 0) {
 		snd_info_free_entry(version_entry);
+		snd_info_free_entry(priv->entry);
 		return -ENOMEM;
 	}
 	priv->version_entry = version_entry;
@@ -2610,6 +2667,8 @@ int wcd937x_info_create_codec_entry(struct snd_info_entry *codec_root,
 		dev_dbg(component->dev,
 			"%s: failed to create wcd937x variant entry\n",
 			__func__);
+		snd_info_free_entry(version_entry);
+		snd_info_free_entry(priv->entry);
 		return -ENOMEM;
 	}
 
@@ -2620,6 +2679,8 @@ int wcd937x_info_create_codec_entry(struct snd_info_entry *codec_root,
 
 	if (snd_info_register(variant_entry) < 0) {
 		snd_info_free_entry(variant_entry);
+		snd_info_free_entry(version_entry);
+		snd_info_free_entry(priv->entry);
 		return -ENOMEM;
 	}
 	priv->variant_entry = variant_entry;
@@ -2713,6 +2774,8 @@ static int wcd937x_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(&wcd937x->clsh_info);
@@ -2781,7 +2844,7 @@ static void wcd937x_soc_codec_remove(struct snd_soc_component *component)
 }
 
 static const struct snd_soc_component_driver soc_codec_dev_wcd937x = {
-	.name = DRV_NAME,
+	.name = WCD937X_DRV_NAME,
 	.probe = wcd937x_soc_codec_probe,
 	.remove = wcd937x_soc_codec_remove,
 	.controls = wcd937x_snd_controls,
@@ -3185,7 +3248,7 @@ static int wcd937x_bind(struct device *dev)
 	wcd_disable_irq(&wcd937x->irq_info, WCD937X_IRQ_AUX_PDM_WD_INT);
 
 	ret = snd_soc_register_component(dev, &soc_codec_dev_wcd937x,
-				     NULL, 0);
+				     wcd937x_dai, ARRAY_SIZE(wcd937x_dai));
 	if (ret) {
 		dev_err(dev, "%s: Codec registration failed\n",
 				__func__);

+ 9 - 7
asoc/codecs/wcd937x/wcd937x.h

@@ -10,12 +10,14 @@
 #define WCD937X_MAX_SLAVE_CH_TYPES 10
 #define ZERO 0
 
-struct swr_slave_ch_map {
+#define WCD937X_DRV_NAME "wcd937x_codec"
+
+struct wcd937x_swr_slave_ch_map {
 	u8 ch_type;
 	u8 index;
 };
 
-static const struct swr_slave_ch_map swr_slv_tx_ch_idx[] = {
+static const struct wcd937x_swr_slave_ch_map wcd937x_swr_slv_tx_ch_idx[] = {
 	{ADC1, 0},
 	{ADC2, 1},
 	{ADC3, 2},
@@ -28,7 +30,7 @@ static const struct swr_slave_ch_map swr_slv_tx_ch_idx[] = {
 	{DMIC5, 9},
 };
 
-static int swr_master_ch_map[] = {
+static int wcd937x_swr_master_ch_map[] = {
 	ZERO,
 	SWRM_TX1_CH1,
 	SWRM_TX1_CH2,
@@ -54,14 +56,14 @@ static inline int wcd937x_slave_get_master_ch_val(int ch)
 	int i;
 
 	for (i = 0; i < WCD937X_MAX_SLAVE_CH_TYPES; i++)
-		if (ch == swr_master_ch_map[i])
+		if (ch == wcd937x_swr_master_ch_map[i])
 			return i;
 	return 0;
 }
 
 static inline int wcd937x_slave_get_master_ch(int idx)
 {
-	return swr_master_ch_map[idx];
+	return wcd937x_swr_master_ch_map[idx];
 }
 
 static inline int wcd937x_slave_get_slave_ch_val(int ch)
@@ -69,8 +71,8 @@ static inline int wcd937x_slave_get_slave_ch_val(int ch)
 	int i;
 
 	for (i = 0; i < WCD937X_MAX_SLAVE_CH_TYPES; i++)
-		if (ch == swr_slv_tx_ch_idx[i].ch_type)
-			return swr_slv_tx_ch_idx[i].index;
+		if (ch == wcd937x_swr_slv_tx_ch_idx[i].ch_type)
+			return wcd937x_swr_slv_tx_ch_idx[i].index;
 
 	return -EINVAL;
 }

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

@@ -69,6 +69,7 @@ struct wcd938x_priv {
 
 	u32 hph_mode;
 	u32 tx_mode[TX_ADC_MAX];
+	s32 adc_count;
 	bool comp1_enable;
 	bool comp2_enable;
 	bool ldoh;

+ 144 - 94
asoc/codecs/wcd938x/wcd938x.c

@@ -105,6 +105,7 @@ static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
 static int wcd938x_handle_post_irq(void *data);
 static int wcd938x_reset(struct device *dev);
 static int wcd938x_reset_low(struct device *dev);
+static int wcd938x_get_adc_mode(int val);
 
 static const struct regmap_irq wcd938x_irqs[WCD938X_NUM_IRQS] = {
 	REGMAP_IRQ_REG(WCD938X_IRQ_MBHC_BUTTON_PRESS_DET, 0, 0x01),
@@ -1412,8 +1413,7 @@ static int wcd938x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
 				true);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
-				wcd938x->tx_swr_dev->dev_num,
+		wcd938x_tx_connect_port(component, DMIC0 + (w->shift), 0,
 				false);
 		snd_soc_component_update_bits(component,
 				WCD938X_DIGITAL_CDC_AMIC_CTL,
@@ -1542,8 +1542,47 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
 	bank = (wcd938x_swr_slv_get_current_bank(wcd938x->tx_swr_dev,
 					wcd938x->tx_swr_dev->dev_num) ? 0 : 1);
 
+	/* power mode is applicable only to analog mics */
+	if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+		/* Get channel rate */
+		rate = wcd938x_get_clk_rate(wcd938x->tx_mode[w->shift - ADC1]);
+	}
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+		/* Check AMIC2 is connected to ADC2 to take an action on BCS */
+		if (w->shift == ADC2 && !(snd_soc_component_read32(component,
+			WCD938X_TX_NEW_AMIC_MUX_CFG) & 0x80)) {
+			if (!wcd938x->bcs_dis)
+				wcd938x_tx_connect_port(component, MBHC,
+					SWR_CLK_RATE_4P8MHZ, true);
+			set_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask);
+		}
+		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+			set_bit(w->shift - ADC1, &wcd938x->status_mask);
+			wcd938x_tx_connect_port(component, w->shift, rate,
+					true);
+		} else {
+			wcd938x_tx_connect_port(component, w->shift,
+					SWR_CLK_RATE_2P4MHZ, true);
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+			if (strnstr(w->name, "ADC1", sizeof("ADC1"))) {
+				clear_bit(WCD_ADC1, &wcd938x->status_mask);
+				clear_bit(WCD_ADC1_MODE, &wcd938x->status_mask);
+			} else if (strnstr(w->name, "ADC2", sizeof("ADC2"))) {
+				clear_bit(WCD_ADC2, &wcd938x->status_mask);
+				clear_bit(WCD_ADC2_MODE, &wcd938x->status_mask);
+			} else if (strnstr(w->name, "ADC3", sizeof("ADC3"))) {
+				clear_bit(WCD_ADC3, &wcd938x->status_mask);
+				clear_bit(WCD_ADC3_MODE, &wcd938x->status_mask);
+			} else if (strnstr(w->name, "ADC4", sizeof("ADC4"))) {
+				clear_bit(WCD_ADC4, &wcd938x->status_mask);
+				clear_bit(WCD_ADC4_MODE, &wcd938x->status_mask);
+			}
+		}
 		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
 			if (test_bit(WCD_ADC1, &wcd938x->status_mask) ||
 				test_bit(WCD_ADC1_MODE, &wcd938x->status_mask))
@@ -1567,49 +1606,19 @@ static int wcd938x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
 				}
 			}
 			rate = wcd938x_get_clk_rate(i);
+			if (wcd938x->adc_count) {
+				rate =  (wcd938x->adc_count * rate);
+				if (rate > SWR_CLK_RATE_9P6MHZ)
+					rate = SWR_CLK_RATE_9P6MHZ;
+			}
 			wcd938x_set_swr_clk_rate(component, rate, bank);
 		}
-		if (w->shift == ADC2 && !(snd_soc_component_read32(component,
-			WCD938X_TX_NEW_AMIC_MUX_CFG) & 0x80)) {
-			if (!wcd938x->bcs_dis)
-				wcd938x_tx_connect_port(component, MBHC,
-					SWR_CLK_RATE_4P8MHZ, true);
-			set_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask);
-		}
-		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
-			wcd938x_tx_connect_port(component, w->shift, rate,
-					true);
-			/* Copy clk settings to active bank */
-			wcd938x_set_swr_clk_rate(component, rate, !bank);
-		} else {
-			wcd938x_tx_connect_port(component, w->shift,
-					SWR_CLK_RATE_2P4MHZ, true);
-		}
-		break;
-	case SND_SOC_DAPM_POST_PMD:
-		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
-			rate = wcd938x_get_clk_rate(ADC_MODE_INVALID);
-			wcd938x_set_swr_clk_rate(component, rate, !bank);
-		}
-		wcd938x_tx_connect_port(component, w->shift, 0, false);
-		if (w->shift == ADC2 &&
-			test_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask)) {
-			if (!wcd938x->bcs_dis)
-				wcd938x_tx_connect_port(component, MBHC, 0,
-					false);
-			clear_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask);
-		}
+		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
+				wcd938x->tx_swr_dev->dev_num,
+				false);
 
 		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);
+			wcd938x_set_swr_clk_rate(component, rate, !bank);
 		break;
 	};
 
@@ -1697,7 +1706,91 @@ static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
 					snd_soc_dapm_to_component(w->dapm);
 	struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
 	int clk_rate = 0, ret = 0;
-	int mode;
+	int mode = 0, i = 0, bank = 0;
+
+	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
+		w->name, event);
+	bank = (wcd938x_swr_slv_get_current_bank(wcd938x->tx_swr_dev,
+		wcd938x->tx_swr_dev->dev_num) ? 0 : 1);
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		wcd938x->adc_count++;
+		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) ||
+			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) ||
+			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) ||
+			test_bit(WCD_ADC4_MODE, &wcd938x->status_mask))
+			mode |= tx_mode_bit[wcd938x->tx_mode[WCD_ADC4]];
+
+		if (mode != 0) {
+			for (i = 0; i < ADC_MODE_ULP2; i++) {
+				if (mode & (1 << i)) {
+					i++;
+					break;
+				}
+			}
+		}
+		clk_rate = wcd938x_get_clk_rate(i);
+
+		/* clk_rate depends on number of paths getting enabled */
+		clk_rate =  (wcd938x->adc_count * clk_rate);
+		if (clk_rate > SWR_CLK_RATE_9P6MHZ)
+			clk_rate = SWR_CLK_RATE_9P6MHZ;
+		wcd938x_set_swr_clk_rate(component, clk_rate, bank);
+		ret = swr_slvdev_datapath_control(wcd938x->tx_swr_dev,
+				 wcd938x->tx_swr_dev->dev_num,
+				 true);
+		wcd938x_set_swr_clk_rate(component, clk_rate, !bank);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		wcd938x->adc_count--;
+		if (wcd938x->adc_count < 0)
+			wcd938x->adc_count = 0;
+
+		wcd938x_tx_connect_port(component, ADC1 + w->shift, 0, false);
+		if (w->shift + ADC1 == ADC2 &&
+			test_bit(AMIC2_BCS_ENABLE, &wcd938x->status_mask)) {
+			if (!wcd938x->bcs_dis)
+				wcd938x_tx_connect_port(component, MBHC, 0,
+					false);
+			clear_bit(AMIC2_BCS_ENABLE, &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);
+	struct wcd938x_priv *wcd938x =
+					snd_soc_component_get_drvdata(component);
+	int ret = 0;
+	u8 mode = 0;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
@@ -1708,11 +1801,12 @@ static int wcd938x_codec_enable_adc(struct snd_soc_dapm_widget *w,
 				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);
+
+		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);
+
 		ret = wcd938x_tx_channel_config(component, w->shift, 1);
 		mode = wcd938x_get_adc_mode(wcd938x->tx_mode[w->shift]);
 		if (mode < 0) {
@@ -1788,53 +1882,9 @@ static int wcd938x_codec_enable_adc(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);
+		if (wcd938x->adc_count == 0)
+			snd_soc_component_update_bits(component,
+					WCD938X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x00);
 		break;
 	};
 	return ret;

+ 124 - 10
asoc/codecs/wsa881x-analog.c

@@ -35,6 +35,19 @@
 #define SPK_GAIN_12DB 4
 #define WIDGET_NAME_MAX_SIZE 80
 
+#define MAX_NAME_LEN 30
+#define WSA881X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
+			SNDRV_PCM_RATE_384000)
+/* Fractional Rates */
+#define WSA881X_FRAC_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_88200 |\
+				SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_352800)
+
+#define WSA881X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+			SNDRV_PCM_FMTBIT_S24_LE |\
+			SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
+
 /*
  * Private data Structure for wsa881x. All parameters related to
  * WSA881X codec needs to be defined here.
@@ -66,6 +79,9 @@ struct wsa881x_pdata {
 	struct device_node *wsa_vi_gpio_p;
 	struct device_node *wsa_clk_gpio_p;
 	struct device_node *wsa_reset_gpio_p;
+	char *wsa881x_name_prefix;
+	struct snd_soc_dai_driver *dai_driver;
+	struct snd_soc_component_driver *driver;
 };
 
 enum {
@@ -1130,8 +1146,6 @@ static int wsa881x_probe(struct snd_soc_component *component)
 	struct snd_soc_dapm_context *dapm =
 					snd_soc_component_get_dapm(component);
 	char *widget_name = NULL;
-	struct snd_soc_card *card = component->card;
-	struct snd_soc_codec_conf *codec_conf = card->codec_conf;
 
 	client = dev_get_drvdata(component->dev);
 	ret = wsa881x_i2c_get_client_index(client, &wsa881x_index);
@@ -1155,17 +1169,17 @@ static int wsa881x_probe(struct snd_soc_component *component)
 	INIT_DELAYED_WORK(&wsa_pdata[wsa881x_index].ocp_ctl_work,
 				wsa881x_ocp_ctl_work);
 
-	if (codec_conf->name_prefix) {
+	if (component->name_prefix) {
 		widget_name = kcalloc(WIDGET_NAME_MAX_SIZE, sizeof(char),
 					GFP_KERNEL);
 		if (!widget_name)
 			return -ENOMEM;
 
 		snprintf(widget_name, WIDGET_NAME_MAX_SIZE,
-			"%s WSA_SPKR", codec_conf->name_prefix);
+			"%s WSA_SPKR", component->name_prefix);
 		snd_soc_dapm_ignore_suspend(dapm, widget_name);
 		snprintf(widget_name, WIDGET_NAME_MAX_SIZE,
-			"%s WSA_IN", codec_conf->name_prefix);
+			"%s WSA_IN", component->name_prefix);
 		snd_soc_dapm_ignore_suspend(dapm, widget_name);
 		kfree(widget_name);
 	} else {
@@ -1190,7 +1204,8 @@ static void wsa881x_remove(struct snd_soc_component *component)
 	mutex_destroy(&wsa881x->res_lock);
 }
 
-static const struct snd_soc_component_driver soc_component_dev_wsa881x = {
+static const struct snd_soc_component_driver soc_codec_dev_wsa881x = {
+	.name = "",
 	.probe	= wsa881x_probe,
 	.remove	= wsa881x_remove,
 
@@ -1205,6 +1220,21 @@ static const struct snd_soc_component_driver soc_component_dev_wsa881x = {
 	.num_dapm_routes = ARRAY_SIZE(wsa881x_audio_map),
 };
 
+static struct snd_soc_dai_driver wsa_dai[] = {
+	{
+		.name = "",
+		.playback = {
+			.stream_name = "",
+			.rates = WSA881X_RATES | WSA881X_FRAC_RATES,
+			.formats = WSA881X_FORMATS,
+			.rate_max = 192000,
+			.rate_min = 8000,
+			.channels_min = 1,
+			.channels_max = 2,
+			},
+	},
+};
+
 static int wsa881x_reset(struct wsa881x_pdata *pdata, bool enable)
 {
 	int ret = 0;
@@ -1332,6 +1362,9 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
 	int wsa881x_index = 0;
 	struct wsa881x_pdata *pdata = NULL;
 	struct clk *wsa_mclk = NULL;
+	char buffer[MAX_NAME_LEN];
+	const char *wsa881x_name_prefix_of = NULL;
+	struct snd_soc_component *component;
 
 	ret = wsa881x_i2c_get_client_index(client, &wsa881x_index);
 	if (ret != 0) {
@@ -1454,13 +1487,84 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
 		}
 		wsa881x_presence_count++;
 		wsa881x_probing_count++;
-		ret = snd_soc_register_component(&client->dev,
-					&soc_component_dev_wsa881x,
-					NULL, 0);
-		if (ret < 0)
+
+		ret = of_property_read_string(client->dev.of_node,
+				"qcom,wsa-prefix", &wsa881x_name_prefix_of);
+		if (ret) {
+			dev_err(&client->dev,
+				"%s: Looking up %s property in node %s failed\n",
+				__func__, "qcom,wsa-prefix",
+				client->dev.of_node->full_name);
 			goto err1;
+		}
+
+		pdata->driver = devm_kzalloc(&client->dev,
+					sizeof(struct snd_soc_component_driver),
+					GFP_KERNEL);
+		if (!pdata->driver) {
+			ret = -ENOMEM;
+			goto err1;
+		}
+
+		memcpy(pdata->driver, &soc_codec_dev_wsa881x,
+				sizeof(struct snd_soc_component_driver));
+
+		pdata->dai_driver = devm_kzalloc(&client->dev,
+					sizeof(struct snd_soc_dai_driver),
+					GFP_KERNEL);
+		if (!pdata->dai_driver) {
+			ret = -ENOMEM;
+			goto err_mem;
+		}
+
+		memcpy(pdata->dai_driver, wsa_dai,
+			sizeof(struct snd_soc_dai_driver));
+
+		snprintf(buffer, sizeof(buffer), "wsa-codec%d", wsa881x_index);
+		pdata->driver->name = kstrndup(buffer,
+					       strlen(buffer), GFP_KERNEL);
+
+		snprintf(buffer, sizeof(buffer), "wsa_rx%d", wsa881x_index);
+		pdata->dai_driver->name =
+				kstrndup(buffer, strlen(buffer), GFP_KERNEL);
+
+		snprintf(buffer, sizeof(buffer),
+			 "WSA881X_AIF%d Playback", wsa881x_index);
+		pdata->dai_driver->playback.stream_name =
+				kstrndup(buffer, strlen(buffer), GFP_KERNEL);
+
+		/* Number of DAI's used is 1 */
+		ret = snd_soc_register_component(&client->dev,
+					pdata->driver, pdata->dai_driver, 1);
+
+
+		pdata->wsa881x_name_prefix = kstrndup(wsa881x_name_prefix_of,
+			strlen(wsa881x_name_prefix_of), GFP_KERNEL);
+
+		component = snd_soc_lookup_component(&client->dev, pdata->driver->name);
+		if (!component) {
+			dev_err(&client->dev, "%s: component is NULL \n", __func__);
+			ret = -EINVAL;
+			goto err_mem;
+		}
+
+		component->name_prefix = pdata->wsa881x_name_prefix;
+
 		pdata->status = WSA881X_STATUS_I2C;
+		goto err1;
+	}
+err_mem:
+	 kfree(pdata->wsa881x_name_prefix);
+	if (pdata->dai_driver) {
+		kfree(pdata->dai_driver->name);
+		kfree(pdata->dai_driver->playback.stream_name);
+		kfree(pdata->dai_driver);
 	}
+	if (pdata->driver) {
+		kfree(pdata->driver->name);
+		kfree(pdata->driver);
+	}
+
 err1:
 	wsa881x_reset(pdata, false);
 err:
@@ -1472,6 +1576,16 @@ static int wsa881x_i2c_remove(struct i2c_client *client)
 	struct wsa881x_pdata *wsa881x = client->dev.platform_data;
 
 	snd_soc_unregister_component(&client->dev);
+	kfree(wsa881x->wsa881x_name_prefix);
+	if (wsa881x->dai_driver) {
+		kfree(wsa881x->dai_driver->name);
+		kfree(wsa881x->dai_driver->playback.stream_name);
+		kfree(wsa881x->dai_driver);
+	}
+	if (wsa881x->driver) {
+		kfree(wsa881x->driver->name);
+		kfree(wsa881x->driver);
+	}
 	i2c_set_clientdata(client, NULL);
 	kfree(wsa881x);
 	return 0;

+ 2 - 0
asoc/codecs/wsa881x.c

@@ -118,6 +118,7 @@ enum {
 	BOLERO_WSA_EVT_SSR_DOWN,
 	BOLERO_WSA_EVT_SSR_UP,
 	BOLERO_WSA_EVT_PA_ON_POST_FSCLK,
+	BOLERO_WSA_EVT_PA_ON_POST_FSCLK_ADIE_LB,
 };
 
 struct wsa_ctrl_platform_data {
@@ -1403,6 +1404,7 @@ static int wsa881x_event_notify(struct notifier_block *nb,
 					      0x80, 0x00);
 		break;
 	case BOLERO_WSA_EVT_PA_ON_POST_FSCLK:
+	case BOLERO_WSA_EVT_PA_ON_POST_FSCLK_ADIE_LB:
 		if ((snd_soc_component_read32(wsa881x->component,
 				WSA881X_SPKR_DAC_CTL) & 0x80) == 0x80)
 			snd_soc_component_update_bits(wsa881x->component,

+ 1 - 0
asoc/codecs/wsa883x/internal.h

@@ -66,6 +66,7 @@ enum {
 	BOLERO_WSA_EVT_SSR_DOWN,
 	BOLERO_WSA_EVT_SSR_UP,
 	BOLERO_WSA_EVT_PA_ON_POST_FSCLK,
+	BOLERO_WSA_EVT_PA_ON_POST_FSCLK_ADIE_LB,
 };
 
 struct wsa_ctrl_platform_data {

+ 88 - 8
asoc/codecs/wsa883x/wsa883x.c

@@ -37,7 +37,7 @@
 #define TEMP_INVALID	0xFFFF
 #define WSA883X_TEMP_RETRY 3
 
-#define MAX_NAME_LEN	30
+#define MAX_NAME_LEN	40
 #define WSA883X_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000 |\
@@ -99,7 +99,6 @@ static const struct wsa_reg_mask_val reg_init[] = {
 	{WSA883X_CDC_SPK_DSM_R7, 0xFF, 0x3F},
 	{WSA883X_DRE_CTL_0, 0xF0, 0x90},
 	{WSA883X_DRE_IDLE_DET_CTL, 0x10, 0x00},
-	{WSA883X_PDM_WD_CTL, 0x01, 0x01},
 	{WSA883X_CURRENT_LIMIT, 0x78, 0x20},
 	{WSA883X_DRE_CTL_0, 0x07, 0x02},
 	{WSA883X_VAGC_TIME, 0x0F, 0x0F},
@@ -119,6 +118,7 @@ static const struct wsa_reg_mask_val reg_init[] = {
 	{WSA883X_ADC_7, 0x04, 0x04},
 	{WSA883X_ADC_7, 0x02, 0x02},
 	{WSA883X_CKWD_CTL_0, 0x60, 0x00},
+	{WSA883X_DRE_CTL_1, 0x3E, 0x20},
 	{WSA883X_CKWD_CTL_1, 0x1F, 0x1B},
 	{WSA883X_GMAMP_SUP1, 0x60, 0x60},
 };
@@ -134,6 +134,7 @@ enum {
 enum {
 	SPKR_STATUS = 0,
 	WSA_SUPPLIES_LPM_MODE,
+	SPKR_ADIE_LB,
 };
 
 enum {
@@ -799,6 +800,30 @@ int wsa883x_codec_info_create_codec_entry(struct snd_info_entry *codec_root,
 }
 EXPORT_SYMBOL(wsa883x_codec_info_create_codec_entry);
 
+/*
+ * wsa883x_codec_get_dev_num - returns swr device number
+ * @component: Codec instance
+ *
+ * Return: swr device number on success or negative error
+ * code on failure.
+ */
+int wsa883x_codec_get_dev_num(struct snd_soc_component *component)
+{
+	struct wsa883x_priv *wsa883x;
+
+	if (!component)
+		return -EINVAL;
+
+	wsa883x = snd_soc_component_get_drvdata(component);
+	if (!wsa883x) {
+		pr_err("%s: wsa883x component is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	return wsa883x->swr_slave->dev_num;
+}
+EXPORT_SYMBOL(wsa883x_codec_get_dev_num);
+
 static int wsa883x_get_compander(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *ucontrol)
 {
@@ -962,6 +987,7 @@ static int wsa883x_enable_swr_dac_port(struct snd_soc_dapm_widget *w,
 					&port_type[0]);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
+		set_bit(SPKR_STATUS, &wsa883x->status_mask);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
 		wsa883x_set_port(component, SWR_DAC_PORT,
@@ -1015,19 +1041,31 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
 		swr_slvdev_datapath_control(wsa883x->swr_slave,
 					    wsa883x->swr_slave->dev_num,
 					    true);
-		wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
+		/* Added delay as per HW sequence */
+		usleep_range(250, 300);
+		snd_soc_component_update_bits(component, WSA883X_DRE_CTL_1,
+						0x01, 0x01);
+		/* Added delay as per HW sequence */
+		usleep_range(250, 300);
 		wcd_enable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO);
 		/* Force remove group */
 		swr_remove_from_group(wsa883x->swr_slave,
 				      wsa883x->swr_slave->dev_num);
-		set_bit(SPKR_STATUS, &wsa883x->status_mask);
+		if (test_bit(SPKR_ADIE_LB, &wsa883x->status_mask))
+			snd_soc_component_update_bits(component,
+				WSA883X_PA_FSM_CTL, 0x01, 0x01);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
+		if (!test_bit(SPKR_ADIE_LB, &wsa883x->status_mask))
+			wcd_disable_irq(&wsa883x->irq_info,
+					WSA883X_IRQ_INT_PDM_WD);
 		snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
 				0x01, 0x00);
-		wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_PDM_WD);
+		snd_soc_component_update_bits(component, WSA883X_PDM_WD_CTL,
+				0x01, 0x00);
 		wcd_disable_irq(&wsa883x->irq_info, WSA883X_IRQ_INT_UVLO);
 		clear_bit(SPKR_STATUS, &wsa883x->status_mask);
+		clear_bit(SPKR_ADIE_LB, &wsa883x->status_mask);
 		break;
 	}
 	return 0;
@@ -1212,6 +1250,7 @@ static int wsa883x_get_temperature(struct snd_soc_component *component,
 
 static int wsa883x_codec_probe(struct snd_soc_component *component)
 {
+	char w_name[MAX_NAME_LEN];
 	struct wsa883x_priv *wsa883x = snd_soc_component_get_drvdata(component);
 	struct swr_device *dev;
 	int variant = 0, version = 0;
@@ -1220,6 +1259,10 @@ static int wsa883x_codec_probe(struct snd_soc_component *component)
 
 	if (!wsa883x)
 		return -EINVAL;
+
+	if (!component->name_prefix)
+		return -EINVAL;
+
 	snd_soc_component_init_regmap(component, wsa883x->regmap);
 
 	dev = wsa883x->swr_slave;
@@ -1236,8 +1279,28 @@ static int wsa883x_codec_probe(struct snd_soc_component *component)
 	wsa883x_codec_init(component);
 	wsa883x->global_pa_cnt = 0;
 
-	snd_soc_dapm_ignore_suspend(dapm,
-		wsa883x->dai_driver->playback.stream_name);
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " ", sizeof(w_name));
+	strlcat(w_name, wsa883x->dai_driver->playback.stream_name,
+				sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " IN", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SWR DAC_PORT", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
+	memset(w_name, 0, sizeof(w_name));
+	strlcpy(w_name, component->name_prefix, sizeof(w_name));
+	strlcat(w_name, " SPKR", sizeof(w_name));
+	snd_soc_dapm_ignore_suspend(dapm, w_name);
+
 	snd_soc_dapm_sync(dapm);
 
 	return 0;
@@ -1375,10 +1438,27 @@ static int wsa883x_event_notify(struct notifier_block *nb,
 		break;
 
 	case BOLERO_WSA_EVT_PA_ON_POST_FSCLK:
-		if (test_bit(SPKR_STATUS, &wsa883x->status_mask))
+		if (test_bit(SPKR_STATUS, &wsa883x->status_mask)) {
+			snd_soc_component_update_bits(wsa883x->component,
+						WSA883X_PDM_WD_CTL,
+						0x01, 0x01);
 			snd_soc_component_update_bits(wsa883x->component,
 						WSA883X_PA_FSM_CTL,
 						0x01, 0x01);
+			wcd_enable_irq(&wsa883x->irq_info,
+					WSA883X_IRQ_INT_PDM_WD);
+			/* Added delay as per HW sequence */
+			usleep_range(3000, 3100);
+			snd_soc_component_update_bits(wsa883x->component,
+						WSA883X_DRE_CTL_1,
+						0x01, 0x00);
+			/* Added delay as per HW sequence */
+			usleep_range(5000, 5050);
+		}
+		break;
+	case BOLERO_WSA_EVT_PA_ON_POST_FSCLK_ADIE_LB:
+		if (test_bit(SPKR_STATUS, &wsa883x->status_mask))
+			set_bit(SPKR_ADIE_LB, &wsa883x->status_mask);
 		break;
 	default:
 		dev_dbg(wsa883x->dev, "%s: unknown event %d\n",

+ 5 - 0
asoc/codecs/wsa883x/wsa883x.h

@@ -21,6 +21,7 @@ int wsa883x_set_channel_map(struct snd_soc_component *component,
 int wsa883x_codec_info_create_codec_entry(
 					struct snd_info_entry *codec_root,
 					struct snd_soc_component *component);
+int wsa883x_codec_get_dev_num(struct snd_soc_component *component);
 #else
 static int wsa883x_set_channel_map(struct snd_soc_component *component,
 				   u8 *port, u8 num_port, unsigned int *ch_mask,
@@ -36,6 +37,10 @@ static int wsa883x_codec_info_create_codec_entry(
 	return 0;
 }
 
+static int wsa883x_codec_get_dev_num(struct snd_soc_component *component)
+{
+	return 0;
+}
 #endif
 
 #endif /* _WSA883X_H */

+ 61 - 0
asoc/holi-port-config.h

@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _HOLI_PORT_CONFIG
+#define _HOLI_PORT_CONFIG
+
+#include <soc/swr-common.h>
+
+#define WSA_MSTR_PORT_MASK 0xFF
+/*
+ * Add port configuration in the format
+ *{ si, off1, off2, hstart, hstop, wd_len, bp_mode, bgp_ctrl, lane_ctrl, dir,
+ *  stream_type}
+ */
+
+static struct port_params rx_frame_params_dsd[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1, 0x00, 0x00},
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0, 0x00, 0x00},
+	{31, 11, 11, 0xFF, 0xFF, 4,    1,    0xFF, 0, 0x00, 0x00},
+	{7,  9,  0,  0xFF, 0xFF, 0xFF, 0xFF, 1,    0, 0x00, 0x00},
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 3,    0, 0x00, 0x00},
+};
+
+/* Headset + PCM Haptics */
+static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 1,    0xFF, 0xFF, 1, 0x00, 0x00}, /* HPH/EAR */
+	{31, 0,  0,  3,    6,    7,    0,    0xFF, 0, 0x00, 0x00}, /* HPH_CLH */
+	{31, 11, 11, 0xFF, 0xFF, 4,    1,    0xFF, 0, 0x00, 0x00}, /* HPH_CMP */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* LO/AUX */
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0,    0, 0x00, 0x00}, /* DSD */
+	{0x18F, 0, 0, 0x8, 0x8, 0x0F,  0x00, 0,    0, 0x00, 0x01}, /* PCM_OUT */
+};
+
+/* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */
+static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+static struct port_params tx_frame_params_wcd937x[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX2 */
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+static struct swr_mstr_port_map sm_port_map[] = {
+	{TX_MACRO, SWR_UC0, tx_frame_params_default},
+	{RX_MACRO, SWR_UC0, rx_frame_params_default},
+	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
+};
+
+static struct swr_mstr_port_map sm_port_map_wcd937x[] = {
+	{TX_MACRO, SWR_UC0, tx_frame_params_wcd937x},
+	{RX_MACRO, SWR_UC0, rx_frame_params_default},
+	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
+};
+
+#endif /* _HOLI_PORT_CONFIG */

+ 6813 - 0
asoc/holi.c

@@ -0,0 +1,6813 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/of_device.h>
+#include <linux/soc/qcom/fsa4480-i2c.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <soc/snd_event.h>
+#include <dsp/audio_notifier.h>
+#include <soc/swr-common.h>
+#include <dsp/q6afe-v2.h>
+#include <dsp/q6core.h>
+#include <soc/soundwire.h>
+#include "device_event.h"
+#include "msm-pcm-routing-v2.h"
+#include "asoc/msm-cdc-pinctrl.h"
+#include "asoc/wcd-mbhc-v2.h"
+#include "codecs/wsa881x-analog.h"
+#include "codecs/wcd937x/wcd937x-mbhc.h"
+#include "codecs/wcd937x/wcd937x.h"
+#include "codecs/wcd938x/wcd938x-mbhc.h"
+#include "codecs/wcd938x/wcd938x.h"
+#include "codecs/bolero/bolero-cdc.h"
+#include <dt-bindings/sound/audio-codec-port-types.h>
+#include "holi-port-config.h"
+#include "msm_holi_dailink.h"
+
+#define DRV_NAME "holi-asoc-snd"
+#define __CHIPSET__ "HOLI "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+#define SAMPLING_RATE_8KHZ      8000
+#define SAMPLING_RATE_11P025KHZ 11025
+#define SAMPLING_RATE_16KHZ     16000
+#define SAMPLING_RATE_22P05KHZ  22050
+#define SAMPLING_RATE_32KHZ     32000
+#define SAMPLING_RATE_44P1KHZ   44100
+#define SAMPLING_RATE_48KHZ     48000
+#define SAMPLING_RATE_88P2KHZ   88200
+#define SAMPLING_RATE_96KHZ     96000
+#define SAMPLING_RATE_176P4KHZ  176400
+#define SAMPLING_RATE_192KHZ    192000
+#define SAMPLING_RATE_352P8KHZ  352800
+#define SAMPLING_RATE_384KHZ    384000
+
+#define IS_FRACTIONAL(x) \
+((x == SAMPLING_RATE_11P025KHZ) || (x == SAMPLING_RATE_22P05KHZ) || \
+(x == SAMPLING_RATE_44P1KHZ) || (x == SAMPLING_RATE_88P2KHZ) || \
+(x == SAMPLING_RATE_176P4KHZ) || (x == SAMPLING_RATE_352P8KHZ))
+
+#define IS_MSM_INTERFACE_MI2S(x) \
+((x == PRIM_MI2S) || (x == SEC_MI2S) || (x == TERT_MI2S))
+
+#define WCD9XXX_MBHC_DEF_RLOADS     5
+#define WCD9XXX_MBHC_DEF_BUTTONS    8
+#define CODEC_EXT_CLK_RATE          9600000
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+#define DEV_NAME_STR_LEN            32
+#define WCD_MBHC_HS_V_MAX           1600
+
+#define TDM_CHANNEL_MAX		8
+#define DEV_NAME_STR_LEN	32
+
+/* time in us to ensure LPM doesn't go in C3/C4 */
+#define MSM_LL_QOS_VALUE	300
+
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+
+#define WCN_CDC_SLIM_RX_CH_MAX 2
+#define WCN_CDC_SLIM_TX_CH_MAX 2
+#define WCN_CDC_SLIM_TX_CH_MAX_LITO 3
+
+enum {
+	RX_PATH = 0,
+	TX_PATH,
+	MAX_PATH,
+};
+
+enum {
+	TDM_0 = 0,
+	TDM_1,
+	TDM_2,
+	TDM_3,
+	TDM_4,
+	TDM_5,
+	TDM_6,
+	TDM_7,
+	TDM_PORT_MAX,
+};
+
+#define TDM_MAX_SLOTS 8
+#define TDM_SLOT_WIDTH_BITS 32
+
+enum {
+	TDM_PRI = 0,
+	TDM_SEC,
+	TDM_TERT,
+	TDM_QUAT,
+	TDM_INTERFACE_MAX,
+};
+
+enum {
+	PRIM_AUX_PCM = 0,
+	SEC_AUX_PCM,
+	TERT_AUX_PCM,
+	QUAT_AUX_PCM,
+	AUX_PCM_MAX,
+};
+
+enum {
+	PRIM_MI2S = 0,
+	SEC_MI2S,
+	TERT_MI2S,
+	QUAT_MI2S,
+	MI2S_MAX,
+};
+
+enum {
+	RX_CDC_DMA_RX_0 = 0,
+	RX_CDC_DMA_RX_1,
+	RX_CDC_DMA_RX_2,
+	RX_CDC_DMA_RX_3,
+	RX_CDC_DMA_RX_5,
+	RX_CDC_DMA_RX_6,
+	CDC_DMA_RX_MAX,
+};
+
+enum {
+	TX_CDC_DMA_TX_0 = 0,
+	TX_CDC_DMA_TX_3,
+	TX_CDC_DMA_TX_4,
+	VA_CDC_DMA_TX_0,
+	VA_CDC_DMA_TX_1,
+	VA_CDC_DMA_TX_2,
+	CDC_DMA_TX_MAX,
+};
+
+enum {
+	SLIM_RX_7 = 0,
+	SLIM_RX_MAX,
+};
+enum {
+	SLIM_TX_7 = 0,
+	SLIM_TX_8,
+	SLIM_TX_MAX,
+};
+
+enum {
+	AFE_LOOPBACK_TX_IDX = 0,
+	AFE_LOOPBACK_TX_IDX_MAX,
+};
+
+struct msm_asoc_mach_data {
+	struct snd_info_entry *codec_root;
+	int usbc_en2_gpio; /* used by gpio driver API */
+	struct device_node *dmic01_gpio_p; /* used by pinctrl API */
+	struct device_node *dmic23_gpio_p; /* used by pinctrl API */
+	struct device_node *dmic45_gpio_p; /* used by pinctrl API */
+	struct device_node *mi2s_gpio_p[MI2S_MAX]; /* used by pinctrl API */
+	atomic_t mi2s_gpio_ref_count[MI2S_MAX]; /* used by pinctrl API */
+	struct device_node *us_euro_gpio_p; /* used by pinctrl API */
+	struct pinctrl *usbc_en2_gpio_p; /* used by pinctrl API */
+	struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
+	struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
+	bool is_afe_config_done;
+	struct device_node *fsa_handle;
+	struct clk *lpass_audio_hw_vote;
+	int core_audio_vote_count;
+	u32 wcd_disabled;
+};
+
+struct tdm_port {
+	u32 mode;
+	u32 channel;
+};
+
+struct tdm_dev_config {
+	unsigned int tdm_slot_offset[TDM_MAX_SLOTS];
+};
+
+struct dev_config {
+	u32 sample_rate;
+	u32 bit_format;
+	u32 channels;
+};
+
+/* Default configuration of slimbus channels */
+static struct dev_config slim_rx_cfg[] = {
+	[SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config slim_tx_cfg[] = {
+	[SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static struct dev_config usb_rx_cfg = {
+	.sample_rate = SAMPLING_RATE_48KHZ,
+	.bit_format = SNDRV_PCM_FORMAT_S16_LE,
+	.channels = 2,
+};
+
+static struct dev_config usb_tx_cfg = {
+	.sample_rate = SAMPLING_RATE_48KHZ,
+	.bit_format = SNDRV_PCM_FORMAT_S16_LE,
+	.channels = 1,
+};
+
+static struct dev_config proxy_rx_cfg = {
+	.sample_rate = SAMPLING_RATE_48KHZ,
+	.bit_format = SNDRV_PCM_FORMAT_S16_LE,
+	.channels = 2,
+};
+
+static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+	{
+		AFE_API_VERSION_I2S_CONFIG,
+		Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
+		Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+		Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+		Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+		0,
+	},
+};
+
+struct mi2s_conf {
+	struct mutex lock;
+	u32 ref_cnt;
+	u32 msm_is_mi2s_master;
+};
+
+static u32 mi2s_ebit_clk[MI2S_MAX] = {
+	Q6AFE_LPASS_CLK_ID_PRI_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT,
+	Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT,
+};
+
+static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
+
+/* Default configuration of TDM channels */
+static struct dev_config tdm_rx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
+	{ /* PRI TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+	{ /* SEC TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+	{ /* TERT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+	{ /* QUAT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* RX_7 */
+	},
+};
+
+static struct dev_config tdm_tx_cfg[TDM_INTERFACE_MAX][TDM_PORT_MAX] = {
+	{ /* PRI TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+	{ /* SEC TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+	{ /* TERT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+	{ /* QUAT TDM */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_0 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_1 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_2 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_3 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_4 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_5 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_6 */
+		{SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, /* TX_7 */
+	},
+};
+
+/* Default configuration of AUX PCM channels */
+static struct dev_config aux_pcm_rx_cfg[] = {
+	[PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEC_AUX_PCM]  = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config aux_pcm_tx_cfg[] = {
+	[PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEC_AUX_PCM]  = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+/* Default configuration of MI2S channels */
+static struct dev_config mi2s_rx_cfg[] = {
+	[PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[SEC_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static struct dev_config mi2s_tx_cfg[] = {
+	[PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[SEC_MI2S]  = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+	[QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct tdm_dev_config pri_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = {
+	{ /* PRI TDM */
+		{ {0,   4, 0xFFFF} }, /* RX_0 */
+		{ {8,  12, 0xFFFF} }, /* RX_1 */
+		{ {16, 20, 0xFFFF} }, /* RX_2 */
+		{ {24, 28, 0xFFFF} }, /* RX_3 */
+		{ {0xFFFF} }, /* RX_4 */
+		{ {0xFFFF} }, /* RX_5 */
+		{ {0xFFFF} }, /* RX_6 */
+		{ {0xFFFF} }, /* RX_7 */
+	},
+	{
+		{ {0,   4,      8, 12, 0xFFFF} }, /* TX_0 */
+		{ {8,  12, 0xFFFF} }, /* TX_1 */
+		{ {16, 20, 0xFFFF} }, /* TX_2 */
+		{ {24, 28, 0xFFFF} }, /* TX_3 */
+		{ {0xFFFF} }, /* TX_4 */
+		{ {0xFFFF} }, /* TX_5 */
+		{ {0xFFFF} }, /* TX_6 */
+		{ {0xFFFF} }, /* TX_7 */
+	},
+};
+
+static struct tdm_dev_config sec_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = {
+	{ /* SEC TDM */
+		{ {0,   4, 0xFFFF} }, /* RX_0 */
+		{ {8,  12, 0xFFFF} }, /* RX_1 */
+		{ {16, 20, 0xFFFF} }, /* RX_2 */
+		{ {24, 28, 0xFFFF} }, /* RX_3 */
+		{ {0xFFFF} }, /* RX_4 */
+		{ {0xFFFF} }, /* RX_5 */
+		{ {0xFFFF} }, /* RX_6 */
+		{ {0xFFFF} }, /* RX_7 */
+	},
+	{
+		{ {0,   4, 0xFFFF} }, /* TX_0 */
+		{ {8,  12, 0xFFFF} }, /* TX_1 */
+		{ {16, 20, 0xFFFF} }, /* TX_2 */
+		{ {24, 28, 0xFFFF} }, /* TX_3 */
+		{ {0xFFFF} }, /* TX_4 */
+		{ {0xFFFF} }, /* TX_5 */
+		{ {0xFFFF} }, /* TX_6 */
+		{ {0xFFFF} }, /* TX_7 */
+	},
+};
+
+static struct tdm_dev_config tert_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = {
+	{ /* TERT TDM */
+		{ {0,   4, 0xFFFF} }, /* RX_0 */
+		{ {8,  12, 0xFFFF} }, /* RX_1 */
+		{ {16, 20, 0xFFFF} }, /* RX_2 */
+		{ {24, 28, 0xFFFF} }, /* RX_3 */
+		{ {0xFFFF} }, /* RX_4 */
+		{ {0xFFFF} }, /* RX_5 */
+		{ {0xFFFF} }, /* RX_6 */
+		{ {0xFFFF} }, /* RX_7 */
+	},
+	{
+		{ {0,   4, 0xFFFF} }, /* TX_0 */
+		{ {8,  12, 0xFFFF} }, /* TX_1 */
+		{ {16, 20, 0xFFFF} }, /* TX_2 */
+		{ {24, 28, 0xFFFF} }, /* TX_3 */
+		{ {0xFFFF} }, /* TX_4 */
+		{ {0xFFFF} }, /* TX_5 */
+		{ {0xFFFF} }, /* TX_6 */
+		{ {0xFFFF} }, /* TX_7 */
+	},
+};
+
+static struct tdm_dev_config quat_tdm_dev_config[MAX_PATH][TDM_PORT_MAX] = {
+	{ /* QUAT TDM */
+		{ {0,   4, 0xFFFF} }, /* RX_0 */
+		{ {8,  12, 0xFFFF} }, /* RX_1 */
+		{ {16, 20, 0xFFFF} }, /* RX_2 */
+		{ {24, 28, 0xFFFF} }, /* RX_3 */
+		{ {0xFFFF} }, /* RX_4 */
+		{ {0xFFFF} }, /* RX_5 */
+		{ {0xFFFF} }, /* RX_6 */
+		{ {0xFFFF} }, /* RX_7 */
+	},
+	{
+		{ {0,   4, 0xFFFF} }, /* TX_0 */
+		{ {8,  12, 0xFFFF} }, /* TX_1 */
+		{ {16, 20, 0xFFFF} }, /* TX_2 */
+		{ {24, 28, 0xFFFF} }, /* TX_3 */
+		{ {0xFFFF} }, /* TX_4 */
+		{ {0xFFFF} }, /* TX_5 */
+		{ {0xFFFF} }, /* TX_6 */
+		{ {0xFFFF} }, /* TX_7 */
+	},
+};
+
+
+static void *tdm_cfg[TDM_INTERFACE_MAX] = {
+	pri_tdm_dev_config,
+	sec_tdm_dev_config,
+	tert_tdm_dev_config,
+	quat_tdm_dev_config,
+};
+
+/* Default configuration of Codec DMA Interface RX */
+static struct dev_config cdc_dma_rx_cfg[] = {
+	[RX_CDC_DMA_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[RX_CDC_DMA_RX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+/* Default configuration of Codec DMA Interface TX */
+static struct dev_config cdc_dma_tx_cfg[] = {
+	[TX_CDC_DMA_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[TX_CDC_DMA_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[TX_CDC_DMA_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+	[VA_CDC_DMA_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 8},
+	[VA_CDC_DMA_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 8},
+	[VA_CDC_DMA_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 8},
+};
+
+static struct dev_config afe_loopback_tx_cfg[] = {
+	[AFE_LOOPBACK_TX_IDX] =
+			 {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static int msm_vi_feed_tx_ch = 2;
+static const char *const vi_feed_ch_text[] = {"One", "Two"};
+static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
+					  "S32_LE"};
+static char const *cdc80_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
+static char const *ch_text[] = {"Two", "Three", "Four", "Five",
+					"Six", "Seven", "Eight"};
+static char const *usb_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
+					"KHZ_16", "KHZ_22P05",
+					"KHZ_32", "KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96", "KHZ_176P4",
+					"KHZ_192", "KHZ_352P8", "KHZ_384"};
+static const char *const usb_ch_text[] = {"One", "Two", "Three", "Four",
+					   "Five", "Six", "Seven",
+					   "Eight"};
+static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32",
+					     "KHZ_48", "KHZ_176P4",
+					     "KHZ_352P8"};
+static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
+static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
+				    "Five", "Six", "Seven", "Eight"};
+static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"};
+static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_11P025", "KHZ_16",
+				      "KHZ_22P05", "KHZ_32", "KHZ_44P1",
+				      "KHZ_48", "KHZ_88P2", "KHZ_96",
+				      "KHZ_176P4", "KHZ_192", "KHZ_352P8",
+				      "KHZ_384"};
+static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
+					   "Five", "Six", "Seven",
+					   "Eight"};
+
+static const char *const cdc_dma_rx_ch_text[] = {"One", "Two"};
+static const char *const cdc_dma_tx_ch_text[] = {"One", "Two", "Three", "Four",
+						"Five", "Six", "Seven",
+						"Eight"};
+static char const *cdc_dma_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
+						 "KHZ_16", "KHZ_22P05",
+						 "KHZ_32", "KHZ_44P1", "KHZ_48",
+						 "KHZ_88P2", "KHZ_96",
+						 "KHZ_176P4", "KHZ_192",
+						 "KHZ_352P8", "KHZ_384"};
+static char const *cdc80_dma_sample_rate_text[] = {"KHZ_8", "KHZ_11P025",
+						 "KHZ_16", "KHZ_22P05",
+						 "KHZ_32", "KHZ_44P1", "KHZ_48",
+						 "KHZ_88P2", "KHZ_96",
+						 "KHZ_176P4", "KHZ_192"};
+static char const *bt_sample_rate_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_rx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static char const *bt_sample_rate_tx_text[] = {"KHZ_8", "KHZ_16",
+					"KHZ_44P1", "KHZ_48",
+					"KHZ_88P2", "KHZ_96"};
+static const char *const afe_loopback_tx_ch_text[] = {"One", "Two"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_sample_rate, usb_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_sample_rate, usb_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_rx_chs, usb_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(usb_tx_chs, usb_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_sample_rate, tdm_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_sample_rate, tdm_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_format, tdm_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_format, tdm_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_tx_chs, tdm_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tdm_rx_chs, tdm_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(aux_pcm_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(mi2s_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(mi2s_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_0_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_1_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_2_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_3_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_5_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_6_chs, cdc_dma_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_0_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_0_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_1_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_2_chs, cdc_dma_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_1_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_2_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_3_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tx_cdc_dma_tx_4_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_1_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(va_cdc_dma_tx_2_sample_rate,
+				cdc_dma_sample_rate_text);
+
+/* WCD9380 */
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_0_format, cdc80_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_1_format, cdc80_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_2_format, cdc80_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_3_format, cdc80_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_5_format, cdc80_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_6_format, cdc80_bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_0_sample_rate,
+				cdc80_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_1_sample_rate,
+				cdc80_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_2_sample_rate,
+				cdc80_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_3_sample_rate,
+				cdc80_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_5_sample_rate,
+				cdc80_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc80_dma_rx_6_sample_rate,
+				cdc80_dma_sample_rate_text);
+/* WCD9385 */
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_1_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_2_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_3_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_5_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_6_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_1_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_2_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_3_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_5_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc85_dma_rx_6_sample_rate,
+				cdc_dma_sample_rate_text);
+
+/* WCD937x */
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_0_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_1_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_2_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_3_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_5_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_0_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_1_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_2_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_3_sample_rate,
+				cdc_dma_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(rx_cdc_dma_rx_5_sample_rate,
+				cdc_dma_sample_rate_text);
+
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate, bt_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_rx, bt_sample_rate_rx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(bt_sample_rate_tx, bt_sample_rate_tx_text);
+static SOC_ENUM_SINGLE_EXT_DECL(afe_loopback_tx_chs, afe_loopback_tx_ch_text);
+
+static bool is_initial_boot;
+static bool codec_reg_done;
+static struct snd_soc_card snd_soc_card_holi_msm;
+static int dmic_0_1_gpio_cnt;
+static int dmic_2_3_gpio_cnt;
+static int dmic_4_5_gpio_cnt;
+
+static void *def_wcd_mbhc_cal(void);
+
+static int msm_aux_codec_init(struct snd_soc_pcm_runtime *);
+static int msm_int_audrx_init(struct snd_soc_pcm_runtime *);
+
+/*
+ * Need to report LINEIN
+ * if R/L channel impedance is larger than 5K ohm
+ */
+static struct wcd_mbhc_config wcd_mbhc_cfg = {
+	.read_fw_bin = false,
+	.calibration = NULL,
+	.detect_extn_cable = true,
+	.mono_stero_detection = false,
+	.swap_gnd_mic = NULL,
+	.hs_ext_micbias = true,
+	.key_code[0] = KEY_MEDIA,
+	.key_code[1] = KEY_VOICECOMMAND,
+	.key_code[2] = KEY_VOLUMEUP,
+	.key_code[3] = KEY_VOLUMEDOWN,
+	.key_code[4] = 0,
+	.key_code[5] = 0,
+	.key_code[6] = 0,
+	.key_code[7] = 0,
+	.linein_th = 5000,
+	.moisture_en = false,
+	.mbhc_micbias = MIC_BIAS_2,
+	.anc_micbias = MIC_BIAS_2,
+	.enable_anc_mic_detect = false,
+	.moisture_duty_cycle_en = true,
+};
+
+/* set audio task affinity to core 1 & 2 */
+static const unsigned int audio_core_list[] = {1, 2};
+static cpumask_t audio_cpu_map = CPU_MASK_NONE;
+static struct dev_pm_qos_request *msm_audio_req = NULL;
+static unsigned int qos_client_active_cnt = 0;
+
+static void msm_audio_add_qos_request()
+{
+	int i;
+	int cpu = 0;
+
+	msm_audio_req = kzalloc(sizeof(struct dev_pm_qos_request) * NR_CPUS,
+				 GFP_KERNEL);
+	if (!msm_audio_req) {
+		pr_err("%s failed to alloc mem for qos req.\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(audio_core_list); i++) {
+		if (audio_core_list[i] >= NR_CPUS)
+			pr_err("%s incorrect cpu id: %d specified.\n",
+				 __func__, audio_core_list[i]);
+		else
+			cpumask_set_cpu(audio_core_list[i], &audio_cpu_map);
+	}
+
+	for_each_cpu(cpu, &audio_cpu_map) {
+		dev_pm_qos_add_request(get_cpu_device(cpu),
+			&msm_audio_req[cpu],
+			DEV_PM_QOS_RESUME_LATENCY,
+			PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE);
+		pr_debug("%s set cpu affinity to core %d.\n", __func__, cpu);
+	}
+}
+
+static void msm_audio_remove_qos_request()
+{
+	int cpu = 0;
+
+	if (msm_audio_req) {
+		for_each_cpu(cpu, &audio_cpu_map) {
+			dev_pm_qos_remove_request(
+				&msm_audio_req[cpu]);
+			pr_debug("%s remove cpu affinity of core %d.\n",
+				 __func__, cpu);
+		}
+		kfree(msm_audio_req);
+	}
+}
+
+static void msm_audio_update_qos_request(u32 latency)
+{
+	int cpu = 0;
+
+	if (msm_audio_req) {
+		for_each_cpu(cpu, &audio_cpu_map) {
+			dev_pm_qos_update_request(
+				&msm_audio_req[cpu], latency);
+			pr_debug("%s update latency of core %d to %ul.\n",
+				 __func__, cpu, latency);
+		}
+	}
+}
+
+static inline int param_is_mask(int p)
+{
+	return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+			(p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
+					     int n)
+{
+	return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n,
+			   unsigned int bit)
+{
+	if (bit >= SNDRV_MASK_MAX)
+		return;
+	if (param_is_mask(n)) {
+		struct snd_mask *m = param_to_mask(p, n);
+
+		m->bits[0] = 0;
+		m->bits[1] = 0;
+		m->bits[bit >> 5] |= (1 << (bit & 31));
+	}
+}
+
+static int usb_audio_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (usb_rx_cfg.sample_rate) {
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: usb_audio_rx_sample_rate = %d\n", __func__,
+		 usb_rx_cfg.sample_rate);
+	return 0;
+}
+
+static int usb_audio_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 12:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	case 11:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 10:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 9:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 8:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 7:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 6:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 5:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 4:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 2:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 1:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 0:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	default:
+		usb_rx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	pr_debug("%s: control value = %ld, usb_audio_rx_sample_rate = %d\n",
+		__func__, ucontrol->value.integer.value[0],
+		usb_rx_cfg.sample_rate);
+	return 0;
+}
+
+static int usb_audio_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val = 0;
+
+	switch (usb_tx_cfg.sample_rate) {
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: usb_audio_tx_sample_rate = %d\n", __func__,
+		 usb_tx_cfg.sample_rate);
+	return 0;
+}
+
+static int usb_audio_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 12:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	case 11:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 10:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 9:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 8:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 7:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 6:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 5:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 4:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 2:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 1:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 0:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	default:
+		usb_tx_cfg.sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	pr_debug("%s: control value = %ld, usb_audio_tx_sample_rate = %d\n",
+		__func__, ucontrol->value.integer.value[0],
+		usb_tx_cfg.sample_rate);
+	return 0;
+}
+static int afe_loopback_tx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: afe_loopback_tx_ch  = %d\n", __func__,
+		afe_loopback_tx_cfg[0].channels);
+	ucontrol->value.enumerated.item[0] =
+		afe_loopback_tx_cfg[0].channels - 1;
+
+	return 0;
+}
+
+static int afe_loopback_tx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	afe_loopback_tx_cfg[0].channels =
+			ucontrol->value.enumerated.item[0] + 1;
+	pr_debug("%s: afe_loopback_tx_ch  = %d\n", __func__,
+			afe_loopback_tx_cfg[0].channels);
+
+	return 1;
+}
+
+static int usb_audio_rx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	switch (usb_rx_cfg.bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: usb_audio_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_rx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int usb_audio_rx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		usb_rx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: usb_audio_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_rx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+static int usb_audio_tx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	switch (usb_tx_cfg.bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: usb_audio_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_tx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int usb_audio_tx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		usb_tx_cfg.bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: usb_audio_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, usb_tx_cfg.bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+static int usb_audio_rx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: usb_audio_rx_ch  = %d\n", __func__,
+		 usb_rx_cfg.channels);
+	ucontrol->value.integer.value[0] = usb_rx_cfg.channels - 1;
+	return 0;
+}
+
+static int usb_audio_rx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	usb_rx_cfg.channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: usb_audio_rx_ch = %d\n", __func__, usb_rx_cfg.channels);
+	return 1;
+}
+
+static int usb_audio_tx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: usb_audio_tx_ch  = %d\n", __func__,
+		 usb_tx_cfg.channels);
+	ucontrol->value.integer.value[0] = usb_tx_cfg.channels - 1;
+	return 0;
+}
+
+static int usb_audio_tx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	usb_tx_cfg.channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: usb_audio_tx_ch = %d\n", __func__, usb_tx_cfg.channels);
+	return 1;
+}
+
+static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
+	pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
+	pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
+	return 1;
+}
+
+
+static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: proxy_rx channels = %d\n",
+		 __func__, proxy_rx_cfg.channels);
+	ucontrol->value.integer.value[0] = proxy_rx_cfg.channels - 2;
+
+	return 0;
+}
+
+static int proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	proxy_rx_cfg.channels = ucontrol->value.integer.value[0] + 2;
+	pr_debug("%s: proxy_rx channels = %d\n",
+		 __func__, proxy_rx_cfg.channels);
+
+	return 1;
+}
+
+static int tdm_get_port_idx(struct snd_kcontrol *kcontrol,
+			    struct tdm_port *port)
+{
+	if (port) {
+		if (strnstr(kcontrol->id.name, "PRI",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_PRI;
+		} else if (strnstr(kcontrol->id.name, "SEC",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_SEC;
+		} else if (strnstr(kcontrol->id.name, "TERT",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_TERT;
+		} else if (strnstr(kcontrol->id.name, "QUAT",
+		    sizeof(kcontrol->id.name))) {
+			port->mode = TDM_QUAT;
+		} else {
+			pr_err("%s: unsupported mode in: %s\n",
+				__func__, kcontrol->id.name);
+			return -EINVAL;
+		}
+
+		if (strnstr(kcontrol->id.name, "RX_0",
+		    sizeof(kcontrol->id.name)) ||
+		    strnstr(kcontrol->id.name, "TX_0",
+		    sizeof(kcontrol->id.name))) {
+			port->channel = TDM_0;
+		} else if (strnstr(kcontrol->id.name, "RX_1",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_1",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_1;
+		} else if (strnstr(kcontrol->id.name, "RX_2",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_2",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_2;
+		} else if (strnstr(kcontrol->id.name, "RX_3",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_3",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_3;
+		} else if (strnstr(kcontrol->id.name, "RX_4",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_4",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_4;
+		} else if (strnstr(kcontrol->id.name, "RX_5",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_5",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_5;
+		} else if (strnstr(kcontrol->id.name, "RX_6",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_6",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_6;
+		} else if (strnstr(kcontrol->id.name, "RX_7",
+			   sizeof(kcontrol->id.name)) ||
+			   strnstr(kcontrol->id.name, "TX_7",
+			   sizeof(kcontrol->id.name))) {
+			port->channel = TDM_7;
+		} else {
+			pr_err("%s: unsupported channel in: %s\n",
+				__func__, kcontrol->id.name);
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tdm_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 0:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	case 1:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 5:
+		sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	default:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int tdm_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 5;
+		break;
+	default:
+		sample_rate_val = 3;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int tdm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
+			tdm_rx_cfg[port.mode][port.channel].sample_rate);
+
+		pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_rx_cfg[port.mode][port.channel].sample_rate =
+			tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_rx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_sample_rate_val(
+			tdm_tx_cfg[port.mode][port.channel].sample_rate);
+
+		pr_debug("%s: tdm_tx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_tx_cfg[port.mode][port.channel].sample_rate =
+			tdm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_tx_sample_rate = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].sample_rate,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_get_format(int value)
+{
+	int format = 0;
+
+	switch (value) {
+	case 0:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	case 1:
+		format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 2:
+		format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	default:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	return format;
+}
+
+static int tdm_get_format_val(int format)
+{
+	int value = 0;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		value = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		value = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		value = 2;
+		break;
+	default:
+		value = 0;
+		break;
+	}
+	return value;
+}
+
+static int tdm_rx_format_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_format_val(
+				tdm_rx_cfg[port.mode][port.channel].bit_format);
+
+		pr_debug("%s: tdm_rx_bit_format = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_format_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_rx_cfg[port.mode][port.channel].bit_format =
+			tdm_get_format(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_rx_bit_format = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_format_get(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] = tdm_get_format_val(
+				tdm_tx_cfg[port.mode][port.channel].bit_format);
+
+		pr_debug("%s: tdm_tx_bit_format = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_format_put(struct snd_kcontrol *kcontrol,
+			     struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_tx_cfg[port.mode][port.channel].bit_format =
+			tdm_get_format(ucontrol->value.enumerated.item[0]);
+
+		pr_debug("%s: tdm_tx_bit_format = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].bit_format,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_ch_get(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+
+		ucontrol->value.enumerated.item[0] =
+			tdm_rx_cfg[port.mode][port.channel].channels - 1;
+
+		pr_debug("%s: tdm_rx_ch = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].channels - 1,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_rx_ch_put(struct snd_kcontrol *kcontrol,
+			 struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_rx_cfg[port.mode][port.channel].channels =
+			ucontrol->value.enumerated.item[0] + 1;
+
+		pr_debug("%s: tdm_rx_ch = %d, item = %d\n", __func__,
+			 tdm_rx_cfg[port.mode][port.channel].channels,
+			 ucontrol->value.enumerated.item[0] + 1);
+	}
+	return ret;
+}
+
+static int tdm_tx_ch_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		ucontrol->value.enumerated.item[0] =
+			tdm_tx_cfg[port.mode][port.channel].channels - 1;
+
+		pr_debug("%s: tdm_tx_ch = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].channels - 1,
+			 ucontrol->value.enumerated.item[0]);
+	}
+	return ret;
+}
+
+static int tdm_tx_ch_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct tdm_port port;
+	int ret = tdm_get_port_idx(kcontrol, &port);
+
+	if (ret) {
+		pr_err("%s: unsupported control: %s\n",
+			__func__, kcontrol->id.name);
+	} else {
+		tdm_tx_cfg[port.mode][port.channel].channels =
+			ucontrol->value.enumerated.item[0] + 1;
+
+		pr_debug("%s: tdm_tx_ch = %d, item = %d\n", __func__,
+			 tdm_tx_cfg[port.mode][port.channel].channels,
+			 ucontrol->value.enumerated.item[0] + 1);
+	}
+	return ret;
+}
+
+static int tdm_slot_map_put(struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol)
+{
+	int slot_index = 0;
+	int interface = ucontrol->value.integer.value[0];
+	int channel = ucontrol->value.integer.value[1];
+	unsigned int offset_val = 0;
+	unsigned int *slot_offset = NULL;
+	struct tdm_dev_config *config = NULL;
+
+	if (interface < 0  || interface >= (TDM_INTERFACE_MAX * MAX_PATH)) {
+		pr_err("%s: incorrect interface = %d\n", __func__, interface);
+		return -EINVAL;
+	}
+	if (channel < 0  || channel >= TDM_PORT_MAX) {
+		pr_err("%s: incorrect channel = %d\n", __func__, channel);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: interface = %d, channel = %d\n", __func__,
+		interface, channel);
+
+	config = ((struct tdm_dev_config *) tdm_cfg[interface / MAX_PATH]) +
+			((interface % MAX_PATH) * TDM_PORT_MAX) + channel;
+	slot_offset = config->tdm_slot_offset;
+
+	for (slot_index = 0; slot_index < TDM_MAX_SLOTS; slot_index++) {
+		offset_val = ucontrol->value.integer.value[MAX_PATH +
+				slot_index];
+		/* Offset value can only be 0, 4, 8, ..28 */
+		if (offset_val % 4 == 0 && offset_val <= 28)
+			slot_offset[slot_index] = offset_val;
+		pr_debug("%s: slot offset[%d] = %d\n", __func__,
+			slot_index, slot_offset[slot_index]);
+	}
+
+	return 0;
+}
+
+static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+	int idx = 0;
+
+	if (strnstr(kcontrol->id.name, "PRIM_AUX_PCM",
+		    sizeof("PRIM_AUX_PCM"))) {
+		idx = PRIM_AUX_PCM;
+	} else if (strnstr(kcontrol->id.name, "SEC_AUX_PCM",
+			 sizeof("SEC_AUX_PCM"))) {
+		idx = SEC_AUX_PCM;
+	} else if (strnstr(kcontrol->id.name, "TERT_AUX_PCM",
+			 sizeof("TERT_AUX_PCM"))) {
+		idx = TERT_AUX_PCM;
+	} else if (strnstr(kcontrol->id.name, "QUAT_AUX_PCM",
+			 sizeof("QUAT_AUX_PCM"))) {
+		idx = QUAT_AUX_PCM;
+	} else {
+		pr_err("%s: unsupported port: %s\n",
+			__func__, kcontrol->id.name);
+		idx = -EINVAL;
+	}
+
+	return idx;
+}
+
+static int aux_pcm_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 1:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 0:
+	default:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int aux_pcm_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		sample_rate_val = 0;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int mi2s_auxpcm_get_format(int value)
+{
+	int format = 0;
+
+	switch (value) {
+	case 0:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	case 1:
+		format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 2:
+		format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 3:
+		format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	default:
+		format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	return format;
+}
+
+static int mi2s_auxpcm_get_format_value(int format)
+{
+	int value = 0;
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		value = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		value = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		value = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		value = 3;
+		break;
+	default:
+		value = 0;
+		break;
+	}
+	return value;
+}
+
+static int aux_pcm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+	     aux_pcm_get_sample_rate_val(aux_pcm_rx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int aux_pcm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_rx_cfg[idx].sample_rate =
+		aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int aux_pcm_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+	     aux_pcm_get_sample_rate_val(aux_pcm_tx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int aux_pcm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_tx_cfg[idx].sample_rate =
+		aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, aux_pcm_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_rx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(aux_pcm_rx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		idx, aux_pcm_rx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_rx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_rx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		  idx, aux_pcm_rx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_tx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(aux_pcm_tx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		idx, aux_pcm_tx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_aux_pcm_tx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = aux_pcm_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	aux_pcm_tx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		  idx, aux_pcm_tx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+	int idx = 0;
+
+	if (strnstr(kcontrol->id.name, "PRIM_MI2S_RX",
+	    sizeof("PRIM_MI2S_RX"))) {
+		idx = PRIM_MI2S;
+	} else if (strnstr(kcontrol->id.name, "SEC_MI2S_RX",
+		 sizeof("SEC_MI2S_RX"))) {
+		idx = SEC_MI2S;
+	} else if (strnstr(kcontrol->id.name, "TERT_MI2S_RX",
+		 sizeof("TERT_MI2S_RX"))) {
+		idx = TERT_MI2S;
+	} else if (strnstr(kcontrol->id.name, "QUAT_MI2S_RX",
+		 sizeof("QUAT_MI2S_RX"))) {
+		idx = QUAT_MI2S;
+	} else if (strnstr(kcontrol->id.name, "PRIM_MI2S_TX",
+		 sizeof("PRIM_MI2S_TX"))) {
+		idx = PRIM_MI2S;
+	} else if (strnstr(kcontrol->id.name, "SEC_MI2S_TX",
+		 sizeof("SEC_MI2S_TX"))) {
+		idx = SEC_MI2S;
+	} else if (strnstr(kcontrol->id.name, "TERT_MI2S_TX",
+		 sizeof("TERT_MI2S_TX"))) {
+		idx = TERT_MI2S;
+	} else if (strnstr(kcontrol->id.name, "QUAT_MI2S_TX",
+		 sizeof("QUAT_MI2S_TX"))) {
+		idx = QUAT_MI2S;
+	} else {
+		pr_err("%s: unsupported channel: %s\n",
+			__func__, kcontrol->id.name);
+		idx = -EINVAL;
+	}
+
+	return idx;
+}
+
+static int mi2s_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 0:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	case 1:
+		sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 2:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 3:
+		sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 4:
+		sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 5:
+		sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 6:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 7:
+		sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 8:
+		sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 9:
+		sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 10:
+		sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 11:
+		sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 12:
+		sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	default:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int mi2s_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_get_sample_rate_val(mi2s_rx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_rx_cfg[idx].sample_rate =
+		mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_get_sample_rate_val(mi2s_tx_cfg[idx].sample_rate);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int mi2s_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_tx_cfg[idx].sample_rate =
+		mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_rx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(mi2s_rx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		idx, mi2s_rx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_rx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_rx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_rx_format = %d, item = %d\n", __func__,
+		  idx, mi2s_rx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_tx_format_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	ucontrol->value.enumerated.item[0] =
+		mi2s_auxpcm_get_format_value(mi2s_tx_cfg[idx].bit_format);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		idx, mi2s_tx_cfg[idx].bit_format,
+		ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_mi2s_tx_format_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_tx_cfg[idx].bit_format =
+		mi2s_auxpcm_get_format(ucontrol->value.enumerated.item[0]);
+
+	pr_debug("%s: idx[%d]_tx_format = %d, item = %d\n", __func__,
+		  idx, mi2s_tx_cfg[idx].bit_format,
+		  ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+static int msm_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	pr_debug("%s: msm_mi2s_[%d]_rx_ch  = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].channels);
+	ucontrol->value.enumerated.item[0] = mi2s_rx_cfg[idx].channels - 1;
+
+	return 0;
+}
+
+static int msm_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_rx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+	pr_debug("%s: msm_mi2s_[%d]_rx_ch  = %d\n", __func__,
+		 idx, mi2s_rx_cfg[idx].channels);
+
+	return 1;
+}
+
+static int msm_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	pr_debug("%s: msm_mi2s_[%d]_tx_ch  = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].channels);
+	ucontrol->value.enumerated.item[0] = mi2s_tx_cfg[idx].channels - 1;
+
+	return 0;
+}
+
+static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
+			      struct snd_ctl_elem_value *ucontrol)
+{
+	int idx = mi2s_get_port_idx(kcontrol);
+
+	if (idx < 0)
+		return idx;
+
+	mi2s_tx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+	pr_debug("%s: msm_mi2s_[%d]_tx_ch  = %d\n", __func__,
+		 idx, mi2s_tx_cfg[idx].channels);
+
+	return 1;
+}
+
+static int msm_get_port_id(int be_id)
+{
+	int afe_port_id = 0;
+
+	switch (be_id) {
+	case MSM_BACKEND_DAI_PRI_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_PRI_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
+		afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX;
+		break;
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
+		afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+		afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+		afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_1;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		afe_port_id = AFE_PORT_ID_VA_CODEC_DMA_TX_2;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_0;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+		afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_1;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_1:
+		afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_1;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_2;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_2:
+		afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_2;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_3;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+		afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_3;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_4:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_4;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+		afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_4;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_5;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_5:
+		afe_port_id = AFE_PORT_ID_TX_CODEC_DMA_TX_5;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_6;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_7:
+		afe_port_id = AFE_PORT_ID_RX_CODEC_DMA_RX_7;
+		break;
+	default:
+		pr_err("%s: Invalid BE id: %d\n", __func__, be_id);
+		afe_port_id = -EINVAL;
+	}
+
+	return afe_port_id;
+}
+
+static u32 get_mi2s_bits_per_sample(u32 bit_format)
+{
+	u32 bit_per_sample = 0;
+
+	switch (bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+	case SNDRV_PCM_FORMAT_S24_3LE:
+	case SNDRV_PCM_FORMAT_S24_LE:
+		bit_per_sample = 32;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		bit_per_sample = 16;
+		break;
+	}
+
+	return bit_per_sample;
+}
+
+static void update_mi2s_clk_val(int dai_id, int stream)
+{
+	u32 bit_per_sample = 0;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		bit_per_sample =
+		    get_mi2s_bits_per_sample(mi2s_rx_cfg[dai_id].bit_format);
+		mi2s_clk[dai_id].clk_freq_in_hz =
+		    mi2s_rx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
+	} else {
+		bit_per_sample =
+		    get_mi2s_bits_per_sample(mi2s_tx_cfg[dai_id].bit_format);
+		mi2s_clk[dai_id].clk_freq_in_hz =
+		    mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
+	}
+}
+
+static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int port_id = 0;
+	int index = cpu_dai->id;
+
+	port_id = msm_get_port_id(rtd->dai_link->id);
+	if (port_id < 0) {
+		dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
+		ret = port_id;
+		goto err;
+	}
+
+	if (enable) {
+		update_mi2s_clk_val(index, substream->stream);
+		dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__,
+			mi2s_clk[index].clk_freq_in_hz);
+	}
+
+	mi2s_clk[index].enable = enable;
+	ret = afe_set_lpass_clock_v2(port_id,
+				     &mi2s_clk[index]);
+	if (ret < 0) {
+		dev_err(rtd->card->dev,
+			"%s: afe lpass clock failed for port 0x%x , err:%d\n",
+			__func__, port_id, ret);
+		goto err;
+	}
+
+err:
+	return ret;
+}
+
+static int cdc_dma_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+	int idx = 0;
+
+	if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_0",
+		sizeof("RX_CDC_DMA_RX_0")))
+		idx = RX_CDC_DMA_RX_0;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_1",
+		sizeof("RX_CDC_DMA_RX_1")))
+		idx = RX_CDC_DMA_RX_1;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_2",
+		sizeof("RX_CDC_DMA_RX_2")))
+		idx = RX_CDC_DMA_RX_2;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_3",
+		sizeof("RX_CDC_DMA_RX_3")))
+		idx = RX_CDC_DMA_RX_3;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_5",
+		sizeof("RX_CDC_DMA_RX_5")))
+		idx = RX_CDC_DMA_RX_5;
+	else if (strnstr(kcontrol->id.name, "RX_CDC_DMA_RX_6",
+		sizeof("RX_CDC_DMA_RX_6")))
+		idx = RX_CDC_DMA_RX_6;
+	else if (strnstr(kcontrol->id.name, "TX_CDC_DMA_TX_0",
+		sizeof("TX_CDC_DMA_TX_0")))
+		idx = TX_CDC_DMA_TX_0;
+	else if (strnstr(kcontrol->id.name, "TX_CDC_DMA_TX_3",
+		sizeof("TX_CDC_DMA_TX_3")))
+		idx = TX_CDC_DMA_TX_3;
+	else if (strnstr(kcontrol->id.name, "TX_CDC_DMA_TX_4",
+		sizeof("TX_CDC_DMA_TX_4")))
+		idx = TX_CDC_DMA_TX_4;
+	else if (strnstr(kcontrol->id.name, "VA_CDC_DMA_TX_0",
+		sizeof("VA_CDC_DMA_TX_0")))
+		idx = VA_CDC_DMA_TX_0;
+	else if (strnstr(kcontrol->id.name, "VA_CDC_DMA_TX_1",
+		sizeof("VA_CDC_DMA_TX_1")))
+		idx = VA_CDC_DMA_TX_1;
+	else if (strnstr(kcontrol->id.name, "VA_CDC_DMA_TX_2",
+		sizeof("VA_CDC_DMA_TX_2")))
+		idx = VA_CDC_DMA_TX_2;
+	else {
+		pr_err("%s: unsupported channel: %s\n",
+			__func__, kcontrol->id.name);
+		return -EINVAL;
+	}
+
+	return idx;
+}
+
+static int cdc_dma_rx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	pr_debug("%s: cdc_dma_rx_ch  = %d\n", __func__,
+		 cdc_dma_rx_cfg[ch_num].channels - 1);
+	ucontrol->value.integer.value[0] = cdc_dma_rx_cfg[ch_num].channels - 1;
+	return 0;
+}
+
+static int cdc_dma_rx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	cdc_dma_rx_cfg[ch_num].channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: cdc_dma_rx_ch = %d\n", __func__,
+		cdc_dma_rx_cfg[ch_num].channels);
+	return 1;
+}
+
+static int cdc_dma_rx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (cdc_dma_rx_cfg[ch_num].bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: cdc_dma_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_rx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int cdc_dma_rx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		cdc_dma_rx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: cdc_dma_rx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_rx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+
+static int cdc_dma_get_sample_rate_val(int sample_rate)
+{
+	int sample_rate_val = 0;
+
+	switch (sample_rate) {
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+	return sample_rate_val;
+}
+
+static int cdc_dma_get_sample_rate(int value)
+{
+	int sample_rate = 0;
+
+	switch (value) {
+	case 0:
+		sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	case 1:
+		sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 2:
+		sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 3:
+		sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 4:
+		sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 5:
+		sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 6:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 7:
+		sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 8:
+		sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 9:
+		sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 10:
+		sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 11:
+		sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 12:
+		sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	default:
+		sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+	return sample_rate;
+}
+
+static int cdc_dma_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	ucontrol->value.enumerated.item[0] =
+		cdc_dma_get_sample_rate_val(cdc_dma_rx_cfg[ch_num].sample_rate);
+
+	pr_debug("%s: cdc_dma_rx_sample_rate = %d\n", __func__,
+		 cdc_dma_rx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0 || ch_num >= CDC_DMA_RX_MAX) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	cdc_dma_rx_cfg[ch_num].sample_rate =
+		cdc_dma_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+
+	pr_debug("%s: control value = %d, cdc_dma_rx_sample_rate = %d\n",
+		__func__, ucontrol->value.enumerated.item[0],
+		cdc_dma_rx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_tx_ch_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	pr_debug("%s: cdc_dma_tx_ch  = %d\n", __func__,
+		 cdc_dma_tx_cfg[ch_num].channels);
+	ucontrol->value.integer.value[0] = cdc_dma_tx_cfg[ch_num].channels - 1;
+	return 0;
+}
+
+static int cdc_dma_tx_ch_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	cdc_dma_tx_cfg[ch_num].channels = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: cdc_dma_tx_ch = %d\n", __func__,
+		cdc_dma_tx_cfg[ch_num].channels);
+	return 1;
+}
+
+static int cdc_dma_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int sample_rate_val;
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (cdc_dma_tx_cfg[ch_num].sample_rate) {
+	case SAMPLING_RATE_384KHZ:
+		sample_rate_val = 12;
+		break;
+	case SAMPLING_RATE_352P8KHZ:
+		sample_rate_val = 11;
+		break;
+	case SAMPLING_RATE_192KHZ:
+		sample_rate_val = 10;
+		break;
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 9;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 8;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 7;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 5;
+		break;
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 4;
+		break;
+	case SAMPLING_RATE_22P05KHZ:
+		sample_rate_val = 3;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		sample_rate_val = 2;
+		break;
+	case SAMPLING_RATE_11P025KHZ:
+		sample_rate_val = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+		sample_rate_val = 0;
+		break;
+	default:
+		sample_rate_val = 6;
+		break;
+	}
+
+	ucontrol->value.integer.value[0] = sample_rate_val;
+	pr_debug("%s: cdc_dma_tx_sample_rate = %d\n", __func__,
+		 cdc_dma_tx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 12:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_384KHZ;
+		break;
+	case 11:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_352P8KHZ;
+		break;
+	case 10:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_192KHZ;
+		break;
+	case 9:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 8:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 7:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 6:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 5:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 4:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_32KHZ;
+		break;
+	case 3:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_22P05KHZ;
+		break;
+	case 2:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 1:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_11P025KHZ;
+		break;
+	case 0:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	default:
+		cdc_dma_tx_cfg[ch_num].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	pr_debug("%s: control value = %ld, cdc_dma_tx_sample_rate = %d\n",
+		__func__, ucontrol->value.integer.value[0],
+		cdc_dma_tx_cfg[ch_num].sample_rate);
+	return 0;
+}
+
+static int cdc_dma_tx_format_get(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (cdc_dma_tx_cfg[ch_num].bit_format) {
+	case SNDRV_PCM_FORMAT_S32_LE:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SNDRV_PCM_FORMAT_S24_LE:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SNDRV_PCM_FORMAT_S16_LE:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+
+	pr_debug("%s: cdc_dma_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_tx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+	return 0;
+}
+
+static int cdc_dma_tx_format_put(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	int rc = 0;
+	int ch_num = cdc_dma_get_port_idx(kcontrol);
+
+	if (ch_num < 0) {
+		pr_err("%s: ch_num: %d is invalid\n", __func__, ch_num);
+		return ch_num;
+	}
+
+	switch (ucontrol->value.integer.value[0]) {
+	case 3:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S32_LE;
+		break;
+	case 2:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
+	case 1:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S24_LE;
+		break;
+	case 0:
+	default:
+		cdc_dma_tx_cfg[ch_num].bit_format = SNDRV_PCM_FORMAT_S16_LE;
+		break;
+	}
+	pr_debug("%s: cdc_dma_tx_format = %d, ucontrol value = %ld\n",
+		 __func__, cdc_dma_tx_cfg[ch_num].bit_format,
+		 ucontrol->value.integer.value[0]);
+
+	return rc;
+}
+
+static int msm_cdc_dma_get_idx_from_beid(int32_t be_id)
+{
+	int idx = 0;
+
+	switch (be_id) {
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+		idx = RX_CDC_DMA_RX_0;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_1:
+		idx = RX_CDC_DMA_RX_1;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_2:
+		idx = RX_CDC_DMA_RX_2;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_3:
+		idx = RX_CDC_DMA_RX_3;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5:
+		idx = RX_CDC_DMA_RX_5;
+		break;
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6:
+		idx = RX_CDC_DMA_RX_6;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+		idx = TX_CDC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+		idx = TX_CDC_DMA_TX_3;
+		break;
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+		idx = TX_CDC_DMA_TX_4;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+		idx = VA_CDC_DMA_TX_0;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+		idx = VA_CDC_DMA_TX_1;
+		break;
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		idx = VA_CDC_DMA_TX_2;
+		break;
+	default:
+		idx = RX_CDC_DMA_RX_0;
+		break;
+	}
+
+	return idx;
+}
+
+static int msm_bt_sample_rate_get(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	/*
+	 * Slimbus_7_Rx/Tx sample rate values should always be in sync (same)
+	 * when used for BT_SCO use case. Return either Rx or Tx sample rate
+	 * value.
+	 */
+	switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate = %d\n", __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_put(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rates: slim7_rx = %d, slim7_tx = %d, value = %d\n",
+		 __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_rx_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (slim_rx_cfg[SLIM_RX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate rx = %d\n", __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_rx_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_rx_cfg[SLIM_RX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rate: slim7_rx = %d, value = %d\n",
+		 __func__,
+		 slim_rx_cfg[SLIM_RX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_get(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (slim_tx_cfg[SLIM_TX_7].sample_rate) {
+	case SAMPLING_RATE_96KHZ:
+		ucontrol->value.integer.value[0] = 5;
+		break;
+	case SAMPLING_RATE_88P2KHZ:
+		ucontrol->value.integer.value[0] = 4;
+		break;
+	case SAMPLING_RATE_48KHZ:
+		ucontrol->value.integer.value[0] = 3;
+		break;
+	case SAMPLING_RATE_44P1KHZ:
+		ucontrol->value.integer.value[0] = 2;
+		break;
+	case SAMPLING_RATE_16KHZ:
+		ucontrol->value.integer.value[0] = 1;
+		break;
+	case SAMPLING_RATE_8KHZ:
+	default:
+		ucontrol->value.integer.value[0] = 0;
+		break;
+	}
+	pr_debug("%s: sample rate tx = %d\n", __func__,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate);
+
+	return 0;
+}
+
+static int msm_bt_sample_rate_tx_put(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_value *ucontrol)
+{
+	switch (ucontrol->value.integer.value[0]) {
+	case 1:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_16KHZ;
+		break;
+	case 2:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_48KHZ;
+		break;
+	case 4:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 5:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_96KHZ;
+		break;
+	case 0:
+	default:
+		slim_tx_cfg[SLIM_TX_7].sample_rate = SAMPLING_RATE_8KHZ;
+		break;
+	}
+	pr_debug("%s: sample rate: slim7_tx = %d, value = %d\n",
+		 __func__,
+		 slim_tx_cfg[SLIM_TX_7].sample_rate,
+		 ucontrol->value.enumerated.item[0]);
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new msm_int_wcd937x_snd_controls[] = {
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 Format", rx_cdc_dma_rx_0_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 Format", rx_cdc_dma_rx_1_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 Format", rx_cdc_dma_rx_2_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 Format", rx_cdc_dma_rx_3_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 Format", rx_cdc_dma_rx_5_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 SampleRate",
+			rx_cdc_dma_rx_0_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 SampleRate",
+			rx_cdc_dma_rx_1_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 SampleRate",
+			rx_cdc_dma_rx_2_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 SampleRate",
+			rx_cdc_dma_rx_3_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 SampleRate",
+			rx_cdc_dma_rx_5_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+};
+
+static const struct snd_kcontrol_new msm_int_snd_controls[] = {
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 Channels", rx_cdc_dma_rx_0_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 Channels", rx_cdc_dma_rx_1_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 Channels", rx_cdc_dma_rx_2_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 Channels", rx_cdc_dma_rx_3_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 Channels", rx_cdc_dma_rx_5_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_6 Channels", rx_cdc_dma_rx_6_chs,
+			cdc_dma_rx_ch_get, cdc_dma_rx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_0 Channels", tx_cdc_dma_tx_0_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_3 Channels", tx_cdc_dma_tx_3_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_4 Channels", tx_cdc_dma_tx_4_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_0 Channels", va_cdc_dma_tx_0_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_1 Channels", va_cdc_dma_tx_1_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_2 Channels", va_cdc_dma_tx_2_chs,
+			cdc_dma_tx_ch_get, cdc_dma_tx_ch_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_0 Format", tx_cdc_dma_tx_0_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_3 Format", tx_cdc_dma_tx_3_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_4 Format", tx_cdc_dma_tx_4_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_0 Format", va_cdc_dma_tx_0_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_1 Format", va_cdc_dma_tx_1_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_2 Format", va_cdc_dma_tx_2_format,
+			cdc_dma_tx_format_get, cdc_dma_tx_format_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_0 SampleRate",
+			tx_cdc_dma_tx_0_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_3 SampleRate",
+			tx_cdc_dma_tx_3_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("TX_CDC_DMA_TX_4 SampleRate",
+			tx_cdc_dma_tx_4_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_0 SampleRate",
+			va_cdc_dma_tx_0_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_1 SampleRate",
+			va_cdc_dma_tx_1_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+	SOC_ENUM_EXT("VA_CDC_DMA_TX_2 SampleRate",
+			va_cdc_dma_tx_2_sample_rate,
+			cdc_dma_tx_sample_rate_get,
+			cdc_dma_tx_sample_rate_put),
+};
+
+static const struct snd_kcontrol_new msm_int_wcd9380_snd_controls[] = {
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 Format", rx_cdc80_dma_rx_0_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 Format", rx_cdc80_dma_rx_1_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 Format", rx_cdc80_dma_rx_2_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 Format", rx_cdc80_dma_rx_3_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 Format", rx_cdc80_dma_rx_5_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_6 Format", rx_cdc80_dma_rx_6_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 SampleRate",
+			rx_cdc80_dma_rx_0_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 SampleRate",
+			rx_cdc80_dma_rx_1_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 SampleRate",
+			rx_cdc80_dma_rx_2_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 SampleRate",
+			rx_cdc80_dma_rx_3_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 SampleRate",
+			rx_cdc80_dma_rx_5_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_6 SampleRate",
+			rx_cdc80_dma_rx_6_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+};
+
+static const struct snd_kcontrol_new msm_int_wcd9385_snd_controls[] = {
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 Format", rx_cdc85_dma_rx_0_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 Format", rx_cdc85_dma_rx_1_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 Format", rx_cdc85_dma_rx_2_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 Format", rx_cdc85_dma_rx_3_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 Format", rx_cdc85_dma_rx_5_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_6 Format", rx_cdc85_dma_rx_6_format,
+			cdc_dma_rx_format_get, cdc_dma_rx_format_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_0 SampleRate",
+			rx_cdc85_dma_rx_0_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_1 SampleRate",
+			rx_cdc85_dma_rx_1_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_2 SampleRate",
+			rx_cdc85_dma_rx_2_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_3 SampleRate",
+			rx_cdc85_dma_rx_3_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_5 SampleRate",
+			rx_cdc85_dma_rx_5_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+	SOC_ENUM_EXT("RX_CDC_DMA_RX_6 SampleRate",
+			rx_cdc85_dma_rx_6_sample_rate,
+			cdc_dma_rx_sample_rate_get,
+			cdc_dma_rx_sample_rate_put),
+};
+
+static const struct snd_kcontrol_new msm_common_snd_controls[] = {
+	SOC_ENUM_EXT("USB_AUDIO_RX SampleRate", usb_rx_sample_rate,
+			usb_audio_rx_sample_rate_get,
+			usb_audio_rx_sample_rate_put),
+	SOC_ENUM_EXT("USB_AUDIO_TX SampleRate", usb_tx_sample_rate,
+			usb_audio_tx_sample_rate_get,
+			usb_audio_tx_sample_rate_put),
+	SOC_ENUM_EXT("PRI_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_TDM_RX_0 SampleRate", tdm_rx_sample_rate,
+			tdm_rx_sample_rate_get,
+			tdm_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRI_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_TDM_TX_0 SampleRate", tdm_tx_sample_rate,
+			tdm_tx_sample_rate_get,
+			tdm_tx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate,
+			mi2s_rx_sample_rate_get,
+			mi2s_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate,
+			mi2s_tx_sample_rate_get,
+			mi2s_tx_sample_rate_put),
+	SOC_ENUM_EXT("USB_AUDIO_RX Format", usb_rx_format,
+			usb_audio_rx_format_get, usb_audio_rx_format_put),
+	SOC_ENUM_EXT("USB_AUDIO_TX Format", usb_tx_format,
+			usb_audio_tx_format_get, usb_audio_tx_format_put),
+	SOC_ENUM_EXT("PRI_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("SEC_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("TERT_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("QUAT_TDM_RX_0 Format", tdm_rx_format,
+			tdm_rx_format_get,
+			tdm_rx_format_put),
+	SOC_ENUM_EXT("PRI_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("SEC_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("TERT_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("QUAT_TDM_TX_0 Format", tdm_tx_format,
+			tdm_tx_format_get,
+			tdm_tx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("SEC_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("TERT_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("QUAT_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("PRIM_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("SEC_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("TERT_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("QUAT_MI2S_RX Format", mi2s_rx_format,
+			msm_mi2s_rx_format_get, msm_mi2s_rx_format_put),
+	SOC_ENUM_EXT("PRIM_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("SEC_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("TERT_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("QUAT_MI2S_TX Format", mi2s_tx_format,
+			msm_mi2s_tx_format_get, msm_mi2s_tx_format_put),
+	SOC_ENUM_EXT("USB_AUDIO_RX Channels", usb_rx_chs,
+			usb_audio_rx_ch_get, usb_audio_rx_ch_put),
+	SOC_ENUM_EXT("USB_AUDIO_TX Channels", usb_tx_chs,
+			usb_audio_tx_ch_get, usb_audio_tx_ch_put),
+	SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
+			proxy_rx_ch_get, proxy_rx_ch_put),
+	SOC_ENUM_EXT("PRI_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("SEC_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("TERT_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("QUAT_TDM_RX_0 Channels", tdm_rx_chs,
+			tdm_rx_ch_get,
+			tdm_rx_ch_put),
+	SOC_ENUM_EXT("PRI_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("SEC_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("TERT_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("QUAT_TDM_TX_0 Channels", tdm_tx_chs,
+			tdm_tx_ch_get,
+			tdm_tx_ch_put),
+	SOC_ENUM_EXT("PRIM_MI2S_RX Channels", prim_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("SEC_MI2S_RX Channels", sec_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("TERT_MI2S_RX Channels", tert_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("QUAT_MI2S_RX Channels", quat_mi2s_rx_chs,
+			msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+	SOC_ENUM_EXT("PRIM_MI2S_TX Channels", prim_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("SEC_MI2S_TX Channels", sec_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("TERT_MI2S_TX Channels", tert_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("QUAT_MI2S_TX Channels", quat_mi2s_tx_chs,
+			msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+	SOC_ENUM_EXT("BT SampleRate", bt_sample_rate,
+			msm_bt_sample_rate_get,
+			msm_bt_sample_rate_put),
+	SOC_ENUM_EXT("BT SampleRate RX", bt_sample_rate_rx,
+			msm_bt_sample_rate_rx_get,
+			msm_bt_sample_rate_rx_put),
+	SOC_ENUM_EXT("BT SampleRate TX", bt_sample_rate_tx,
+			msm_bt_sample_rate_tx_get,
+			msm_bt_sample_rate_tx_put),
+	SOC_ENUM_EXT("AFE_LOOPBACK_TX Channels", afe_loopback_tx_chs,
+			afe_loopback_tx_ch_get, afe_loopback_tx_ch_put),
+	SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
+			msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
+	SOC_SINGLE_MULTI_EXT("TDM Slot Map", SND_SOC_NOPM, 0, 255, 0,
+			TDM_MAX_SLOTS + MAX_PATH, NULL, tdm_slot_map_put),
+};
+
+static const struct snd_kcontrol_new msm_snd_controls[] = {
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX Format", aux_pcm_rx_format,
+			msm_aux_pcm_rx_format_get, msm_aux_pcm_rx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX Format", aux_pcm_tx_format,
+			msm_aux_pcm_tx_format_get, msm_aux_pcm_tx_format_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
+			aux_pcm_rx_sample_rate_get,
+			aux_pcm_rx_sample_rate_put),
+	SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
+			aux_pcm_tx_sample_rate_get,
+			aux_pcm_tx_sample_rate_put),
+};
+
+static int holi_send_island_va_config(int32_t be_id)
+{
+	int rc = 0;
+	int port_id = 0xFFFF;
+
+	port_id = msm_get_port_id(be_id);
+	if (port_id < 0) {
+		pr_err("%s: Invalid island interface, be_id: %d\n",
+		       __func__, be_id);
+		rc = -EINVAL;
+	} else {
+		/*
+		 * send island mode config
+		 * This should be the first configuration
+		 */
+		rc = afe_send_port_island_mode(port_id);
+		if (rc)
+			pr_err("%s: afe send island mode failed %d\n",
+				__func__, rc);
+	}
+
+	return rc;
+}
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+	int idx = 0, rc = 0;
+
+	pr_debug("%s: dai_id= %d, format = %d, rate = %d\n",
+		  __func__, dai_link->id, params_format(params),
+		  params_rate(params));
+
+	switch (dai_link->id) {
+	case MSM_BACKEND_DAI_USB_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				usb_rx_cfg.bit_format);
+		rate->min = rate->max = usb_rx_cfg.sample_rate;
+		channels->min = channels->max = usb_rx_cfg.channels;
+		break;
+
+	case MSM_BACKEND_DAI_USB_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				usb_tx_cfg.bit_format);
+		rate->min = rate->max = usb_tx_cfg.sample_rate;
+		channels->min = channels->max = usb_tx_cfg.channels;
+		break;
+
+	case MSM_BACKEND_DAI_AFE_PCM_RX:
+		channels->min = channels->max = proxy_rx_cfg.channels;
+		rate->min = rate->max = SAMPLING_RATE_48KHZ;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_PRI][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_PRI][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_PRI][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_PRI][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_PRI][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_PRI][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_SEC][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_SEC][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_SEC][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_SEC][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_SEC][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_SEC][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_TERT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_TERT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_TERT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_TERT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_TERT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_TERT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_TDM_RX_0:
+		channels->min = channels->max =
+				tdm_rx_cfg[TDM_QUAT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_rx_cfg[TDM_QUAT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_rx_cfg[TDM_QUAT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_TDM_TX_0:
+		channels->min = channels->max =
+				tdm_tx_cfg[TDM_QUAT][TDM_0].channels;
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			       tdm_tx_cfg[TDM_QUAT][TDM_0].bit_format);
+		rate->min = rate->max = tdm_tx_cfg[TDM_QUAT][TDM_0].sample_rate;
+		break;
+
+	case MSM_BACKEND_DAI_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[PRIM_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[PRIM_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[SEC_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[SEC_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[SEC_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SEC_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[SEC_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[SEC_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[SEC_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[TERT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[TERT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[TERT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERT_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[TERT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[TERT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[TERT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_AUXPCM_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_rx_cfg[QUAT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUAT_AUXPCM_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].bit_format);
+		rate->min = rate->max =
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].sample_rate;
+		channels->min = channels->max =
+			aux_pcm_tx_cfg[QUAT_AUX_PCM].channels;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[PRIM_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[PRIM_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[PRIM_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_PRI_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[PRIM_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[PRIM_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[PRIM_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[SEC_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[SEC_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[SEC_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SECONDARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[SEC_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[SEC_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[SEC_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[TERT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[TERT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[TERT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[TERT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[TERT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[TERT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_rx_cfg[QUAT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_rx_cfg[QUAT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_rx_cfg[QUAT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+			mi2s_tx_cfg[QUAT_MI2S].bit_format);
+		rate->min = rate->max = mi2s_tx_cfg[QUAT_MI2S].sample_rate;
+		channels->min = channels->max =
+			mi2s_tx_cfg[QUAT_MI2S].channels;
+		break;
+
+	case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+	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_6:
+		idx = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				cdc_dma_rx_cfg[idx].bit_format);
+		rate->min = rate->max = cdc_dma_rx_cfg[idx].sample_rate;
+		channels->min = channels->max = cdc_dma_rx_cfg[idx].channels;
+		break;
+
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+	case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		idx = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				cdc_dma_tx_cfg[idx].bit_format);
+		rate->min = rate->max = cdc_dma_tx_cfg[idx].sample_rate;
+		channels->min = channels->max = cdc_dma_tx_cfg[idx].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				slim_rx_cfg[SLIM_RX_7].bit_format);
+		rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
+		channels->min = channels->max =
+			slim_rx_cfg[SLIM_RX_7].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SLIMBUS_7_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				slim_tx_cfg[SLIM_TX_7].bit_format);
+		rate->min = rate->max = slim_tx_cfg[SLIM_TX_7].sample_rate;
+		channels->min = channels->max =
+			slim_tx_cfg[SLIM_TX_7].channels;
+		break;
+
+	case MSM_BACKEND_DAI_SLIMBUS_8_TX:
+		rate->min = rate->max = slim_tx_cfg[SLIM_TX_8].sample_rate;
+		channels->min = channels->max =
+			slim_tx_cfg[SLIM_TX_8].channels;
+		break;
+
+	case MSM_BACKEND_DAI_AFE_LOOPBACK_TX:
+		param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				afe_loopback_tx_cfg[idx].bit_format);
+		rate->min = rate->max = afe_loopback_tx_cfg[idx].sample_rate;
+		channels->min = channels->max =
+				afe_loopback_tx_cfg[idx].channels;
+		break;
+
+	default:
+		rate->min = rate->max = SAMPLING_RATE_48KHZ;
+		break;
+	}
+
+	return rc;
+}
+
+static bool msm_usbc_swap_gnd_mic(struct snd_soc_component *component,
+				  bool active)
+{
+	struct snd_soc_card *card = component->card;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(card);
+
+	if (!pdata->fsa_handle)
+		return false;
+
+	return fsa4480_switch_event(pdata->fsa_handle, FSA_MIC_GND_SWAP);
+}
+
+static bool msm_swap_gnd_mic(struct snd_soc_component *component, bool active)
+{
+	int value = 0;
+	bool ret = false;
+	struct snd_soc_card *card;
+	struct msm_asoc_mach_data *pdata;
+
+	if (!component) {
+		pr_err("%s component is NULL\n", __func__);
+		return false;
+	}
+	card = component->card;
+	pdata = snd_soc_card_get_drvdata(card);
+
+	if (!pdata)
+		return false;
+
+	if (wcd_mbhc_cfg.enable_usbc_analog)
+		return msm_usbc_swap_gnd_mic(component, active);
+
+	/* if usbc is not defined, swap using us_euro_gpio_p */
+	if (pdata->us_euro_gpio_p) {
+		value = msm_cdc_pinctrl_get_state(
+				pdata->us_euro_gpio_p);
+		if (value)
+			msm_cdc_pinctrl_select_sleep_state(
+					pdata->us_euro_gpio_p);
+		else
+			msm_cdc_pinctrl_select_active_state(
+					pdata->us_euro_gpio_p);
+		dev_dbg(component->dev, "%s: swap select switch %d to %d\n",
+			__func__, value, !value);
+		ret = true;
+	}
+
+	return ret;
+}
+
+static int holi_tdm_snd_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	int slot_width = TDM_SLOT_WIDTH_BITS;
+	int channels, slots = TDM_MAX_SLOTS;
+	unsigned int slot_mask, rate, clk_freq;
+	unsigned int *slot_offset;
+	struct tdm_dev_config *config;
+	unsigned int path_dir = 0, interface = 0, channel_interface = 0;
+
+	pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id);
+
+	if (cpu_dai->id < AFE_PORT_ID_TDM_PORT_RANGE_START) {
+		pr_err("%s: dai id 0x%x not supported\n",
+			__func__, cpu_dai->id);
+		return -EINVAL;
+	}
+
+	/* RX or TX */
+	path_dir = cpu_dai->id % MAX_PATH;
+
+	/* PRI, SEC, TERT, QUAT ... */
+	interface = (cpu_dai->id - AFE_PORT_ID_TDM_PORT_RANGE_START)
+			/ (MAX_PATH * TDM_PORT_MAX);
+
+	/* 0, 1, 2, .. 7 */
+	channel_interface =
+		((cpu_dai->id - AFE_PORT_ID_TDM_PORT_RANGE_START) / MAX_PATH)
+		% TDM_PORT_MAX;
+
+	pr_debug("%s: path dir: %u, interface %u, channel interface %u\n",
+		__func__, path_dir, interface, channel_interface);
+
+	config = ((struct tdm_dev_config *) tdm_cfg[interface]) +
+			(path_dir * TDM_PORT_MAX) + channel_interface;
+	slot_offset = config->tdm_slot_offset;
+
+	if (path_dir)
+		channels = tdm_tx_cfg[interface][channel_interface].channels;
+	else
+		channels = tdm_rx_cfg[interface][channel_interface].channels;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/*2 slot config - bits 0 and 1 set for the first two slots */
+		slot_mask = 0x0000FFFF >> (16 - slots);
+
+		pr_debug("%s: tdm rx slot_width %d slots %d slot_mask %x\n",
+			__func__, slot_width, slots, slot_mask);
+
+		ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask,
+			slots, slot_width);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm rx slot, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+
+		pr_debug("%s: tdm rx channels: %d\n", __func__, channels);
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+			0, NULL, channels, slot_offset);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm rx channel map, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		/*2 slot config - bits 0 and 1 set for the first two slots */
+		slot_mask = 0x0000FFFF >> (16 - slots);
+
+		pr_debug("%s: tdm tx slot_width %d slots %d slot_mask %x\n",
+			__func__, slot_width, slots, slot_mask);
+
+		ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0,
+			slots, slot_width);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm tx slot, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+
+		pr_debug("%s: tdm tx channels: %d\n", __func__, channels);
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai,
+			channels, slot_offset, 0, NULL);
+		if (ret < 0) {
+			pr_err("%s: failed to set tdm tx channel map, err:%d\n",
+				__func__, ret);
+			goto end;
+		}
+	} else {
+		ret = -EINVAL;
+		pr_err("%s: invalid use case, err:%d\n",
+			__func__, ret);
+		goto end;
+	}
+
+	rate = params_rate(params);
+	clk_freq = rate * slot_width * slots;
+	ret = snd_soc_dai_set_sysclk(cpu_dai, 0, clk_freq, SND_SOC_CLOCK_OUT);
+	if (ret < 0)
+		pr_err("%s: failed to set tdm clk, err:%d\n",
+			__func__, ret);
+
+end:
+	return ret;
+}
+
+static int msm_get_tdm_mode(u32 port_id)
+{
+	int tdm_mode;
+
+	switch (port_id) {
+	case AFE_PORT_ID_PRIMARY_TDM_RX:
+	case AFE_PORT_ID_PRIMARY_TDM_TX:
+		tdm_mode = TDM_PRI;
+		break;
+	case AFE_PORT_ID_SECONDARY_TDM_RX:
+	case AFE_PORT_ID_SECONDARY_TDM_TX:
+		tdm_mode = TDM_SEC;
+		break;
+	case AFE_PORT_ID_TERTIARY_TDM_RX:
+	case AFE_PORT_ID_TERTIARY_TDM_TX:
+		tdm_mode = TDM_TERT;
+		break;
+	case AFE_PORT_ID_QUATERNARY_TDM_RX:
+	case AFE_PORT_ID_QUATERNARY_TDM_TX:
+		tdm_mode = TDM_QUAT;
+		break;
+	default:
+		pr_err("%s: Invalid port id: %d\n", __func__, port_id);
+		tdm_mode = -EINVAL;
+	}
+	return tdm_mode;
+}
+
+static int holi_tdm_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int tdm_mode = msm_get_tdm_mode(cpu_dai->id);
+
+	if (tdm_mode >= TDM_INTERFACE_MAX || tdm_mode < 0) {
+		ret = -EINVAL;
+		pr_err("%s: Invalid TDM interface %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (pdata->mi2s_gpio_p[tdm_mode]) {
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[tdm_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+				pdata->mi2s_gpio_p[tdm_mode]);
+			if (ret) {
+				pr_err("%s: TDM GPIO pinctrl set active failed with %d\n",
+					__func__, ret);
+				goto done;
+			}
+		}
+		atomic_inc(&(pdata->mi2s_gpio_ref_count[tdm_mode]));
+	}
+
+done:
+	return ret;
+}
+
+static void holi_tdm_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int tdm_mode = msm_get_tdm_mode(cpu_dai->id);
+
+	if (tdm_mode >= TDM_INTERFACE_MAX || tdm_mode < 0) {
+		ret = -EINVAL;
+		pr_err("%s: Invalid TDM interface %d\n",
+			__func__, ret);
+		return;
+	}
+
+	if (pdata->mi2s_gpio_p[tdm_mode]) {
+		atomic_dec(&(pdata->mi2s_gpio_ref_count[tdm_mode]));
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[tdm_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+				pdata->mi2s_gpio_p[tdm_mode]);
+			if (ret)
+				pr_err("%s: TDM GPIO pinctrl set sleep failed with %d\n",
+					__func__, ret);
+		}
+	}
+}
+
+static int holi_aux_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	u32 aux_mode = cpu_dai->id - 1;
+
+	if (aux_mode >= AUX_PCM_MAX) {
+		ret = -EINVAL;
+		pr_err("%s: Invalid AUX interface %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (pdata->mi2s_gpio_p[aux_mode]) {
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[aux_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_active_state(
+				pdata->mi2s_gpio_p[aux_mode]);
+			if (ret) {
+				pr_err("%s: AUX GPIO pinctrl set active failed with %d\n",
+					__func__, ret);
+				goto done;
+			}
+		}
+		atomic_inc(&(pdata->mi2s_gpio_ref_count[aux_mode]));
+	}
+
+done:
+	return ret;
+}
+
+static void holi_aux_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	u32 aux_mode = cpu_dai->id - 1;
+
+	if (aux_mode >= AUX_PCM_MAX) {
+		pr_err("%s: Invalid AUX interface %d\n",
+			__func__, ret);
+		return;
+	}
+
+	if (pdata->mi2s_gpio_p[aux_mode]) {
+		atomic_dec(&(pdata->mi2s_gpio_ref_count[aux_mode]));
+		if (atomic_read(&(pdata->mi2s_gpio_ref_count[aux_mode]))
+									== 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+				pdata->mi2s_gpio_p[aux_mode]);
+			if (ret)
+				pr_err("%s: AUX GPIO pinctrl set sleep failed with %d\n",
+					__func__, ret);
+		}
+	}
+}
+
+static int msm_snd_cdc_dma_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+	switch (dai_link->id) {
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+	case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		ret = holi_send_island_va_config(dai_link->id);
+		if (ret)
+			pr_err("%s: send island va cfg failed, err: %d\n",
+			       __func__, ret);
+		break;
+	}
+
+	return ret;
+}
+
+static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+	int ret = 0;
+	u32 rx_ch_cdc_dma, tx_ch_cdc_dma;
+	u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+	u32 user_set_tx_ch = 0;
+	u32 user_set_rx_ch = 0;
+	u32 ch_id;
+
+	ret = snd_soc_dai_get_channel_map(codec_dai,
+				&tx_ch_cnt, &tx_ch_cdc_dma, &rx_ch_cnt,
+				&rx_ch_cdc_dma);
+	if (ret < 0) {
+		pr_err("%s: failed to get codec chan map, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		switch (dai_link->id) {
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_0:
+		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_4:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_5:
+		case MSM_BACKEND_DAI_RX_CDC_DMA_RX_6:
+		{
+			ch_id = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+			pr_debug("%s: id %d rx_ch=%d\n", __func__,
+				ch_id, cdc_dma_rx_cfg[ch_id].channels);
+			user_set_rx_ch = cdc_dma_rx_cfg[ch_id].channels;
+			ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+					  user_set_rx_ch, &rx_ch_cdc_dma);
+			if (ret < 0) {
+				pr_err("%s: failed to set cpu chan map, err:%d\n",
+				__func__, ret);
+				goto err;
+			}
+
+		}
+		break;
+		}
+	} else {
+		switch (dai_link->id) {
+		case MSM_BACKEND_DAI_TX_CDC_DMA_TX_0:
+		case MSM_BACKEND_DAI_TX_CDC_DMA_TX_3:
+		case MSM_BACKEND_DAI_TX_CDC_DMA_TX_4:
+		case MSM_BACKEND_DAI_VA_CDC_DMA_TX_0:
+		case MSM_BACKEND_DAI_VA_CDC_DMA_TX_1:
+		case MSM_BACKEND_DAI_VA_CDC_DMA_TX_2:
+		{
+			ch_id = msm_cdc_dma_get_idx_from_beid(dai_link->id);
+			pr_debug("%s: id %d tx_ch=%d\n", __func__,
+				ch_id, cdc_dma_tx_cfg[ch_id].channels);
+			user_set_tx_ch = cdc_dma_tx_cfg[ch_id].channels;
+		}
+		break;
+		}
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, user_set_tx_ch,
+					&tx_ch_cdc_dma, 0, 0);
+		if (ret < 0) {
+			pr_err("%s: failed to set cpu chan map, err:%d\n",
+			__func__, ret);
+			goto err;
+		}
+	}
+
+err:
+	return ret;
+}
+
+static int msm_fe_qos_prepare(struct snd_pcm_substream *substream)
+{
+	(void)substream;
+
+	qos_client_active_cnt++;
+	if (qos_client_active_cnt == 1)
+		msm_audio_update_qos_request(MSM_LL_QOS_VALUE);
+
+	return 0;
+}
+
+static void msm_fe_qos_shutdown(struct snd_pcm_substream *substream)
+{
+	(void)substream;
+
+	if (qos_client_active_cnt > 0)
+		qos_client_active_cnt--;
+	if (qos_client_active_cnt == 0)
+		msm_audio_update_qos_request(PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE);
+}
+
+void mi2s_disable_audio_vote(struct snd_pcm_substream *substream)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int index = cpu_dai->id;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int sample_rate = 0;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		sample_rate = mi2s_rx_cfg[index].sample_rate;
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		sample_rate = mi2s_tx_cfg[index].sample_rate;
+	} else {
+		pr_err("%s: invalid stream %d\n", __func__, substream->stream);
+		return;
+	}
+
+	if (IS_MSM_INTERFACE_MI2S(index) && IS_FRACTIONAL(sample_rate)) {
+		if (pdata->lpass_audio_hw_vote != NULL) {
+			if (--pdata->core_audio_vote_count == 0) {
+				clk_disable_unprepare(
+					pdata->lpass_audio_hw_vote);
+			} else if (pdata->core_audio_vote_count < 0) {
+				pr_err("%s: audio vote mismatch\n", __func__);
+				pdata->core_audio_vote_count = 0;
+			}
+		} else {
+			pr_err("%s: Invalid lpass audio hw node\n", __func__);
+		}
+	}
+}
+
+static int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int index = cpu_dai->id;
+	unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+	int sample_rate = 0;
+
+	dev_dbg(rtd->card->dev,
+		"%s: substream = %s  stream = %d, dai name %s, dai ID %d\n",
+		__func__, substream->name, substream->stream,
+		cpu_dai->name, cpu_dai->id);
+
+	if (index < PRIM_MI2S || index >= MI2S_MAX) {
+		ret = -EINVAL;
+		dev_err(rtd->card->dev,
+			"%s: CPU DAI id (%d) out of range\n",
+			__func__, cpu_dai->id);
+		goto err;
+	}
+	/*
+	 * Mutex protection in case the same MI2S
+	 * interface using for both TX and RX so
+	 * that the same clock won't be enable twice.
+	 */
+	mutex_lock(&mi2s_intf_conf[index].lock);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		sample_rate = mi2s_rx_cfg[index].sample_rate;
+	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		sample_rate = mi2s_tx_cfg[index].sample_rate;
+	} else {
+		pr_err("%s: invalid stream %d\n", __func__, substream->stream);
+		ret = -EINVAL;
+		goto vote_err;
+	}
+
+	if (IS_MSM_INTERFACE_MI2S(index) && IS_FRACTIONAL(sample_rate)) {
+		if (pdata->lpass_audio_hw_vote == NULL) {
+			dev_err(rtd->card->dev, "%s: Invalid lpass audio hw node\n",
+				__func__);
+			ret = -EINVAL;
+			goto vote_err;
+		}
+		if (pdata->core_audio_vote_count == 0) {
+			ret = clk_prepare_enable(pdata->lpass_audio_hw_vote);
+			if (ret < 0) {
+				dev_err(rtd->card->dev, "%s: audio vote error\n",
+					__func__);
+				goto vote_err;
+			}
+		}
+		pdata->core_audio_vote_count++;
+	}
+
+	if (++mi2s_intf_conf[index].ref_cnt == 1) {
+		/* Check if msm needs to provide the clock to the interface */
+		if (!mi2s_intf_conf[index].msm_is_mi2s_master) {
+			mi2s_clk[index].clk_id = mi2s_ebit_clk[index];
+			fmt = SND_SOC_DAIFMT_CBM_CFM;
+		}
+		ret = msm_mi2s_set_sclk(substream, true);
+		if (ret < 0) {
+			dev_err(rtd->card->dev,
+				"%s: afe lpass clock failed to enable MI2S clock, err:%d\n",
+				__func__, ret);
+			goto clean_up;
+		}
+
+		ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+		if (ret < 0) {
+			pr_err("%s: set fmt cpu dai failed for MI2S (%d), err:%d\n",
+				__func__, index, ret);
+			goto clk_off;
+		}
+		if (pdata->mi2s_gpio_p[index]) {
+			if (atomic_read(&(pdata->mi2s_gpio_ref_count[index]))
+									== 0) {
+				ret = msm_cdc_pinctrl_select_active_state(
+						pdata->mi2s_gpio_p[index]);
+				if (ret) {
+					pr_err("%s: MI2S GPIO pinctrl set active failed with %d\n",
+						__func__, ret);
+					goto clk_off;
+				}
+			}
+			atomic_inc(&(pdata->mi2s_gpio_ref_count[index]));
+		}
+	}
+clk_off:
+	if (ret < 0)
+		msm_mi2s_set_sclk(substream, false);
+clean_up:
+	if (ret < 0) {
+		mi2s_intf_conf[index].ref_cnt--;
+		mi2s_disable_audio_vote(substream);
+	}
+vote_err:
+	mutex_unlock(&mi2s_intf_conf[index].lock);
+err:
+	return ret;
+}
+
+static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	int index = rtd->cpu_dai->id;
+	struct snd_soc_card *card = rtd->card;
+	struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
+		 substream->name, substream->stream);
+	if (index < PRIM_MI2S || index >= MI2S_MAX) {
+		pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index);
+		return;
+	}
+
+	mutex_lock(&mi2s_intf_conf[index].lock);
+	if (--mi2s_intf_conf[index].ref_cnt == 0) {
+		if (pdata->mi2s_gpio_p[index]) {
+			atomic_dec(&(pdata->mi2s_gpio_ref_count[index]));
+			if (atomic_read(&(pdata->mi2s_gpio_ref_count[index]))
+									== 0) {
+				ret = msm_cdc_pinctrl_select_sleep_state(
+						pdata->mi2s_gpio_p[index]);
+				if (ret)
+					pr_err("%s: MI2S GPIO pinctrl set sleep failed with %d\n",
+						__func__, ret);
+			}
+		}
+
+		ret = msm_mi2s_set_sclk(substream, false);
+		if (ret < 0)
+			pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
+				__func__, index, ret);
+	}
+	mi2s_disable_audio_vote(substream);
+	mutex_unlock(&mi2s_intf_conf[index].lock);
+}
+
+static int msm_wcn_hw_params_lito(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	struct snd_soc_dai_link *dai_link = rtd->dai_link;
+	u32 rx_ch[WCN_CDC_SLIM_RX_CH_MAX], tx_ch[WCN_CDC_SLIM_TX_CH_MAX_LITO];
+	u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+	int ret = 0;
+
+	dev_dbg(rtd->dev, "%s: %s_tx_dai_id_%d\n", __func__,
+		 codec_dai->name, codec_dai->id);
+	ret = snd_soc_dai_get_channel_map(codec_dai,
+				 &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+	if (ret) {
+		dev_err(rtd->dev,
+			"%s: failed to get BTFM codec chan map\n, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) BE id %d\n",
+		__func__, tx_ch_cnt, dai_link->id);
+
+	ret = snd_soc_dai_set_channel_map(cpu_dai,
+					  tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
+	if (ret)
+		dev_err(rtd->dev, "%s: failed to set cpu chan map, err:%d\n",
+			__func__, ret);
+
+err:
+	return ret;
+}
+
+static struct snd_soc_ops holi_aux_be_ops = {
+	.startup = holi_aux_snd_startup,
+	.shutdown = holi_aux_snd_shutdown
+};
+
+static struct snd_soc_ops holi_tdm_be_ops = {
+	.hw_params = holi_tdm_snd_hw_params,
+	.startup = holi_tdm_snd_startup,
+	.shutdown = holi_tdm_snd_shutdown
+};
+
+static struct snd_soc_ops msm_mi2s_be_ops = {
+	.startup = msm_mi2s_snd_startup,
+	.shutdown = msm_mi2s_snd_shutdown,
+};
+
+static struct snd_soc_ops msm_fe_qos_ops = {
+	.prepare = msm_fe_qos_prepare,
+	.shutdown = msm_fe_qos_shutdown,
+};
+
+static struct snd_soc_ops msm_cdc_dma_be_ops = {
+	.startup = msm_snd_cdc_dma_startup,
+	.hw_params = msm_snd_cdc_dma_hw_params,
+};
+
+static struct snd_soc_ops msm_wcn_ops_lito = {
+	.hw_params = msm_wcn_hw_params_lito,
+};
+
+static int msm_dmic_event(struct snd_soc_dapm_widget *w,
+			  struct snd_kcontrol *kcontrol, int event)
+{
+	struct msm_asoc_mach_data *pdata = NULL;
+	struct snd_soc_component *component =
+					 snd_soc_dapm_to_component(w->dapm);
+	int ret = 0;
+	u32 dmic_idx;
+	int *dmic_gpio_cnt;
+	struct device_node *dmic_gpio;
+	char  *wname;
+
+	wname = strpbrk(w->name, "012345");
+	if (!wname) {
+		dev_err(component->dev, "%s: widget not found\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = kstrtouint(wname, 10, &dmic_idx);
+	if (ret < 0) {
+		dev_err(component->dev, "%s: Invalid DMIC line on the codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	pdata = snd_soc_card_get_drvdata(component->card);
+
+	switch (dmic_idx) {
+	case 0:
+	case 1:
+		dmic_gpio_cnt = &dmic_0_1_gpio_cnt;
+		dmic_gpio = pdata->dmic01_gpio_p;
+		break;
+	case 2:
+	case 3:
+		dmic_gpio_cnt = &dmic_2_3_gpio_cnt;
+		dmic_gpio = pdata->dmic23_gpio_p;
+		break;
+	case 4:
+	case 5:
+		dmic_gpio_cnt = &dmic_4_5_gpio_cnt;
+		dmic_gpio = pdata->dmic45_gpio_p;
+		break;
+	default:
+		dev_err(component->dev, "%s: Invalid DMIC Selection\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	dev_dbg(component->dev, "%s: event %d DMIC%d dmic_gpio_cnt %d\n",
+			__func__, event, dmic_idx, *dmic_gpio_cnt);
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		(*dmic_gpio_cnt)++;
+		if (*dmic_gpio_cnt == 1) {
+			ret = msm_cdc_pinctrl_select_active_state(
+						dmic_gpio);
+			if (ret < 0) {
+				pr_err("%s: gpio set cannot be activated %sd",
+					__func__, "dmic_gpio");
+				return ret;
+			}
+		}
+
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		(*dmic_gpio_cnt)--;
+		if (*dmic_gpio_cnt == 0) {
+			ret = msm_cdc_pinctrl_select_sleep_state(
+					dmic_gpio);
+			if (ret < 0) {
+				pr_err("%s: gpio set cannot be de-activated %sd",
+					__func__, "dmic_gpio");
+				return ret;
+			}
+		}
+		break;
+	default:
+		pr_err("%s: invalid DAPM event %d\n", __func__, event);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = {
+	SND_SOC_DAPM_MIC("Analog Mic1", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic2", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic3", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic4", NULL),
+	SND_SOC_DAPM_MIC("Analog Mic5", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic0", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic2", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic3", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic4", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic5", msm_dmic_event),
+	SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+	SND_SOC_DAPM_MIC("Digital Mic7", NULL),
+};
+
+static int msm_wcn_init_lito(struct snd_soc_pcm_runtime *rtd)
+{
+	unsigned int rx_ch[WCN_CDC_SLIM_RX_CH_MAX] = {157, 158};
+	unsigned int tx_ch[WCN_CDC_SLIM_TX_CH_MAX_LITO]  = {159, 160, 161};
+	struct snd_soc_dai *codec_dai = rtd->codec_dai;
+
+	return snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+					   tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+}
+
+static struct snd_info_entry *msm_snd_info_create_subdir(struct module *mod,
+				const char *name,
+				struct snd_info_entry *parent)
+{
+	struct snd_info_entry *entry;
+
+	entry = snd_info_create_module_entry(mod, name, parent);
+	if (!entry)
+		return NULL;
+	entry->mode = S_IFDIR | 0555;
+	if (snd_info_register(entry) < 0) {
+		snd_info_free_entry(entry);
+		return NULL;
+	}
+	return entry;
+}
+
+static void *def_wcd_mbhc_cal(void)
+{
+	void *wcd_mbhc_cal;
+	struct wcd_mbhc_btn_detect_cfg *btn_cfg;
+	u16 *btn_high;
+
+	wcd_mbhc_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+				WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
+	if (!wcd_mbhc_cal)
+		return NULL;
+
+	WCD_MBHC_CAL_PLUG_TYPE_PTR(wcd_mbhc_cal)->v_hs_max = WCD_MBHC_HS_V_MAX;
+	WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal)->num_btn = WCD_MBHC_DEF_BUTTONS;
+	btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(wcd_mbhc_cal);
+	btn_high = ((void *)&btn_cfg->_v_btn_low) +
+		(sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
+
+	btn_high[0] = 75;
+	btn_high[1] = 150;
+	btn_high[2] = 237;
+	btn_high[3] = 500;
+	btn_high[4] = 500;
+	btn_high[5] = 500;
+	btn_high[6] = 500;
+	btn_high[7] = 500;
+
+	return wcd_mbhc_cal;
+}
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm_common_dai_links[] = {
+	/* FrontEnd DAI Links */
+	{/* hw:x,0 */
+		.name = MSM_DAILINK_NAME(Media1),
+		.stream_name = "MultiMedia1",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA1,
+		SND_SOC_DAILINK_REG(multimedia1),
+	},
+	{/* hw:x,1 */
+		.name = MSM_DAILINK_NAME(Media2),
+		.stream_name = "MultiMedia2",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+		SND_SOC_DAILINK_REG(multimedia2),
+	},
+	{/* hw:x,2 */
+		.name = "VoiceMMode1",
+		.stream_name = "VoiceMMode1",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_VOICEMMODE1,
+		SND_SOC_DAILINK_REG(voicemmode1),
+	},
+	{/* hw:x,3 */
+		.name = "MSM VoIP",
+		.stream_name = "VoIP",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_VOIP,
+		SND_SOC_DAILINK_REG(msmvoip),
+	},
+	{/* hw:x,4 */
+		.name = MSM_DAILINK_NAME(ULL),
+		.stream_name = "MultiMedia3",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+		SND_SOC_DAILINK_REG(multimedia3),
+	},
+	{/* hw:x,5 */
+		.name = "MSM AFE-PCM RX",
+		.stream_name = "AFE-PROXY RX",
+		.dpcm_playback = 1,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(afepcm_rx),
+	},
+	{/* hw:x,6 */
+		.name = "MSM AFE-PCM TX",
+		.stream_name = "AFE-PROXY TX",
+		.dpcm_capture = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(afepcm_tx),
+	},
+	{/* hw:x,7 */
+		.name = MSM_DAILINK_NAME(Compress1),
+		.stream_name = "Compress1",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_HW_PARAMS,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+		SND_SOC_DAILINK_REG(multimedia4),
+	},
+	/* Hostless PCM purpose */
+	{/* hw:x,8 */
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(auxpcm_hostless),
+	},
+	{/* hw:x,9 */
+		.name = MSM_DAILINK_NAME(LowLatency),
+		.stream_name = "MultiMedia5",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+		.ops = &msm_fe_qos_ops,
+		SND_SOC_DAILINK_REG(multimedia5),
+	},
+	{/* hw:x,10 */
+		.name = "Listen 1 Audio Service",
+		.stream_name = "Listen 1 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+			     SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM1,
+		SND_SOC_DAILINK_REG(listen1),
+	},
+	/* Multiple Tunnel instances */
+	{/* hw:x,11 */
+		.name = MSM_DAILINK_NAME(Compress2),
+		.stream_name = "Compress2",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+		SND_SOC_DAILINK_REG(multimedia7),
+	},
+	{/* hw:x,12 */
+		.name = MSM_DAILINK_NAME(MultiMedia10),
+		.stream_name = "MultiMedia10",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+		SND_SOC_DAILINK_REG(multimedia10),
+	},
+	{/* hw:x,13 */
+		.name = MSM_DAILINK_NAME(ULL_NOIRQ),
+		.stream_name = "MM_NOIRQ",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+		.ops = &msm_fe_qos_ops,
+		SND_SOC_DAILINK_REG(multimedia8),
+	},
+	/* HDMI Hostless */
+	{/* hw:x,14 */
+		.name = "HDMI_RX_HOSTLESS",
+		.stream_name = "HDMI_RX_HOSTLESS",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(hdmi_rx_hostless),
+	},
+	{/* hw:x,15 */
+		.name = "VoiceMMode2",
+		.stream_name = "VoiceMMode2",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_VOICEMMODE2,
+		SND_SOC_DAILINK_REG(voicemmode2),
+	},
+	/* LSM FE */
+	{/* hw:x,16 */
+		.name = "Listen 2 Audio Service",
+		.stream_name = "Listen 2 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM2,
+		SND_SOC_DAILINK_REG(listen2),
+	},
+	{/* hw:x,17 */
+		.name = "Listen 3 Audio Service",
+		.stream_name = "Listen 3 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM3,
+		SND_SOC_DAILINK_REG(listen3),
+	},
+	{/* hw:x,18 */
+		.name = "Listen 4 Audio Service",
+		.stream_name = "Listen 4 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM4,
+		SND_SOC_DAILINK_REG(listen4),
+	},
+	{/* hw:x,19 */
+		.name = "Listen 5 Audio Service",
+		.stream_name = "Listen 5 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM5,
+		SND_SOC_DAILINK_REG(listen5),
+	},
+	{/* hw:x,20 */
+		.name = "Listen 6 Audio Service",
+		.stream_name = "Listen 6 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM6,
+		SND_SOC_DAILINK_REG(listen6),
+	},
+	{/* hw:x,21 */
+		.name = "Listen 7 Audio Service",
+		.stream_name = "Listen 7 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM7,
+		SND_SOC_DAILINK_REG(listen7),
+	},
+	{/* hw:x,22 */
+		.name = "Listen 8 Audio Service",
+		.stream_name = "Listen 8 Audio Service",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = { SND_SOC_DPCM_TRIGGER_POST,
+				 SND_SOC_DPCM_TRIGGER_POST },
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.id = MSM_FRONTEND_DAI_LSM8,
+		SND_SOC_DAILINK_REG(listen8),
+	},
+	{/* hw:x,23 */
+		.name = MSM_DAILINK_NAME(Media9),
+		.stream_name = "MultiMedia9",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+		SND_SOC_DAILINK_REG(multimedia9),
+	},
+	{/* hw:x,24 */
+		.name = MSM_DAILINK_NAME(Compress4),
+		.stream_name = "Compress4",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+		SND_SOC_DAILINK_REG(multimedia11),
+	},
+	{/* hw:x,25 */
+		.name = MSM_DAILINK_NAME(Compress5),
+		.stream_name = "Compress5",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+		SND_SOC_DAILINK_REG(multimedia12),
+	},
+	{/* hw:x,26 */
+		.name = MSM_DAILINK_NAME(Compress6),
+		.stream_name = "Compress6",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+		SND_SOC_DAILINK_REG(multimedia13),
+	},
+	{/* hw:x,27 */
+		.name = MSM_DAILINK_NAME(Compress7),
+		.stream_name = "Compress7",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+		SND_SOC_DAILINK_REG(multimedia14),
+	},
+	{/* hw:x,28 */
+		.name = MSM_DAILINK_NAME(Compress8),
+		.stream_name = "Compress8",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+		SND_SOC_DAILINK_REG(multimedia15),
+	},
+	{/* hw:x,29 */
+		.name = MSM_DAILINK_NAME(ULL_NOIRQ_2),
+		.stream_name = "MM_NOIRQ_2",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+		.ops = &msm_fe_qos_ops,
+		SND_SOC_DAILINK_REG(multimedia16),
+	},
+	{/* hw:x,30 */
+		.name = "CDC_DMA Hostless",
+		.stream_name = "CDC_DMA Hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		 /* this dailink has playback support */
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(cdcdma_hostless),
+	},
+	{/* hw:x,31 */
+		.name = "TX3_CDC_DMA Hostless",
+		.stream_name = "TX3_CDC_DMA Hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tx3_cdcdma_hostless),
+	},
+	{/* hw:x,32 */
+		.name = "Tertiary MI2S TX_Hostless",
+		.stream_name = "Tertiary MI2S_TX Hostless Capture",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(tert_mi2s_tx_hostless),
+	},
+};
+
+static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = {
+	{/* hw:x,33 */
+		.name = MSM_DAILINK_NAME(ASM Loopback),
+		.stream_name = "MultiMedia6",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+		SND_SOC_DAILINK_REG(multimedia6),
+	},
+	{/* hw:x,34 */
+		.name = "USB Audio Hostless",
+		.stream_name = "USB Audio Hostless",
+		.dynamic = 1,
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(usbaudio_hostless),
+	},
+	{/* hw:x,35 */
+		.name = "SLIMBUS_7 Hostless",
+		.stream_name = "SLIMBUS_7 Hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(slimbus7_hostless),
+	},
+	{/* hw:x,36 */
+		.name = "Compress Capture",
+		.stream_name = "Compress9",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA17,
+		SND_SOC_DAILINK_REG(multimedia17),
+	},
+	{/* hw:x,37 */
+		.name = "SLIMBUS_8 Hostless",
+		.stream_name = "SLIMBUS_8 Hostless",
+		.dynamic = 1,
+		.dpcm_capture = 1,
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			    SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(slimbus8_hostless),
+	},
+	{/* hw:x,38 */
+		.name = LPASS_BE_TX_CDC_DMA_TX_5,
+		.stream_name = "TX CDC DMA5 Capture",
+		.id = MSM_BACKEND_DAI_TX_CDC_DMA_TX_5,
+		.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(tx_cdcdma5_tx),
+	},
+	{/* hw:x,39 */
+		.name = MSM_DAILINK_NAME(Media31),
+		.stream_name = "MultiMedia31",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA31,
+		SND_SOC_DAILINK_REG(multimedia31),
+	},
+	{/* hw:x,40 */
+		.name = MSM_DAILINK_NAME(Media32),
+		.stream_name = "MultiMedia32",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA32,
+		SND_SOC_DAILINK_REG(multimedia32),
+	},
+	{/* hw:x,41 */
+		.name = "MSM AFE-PCM TX1",
+		.stream_name = "AFE-PROXY TX1",
+		.dpcm_capture = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(afepcm_tx1),
+	},
+};
+
+static struct snd_soc_dai_link msm_common_be_dai_links[] = {
+	/* Backend AFE DAI Links */
+	{
+		.name = LPASS_BE_AFE_PCM_RX,
+		.stream_name = "AFE Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_AFE_PCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(afe_pcm_rx),
+	},
+	{
+		.name = LPASS_BE_AFE_PCM_TX,
+		.stream_name = "AFE Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_AFE_PCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(afe_pcm_tx),
+	},
+	/* Incall Record Uplink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_TX,
+		.stream_name = "Voice Uplink Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(incall_record_tx),
+	},
+	/* Incall Record Downlink BACK END DAI Link */
+	{
+		.name = LPASS_BE_INCALL_RECORD_RX,
+		.stream_name = "Voice Downlink Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(incall_record_rx),
+	},
+	/* Incall Music BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE_PLAYBACK_TX,
+		.stream_name = "Voice Farend Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(voice_playback_tx),
+	},
+	/* Incall Music 2 BACK END DAI Link */
+	{
+		.name = LPASS_BE_VOICE2_PLAYBACK_TX,
+		.stream_name = "Voice2 Farend Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(voice2_playback_tx),
+	},
+	/* Proxy Tx BACK END DAI Link */
+	{
+		.name = LPASS_BE_PROXY_TX,
+		.stream_name = "Proxy Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_PROXY_TX,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(proxy_tx),
+	},
+	/* Proxy Rx BACK END DAI Link */
+	{
+		.name = LPASS_BE_PROXY_RX,
+		.stream_name = "Proxy Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_PROXY_RX,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(proxy_rx),
+	},
+	{
+		.name = LPASS_BE_USB_AUDIO_RX,
+		.stream_name = "USB Audio Playback",
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.dynamic_be = 1,
+#endif /* CONFIG_AUDIO_QGKI */
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_USB_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(usb_audio_rx),
+	},
+	{
+		.name = LPASS_BE_USB_AUDIO_TX,
+		.stream_name = "USB Audio Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_USB_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(usb_audio_tx),
+	},
+	{
+		.name = LPASS_BE_PRI_TDM_RX_0,
+		.stream_name = "Primary TDM0 Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(pri_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_PRI_TDM_TX_0,
+		.stream_name = "Primary TDM0 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(pri_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_SEC_TDM_RX_0,
+		.stream_name = "Secondary TDM0 Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(sec_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_SEC_TDM_TX_0,
+		.stream_name = "Secondary TDM0 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_TERT_TDM_RX_0,
+		.stream_name = "Tertiary TDM0 Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(tert_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_TERT_TDM_TX_0,
+		.stream_name = "Tertiary TDM0 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_tdm_tx_0),
+	},
+	{
+		.name = LPASS_BE_QUAT_TDM_RX_0,
+		.stream_name = "Quaternary TDM0 Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(quat_tdm_rx_0),
+	},
+	{
+		.name = LPASS_BE_QUAT_TDM_TX_0,
+		.stream_name = "Quaternary TDM0 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_tdm_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_tdm_tx_0),
+	},
+};
+
+static struct snd_soc_dai_link msm_wcn_btfm_be_dai_links[] = {
+	{
+		.name = LPASS_BE_SLIMBUS_7_RX,
+		.stream_name = "Slimbus7 Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.init = &msm_wcn_init_lito,
+		.ops = &msm_wcn_ops_lito,
+		/* dai link has playback support */
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(slimbus_7_rx),
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_7_TX,
+		.stream_name = "Slimbus7 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_wcn_ops_lito,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(slimbus_7_tx),
+	},
+	{
+		.name = LPASS_BE_SLIMBUS_8_TX,
+		.stream_name = "Slimbus8 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_wcn_ops_lito,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(slimbus_8_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
+	{
+		.name = LPASS_BE_PRI_MI2S_RX,
+		.stream_name = "Primary MI2S Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_PRI_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(pri_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_PRI_MI2S_TX,
+		.stream_name = "Primary MI2S Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_PRI_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(pri_mi2s_tx),
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_RX,
+		.stream_name = "Secondary MI2S Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(sec_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_SEC_MI2S_TX,
+		.stream_name = "Secondary MI2S Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_mi2s_tx),
+	},
+	{
+		.name = LPASS_BE_TERT_MI2S_RX,
+		.stream_name = "Tertiary MI2S Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(tert_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_TERT_MI2S_TX,
+		.stream_name = "Tertiary MI2S Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_mi2s_tx),
+	},
+	{
+		.name = LPASS_BE_QUAT_MI2S_RX,
+		.stream_name = "Quaternary MI2S Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		SND_SOC_DAILINK_REG(quat_mi2s_rx),
+	},
+	{
+		.name = LPASS_BE_QUAT_MI2S_TX,
+		.stream_name = "Quaternary MI2S Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &msm_mi2s_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_mi2s_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
+	/* Primary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_AUXPCM_RX,
+		.stream_name = "AUX PCM Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_AUXPCM_TX,
+		.stream_name = "AUX PCM Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(auxpcm_tx),
+	},
+	/* Secondary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_SEC_AUXPCM_RX,
+		.stream_name = "Sec AUX PCM Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_SEC_AUXPCM_TX,
+		.stream_name = "Sec AUX PCM Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(sec_auxpcm_tx),
+	},
+	/* Tertiary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_TERT_AUXPCM_RX,
+		.stream_name = "Tert AUX PCM Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_TERT_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_TERT_AUXPCM_TX,
+		.stream_name = "Tert AUX PCM Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(tert_auxpcm_tx),
+	},
+	/* Quaternary AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_QUAT_AUXPCM_RX,
+		.stream_name = "Quat AUX PCM Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_QUAT_AUXPCM_TX,
+		.stream_name = "Quat AUX PCM Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ops = &holi_aux_be_ops,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(quat_auxpcm_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
+	/* RX CDC DMA Backend DAI Links */
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_0,
+		.stream_name = "RX CDC DMA0 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_0,
+		.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_rx0),
+		.init = &msm_aux_codec_init,
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_1,
+		.stream_name = "RX CDC DMA1 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_1,
+		.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_rx1),
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_2,
+		.stream_name = "RX CDC DMA2 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_2,
+		.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_rx2),
+	},
+	{
+		.name = LPASS_BE_RX_CDC_DMA_RX_3,
+		.stream_name = "RX CDC DMA3 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_3,
+		.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_rx3),
+	},
+	/* TX CDC DMA Backend DAI Links */
+	{
+		.name = LPASS_BE_TX_CDC_DMA_TX_3,
+		.stream_name = "TX CDC DMA3 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TX_CDC_DMA_TX_3,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(tx_dma_tx3),
+	},
+	{
+		.name = LPASS_BE_TX_CDC_DMA_TX_4,
+		.stream_name = "TX CDC DMA4 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_TX_CDC_DMA_TX_4,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(tx_dma_tx4),
+	},
+};
+
+static struct snd_soc_dai_link msm_va_cdc_dma_be_dai_links[] = {
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_0,
+		.stream_name = "VA CDC DMA0 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_VA_CDC_DMA_TX_0,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(va_dma_tx0),
+		.init = &msm_int_audrx_init,
+	},
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_1,
+		.stream_name = "VA CDC DMA1 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_VA_CDC_DMA_TX_1,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(va_dma_tx1),
+	},
+	{
+		.name = LPASS_BE_VA_CDC_DMA_TX_2,
+		.stream_name = "VA CDC DMA2 Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_VA_CDC_DMA_TX_2,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_cdc_dma_be_ops,
+		SND_SOC_DAILINK_REG(va_dma_tx2),
+	},
+};
+
+static struct snd_soc_dai_link msm_afe_rxtx_lb_be_dai_link[] = {
+	{
+		.name = LPASS_BE_AFE_LOOPBACK_TX,
+		.stream_name = "AFE Loopback Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_AFE_LOOPBACK_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		SND_SOC_DAILINK_REG(afe_loopback_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_holi_dai_links[
+			ARRAY_SIZE(msm_common_dai_links) +
+			ARRAY_SIZE(msm_common_misc_fe_dai_links) +
+			ARRAY_SIZE(msm_common_be_dai_links) +
+			ARRAY_SIZE(msm_mi2s_be_dai_links) +
+			ARRAY_SIZE(msm_auxpcm_be_dai_links) +
+			ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links) +
+			ARRAY_SIZE(msm_va_cdc_dma_be_dai_links) +
+			ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) +
+			ARRAY_SIZE(msm_wcn_btfm_be_dai_links)];
+
+static int msm_populate_dai_link_component_of_node(
+					struct snd_soc_card *card)
+{
+	int i, j, index, ret = 0;
+	struct device *cdev = card->dev;
+	struct snd_soc_dai_link *dai_link = card->dai_link;
+	struct device_node *np = NULL;
+	int codecs_enabled = 0;
+	struct snd_soc_dai_link_component *codecs_comp = NULL;
+
+	if (!cdev) {
+		dev_err(cdev, "%s: Sound card device memory NULL\n", __func__);
+		return -ENODEV;
+	}
+
+	for (i = 0; i < card->num_links; i++) {
+		if (dai_link[i].platforms->of_node && dai_link[i].cpus->of_node)
+			continue;
+
+		/* populate platform_of_node for snd card dai links */
+		if (dai_link[i].platforms->name &&
+		    !dai_link[i].platforms->of_node) {
+			index = of_property_match_string(cdev->of_node,
+						"asoc-platform-names",
+						dai_link[i].platforms->name);
+			if (index < 0) {
+				dev_err(cdev, "%s: No match found for platform name: %s\n",
+					__func__, dai_link[i].platforms->name);
+				ret = index;
+				goto err;
+			}
+			np = of_parse_phandle(cdev->of_node, "asoc-platform",
+					      index);
+			if (!np) {
+				dev_err(cdev, "%s: retrieving phandle for platform %s, index %d failed\n",
+					__func__, dai_link[i].platforms->name,
+					index);
+				ret = -ENODEV;
+				goto err;
+			}
+			dai_link[i].platforms->of_node = np;
+			dai_link[i].platforms->name = NULL;
+		}
+
+		/* populate cpu_of_node for snd card dai links */
+		if (dai_link[i].cpus->dai_name && !dai_link[i].cpus->of_node) {
+			index = of_property_match_string(cdev->of_node,
+						 "asoc-cpu-names",
+						 dai_link[i].cpus->dai_name);
+			if (index >= 0) {
+				np = of_parse_phandle(cdev->of_node, "asoc-cpu",
+						index);
+				if (!np) {
+					dev_err(cdev, "%s: retrieving phandle for cpu dai %s failed\n",
+						__func__,
+						dai_link[i].cpus->dai_name);
+					ret = -ENODEV;
+					goto err;
+				}
+				dai_link[i].cpus->of_node = np;
+				dai_link[i].cpus->dai_name = NULL;
+			}
+		}
+
+		/* populate codec_of_node for snd card dai links */
+		if (dai_link[i].num_codecs > 0) {
+			for (j = 0; j < dai_link[i].num_codecs; j++) {
+				if (dai_link[i].codecs[j].of_node ||
+						!dai_link[i].codecs[j].name)
+					continue;
+
+				index = of_property_match_string(cdev->of_node,
+						"asoc-codec-names",
+						dai_link[i].codecs[j].name);
+				if (index < 0)
+					continue;
+				np = of_parse_phandle(cdev->of_node,
+						      "asoc-codec",
+						      index);
+				if (!np) {
+					dev_err(cdev, "%s: retrieving phandle for codec %s failed\n",
+						__func__,
+						dai_link[i].codecs[j].name);
+					ret = -ENODEV;
+					goto err;
+				}
+				dai_link[i].codecs[j].of_node = np;
+				dai_link[i].codecs[j].name = NULL;
+			}
+		}
+	}
+
+	/* In multi-codec scenario, check if codecs are enabled for this platform */
+	for (i = 0; i < card->num_links; i++) {
+		codecs_enabled = 0;
+		if (dai_link[i].num_codecs > 1) {
+			for (j = 0; j < dai_link[i].num_codecs; j++) {
+				if (!dai_link[i].codecs[j].of_node)
+					continue;
+
+				np = dai_link[i].codecs[j].of_node;
+				if (!of_device_is_available(np)) {
+					dev_err(cdev, "%s: codec is disabled: %s\n",
+						__func__,
+						np->full_name);
+					dai_link[i].codecs[j].of_node = NULL;
+					continue;
+				}
+
+				codecs_enabled++;
+			}
+			if (codecs_enabled > 0 &&
+				    codecs_enabled < dai_link[i].num_codecs) {
+				codecs_comp = devm_kzalloc(cdev,
+				    sizeof(struct snd_soc_dai_link_component)
+				    * codecs_enabled, GFP_KERNEL);
+				if (!codecs_comp) {
+					dev_err(cdev, "%s: %s dailink codec component alloc failed\n",
+						__func__, dai_link[i].name);
+					ret = -ENOMEM;
+					goto err;
+				}
+				index = 0;
+				for (j = 0; j < dai_link[i].num_codecs; j++) {
+					if (dai_link[i].codecs[j].of_node) {
+						codecs_comp[index].of_node =
+						  dai_link[i].codecs[j].of_node;
+						codecs_comp[index].dai_name =
+						  dai_link[i].codecs[j].dai_name;
+						codecs_comp[index].name = NULL;
+						index++;
+					}
+				}
+				dai_link[i].codecs = codecs_comp;
+				dai_link[i].num_codecs = codecs_enabled;
+			}
+		}
+	}
+
+err:
+	return ret;
+}
+
+static int msm_audrx_stub_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int ret = -EINVAL;
+	struct snd_soc_component *component =
+				 snd_soc_rtdcom_lookup(rtd, "msm-stub-codec");
+
+	if (!component) {
+		pr_err("* %s: No match for msm-stub-codec component\n", __func__);
+		return ret;
+	}
+
+	ret = snd_soc_add_component_controls(component, msm_snd_controls,
+			ARRAY_SIZE(msm_snd_controls));
+	if (ret < 0) {
+		dev_err(component->dev,
+			"%s: add_codec_controls failed, err = %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int msm_snd_stub_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	return 0;
+}
+
+static struct snd_soc_ops msm_stub_be_ops = {
+	.hw_params = msm_snd_stub_hw_params,
+};
+
+struct snd_soc_card snd_soc_card_stub_msm = {
+	.name		= "holi-stub-snd-card",
+};
+
+static struct snd_soc_dai_link msm_stub_fe_dai_links[] = {
+	/* FrontEnd DAI Links */
+	{
+		.name = "MSMSTUB Media1",
+		.stream_name = "MultiMedia1",
+		.dynamic = 1,
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+		.async_ops = ASYNC_DPCM_SND_SOC_PREPARE,
+#endif /* CONFIG_AUDIO_QGKI */
+		.dpcm_playback = 1,
+		.dpcm_capture = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			SND_SOC_DPCM_TRIGGER_POST},
+		.ignore_suspend = 1,
+		/* this dainlink has playback support */
+		.ignore_pmdown_time = 1,
+		.id = MSM_FRONTEND_DAI_MULTIMEDIA1,
+		SND_SOC_DAILINK_REG(multimedia1),
+	},
+};
+
+static struct snd_soc_dai_link msm_stub_be_dai_links[] = {
+	/* Backend DAI Links */
+	{
+		.name = LPASS_BE_AUXPCM_RX,
+		.stream_name = "AUX PCM Playback",
+		.no_pcm = 1,
+		.dpcm_playback = 1,
+		.id = MSM_BACKEND_DAI_AUXPCM_RX,
+		.init = &msm_audrx_stub_init,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_pmdown_time = 1,
+		.ignore_suspend = 1,
+		.ops = &msm_stub_be_ops,
+		SND_SOC_DAILINK_REG(auxpcm_rx),
+	},
+	{
+		.name = LPASS_BE_AUXPCM_TX,
+		.stream_name = "AUX PCM Capture",
+		.no_pcm = 1,
+		.dpcm_capture = 1,
+		.id = MSM_BACKEND_DAI_AUXPCM_TX,
+		.be_hw_params_fixup = msm_be_hw_params_fixup,
+		.ignore_suspend = 1,
+		.ops = &msm_stub_be_ops,
+		SND_SOC_DAILINK_REG(auxpcm_tx),
+	},
+};
+
+static struct snd_soc_dai_link msm_stub_dai_links[
+			 ARRAY_SIZE(msm_stub_fe_dai_links) +
+			 ARRAY_SIZE(msm_stub_be_dai_links)];
+
+static const struct of_device_id holi_asoc_machine_of_match[]  = {
+	{ .compatible = "qcom,holi-asoc-snd",
+	  .data = "codec"},
+	{ .compatible = "qcom,holi-asoc-snd-stub",
+	  .data = "stub_codec"},
+	{},
+};
+
+static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+	struct snd_soc_card *card = NULL;
+	struct snd_soc_dai_link *dailink = NULL;
+	int len_1 = 0;
+	int len_2 = 0;
+	int total_links = 0;
+	int rc = 0;
+	u32 mi2s_audio_intf = 0;
+	u32 auxpcm_audio_intf = 0;
+	u32 val = 0;
+	u32 wcn_btfm_intf = 0;
+	const struct of_device_id *match;
+
+	match = of_match_node(holi_asoc_machine_of_match, dev->of_node);
+	if (!match) {
+		dev_err(dev, "%s: No DT match found for sound card\n",
+			__func__);
+		return NULL;
+	}
+
+	if (!strcmp(match->data, "codec")) {
+		card = &snd_soc_card_holi_msm;
+
+		memcpy(msm_holi_dai_links + total_links,
+		       msm_common_dai_links,
+		       sizeof(msm_common_dai_links));
+		total_links += ARRAY_SIZE(msm_common_dai_links);
+
+		memcpy(msm_holi_dai_links + total_links,
+		       msm_common_misc_fe_dai_links,
+		       sizeof(msm_common_misc_fe_dai_links));
+		total_links += ARRAY_SIZE(msm_common_misc_fe_dai_links);
+
+		memcpy(msm_holi_dai_links + total_links,
+		       msm_common_be_dai_links,
+		       sizeof(msm_common_be_dai_links));
+		total_links += ARRAY_SIZE(msm_common_be_dai_links);
+
+		memcpy(msm_holi_dai_links + total_links,
+		       msm_rx_tx_cdc_dma_be_dai_links,
+		       sizeof(msm_rx_tx_cdc_dma_be_dai_links));
+		total_links +=
+			ARRAY_SIZE(msm_rx_tx_cdc_dma_be_dai_links);
+
+		memcpy(msm_holi_dai_links + total_links,
+		       msm_va_cdc_dma_be_dai_links,
+		       sizeof(msm_va_cdc_dma_be_dai_links));
+		total_links +=
+			ARRAY_SIZE(msm_va_cdc_dma_be_dai_links);
+
+		rc = of_property_read_u32(dev->of_node, "qcom,mi2s-audio-intf",
+					  &mi2s_audio_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match MI2S audio interface\n",
+				__func__);
+		} else {
+			if (mi2s_audio_intf) {
+				memcpy(msm_holi_dai_links + total_links,
+					msm_mi2s_be_dai_links,
+					sizeof(msm_mi2s_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_mi2s_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node,
+					  "qcom,auxpcm-audio-intf",
+					  &auxpcm_audio_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match Aux PCM interface\n",
+				__func__);
+		} else {
+			if (auxpcm_audio_intf) {
+				memcpy(msm_holi_dai_links + total_links,
+					msm_auxpcm_be_dai_links,
+					sizeof(msm_auxpcm_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_auxpcm_be_dai_links);
+			}
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,afe-rxtx-lb",
+				&val);
+		if (!rc && val) {
+			memcpy(msm_holi_dai_links + total_links,
+				msm_afe_rxtx_lb_be_dai_link,
+				sizeof(msm_afe_rxtx_lb_be_dai_link));
+			total_links +=
+				ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link);
+		}
+
+		rc = of_property_read_u32(dev->of_node, "qcom,wcn-btfm",
+					  &wcn_btfm_intf);
+		if (rc) {
+			dev_dbg(dev, "%s: No DT match wcn btfm interface\n",
+				__func__);
+		} else {
+			if (wcn_btfm_intf) {
+				memcpy(msm_holi_dai_links + total_links,
+					msm_wcn_btfm_be_dai_links,
+					sizeof(msm_wcn_btfm_be_dai_links));
+				total_links +=
+					ARRAY_SIZE(msm_wcn_btfm_be_dai_links);
+			}
+		}
+		dailink = msm_holi_dai_links;
+	} else if (!strcmp(match->data, "stub_codec")) {
+		card = &snd_soc_card_stub_msm;
+		len_1 = ARRAY_SIZE(msm_stub_fe_dai_links);
+		len_2 = len_1 + ARRAY_SIZE(msm_stub_be_dai_links);
+
+		memcpy(msm_stub_dai_links,
+		       msm_stub_fe_dai_links,
+		       sizeof(msm_stub_fe_dai_links));
+		memcpy(msm_stub_dai_links + len_1,
+		       msm_stub_be_dai_links,
+		       sizeof(msm_stub_be_dai_links));
+
+		dailink = msm_stub_dai_links;
+		total_links = len_2;
+	}
+
+	if (card) {
+		card->dai_link = dailink;
+		card->num_links = total_links;
+	}
+
+	return card;
+}
+
+static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *component = NULL;
+	struct snd_soc_dapm_context *dapm = NULL;
+	struct snd_card *card = NULL;
+	struct snd_info_entry *entry = NULL;
+	struct msm_asoc_mach_data *pdata =
+				snd_soc_card_get_drvdata(rtd->card);
+	int ret = 0;
+
+	component = snd_soc_rtdcom_lookup(rtd, "bolero_codec");
+	if (!component) {
+		pr_err("%s: could not find component for bolero_codec\n",
+			__func__);
+		return ret;
+	}
+
+	dapm = snd_soc_component_get_dapm(component);
+
+	ret = snd_soc_add_component_controls(component, msm_int_snd_controls,
+				ARRAY_SIZE(msm_int_snd_controls));
+	if (ret < 0) {
+		pr_err("%s: add_component_controls failed: %d\n",
+			__func__, ret);
+		return ret;
+	}
+	ret = snd_soc_add_component_controls(component, msm_common_snd_controls,
+				ARRAY_SIZE(msm_common_snd_controls));
+	if (ret < 0) {
+		pr_err("%s: add common snd controls failed: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets,
+				ARRAY_SIZE(msm_int_dapm_widgets));
+
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic6");
+	snd_soc_dapm_ignore_suspend(dapm, "Digital Mic7");
+
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic1");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic2");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic3");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
+	snd_soc_dapm_ignore_suspend(dapm, "Analog Mic5");
+
+
+	snd_soc_dapm_sync(dapm);
+
+	card = rtd->card->snd_card;
+	if (!pdata->codec_root) {
+		entry = msm_snd_info_create_subdir(card->module, "codecs",
+						 card->proc_root);
+		if (!entry) {
+			pr_debug("%s: Cannot create codecs module entry\n",
+				 __func__);
+			ret = 0;
+			goto err;
+		}
+		pdata->codec_root = entry;
+	}
+	bolero_info_create_codec_entry(pdata->codec_root, component);
+	bolero_register_wake_irq(component, false);
+	codec_reg_done = true;
+
+err:
+	return ret;
+}
+
+static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *bolero_component = NULL;
+	struct snd_soc_component *component = NULL;
+	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;
+
+	pdata = snd_soc_card_get_drvdata(rtd->card);
+	if(!pdata)
+		return -EINVAL;
+
+	bolero_component = snd_soc_rtdcom_lookup(rtd, "bolero_codec");
+	if (!bolero_component) {
+		pr_err("%s: could not find component for bolero_codec\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	if (pdata->wcd_disabled) {
+		bolero_set_port_map(bolero_component,
+			 ARRAY_SIZE(sm_port_map), sm_port_map);
+		return 0;
+	}
+
+	component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME);
+	if (!component) {
+		component = snd_soc_rtdcom_lookup(rtd, WCD937X_DRV_NAME);
+	}
+	if (!component) {
+		pr_err("%s component is NULL\n", __func__);
+		return -EINVAL;
+	}
+	dapm = snd_soc_component_get_dapm(component);
+	card = component->card->snd_card;
+
+	snd_soc_dapm_ignore_suspend(dapm, "EAR");
+	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, "AMIC1");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
+	snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
+	snd_soc_dapm_sync(dapm);
+
+	if (!pdata->codec_root) {
+		entry = msm_snd_info_create_subdir(card->module, "codecs",
+						 card->proc_root);
+		if (!entry) {
+			dev_dbg(component->dev, "%s: Cannot create codecs module entry\n",
+				 __func__);
+			ret = 0;
+			goto mbhc_cfg_cal;
+		}
+		pdata->codec_root = entry;
+	}
+
+	if (!strncmp(component->driver->name, WCD937X_DRV_NAME, 13)) {
+		wcd937x_info_create_codec_entry(pdata->codec_root, component);
+		ret = snd_soc_add_component_controls(component,
+				msm_int_wcd937x_snd_controls,
+				ARRAY_SIZE(msm_int_wcd937x_snd_controls));
+		bolero_set_port_map(bolero_component,
+			ARRAY_SIZE(sm_port_map_wcd937x), sm_port_map_wcd937x);
+	} else if (!strncmp(component->driver->name, WCD938X_DRV_NAME, 13)) {
+		wcd938x_info_create_codec_entry(pdata->codec_root, component);
+
+		codec_variant = wcd938x_get_codec_variant(component);
+		dev_dbg(component->dev, "%s: variant %d\n",
+			 __func__, codec_variant);
+		if (codec_variant == WCD9380)
+			ret = snd_soc_add_component_controls(component,
+				msm_int_wcd9380_snd_controls,
+				ARRAY_SIZE(msm_int_wcd9380_snd_controls));
+		else if (codec_variant == WCD9385)
+			ret = snd_soc_add_component_controls(component,
+				msm_int_wcd9385_snd_controls,
+				ARRAY_SIZE(msm_int_wcd9385_snd_controls));
+		bolero_set_port_map(bolero_component, ARRAY_SIZE(sm_port_map),
+				 sm_port_map);
+	} else {
+		bolero_set_port_map(bolero_component, ARRAY_SIZE(sm_port_map),
+				 sm_port_map);
+	}
+
+	if (ret < 0) {
+		dev_err(component->dev,
+			 "%s: add codec specific snd controls failed: %d\n",
+			__func__, ret);
+		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)
+{
+	int count = 0;
+	u32 mi2s_master_slave[MI2S_MAX];
+	int ret = 0;
+
+	for (count = 0; count < MI2S_MAX; count++) {
+		mutex_init(&mi2s_intf_conf[count].lock);
+		mi2s_intf_conf[count].ref_cnt = 0;
+	}
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+			"qcom,msm-mi2s-master",
+			mi2s_master_slave, MI2S_MAX);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-master in DT node\n",
+			__func__);
+	} else {
+		for (count = 0; count < MI2S_MAX; count++) {
+			mi2s_intf_conf[count].msm_is_mi2s_master =
+				mi2s_master_slave[count];
+		}
+	}
+}
+
+static void msm_i2s_auxpcm_deinit(void)
+{
+	int count = 0;
+
+	for (count = 0; count < MI2S_MAX; count++) {
+		mutex_destroy(&mi2s_intf_conf[count].lock);
+		mi2s_intf_conf[count].ref_cnt = 0;
+		mi2s_intf_conf[count].msm_is_mi2s_master = 0;
+	}
+}
+
+static int holi_ssr_enable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+	int ret = 0;
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	if (!strcmp(card->name, "holi-stub-snd-card")) {
+		/* TODO */
+		dev_dbg(dev, "%s: TODO \n", __func__);
+	}
+
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+	snd_soc_card_change_online_state(card, 1);
+#endif /* CONFIG_AUDIO_QGKI */
+	dev_dbg(dev, "%s: setting snd_card to ONLINE\n", __func__);
+
+err:
+	return ret;
+}
+
+static void holi_ssr_disable(struct device *dev, void *data)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	if (!card) {
+		dev_err(dev, "%s: card is NULL\n", __func__);
+		return;
+	}
+
+	dev_dbg(dev, "%s: setting snd_card to OFFLINE\n", __func__);
+#if IS_ENABLED(CONFIG_AUDIO_QGKI)
+	snd_soc_card_change_online_state(card, 0);
+#endif /* CONFIG_AUDIO_QGKI */
+
+	if (!strcmp(card->name, "holi-stub-snd-card")) {
+		/* TODO */
+		dev_dbg(dev, "%s: TODO \n", __func__);
+	}
+}
+
+static const struct snd_event_ops holi_ssr_ops = {
+	.enable = holi_ssr_enable,
+	.disable = holi_ssr_disable,
+};
+
+static int msm_audio_ssr_compare(struct device *dev, void *data)
+{
+	struct device_node *node = data;
+
+	dev_dbg(dev, "%s: dev->of_node = 0x%p, node = 0x%p\n",
+		__func__, dev->of_node, node);
+	return (dev->of_node && dev->of_node == node);
+}
+
+static int msm_audio_ssr_register(struct device *dev)
+{
+	struct device_node *np = dev->of_node;
+	struct snd_event_clients *ssr_clients = NULL;
+	struct device_node *node = NULL;
+	int ret = 0;
+	int i = 0;
+
+	for (i = 0; ; i++) {
+		node = of_parse_phandle(np, "qcom,msm_audio_ssr_devs", i);
+		if (!node)
+			break;
+		snd_event_mstr_add_client(&ssr_clients,
+					msm_audio_ssr_compare, node);
+	}
+
+	ret = snd_event_master_register(dev, &holi_ssr_ops,
+					ssr_clients, NULL);
+	if (!ret)
+		snd_event_notify(dev, SND_EVENT_UP);
+
+	return ret;
+}
+
+static int msm_asoc_machine_probe(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = NULL;
+	struct msm_asoc_mach_data *pdata = NULL;
+	const char *mbhc_audio_jack_type = NULL;
+	int ret = 0;
+	uint index = 0;
+	struct clk *lpass_audio_hw_vote = NULL;
+
+	if (!pdev->dev.of_node) {
+		dev_err(&pdev->dev,
+		 "%s: No platform supplied from device tree\n", __func__);
+		return -EINVAL;
+	}
+
+	pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct msm_asoc_mach_data), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	of_property_read_u32(pdev->dev.of_node,
+				"qcom,wcd-disabled",
+				&pdata->wcd_disabled);
+
+	card = populate_snd_card_dailinks(&pdev->dev);
+	if (!card) {
+		dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	card->dev = &pdev->dev;
+	platform_set_drvdata(pdev, card);
+	snd_soc_card_set_drvdata(card, pdata);
+
+	ret = snd_soc_of_parse_card_name(card, "qcom,model");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: parse card name failed, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+	if (ret) {
+		dev_err(&pdev->dev, "%s: parse audio routing failed, err:%d\n",
+			__func__, ret);
+		goto err;
+	}
+
+	ret = msm_populate_dai_link_component_of_node(card);
+	if (ret) {
+		ret = -EPROBE_DEFER;
+		goto err;
+	}
+
+	ret = devm_snd_soc_register_card(&pdev->dev, card);
+	if (ret == -EPROBE_DEFER) {
+		if (codec_reg_done)
+			ret = -EINVAL;
+		goto err;
+	} else if (ret) {
+		dev_err(&pdev->dev, "%s: snd_soc_register_card failed (%d)\n",
+			__func__, ret);
+		goto err;
+	}
+	dev_info(&pdev->dev, "%s: Sound card %s registered\n",
+		 __func__, card->name);
+
+	pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
+						"qcom,hph-en1-gpio", 0);
+	if (!pdata->hph_en1_gpio_p) {
+		dev_dbg(&pdev->dev, "%s: property %s not detected in node %s\n",
+			__func__, "qcom,hph-en1-gpio",
+			pdev->dev.of_node->full_name);
+	}
+
+	pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
+						"qcom,hph-en0-gpio", 0);
+	if (!pdata->hph_en0_gpio_p) {
+		dev_dbg(&pdev->dev, "%s: property %s not detected in node %s\n",
+			__func__, "qcom,hph-en0-gpio",
+			pdev->dev.of_node->full_name);
+	}
+
+	ret = of_property_read_string(pdev->dev.of_node,
+		"qcom,mbhc-audio-jack-type", &mbhc_audio_jack_type);
+	if (ret) {
+		dev_dbg(&pdev->dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,mbhc-audio-jack-type",
+			pdev->dev.of_node->full_name);
+		dev_dbg(&pdev->dev, "Jack type properties set to default\n");
+	} else {
+		if (!strcmp(mbhc_audio_jack_type, "4-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
+			dev_dbg(&pdev->dev, "This hardware has 4 pole jack");
+		} else if (!strcmp(mbhc_audio_jack_type, "5-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
+			dev_dbg(&pdev->dev, "This hardware has 5 pole jack");
+		} else if (!strcmp(mbhc_audio_jack_type, "6-pole-jack")) {
+			wcd_mbhc_cfg.enable_anc_mic_detect = true;
+			dev_dbg(&pdev->dev, "This hardware has 6 pole jack");
+		} else {
+			wcd_mbhc_cfg.enable_anc_mic_detect = false;
+			dev_dbg(&pdev->dev, "Unknown value, set to default\n");
+		}
+	}
+	/*
+	 * Parse US-Euro gpio info from DT. Report no error if us-euro
+	 * entry is not found in DT file as some targets do not support
+	 * US-Euro detection
+	 */
+	pdata->us_euro_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					"qcom,us-euro-gpios", 0);
+	if (!pdata->us_euro_gpio_p) {
+		dev_dbg(&pdev->dev, "property %s not detected in node %s",
+			"qcom,us-euro-gpios", pdev->dev.of_node->full_name);
+	} else {
+		dev_dbg(&pdev->dev, "%s detected\n",
+			"qcom,us-euro-gpios");
+		wcd_mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
+	}
+
+	if (wcd_mbhc_cfg.enable_usbc_analog)
+		wcd_mbhc_cfg.swap_gnd_mic = msm_usbc_swap_gnd_mic;
+
+	pdata->fsa_handle = of_parse_phandle(pdev->dev.of_node,
+					"fsa4480-i2c-handle", 0);
+	if (!pdata->fsa_handle)
+		dev_dbg(&pdev->dev, "property %s not detected in node %s\n",
+			"fsa4480-i2c-handle", pdev->dev.of_node->full_name);
+
+	msm_i2s_auxpcm_init(pdev);
+	pdata->dmic01_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic01-gpios",
+					       0);
+	pdata->dmic23_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic23-gpios",
+					       0);
+	pdata->dmic45_gpio_p = of_parse_phandle(pdev->dev.of_node,
+					      "qcom,cdc-dmic45-gpios",
+					       0);
+	if (pdata->dmic01_gpio_p)
+		msm_cdc_pinctrl_set_wakeup_capable(pdata->dmic01_gpio_p, false);
+	if (pdata->dmic23_gpio_p)
+		msm_cdc_pinctrl_set_wakeup_capable(pdata->dmic23_gpio_p, false);
+	if (pdata->dmic45_gpio_p)
+		msm_cdc_pinctrl_set_wakeup_capable(pdata->dmic45_gpio_p, false);
+
+	pdata->mi2s_gpio_p[PRIM_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,pri-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[SEC_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,sec-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[TERT_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,tert-mi2s-gpios", 0);
+	pdata->mi2s_gpio_p[QUAT_MI2S] = of_parse_phandle(pdev->dev.of_node,
+					"qcom,quat-mi2s-gpios", 0);
+	for (index = PRIM_MI2S; index < MI2S_MAX; index++)
+		atomic_set(&(pdata->mi2s_gpio_ref_count[index]), 0);
+
+	/* Register LPASS audio hw vote */
+	lpass_audio_hw_vote = devm_clk_get(&pdev->dev, "lpass_audio_hw_vote");
+	if (IS_ERR(lpass_audio_hw_vote)) {
+		ret = PTR_ERR(lpass_audio_hw_vote);
+		dev_dbg(&pdev->dev, "%s: clk get %s failed %d\n",
+			__func__, "lpass_audio_hw_vote", ret);
+		lpass_audio_hw_vote = NULL;
+		ret = 0;
+	}
+	pdata->lpass_audio_hw_vote = lpass_audio_hw_vote;
+	pdata->core_audio_vote_count = 0;
+
+	ret = msm_audio_ssr_register(&pdev->dev);
+	if (ret)
+		pr_err("%s: Registration with SND event FWK failed ret = %d\n",
+			__func__, ret);
+
+	is_initial_boot = true;
+
+	/* Add QoS request for audio tasks */
+	msm_audio_add_qos_request();
+
+	return 0;
+err:
+	devm_kfree(&pdev->dev, pdata);
+	return ret;
+}
+
+static int msm_asoc_machine_remove(struct platform_device *pdev)
+{
+	struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+	snd_event_master_deregister(&pdev->dev);
+	snd_soc_unregister_card(card);
+	msm_i2s_auxpcm_deinit();
+	msm_audio_remove_qos_request();
+
+	return 0;
+}
+
+static struct platform_driver holi_asoc_machine_driver = {
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = holi_asoc_machine_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = msm_asoc_machine_probe,
+	.remove = msm_asoc_machine_remove,
+};
+module_platform_driver(holi_asoc_machine_driver);
+
+MODULE_SOFTDEP("pre: bt_fm_slim");
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, holi_asoc_machine_of_match);

+ 24 - 2
asoc/lahaina-port-config.h

@@ -46,13 +46,35 @@ static struct port_params rx_frame_params_default[SWR_MSTR_PORT_LEN] = {
 
 /* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */
 static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX2 */
+	{7,  5,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+/* TX UC1: TX1: 1ch, TX2: 2chs, TX3: 1ch(MBHC) */
+static struct port_params tx_frame_params_shima[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX2 */
+	{7,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+/* 4.8 MHz clock */
+static struct port_params tx_frame_params_4p8MHz[SWR_MSTR_PORT_LEN] = {
 	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
-	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
-	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX2 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
 };
 
 static struct swr_mstr_port_map sm_port_map[] = {
 	{TX_MACRO, SWR_UC0, tx_frame_params_default},
+	{TX_MACRO, SWR_UC1, tx_frame_params_4p8MHz},
+	{RX_MACRO, SWR_UC0, rx_frame_params_default},
+	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
+	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},
+};
+
+static struct swr_mstr_port_map sm_port_map_shima[] = {
+	{TX_MACRO, SWR_UC0, tx_frame_params_shima},
 	{RX_MACRO, SWR_UC0, rx_frame_params_default},
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},

+ 2 - 1
asoc/msm_dailink.h

@@ -5,6 +5,7 @@
 
 #include <sound/soc.h>
 
+
 SND_SOC_DAILINK_DEFS(usb_audio_rx,
 	DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
 	DAILINK_COMP_ARRAY(COMP_DUMMY()),
@@ -145,4 +146,4 @@ SND_SOC_DAILINK_DEFS(proxy_tx,
 SND_SOC_DAILINK_DEFS(proxy_rx,
 	DAILINK_COMP_ARRAY(COMP_CPU("snd-soc-dummy-dai")),
 	DAILINK_COMP_ARRAY(COMP_DUMMY()),
-	DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("snd-soc-dummy")));

+ 471 - 0
asoc/msm_holi_dailink.h

@@ -0,0 +1,471 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#include <sound/soc.h>
+
+/* FE dai-links */
+SND_SOC_DAILINK_DEFS(multimedia1,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.0")));
+
+SND_SOC_DAILINK_DEFS(multimedia2,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.0")));
+
+SND_SOC_DAILINK_DEFS(voicemmode1,
+	DAILINK_COMP_ARRAY(COMP_CPU("VoiceMMode1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-voice")));
+
+SND_SOC_DAILINK_DEFS(msmvoip,
+	DAILINK_COMP_ARRAY(COMP_CPU("VoIP")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-voip-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia3,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia3")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.2")));
+
+SND_SOC_DAILINK_DEFS(afepcm_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.241")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-afe")));
+
+SND_SOC_DAILINK_DEFS(afepcm_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.240")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-afe")));
+
+SND_SOC_DAILINK_DEFS(multimedia4,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia4")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(auxpcm_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("AUXPCM_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(multimedia5,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia5")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.1")));
+
+SND_SOC_DAILINK_DEFS(listen1,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(multimedia7,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia7")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia10,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia10")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.1")));
+
+SND_SOC_DAILINK_DEFS(multimedia8,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia8")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp-noirq")));
+
+SND_SOC_DAILINK_DEFS(hdmi_rx_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("HDMI_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(voicemmode2,
+	DAILINK_COMP_ARRAY(COMP_CPU("VoiceMMode2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-voice")));
+
+SND_SOC_DAILINK_DEFS(listen2,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(listen3,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM3")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(listen4,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM4")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(listen5,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM5")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(listen6,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM6")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(listen7,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM7")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(listen8,
+	DAILINK_COMP_ARRAY(COMP_CPU("LSM8")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-lsm-client")));
+
+SND_SOC_DAILINK_DEFS(multimedia9,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia9")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.0")));
+
+SND_SOC_DAILINK_DEFS(multimedia11,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia11")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia12,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia12")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia13,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia13")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia14,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia14")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia15,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia15")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(multimedia16,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia16")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp-noirq")));
+
+SND_SOC_DAILINK_DEFS(cdcdma_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("CDC_DMA_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(tx3_cdcdma_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("TX3_CDC_DMA_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(tert_mi2s_tx_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("TERT_MI2S_TX_HOSTLESS")),
+	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")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-loopback")));
+
+SND_SOC_DAILINK_DEFS(usbaudio_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("USBAUDIO_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(slimbus7_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("SLIMBUS7_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(multimedia17,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia17")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-compress-dsp")));
+
+SND_SOC_DAILINK_DEFS(slimbus8_hostless,
+	DAILINK_COMP_ARRAY(COMP_CPU("SLIMBUS8_HOSTLESS")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(tx_cdcdma5_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45115")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "tx_macro_tx3"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-hostless")));
+
+SND_SOC_DAILINK_DEFS(multimedia31,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia31")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.0")));
+
+SND_SOC_DAILINK_DEFS(multimedia32,
+	DAILINK_COMP_ARRAY(COMP_CPU("MultiMedia32")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-dsp.0")));
+
+SND_SOC_DAILINK_DEFS(afepcm_tx1,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.242")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-afe")));
+
+/* BE dai-links */
+SND_SOC_DAILINK_DEFS(afe_pcm_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.224")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(afe_pcm_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.225")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(incall_record_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.32772")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(incall_record_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.32771")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(voice_playback_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.32773")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(voice2_playback_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.32770")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(usb_audio_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.28672")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(usb_audio_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.28673")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(pri_tdm_rx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36864")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(pri_tdm_tx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36865")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(sec_tdm_rx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36880")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(sec_tdm_tx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36881")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tert_tdm_rx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36896")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tert_tdm_tx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36897")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(quat_tdm_rx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36912")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(quat_tdm_tx_0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-tdm.36913")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(slimbus_7_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.16398")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("btfmslim_slave",
+			"btfm_bt_sco_a2dp_slim_rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(slimbus_7_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.16399")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("btfmslim_slave",
+			"btfm_bt_sco_slim_tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(slimbus_8_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.16401")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("btfmslim_slave",
+			"btfm_fm_slim_tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(pri_mi2s_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.0")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(pri_mi2s_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.0")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(sec_mi2s_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(sec_mi2s_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tert_mi2s_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tert_mi2s_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(quat_mi2s_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.3")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(quat_mi2s_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-mi2s.3")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(auxpcm_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(auxpcm_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.1")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(sec_auxpcm_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(sec_auxpcm_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.2")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tert_auxpcm_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.3")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tert_auxpcm_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.3")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(quat_auxpcm_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.4")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(quat_auxpcm_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-auxpcm.4")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(rx_dma_rx0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45104")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx1"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc"),
+			   COMP_CODEC("wcd937x_codec", "wcd937x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(rx_dma_rx1,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45106")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx2"),
+			   COMP_CODEC("wsa-codec0", "wsa_rx0"),
+			   COMP_CODEC("wsa-codec1", "wsa_rx1"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc"),
+			   COMP_CODEC("wcd937x_codec", "wcd937x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(rx_dma_rx2,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45108")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx3"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc"),
+			   COMP_CODEC("wcd937x_codec", "wcd937x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(rx_dma_rx3,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45110")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "rx_macro_rx4"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc"),
+			   COMP_CODEC("wcd937x_codec", "wcd937x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tx_dma_tx3,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45111")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "tx_macro_tx1"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc"),
+			   COMP_CODEC("wcd937x_codec", "wcd937x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(tx_dma_tx4,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45113")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "tx_macro_tx2"),
+			   COMP_CODEC("wcd938x_codec", "wcd938x_cdc"),
+			   COMP_CODEC("wcd937x_codec", "wcd937x_cdc")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(va_dma_tx0,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45089")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "va_macro_tx1")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(va_dma_tx1,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45091")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "va_macro_tx2")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(va_dma_tx2,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-cdc-dma-dev.45093")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("bolero_codec", "va_macro_tx3")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(afe_loopback_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.24577")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(proxy_tx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.8195")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-tx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));
+
+SND_SOC_DAILINK_DEFS(proxy_rx,
+	DAILINK_COMP_ARRAY(COMP_CPU("msm-dai-q6-dev.8194")),
+	DAILINK_COMP_ARRAY(COMP_CODEC("msm-stub-codec.1", "msm-stub-rx")),
+	DAILINK_COMP_ARRAY(COMP_PLATFORM("msm-pcm-routing")));

+ 34 - 0
config/holiauto.conf

@@ -0,0 +1,34 @@
+export CONFIG_PINCTRL_LPI=m
+export CONFIG_AUDIO_EXT_CLK=m
+export CONFIG_SND_SOC_WCD9XXX_V2=m
+export CONFIG_SND_SOC_WCD_MBHC=m
+export CONFIG_WCD9XXX_CODEC_CORE_V2=m
+export CONFIG_MSM_CDC_PINCTRL=m
+export CONFIG_MSM_QDSP6V2_CODECS=m
+export CONFIG_MSM_QDSP6_APRV2_RPMSG=m
+export CONFIG_MSM_ADSP_LOADER=m
+export CONFIG_REGMAP_SWR=m
+export CONFIG_MSM_QDSP6_SSR=m
+export CONFIG_MSM_QDSP6_PDR=m
+export CONFIG_MSM_QDSP6_NOTIFIER=m
+export CONFIG_SND_SOC_MSM_QDSP6V2_INTF=m
+export CONFIG_SOUNDWIRE=m
+export CONFIG_SOUNDWIRE_MSTR_CTRL=m
+export CONFIG_SND_SOC_QDSP6V2=m
+export CONFIG_SND_SOC_WCD_MBHC_ADC=m
+export CONFIG_QTI_PP=m
+export CONFIG_SND_HWDEP_ROUTING=m
+export CONFIG_SND_SOC_MSM_STUB=m
+export CONFIG_SND_SOC_BOLERO=m
+export CONFIG_VA_MACRO=m
+export CONFIG_RX_MACRO=m
+export CONFIG_TX_MACRO=m
+export CONFIG_SND_SOC_WCD_IRQ=m
+export CONFIG_SND_SOC_WCD938X=m
+export CONFIG_SND_SOC_WCD938X_SLAVE=m
+export CONFIG_SND_SOC_WCD937X=m
+export CONFIG_SND_SOC_WCD937X_SLAVE=m
+export CONFIG_SND_SOC_WSA881X_ANALOG=m
+export CONFIG_SND_SOC_HOLI=m
+export CONFIG_SND_EVENT=m
+export CONFIG_DIGITAL_CDC_RSC_MGR=m

+ 38 - 0
config/holiautoconf.h

@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+#define CONFIG_PINCTRL_LPI 1
+#define CONFIG_AUDIO_EXT_CLK 1
+#define CONFIG_SND_SOC_WCD9XXX_V2 1
+#define CONFIG_SND_SOC_WCD_MBHC 1
+#define CONFIG_WCD9XXX_CODEC_CORE_V2 1
+#define CONFIG_MSM_CDC_PINCTRL 1
+#define CONFIG_MSM_QDSP6V2_CODECS 1
+#define CONFIG_MSM_QDSP6_APRV2_RPMSG 1
+#define CONFIG_SND_SOC_MSM_QDSP6V2_INTF 1
+#define CONFIG_MSM_ADSP_LOADER 1
+#define CONFIG_REGMAP_SWR 1
+#define CONFIG_MSM_QDSP6_SSR 1
+#define CONFIG_MSM_QDSP6_PDR 1
+#define CONFIG_MSM_QDSP6_NOTIFIER 1
+#define CONFIG_SOUNDWIRE 1
+#define CONFIG_SOUNDWIRE_MSTR_CTRL 1
+#define CONFIG_SND_SOC_WCD_MBHC_ADC 1
+#define CONFIG_SND_SOC_QDSP6V2 1
+#define CONFIG_QTI_PP 1
+#define CONFIG_SND_HWDEP_ROUTING 1
+#define CONFIG_SND_SOC_MSM_STUB 1
+#define CONFIG_SND_SOC_BOLERO 1
+#define CONFIG_VA_MACRO 1
+#define CONFIG_RX_MACRO 1
+#define CONFIG_TX_MACRO 1
+#define CONFIG_SND_SOC_WCD_IRQ 1
+#define CONFIG_SND_SOC_WCD938X 1
+#define CONFIG_SND_SOC_WCD938X_SLAVE 1
+#define CONFIG_SND_SOC_WCD937X 1
+#define CONFIG_SND_SOC_WCD937X_SLAVE 1
+#define CONFIG_SND_SOC_WSA881X_ANALOG 1
+#define CONFIG_SND_SOC_HOLI 1
+#define CONFIG_SND_EVENT 1
+#define CONFIG_DIGITAL_CDC_RSC_MGR 1

+ 1 - 1
dsp/adsp-loader.c

@@ -404,7 +404,7 @@ static int adsp_loader_probe(struct platform_device *pdev)
 					  &adsp_fuse_not_supported);
 		if (ret) {
 			dev_dbg(&pdev->dev,
-				"%s: adsp_fuse_not_supported prop not found",
+				"%s: adsp_fuse_not_supported prop not found %d\n",
 				__func__, ret);
 			goto wqueue;
 		}

+ 104 - 8
dsp/msm_audio_ion.c

@@ -41,6 +41,7 @@
 struct msm_audio_ion_private {
 	bool smmu_enabled;
 	struct device *cb_dev;
+	struct device *cb_cma_dev;
 	u8 device_status;
 	struct list_head alloc_list;
 	struct mutex list_mutex;
@@ -127,7 +128,8 @@ exit:
 }
 
 static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
-				 dma_addr_t *addr, size_t *len, bool is_iova)
+				 dma_addr_t *addr, size_t *len, bool is_iova,
+				 bool cma_mem)
 {
 
 	struct msm_audio_alloc_data *alloc_data;
@@ -136,7 +138,10 @@ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
 	int rc = 0;
 	void *vaddr = NULL;
 
-	cb_dev = msm_audio_ion_data.cb_dev;
+	if (cma_mem)
+		cb_dev = msm_audio_ion_data.cb_cma_dev;
+	else
+		cb_dev = msm_audio_ion_data.cb_dev;
 
 	/* Data required per buffer mapping */
 	alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL);
@@ -213,14 +218,18 @@ free_alloc_data:
 	return rc;
 }
 
-static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
+static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf, bool cma_mem)
 {
 	int rc = 0;
 	struct msm_audio_alloc_data *alloc_data = NULL;
 	struct list_head *ptr, *next;
-	struct device *cb_dev = msm_audio_ion_data.cb_dev;
+	struct device *cb_dev;
 	bool found = false;
 
+	if (cma_mem)
+		cb_dev = msm_audio_ion_data.cb_cma_dev;
+	else
+		cb_dev = msm_audio_ion_data.cb_dev;
 	/*
 	 * Though list_for_each_safe is delete safe, lock
 	 * should be explicitly acquired to avoid race condition
@@ -266,7 +275,7 @@ static int msm_audio_ion_get_phys(struct dma_buf *dma_buf,
 {
 	int rc = 0;
 
-	rc = msm_audio_dma_buf_map(dma_buf, addr, len, is_iova);
+	rc = msm_audio_dma_buf_map(dma_buf, addr, len, is_iova, false);
 	if (rc) {
 		pr_err("%s: failed to map DMA buf, err = %d\n",
 			__func__, rc);
@@ -364,7 +373,7 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
 	if (IS_ERR_OR_NULL(*vaddr)) {
 		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
 		rc = -ENOMEM;
-		msm_audio_dma_buf_unmap(dma_buf);
+		msm_audio_dma_buf_unmap(dma_buf, false);
 		goto err;
 	}
 
@@ -606,7 +615,7 @@ void msm_audio_get_handle(int fd, void **handle)
  * @bufsz: buffer size
  * @paddr: Physical address to be assigned with allocated region
  * @plen: length of allocated region to be assigned
- * vaddr: virtual address to be assigned
+ * @vaddr: virtual address to be assigned
  *
  * Returns 0 on success or error on failure
  */
@@ -662,6 +671,67 @@ err:
 }
 EXPORT_SYMBOL(msm_audio_ion_import);
 
+/**
+ * msm_audio_ion_import_cma-
+ *        Import ION buffer with given file descriptor
+ *
+ * @dma_buf: dma_buf for the ION memory
+ * @fd: file descriptor for the ION memory
+ * @ionflag: flags associated with ION buffer
+ * @bufsz: buffer size
+ * @paddr: Physical address to be assigned with allocated region
+ * @plen: length of allocated region to be assigned
+ * vaddr: virtual address to be assigned
+ *
+ * Returns 0 on success or error on failure
+ */
+int msm_audio_ion_import_cma(struct dma_buf **dma_buf, int fd,
+			unsigned long *ionflag, size_t bufsz,
+			dma_addr_t *paddr, size_t *plen, void **vaddr)
+{
+	int rc = 0;
+
+	if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) {
+		pr_debug("%s: probe is not done, deferred\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	if (!dma_buf || !paddr || !vaddr || !plen ||
+	    !msm_audio_ion_data.cb_cma_dev) {
+		pr_err("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* bufsz should be 0 and fd shouldn't be 0 as of now */
+	*dma_buf = dma_buf_get(fd);
+	pr_debug("%s: dma_buf =%pK, fd=%d\n", __func__, *dma_buf, fd);
+	if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
+		pr_err("%s: dma_buf_get failed\n", __func__);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	if (ionflag != NULL) {
+		rc = dma_buf_get_flags(*dma_buf, ionflag);
+		if (rc) {
+			pr_err("%s: could not get flags for the dma_buf\n",
+				__func__);
+			goto err_ion_flag;
+		}
+	}
+
+	msm_audio_dma_buf_map(*dma_buf, paddr, plen, true, true);
+
+	return 0;
+
+err_ion_flag:
+	dma_buf_put(*dma_buf);
+err:
+	*dma_buf = NULL;
+	return rc;
+}
+EXPORT_SYMBOL(msm_audio_ion_import_cma);
+
 /**
  * msm_audio_ion_free -
  *        fress ION memory for given client and handle
@@ -683,7 +753,7 @@ int msm_audio_ion_free(struct dma_buf *dma_buf)
 	if (ret)
 		return ret;
 
-	msm_audio_dma_buf_unmap(dma_buf);
+	msm_audio_dma_buf_unmap(dma_buf, false);
 
 	return 0;
 }
@@ -717,6 +787,27 @@ void msm_audio_ion_crash_handler(void)
 }
 EXPORT_SYMBOL(msm_audio_ion_crash_handler);
 
+/**
+ * msm_audio_ion_free_cma -
+ *        fress ION memory for given client and handle
+ *
+ * @dma_buf: dma_buf for the ION memory
+ *
+ * Returns 0 on success or error on failure
+ */
+int msm_audio_ion_free_cma(struct dma_buf *dma_buf)
+{
+	if (!dma_buf) {
+		pr_err("%s: dma_buf invalid\n", __func__);
+		return -EINVAL;
+	}
+
+	msm_audio_dma_buf_unmap(dma_buf, true);
+
+	return 0;
+}
+EXPORT_SYMBOL(msm_audio_ion_free_cma);
+
 /**
  * msm_audio_ion_mmap -
  *       Audio ION memory map
@@ -954,6 +1045,7 @@ static int msm_audio_smmu_init(struct device *dev)
 
 static const struct of_device_id msm_audio_ion_dt_match[] = {
 	{ .compatible = "qcom,msm-audio-ion" },
+	{ .compatible = "qcom,msm-audio-ion-cma"},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
@@ -1047,6 +1139,10 @@ static int msm_audio_ion_probe(struct platform_device *pdev)
 					     msm_audio_ion_non_hyp);
 	msm_audio_ion_data.is_non_hypervisor = is_non_hypervisor_en;
 
+	if (of_device_is_compatible(dev->of_node, "qcom,msm-audio-ion-cma")) {
+		msm_audio_ion_data.cb_cma_dev = dev;
+		return 0;
+	}
 	smmu_enabled = of_property_read_bool(dev->of_node,
 					     msm_audio_ion_dt);
 	msm_audio_ion_data.smmu_enabled = smmu_enabled;

+ 5 - 0
include/asoc/msm-cdc-supply.h

@@ -69,5 +69,10 @@ extern int msm_cdc_init_supplies_v2(struct device *dev,
 int msm_cdc_init_wcd_supply(struct device_node *np, const char *name,
 			    struct cdc_wcd_supply *cdc_supply);
 int msm_cdc_enable_wcd_supply(struct cdc_wcd_supply *cdc_supply, bool enable);
+extern int msm_cdc_set_supply_min_voltage(struct device *dev,
+				struct regulator_bulk_data *supplies,
+				struct cdc_regulator *cdc_vreg,
+				int num_supplies, char *supply_name,
+				int vval_min, bool override_min_vol);
 
 #endif

+ 5 - 0
include/dsp/apr_audio-v2.h

@@ -5467,6 +5467,7 @@ struct afe_param_id_lpass_core_shared_clk_cfg {
 #define ADM_CMD_COPP_OPEN_TOPOLOGY_ID_DTS_HPX		0x10015002
 #define ADM_CMD_COPP_OPEN_TOPOLOGY_ID_AUDIOSPHERE	0x10028000
 #define VPM_TX_DM_FLUENCE_EF_COPP_TOPOLOGY		0x10000005
+#define AUDIO_RX_MONO_VOIP_COPP_TOPOLOGY		0x11000101
 
 /* Memory map regions command payload used by the
  * #ASM_CMD_SHARED_MEM_MAP_REGIONS ,#ADM_CMD_SHARED_MEM_MAP_REGIONS
@@ -11717,6 +11718,10 @@ struct avcs_fwk_ver_info {
 #define LSM_SESSION_CMD_SET_PARAMS			(0x00012A83)
 #define LSM_SESSION_CMD_SET_PARAMS_V2			(0x00012A8F)
 #define LSM_SESSION_CMD_SET_PARAMS_V3			(0x00012A92)
+#define LSM_SESSION_CMD_GET_PARAMS_V2			(0x00012A90)
+#define LSM_SESSION_CMDRSP_GET_PARAMS_V2		(0x00012A91)
+#define LSM_SESSION_CMD_GET_PARAMS_V3			(0x00012A93)
+#define LSM_SESSION_CMDRSP_GET_PARAMS_V3		(0x00012A94)
 #define LSM_SESSION_CMD_REGISTER_SOUND_MODEL		(0x00012A84)
 #define LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL		(0x00012A85)
 #define LSM_SESSION_CMD_START				(0x00012A86)

+ 1 - 0
include/dsp/audio_cal_utils.h

@@ -30,6 +30,7 @@ struct cal_block_data {
 	struct list_head	list;
 	struct cal_data		cal_data;
 	bool			cal_stale;
+	bool			cma_mem;
 	struct mem_map_data	map_data;
 	int32_t			buffer_number;
 };

+ 4 - 0
include/dsp/msm_audio_ion.h

@@ -34,6 +34,10 @@ int msm_audio_ion_import(struct dma_buf **dma_buf, int fd,
 			unsigned long *ionflag, size_t bufsz,
 			dma_addr_t *paddr, size_t *pa_len, void **vaddr);
 int msm_audio_ion_free(struct dma_buf *dma_buf);
+int msm_audio_ion_import_cma(struct dma_buf **dma_buf, int fd,
+			     unsigned long *ionflag, size_t bufsz,
+			     dma_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free_cma(struct dma_buf *dma_buf);
 int msm_audio_ion_mmap(struct audio_buffer *abuff, struct vm_area_struct *vma);
 int msm_audio_ion_cache_operations(struct audio_buffer *abuff, int cache_op);
 

+ 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

+ 27 - 2
include/uapi/audio/sound/lsm_params.h

@@ -36,7 +36,8 @@
 #define LSM_REG_MULTI_SND_MODEL (10)
 #define LSM_DEREG_MULTI_SND_MODEL (11)
 #define LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS (12)
-#define LSM_PARAMS_MAX (LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS + 1)
+#define LSM_GET_CUSTOM_PARAMS (13)
+#define LSM_PARAMS_MAX (LSM_GET_CUSTOM_PARAMS + 1)
 
 #define LSM_EVENT_NON_TIME_STAMP_MODE (0)
 #define LSM_EVENT_TIME_STAMP_MODE (1)
@@ -288,6 +289,29 @@ struct snd_lsm_input_hw_params {
 	__u16 num_channels;
 } __packed;
 
+/*
+ * Param get info  for each parameter type
+ * add "for SNDRV_LSM_GET_MODULE_PARAMS ioctl"
+ * Existing member variables:
+ * @module_id: Module to which parameter is to be set
+ * @instance_id: instance id of the param to which parameter is to be set
+ * @param_id: Parameter that is to be set
+ * @param_size: size of requested param
+ * @param_type: Parameter type as defined in values upto LSM_PARAMS_MAX
+ * @stage_idx: detection stage for which the param is applicable
+ * @payload: memory where requested param info will be populated
+ */
+struct lsm_params_get_info {
+	__u32 module_id;
+	__u16 instance_id;
+	__u16 reserved;
+	__u32 param_id;
+	__u32 param_size;
+	__u32 param_type;
+	__u16 stage_idx;
+	__u8 payload[0];
+} __packed;
+
 #define SNDRV_LSM_DEREG_SND_MODEL _IOW('U', 0x01, int)
 #define SNDRV_LSM_EVENT_STATUS	_IOW('U', 0x02, struct snd_lsm_event_status)
 #define SNDRV_LSM_ABORT_EVENT	_IOW('U', 0x03, int)
@@ -315,5 +339,6 @@ struct snd_lsm_input_hw_params {
 					struct snd_lsm_session_data_v2)
 #define SNDRV_LSM_SET_MODULE_PARAMS_V2 _IOW('U', 0x13, \
 					struct snd_lsm_module_params)
-
+#define SNDRV_LSM_GET_MODULE_PARAMS _IOWR('U', 0x14, \
+					struct lsm_params_get_info)
 #endif

+ 241 - 59
soc/swr-mstr-ctrl.c

@@ -26,6 +26,7 @@
 #include "swr-slave-registers.h"
 #include <dsp/digital-cdc-rsc-mgr.h>
 #include "swr-mstr-ctrl.h"
+#include "swr-slave-port-config.h"
 
 #define SWR_NUM_PORTS    4 /* TODO - Get this info from DT */
 
@@ -80,6 +81,8 @@
 #define SWRM_DP_PORT_CTRL_OFFSET2_SHFT    0x10
 #define SWRM_DP_PORT_CTRL_OFFSET1_SHFT    0x08
 
+#define SWR_OVERFLOW_RETRY_COUNT 30
+
 /* pm runtime auto suspend timer in msecs */
 static int auto_suspend_timer = 500;
 module_param(auto_suspend_timer, int, 0664);
@@ -108,6 +111,11 @@ enum {
 	LPASS_AUDIO_CORE,
 };
 
+enum {
+	SWRM_WR_CHECK_AVAIL,
+	SWRM_RD_CHECK_AVAIL,
+};
+
 #define TRUE 1
 #define FALSE 0
 
@@ -122,6 +130,32 @@ 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 u64 swrm_phy_dev[] = {
+	0,
+	0xd01170223,
+	0x858350223,
+	0x858350222,
+	0x858350221,
+	0x858350220,
+};
+
+static u8 swrm_get_device_id(struct swr_mstr_ctrl *swrm, u8 devnum)
+{
+	int i;
+
+	for (i = 1; i < (swrm->num_dev + 1); i++) {
+		if (swrm->logical_dev[devnum] == swrm_phy_dev[i])
+			break;
+	}
+
+	if (i == (swrm->num_dev + 1)) {
+		pr_info("%s: could not find the slave\n", __func__);
+		i = devnum;
+	}
+
+	return i;
+}
+
 static u8 swrm_get_clk_div(int mclk_freq, int bus_clk_freq)
 {
 	int clk_div = 0;
@@ -719,6 +753,9 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
 				(swrm->master_id == MASTER_ID_RX))
 		usecase = 1;
 
+	if (swrm->bus_clk == SWR_CLK_RATE_4P8MHZ)
+		usecase = 1;
+
 	params = swrm->port_param[usecase];
 	copy_port_tables(swrm, params);
 
@@ -790,6 +827,54 @@ static u32 swrm_get_packed_reg_val(u8 *cmd_id, u8 cmd_data,
 	return val;
 }
 
+static void swrm_wait_for_fifo_avail(struct swr_mstr_ctrl *swrm, int swrm_rd_wr)
+{
+	u32 fifo_outstanding_cmd;
+	u32 fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT;
+
+	if (swrm_rd_wr) {
+		/* Check for fifo underflow during read */
+		/* Check no of outstanding commands in fifo before read */
+		fifo_outstanding_cmd = ((swr_master_read(swrm,
+				SWRM_CMD_FIFO_STATUS) & 0x001F0000) >> 16);
+		if (fifo_outstanding_cmd == 0) {
+			while (fifo_retry_count) {
+				usleep_range(500, 510);
+				fifo_outstanding_cmd =
+					((swr_master_read (swrm,
+					  SWRM_CMD_FIFO_STATUS) & 0x001F0000)
+					  >> 16);
+				fifo_retry_count--;
+				if (fifo_outstanding_cmd > 0)
+					break;
+			}
+		}
+		if (fifo_outstanding_cmd == 0)
+			dev_err_ratelimited(swrm->dev,
+					"%s err read underflow\n", __func__);
+	} else {
+		/* Check for fifo overflow during write */
+		/* Check no of outstanding commands in fifo before write */
+		fifo_outstanding_cmd = ((swr_master_read(swrm,
+					 SWRM_CMD_FIFO_STATUS) & 0x00001F00)
+					 >> 8);
+		if (fifo_outstanding_cmd == swrm->wr_fifo_depth) {
+			while (fifo_retry_count) {
+				usleep_range(500, 510);
+				fifo_outstanding_cmd =
+				((swr_master_read(swrm, SWRM_CMD_FIFO_STATUS)
+				  & 0x00001F00) >> 8);
+				fifo_retry_count--;
+				if (fifo_outstanding_cmd < swrm->wr_fifo_depth)
+					break;
+			}
+		}
+		if (fifo_outstanding_cmd == swrm->wr_fifo_depth)
+			dev_err_ratelimited(swrm->dev,
+					"%s err write overflow\n", __func__);
+	}
+}
+
 static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
 				 u8 dev_addr, u8 cmd_id, u16 reg_addr,
 				 u32 len)
@@ -803,12 +888,19 @@ static int swrm_cmd_fifo_rd_cmd(struct swr_mstr_ctrl *swrm, int *cmd_data,
 		/* skip delay if read is handled in platform driver */
 		swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
 	} else {
+		/*
+		 * Check for outstanding cmd wrt. write fifo depth to avoid
+		 * overflow as read will also increase write fifo cnt.
+		 */
+		swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL);
 		/* wait for FIFO RD to complete to avoid overflow */
 		usleep_range(100, 105);
 		swr_master_write(swrm, SWRM_CMD_FIFO_RD_CMD, val);
 		/* wait for FIFO RD CMD complete to avoid overflow */
 		usleep_range(250, 255);
 	}
+	/* Check if slave responds properly after FIFO RD is complete */
+	swrm_wait_for_fifo_avail(swrm, SWRM_RD_CHECK_AVAIL);
 retry_read:
 	*cmd_data = swr_master_read(swrm, SWRM_CMD_FIFO_RD_FIFO);
 	dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x, rcmd_id: 0x%x, \
@@ -855,6 +947,11 @@ static int swrm_cmd_fifo_wr_cmd(struct swr_mstr_ctrl *swrm, u8 cmd_data,
 	dev_dbg(swrm->dev, "%s: reg: 0x%x, cmd_id: 0x%x,wcmd_id: 0x%x, \
 			dev_num: 0x%x, cmd_data: 0x%x\n", __func__,
 			reg_addr, cmd_id, swrm->wcmd_id,dev_addr, cmd_data);
+	/*
+	 * Check for outstanding cmd wrt. write fifo depth to avoid
+	 * overflow.
+	 */
+	swrm_wait_for_fifo_avail(swrm, SWRM_WR_CHECK_AVAIL);
 	swr_master_write(swrm, SWRM_CMD_FIFO_WR_CMD, val);
 	/*
 	 * wait for FIFO WR command to complete to avoid overflow
@@ -1102,9 +1199,9 @@ int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq)
 		if (bus_clk_freq <= SWR_CLK_RATE_0P6MHZ)
 			bus_clk_freq = SWR_CLK_RATE_0P6MHZ;
 		else if (bus_clk_freq <= SWR_CLK_RATE_1P2MHZ)
-			bus_clk_freq = SWR_CLK_RATE_1P2MHZ;
+			bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
 		else if (bus_clk_freq <= SWR_CLK_RATE_2P4MHZ)
-			bus_clk_freq = SWR_CLK_RATE_2P4MHZ;
+			bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
 		else if(bus_clk_freq <= SWR_CLK_RATE_4P8MHZ)
 			bus_clk_freq = SWR_CLK_RATE_4P8MHZ;
 		else if(bus_clk_freq <= SWR_CLK_RATE_9P6MHZ)
@@ -1235,26 +1332,91 @@ static void swrm_cleanup_disabled_port_reqs(struct swr_master *master)
 		}
 	}
 }
+
+static u8 swrm_get_controller_offset1(struct swr_mstr_ctrl *swrm,
+					u8* dev_offset, u8 off1)
+{
+	u8 offset1 = 0x0F;
+	int i = 0;
+
+	if (swrm->master_id == MASTER_ID_TX) {
+		for (i = 1; i < SWRM_NUM_AUTO_ENUM_SLAVES; i++) {
+			pr_debug("%s: dev offset: %d\n",
+				__func__, dev_offset[i]);
+			if (offset1 > dev_offset[i])
+				offset1 = dev_offset[i];
+		}
+	} else {
+		offset1 = off1;
+	}
+
+	pr_debug("%s: offset: %d\n", __func__, offset1);
+
+	return offset1;
+}
+
+static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
+					struct swrm_mports *mport,
+					struct swr_port_info *port_req)
+{
+	u32 port_id = 0;
+	u8 dev_num = 0;
+	struct port_params *pp_dev;
+	struct port_params *pp_port;
+
+	if ((swrm->master_id == MASTER_ID_TX) &&
+		((swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) ||
+		 (swrm->bus_clk == SWR_CLK_RATE_4P8MHZ))) {
+		dev_num = swrm_get_device_id(swrm, port_req->dev_num);
+		port_id = port_req->slave_port_id;
+		if (swrm->bus_clk == SWR_CLK_RATE_9P6MHZ)
+			pp_dev = swrdev_frame_params_9p6MHz[dev_num].pp;
+		else
+			pp_dev = swrdev_frame_params_4p8MHz[dev_num].pp;
+		pp_port = &pp_dev[port_id];
+		port_req->sinterval = pp_port->si;
+		port_req->offset1 = pp_port->off1;
+		port_req->offset2 = pp_port->off2;
+		port_req->hstart = pp_port->hstart;
+		port_req->hstop = pp_port->hstop;
+		port_req->word_length = pp_port->wd_len;
+		port_req->blk_pack_mode = pp_port->bp_mode;
+		port_req->blk_grp_count = pp_port->bgp_ctrl;
+		port_req->lane_ctrl = pp_port->lane_ctrl;
+	} else {
+		/* copy master port config to slave */
+		port_req->sinterval = mport->sinterval;
+		port_req->offset1 = mport->offset1;
+		port_req->offset2 = mport->offset2;
+		port_req->hstart = mport->hstart;
+		port_req->hstop = mport->hstop;
+		port_req->word_length = mport->word_length;
+		port_req->blk_pack_mode = mport->blk_pack_mode;
+		port_req->blk_grp_count = mport->blk_grp_count;
+		port_req->lane_ctrl = mport->lane_ctrl;
+	}
+}
+
 static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
 {
-	u32 value, slv_id;
+	u32 value = 0, slv_id = 0;
 	struct swr_port_info *port_req;
 	int i;
 	struct swrm_mports *mport;
-	struct swrm_mports *prev_mport = NULL;
 	u32 reg[SWRM_MAX_PORT_REG];
 	u32 val[SWRM_MAX_PORT_REG];
 	int len = 0;
-	u8 hparams;
-	u8 offset1 = 0;
-
+	u8 hparams = 0;
+	u32 controller_offset = 0;
 	struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
+	u8 dev_offset[SWRM_NUM_AUTO_ENUM_SLAVES];
 
 	if (!swrm) {
 		pr_err("%s: swrm is null\n", __func__);
 		return;
 	}
 
+	memset(dev_offset, 0xff, SWRM_NUM_AUTO_ENUM_SLAVES);
 	dev_dbg(swrm->dev, "%s: master num_port: %d\n", __func__,
 		master->num_port);
 
@@ -1268,6 +1430,12 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
 
 		list_for_each_entry(port_req, &mport->port_req_list, list) {
 			slv_id = port_req->slave_port_id;
+			/* Assumption: If different channels in the same port
+			 * on master is enabled for different slaves, then each
+			 * slave offset should be configured differently.
+			 */
+			swrm_get_device_frame_shape(swrm, mport, port_req);
+
 			reg[len] = SWRM_CMD_FIFO_WR_CMD;
 			val[len++] = SWR_REG_VAL_PACK(port_req->req_ch,
 					port_req->dev_num, 0x00,
@@ -1275,36 +1443,36 @@ 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(
+					port_req->sinterval & 0xFF,
 					port_req->dev_num, 0x00,
 					SWRS_DP_SAMPLE_CONTROL_1_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.
-			 */
-			if (prev_mport == mport)
-				offset1 += mport->offset1;
-			else {
-				offset1 = mport->offset1;
-				prev_mport = mport;
-			}
+
+			reg[len] = SWRM_CMD_FIFO_WR_CMD;
+			val[len++] = SWR_REG_VAL_PACK(
+					(port_req->sinterval >> 8)& 0xFF,
+					port_req->dev_num, 0x00,
+					SWRS_DP_SAMPLE_CONTROL_2_BANK(slv_id,
+								bank));
+
 			reg[len] = SWRM_CMD_FIFO_WR_CMD;
-			val[len++] = SWR_REG_VAL_PACK(offset1,
+			val[len++] = SWR_REG_VAL_PACK(port_req->offset1,
 					port_req->dev_num, 0x00,
 					SWRS_DP_OFFSET_CONTROL_1_BANK(slv_id,
 								bank));
 
-			if (mport->offset2 != SWR_INVALID_PARAM) {
+			if (port_req->offset2 != SWR_INVALID_PARAM) {
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
-				val[len++] = SWR_REG_VAL_PACK(mport->offset2,
+				val[len++] = SWR_REG_VAL_PACK(port_req->offset2,
 						port_req->dev_num, 0x00,
 						SWRS_DP_OFFSET_CONTROL_2_BANK(
 							slv_id, bank));
 			}
-			if (mport->hstart != SWR_INVALID_PARAM
-				&& mport->hstop != SWR_INVALID_PARAM) {
-				hparams = (mport->hstart << 4) | mport->hstop;
+			if (port_req->hstart != SWR_INVALID_PARAM
+				&& port_req->hstop != SWR_INVALID_PARAM) {
+				hparams = (port_req->hstart << 4) |
+						port_req->hstop;
 
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
 				val[len++] = SWR_REG_VAL_PACK(hparams,
@@ -1312,39 +1480,42 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
 						SWRS_DP_HCONTROL_BANK(slv_id,
 									bank));
 			}
-			if (mport->word_length != SWR_INVALID_PARAM) {
+			if (port_req->word_length != SWR_INVALID_PARAM) {
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
 				val[len++] =
-					SWR_REG_VAL_PACK(mport->word_length,
+					SWR_REG_VAL_PACK(port_req->word_length,
 						port_req->dev_num, 0x00,
 						SWRS_DP_BLOCK_CONTROL_1(slv_id));
 			}
-			if (mport->blk_pack_mode != SWR_INVALID_PARAM
+			if (port_req->blk_pack_mode != SWR_INVALID_PARAM
 					&& swrm->master_id != MASTER_ID_WSA) {
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
 				val[len++] =
-					SWR_REG_VAL_PACK(mport->blk_pack_mode,
+					SWR_REG_VAL_PACK(
+					port_req->blk_pack_mode,
 					port_req->dev_num, 0x00,
 					SWRS_DP_BLOCK_CONTROL_3_BANK(slv_id,
 									bank));
 			}
-			if (mport->blk_grp_count != SWR_INVALID_PARAM) {
+			if (port_req->blk_grp_count != SWR_INVALID_PARAM) {
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
 				val[len++] =
-					 SWR_REG_VAL_PACK(mport->blk_grp_count,
+					 SWR_REG_VAL_PACK(
+						port_req->blk_grp_count,
 						port_req->dev_num, 0x00,
-						SWRS_DP_BLOCK_CONTROL_2_BANK(slv_id,
-									bank));
+						SWRS_DP_BLOCK_CONTROL_2_BANK(
+								slv_id, bank));
 			}
-			if (mport->lane_ctrl != SWR_INVALID_PARAM) {
+			if (port_req->lane_ctrl != SWR_INVALID_PARAM) {
 				reg[len] = SWRM_CMD_FIFO_WR_CMD;
 				val[len++] =
-					SWR_REG_VAL_PACK(mport->lane_ctrl,
+					SWR_REG_VAL_PACK(port_req->lane_ctrl,
 						port_req->dev_num, 0x00,
-						SWRS_DP_LANE_CONTROL_BANK(slv_id,
-									bank));
+						SWRS_DP_LANE_CONTROL_BANK(
+								slv_id, bank));
 			}
 			port_req->ch_en = port_req->req_ch;
+			dev_offset[port_req->dev_num] = port_req->offset1;
 		}
 		value = ((mport->req_ch)
 				<< SWRM_DP_PORT_CTRL_EN_CHAN_SHFT);
@@ -1352,15 +1523,16 @@ static void swrm_copy_data_port_config(struct swr_master *master, u8 bank)
 		if (mport->offset2 != SWR_INVALID_PARAM)
 			value |= ((mport->offset2)
 					<< SWRM_DP_PORT_CTRL_OFFSET2_SHFT);
-		value |= ((mport->offset1)
-				<< SWRM_DP_PORT_CTRL_OFFSET1_SHFT);
+		controller_offset = (swrm_get_controller_offset1(swrm,
+						dev_offset, mport->offset1));
+		value |= (controller_offset << SWRM_DP_PORT_CTRL_OFFSET1_SHFT);
+		mport->offset1 = controller_offset;
 		value |= (mport->sinterval & 0xFF);
 
-
 		reg[len] = SWRM_DP_PORT_CTRL_BANK((i + 1), bank);
 		val[len++] = value;
 		dev_dbg(swrm->dev, "%s: mport :%d, reg: 0x%x, val: 0x%x\n",
-			__func__, i,
+			__func__, (i + 1),
 			(SWRM_DP_PORT_CTRL_BANK((i + 1), bank)), value);
 
 		reg[len] = SWRM_DP_SAMPLECTRL2_BANK((i + 1), bank);
@@ -1746,6 +1918,7 @@ static void swrm_enable_slave_irq(struct swr_mstr_ctrl *swrm)
 {
 	int i;
 	int status = 0;
+	u32 temp;
 
 	status = swr_master_read(swrm, SWRM_MCP_SLV_STATUS);
 	if (!status) {
@@ -1756,6 +1929,8 @@ static void swrm_enable_slave_irq(struct swr_mstr_ctrl *swrm)
 	dev_dbg(swrm->dev, "%s: slave status: 0x%x\n", __func__, status);
 	for (i = 0; i < (swrm->master.num_dev + 1); i++) {
 		if (status & SWRM_MCP_SLV_STATUS_MASK) {
+			swrm_cmd_fifo_rd_cmd(swrm, &temp, i, 0x0,
+					SWRS_SCP_INT_STATUS_CLEAR_1, 1);
 			swrm_cmd_fifo_wr_cmd(swrm, 0xFF, i, 0x0,
 					SWRS_SCP_INT_STATUS_CLEAR_1);
 			swrm_cmd_fifo_wr_cmd(swrm, 0x4, i, 0x0,
@@ -1894,10 +2069,7 @@ handle_irq:
 					 * as hw will mask host_irq at slave
 					 * but will not unmask it afterwards.
 					 */
-					swrm_cmd_fifo_wr_cmd(swrm, 0xFF, devnum, 0x0,
-						SWRS_SCP_INT_STATUS_CLEAR_1);
-					swrm_cmd_fifo_wr_cmd(swrm, 0x4, devnum, 0x0,
-						SWRS_SCP_INT_STATUS_MASK_1);
+					swrm->enable_slave_irq = true;
 				}
 				break;
 			case SWR_ATTACHED_OK:
@@ -1905,11 +2077,7 @@ handle_irq:
 					"%s: device %d got attached\n",
 					__func__, devnum);
 				/* enable host irq from slave device*/
-				swrm_cmd_fifo_wr_cmd(swrm, 0xFF, devnum, 0x0,
-					SWRS_SCP_INT_STATUS_CLEAR_1);
-				swrm_cmd_fifo_wr_cmd(swrm, 0x4, devnum, 0x0,
-					SWRS_SCP_INT_STATUS_MASK_1);
-
+				swrm->enable_slave_irq = true;
 				break;
 			case SWR_ALERT:
 				dev_dbg(swrm->dev,
@@ -1931,19 +2099,19 @@ handle_irq:
 		case SWRM_INTERRUPT_STATUS_RD_FIFO_OVERFLOW:
 			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
 			dev_err(swrm->dev,
-				"%s: SWR read FIFO overflow fifo status\n",
+				"%s: SWR read FIFO overflow fifo status %x\n",
 				__func__, value);
 			break;
 		case SWRM_INTERRUPT_STATUS_RD_FIFO_UNDERFLOW:
 			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
 			dev_err(swrm->dev,
-				"%s: SWR read FIFO underflow fifo status\n",
+				"%s: SWR read FIFO underflow fifo status %x\n",
 				__func__, value);
 			break;
 		case SWRM_INTERRUPT_STATUS_WR_CMD_FIFO_OVERFLOW:
 			value = swr_master_read(swrm, SWRM_CMD_FIFO_STATUS);
 			dev_err(swrm->dev,
-				"%s: SWR write FIFO overflow fifo status\n",
+				"%s: SWR write FIFO overflow fifo status %x\n",
 				__func__, value);
 			swr_master_write(swrm, SWRM_CMD_FIFO_CMD, 0x1);
 			break;
@@ -2023,6 +2191,12 @@ handle_irq:
 	swr_master_write(swrm, SWRM_INTERRUPT_CLEAR, intr_sts);
 	swr_master_write(swrm, SWRM_INTERRUPT_CLEAR, 0x0);
 
+	if (swrm->enable_slave_irq) {
+		/* Enable slave irq here */
+		swrm_enable_slave_irq(swrm);
+		swrm->enable_slave_irq = false;
+	}
+
 	intr_sts = swr_master_read(swrm, SWRM_INTERRUPT_STATUS);
 	intr_sts_masked = intr_sts & swrm->intr_mask;
 
@@ -2058,7 +2232,7 @@ static irqreturn_t swrm_wakeup_interrupt(int irq, void *dev)
 
 	trace_printk("%s enter\n", __func__);
 	mutex_lock(&swrm->devlock);
-	if (!swrm->dev_up) {
+	if (swrm->state == SWR_MSTR_SSR || !swrm->dev_up) {
 		if (swrm->wake_irq > 0) {
 			if (unlikely(!irq_get_irq_data(swrm->wake_irq))) {
 				pr_err("%s: irq data is NULL\n", __func__);
@@ -2191,6 +2365,7 @@ static int swrm_get_logical_dev_num(struct swr_master *mstr, u64 dev_id,
 							"%s: devnum %d assigned for dev %llx\n",
 							__func__, i,
 							swr_dev->addr);
+						swrm->logical_dev[i] = swr_dev->addr;
 					}
 				}
 			}
@@ -2694,6 +2869,11 @@ static int swrm_probe(struct platform_device *pdev)
 	if (pdev->dev.of_node)
 		of_register_swr_devices(&swrm->master);
 
+	swrm->rd_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS)
+				& SWRM_COMP_PARAMS_RD_FIFO_DEPTH) >> 15);
+	swrm->wr_fifo_depth = ((swr_master_read(swrm, SWRM_COMP_PARAMS)
+				& SWRM_COMP_PARAMS_WR_FIFO_DEPTH) >> 10);
+
 #ifdef CONFIG_DEBUG_FS
 	swrm->debugfs_swrm_dent = debugfs_create_dir(dev_name(&pdev->dev), 0);
 	if (!IS_ERR(swrm->debugfs_swrm_dent)) {
@@ -2737,9 +2917,10 @@ err_mstr_fail:
 		swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
 				swrm, SWR_IRQ_FREE);
 	} else if (swrm->irq) {
-		irqd_set_trigger_type(
-			irq_get_irq_data(swrm->irq),
-			IRQ_TYPE_NONE);
+		if (irq_get_irq_data(swrm->irq) != NULL)
+			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);
@@ -2767,9 +2948,10 @@ static int swrm_remove(struct platform_device *pdev)
 		swrm->reg_irq(swrm->handle, swr_mstr_interrupt,
 				swrm, SWR_IRQ_FREE);
 	} else if (swrm->irq) {
-		irqd_set_trigger_type(
-			irq_get_irq_data(swrm->irq),
-			IRQ_TYPE_NONE);
+		if (irq_get_irq_data(swrm->irq) != NULL)
+			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);

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

@@ -190,6 +190,10 @@ struct swr_mstr_ctrl {
 	int aud_core_clk_en;
 	int clk_src;
 	u32 disable_div2_clk_switch;
+	u32 rd_fifo_depth;
+	u32 wr_fifo_depth;
+	bool enable_slave_irq;
+	u64 logical_dev[SWRM_NUM_AUTO_ENUM_SLAVES];
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_swrm_dent;
 	struct dentry *debugfs_peek;

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

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015, 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2018-2020 The Linux Foundation. All rights reserved.
  */
 
 #ifndef _SWRM_REGISTERS_H
@@ -108,4 +108,7 @@
 #define SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP            0x10000
 
 #define SWRM_INTERRUPT_MAX    0x11
+
+#define SWRM_COMP_PARAMS_WR_FIFO_DEPTH		0x00007C00
+#define SWRM_COMP_PARAMS_RD_FIFO_DEPTH		0x000F8000
 #endif /* _SWRM_REGISTERS_H */

+ 113 - 0
soc/swr-slave-port-config.h

@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _SWR_SLAVE_PORT_CONFIG
+#define _SWR_SLAVE_PORT_CONFIG
+
+#include <soc/swr-common.h>
+
+#define WSA_MSTR_PORT_MASK 0xFF
+/*
+ * Add port configuration in the format
+ *{ si, off1, off2, hstart, hstop, wd_len, bp_mode, bgp_ctrl, lane_ctrl, dir,
+ *  stream_type}
+ */
+
+/* DUMMY */
+static struct port_params tx_dummy[SWR_MSTR_PORT_LEN] = {
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{0,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+/* AMIC 9.6 MHz clock */
+static struct port_params tx_wcd_9p6MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX1 */
+	{7,  5,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX4 */
+};
+
+/* AMIC 4.8 MHz clock */
+static struct port_params tx_wcd_4p8MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX1 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX4 */
+};
+
+/* 4 Channel configuration */
+/* SWR DMIC0 */
+static struct port_params tx_bottom_mic_9p6MHz[SWR_MSTR_PORT_LEN] = {
+	{7,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  6,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC1 */
+static struct port_params tx_receiver_mic_9p6MHz[SWR_MSTR_PORT_LEN] = {
+	{7,  4,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  7,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC2 */
+static struct port_params tx_back_mic_9p6MHz[SWR_MSTR_PORT_LEN] = {
+	{7,  3,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC3 */
+static struct port_params tx_top_mic_9p6MHz[SWR_MSTR_PORT_LEN] = {
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  5,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* 3 Channel configuration */
+/* SWR DMIC0 */
+static struct port_params tx_bottom_mic_4p8MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  3,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC1 */
+static struct port_params tx_receiver_mic_4p8MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC2 */
+static struct port_params tx_back_mic_4p8MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC3 */
+static struct port_params tx_top_mic_4p8MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  3,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+struct swr_dev_frame_config {
+	struct port_params *pp;
+};
+
+static struct swr_dev_frame_config swrdev_frame_params_9p6MHz[] = {
+	{tx_dummy},
+	{tx_wcd_9p6MHz},
+	{tx_top_mic_9p6MHz},
+	{tx_back_mic_9p6MHz},
+	{tx_receiver_mic_9p6MHz},
+	{tx_bottom_mic_9p6MHz},
+};
+
+static struct swr_dev_frame_config swrdev_frame_params_4p8MHz[] = {
+	{tx_dummy},
+	{tx_wcd_4p8MHz},
+	{tx_top_mic_4p8MHz},
+	{tx_back_mic_4p8MHz},
+	{tx_receiver_mic_4p8MHz},
+	{tx_bottom_mic_4p8MHz},
+};
+
+#endif /* _LAHAINA_PORT_CONFIG */

+ 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 + \