Parcourir la source

Merge a387074fd0a085cdd138efbefa2f453f5c5d3af6 on remote branch

Change-Id: Ie83fbf5dbdd09f7eb60d9425e252cf395c939a04
Linux Build Service Account il y a 4 ans
Parent
commit
1a639ec59f

+ 8 - 0
Makefile

@@ -1,5 +1,9 @@
 # auto-detect subdirs
 ifneq ($(CONFIG_ARCH_QTI_VM), y)
+ifeq ($(CONFIG_QTI_QUIN_GVM), y)
+include $(srctree)/techpack/audio/config/gvmauto.conf
+export
+endif
 ifeq ($(CONFIG_ARCH_SDXPOORWILLS), y)
 include $(srctree)/techpack/audio/config/sdxpoorwillsauto.conf
 export
@@ -34,6 +38,10 @@ LINUXINCLUDE    += \
                 -I$(srctree)/techpack/audio/include/uapi/audio \
                 -I$(srctree)/techpack/audio/include
 
+ifeq ($(CONFIG_QTI_QUIN_GVM), y)
+LINUXINCLUDE    += \
+                -include $(srctree)/techpack/audio/config/gvmautoconf.h
+endif
 ifeq ($(CONFIG_ARCH_SDXPOORWILLS), y)
 LINUXINCLUDE    += \
                 -include $(srctree)/techpack/audio/config/sdxpoorwillsautoconf.h

+ 3 - 0
Makefile.am

@@ -40,6 +40,7 @@ obj-m += asoc/codecs/wcd937x/
 endif
 
 ifeq ($(TARGET_SUPPORT), $(filter $(TARGET_SUPPORT), sa8155 sa8155ivi sa6155 sa8195 qtiquingvm))
+KBUILD_OPTIONS += CONFIG_SND_SOC_AUTO=y
 obj-m := ipc/
 obj-m += dsp/
 obj-m += asoc/
@@ -64,6 +65,8 @@ all:
 	$(shell ln -s $(KERNEL_SRC)/drivers/base/regmap/internal.h $(shell pwd)/include/soc/internal.h)
 	$(shell rm -fr $(shell pwd)/soc/pinctrl-utils.h)
 	$(shell ln -s $(KERNEL_SRC)/drivers/pinctrl/pinctrl-utils.h $(shell pwd)/soc/pinctrl-utils.h)
+	$(shell rm -fr $(shell pwd)/include/soc/qcom/secure_buffer.h)
+	$(shell ln -s $(KERNEL_SRC)/include/soc/qcom/secure_buffer.h $(shell pwd)/include/soc/qcom/secure_buffer.h)
 	$(shell mkdir $(shell pwd)/linux)
 	$(shell mkdir $(shell pwd)/sound)
 	$(shell mkdir $(shell pwd)/linux/mfd)

+ 14 - 1
asoc/Kbuild

@@ -13,6 +13,18 @@ ifeq ($(KERNEL_BUILD), 1)
 	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
 endif
 
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+else
 ifeq ($(KERNEL_BUILD), 0)
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		ifdef CONFIG_SND_SOC_SA8155
@@ -71,12 +83,13 @@ ifeq ($(KERNEL_BUILD), 0)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
 	endif
-	ifeq ($(CONFIG_QTI_GVM), y)
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
 		include $(AUDIO_ROOT)/config/gvmauto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
 	endif
 endif
+endif
 
 # As per target team, build is done as follows:
 # Defconfig : build with default flags

+ 14 - 1
asoc/codecs/Kbuild

@@ -13,6 +13,18 @@ ifeq ($(KERNEL_BUILD), 1)
 	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
 endif
 
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+else
 ifeq ($(KERNEL_BUILD), 0)
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		ifdef CONFIG_SND_SOC_SA8155
@@ -65,12 +77,13 @@ ifeq ($(KERNEL_BUILD), 0)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
 	endif
-	ifeq ($(CONFIG_QTI_GVM), y)
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
 		include $(AUDIO_ROOT)/config/gvmauto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
 	endif
 endif
+endif
 
 # As per target team, build is done as follows:
 # Defconfig : build with default flags

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

@@ -851,6 +851,9 @@ static ssize_t bolero_version_read(struct snd_info_entry *entry,
 	case BOLERO_VERSION_1_2:
 		len = snprintf(buffer, sizeof(buffer), "BOLERO_1_2\n");
 		break;
+	case BOLERO_VERSION_2_0:
+		len = snprintf(buffer, sizeof(buffer), "BOLERO_2_0\n");
+		break;
 	case BOLERO_VERSION_2_1:
 		len = snprintf(buffer, sizeof(buffer), "BOLERO_2_1\n");
 		break;

+ 126 - 0
asoc/codecs/ep92/ep92.c

@@ -44,6 +44,61 @@ static const unsigned int ep92_dsd_freq_table[4] = {
 	64, 128, 256, 0
 };
 
+/* EP92 register default values */
+static struct reg_default ep92_reg_defaults[] = {
+	{EP92_BI_VENDOR_ID_0,                   0x17},
+	{EP92_BI_VENDOR_ID_1,                   0x7A},
+	{EP92_BI_DEVICE_ID_0,                   0x94},
+	{EP92_BI_DEVICE_ID_1,                   0xA3},
+	{EP92_BI_VERSION_NUM,                   0x10},
+	{EP92_BI_VERSION_YEAR,                  0x09},
+	{EP92_BI_VERSION_MONTH,                 0x07},
+	{EP92_BI_VERSION_DATE,                  0x06},
+	{EP92_BI_GENERAL_INFO_0,                0x00},
+	{EP92_BI_GENERAL_INFO_1,                0x00},
+	{EP92_BI_GENERAL_INFO_2,                0x00},
+	{EP92_BI_GENERAL_INFO_3,                0x00},
+	{EP92_BI_GENERAL_INFO_4,                0x00},
+	{EP92_BI_GENERAL_INFO_5,                0x00},
+	{EP92_BI_GENERAL_INFO_6,                0x00},
+	{EP92_ISP_MODE_ENTER_ISP,               0x00},
+	{EP92_GENERAL_CONTROL_0,                0x20},
+	{EP92_GENERAL_CONTROL_1,                0x00},
+	{EP92_GENERAL_CONTROL_2,                0x00},
+	{EP92_GENERAL_CONTROL_3,                0x10},
+	{EP92_GENERAL_CONTROL_4,                0x00},
+	{EP92_CEC_EVENT_CODE,                   0x00},
+	{EP92_CEC_EVENT_PARAM_1,                0x00},
+	{EP92_CEC_EVENT_PARAM_2,                0x00},
+	{EP92_CEC_EVENT_PARAM_3,                0x00},
+	{EP92_CEC_EVENT_PARAM_4,                0x00},
+	{EP92_AUDIO_INFO_SYSTEM_STATUS_0,       0x00},
+	{EP92_AUDIO_INFO_SYSTEM_STATUS_1,       0x00},
+	{EP92_AUDIO_INFO_AUDIO_STATUS,          0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_0,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_1,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_2,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_3,      0x00},
+	{EP92_AUDIO_INFO_CHANNEL_STATUS_4,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_0,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_1,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_2,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_3,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_4,      0x00},
+	{EP92_AUDIO_INFO_ADO_INFO_FRAME_5,      0x00},
+	{EP92_OTHER_PACKETS_HDMI_VS_0,          0x00},
+	{EP92_OTHER_PACKETS_HDMI_VS_1,          0x00},
+	{EP92_OTHER_PACKETS_ACP_PACKET,         0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_0,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_1,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_2,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_3,   0x00},
+	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_4,   0x00},
+	{EP92_OTHER_PACKETS_GC_PACKET_0,        0x00},
+	{EP92_OTHER_PACKETS_GC_PACKET_1,        0x00},
+	{EP92_OTHER_PACKETS_GC_PACKET_2,        0x00},
+};
+
 static bool ep92_volatile_register(struct device *dev, unsigned int reg)
 {
 	/* do not cache register state in regmap */
@@ -115,6 +170,77 @@ struct ep92_pdata {
 #endif /* CONFIG_DEBUG_FS */
 };
 
+struct ep92_mclk_cfg_info {
+	uint32_t in_sample_rate;
+	uint32_t out_mclk_freq;
+	uint8_t mul_val;
+};
+
+#define EP92_MCLK_MUL_512		0x3
+#define EP92_MCLK_MUL_384		0x2
+#define EP92_MCLK_MUL_256		0x1
+#define EP92_MCLK_MUL_128		0x0
+#define EP92_MCLK_MUL_MASK		0x3
+
+/**
+ * ep92_set_ext_mclk - Configure the mclk based on sample freq
+ *
+ * @codec: handle pointer to ep92 codec
+ * @mclk_freq: mclk frequency to be set
+ *
+ * Returns 0 for sucess or appropriate negative error code
+ */
+int ep92_set_ext_mclk(struct snd_soc_codec *codec, uint32_t mclk_freq)
+{
+	unsigned int samp_freq = 0;
+	struct ep92_pdata *ep92 = NULL;
+	uint8_t value = 0;
+	int ret = 0;
+
+	if (!codec)
+		return -EINVAL;
+
+	ep92 = snd_soc_codec_get_drvdata(codec);
+
+	samp_freq = ep92_samp_freq_table[(ep92->ai.audio_status) &
+						EP92_AI_RATE_MASK];
+
+	if (!mclk_freq || (mclk_freq % samp_freq)) {
+		pr_err("%s incompatbile mclk:%u and sample freq:%u\n",
+				__func__, mclk_freq, samp_freq);
+		return -EINVAL;
+	}
+
+	switch (mclk_freq / samp_freq) {
+	case 512:
+		value = EP92_MCLK_MUL_512;
+		break;
+	case 384:
+		value = EP92_MCLK_MUL_384;
+		break;
+	case 256:
+		value = EP92_MCLK_MUL_256;
+		break;
+	case 128:
+		value = EP92_MCLK_MUL_128;
+		break;
+	default:
+		dev_err(codec->dev, "unsupported mclk:%u for sample freq:%u\n",
+					mclk_freq, samp_freq);
+		return -EINVAL;
+	}
+
+	pr_debug("%s mclk:%u, in sample freq:%u, write reg:0x%02x val:0x%02x\n",
+		__func__, mclk_freq, samp_freq,
+		EP92_GENERAL_CONTROL_2, EP92_MCLK_MUL_MASK & value);
+
+	ret = snd_soc_update_bits(codec, EP92_GENERAL_CONTROL_2,
+					EP92_MCLK_MUL_MASK, value);
+
+	return (((ret == 0) || (ret == 1)) ? 0 : ret);
+}
+EXPORT_SYMBOL(ep92_set_ext_mclk);
+
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 static int debugfs_codec_open_op(struct inode *inode, struct file *file)
 {

+ 2 - 57
asoc/codecs/ep92/ep92.h

@@ -69,63 +69,6 @@
 
 #define   EP92_MAX_REGISTER_ADDR                EP92_OTHER_PACKETS_GC_PACKET_2
 
-
-/* EP92 register default values */
-static struct reg_default ep92_reg_defaults[] = {
-	{EP92_BI_VENDOR_ID_0,                   0x17},
-	{EP92_BI_VENDOR_ID_1,                   0x7A},
-	{EP92_BI_DEVICE_ID_0,                   0x94},
-	{EP92_BI_DEVICE_ID_1,                   0xA3},
-	{EP92_BI_VERSION_NUM,                   0x10},
-	{EP92_BI_VERSION_YEAR,                  0x09},
-	{EP92_BI_VERSION_MONTH,                 0x07},
-	{EP92_BI_VERSION_DATE,                  0x06},
-	{EP92_BI_GENERAL_INFO_0,                0x00},
-	{EP92_BI_GENERAL_INFO_1,                0x00},
-	{EP92_BI_GENERAL_INFO_2,                0x00},
-	{EP92_BI_GENERAL_INFO_3,                0x00},
-	{EP92_BI_GENERAL_INFO_4,                0x00},
-	{EP92_BI_GENERAL_INFO_5,                0x00},
-	{EP92_BI_GENERAL_INFO_6,                0x00},
-	{EP92_ISP_MODE_ENTER_ISP,               0x00},
-	{EP92_GENERAL_CONTROL_0,                0x20},
-	{EP92_GENERAL_CONTROL_1,                0x00},
-	{EP92_GENERAL_CONTROL_2,                0x00},
-	{EP92_GENERAL_CONTROL_3,                0x10},
-	{EP92_GENERAL_CONTROL_4,                0x00},
-	{EP92_CEC_EVENT_CODE,                   0x00},
-	{EP92_CEC_EVENT_PARAM_1,                0x00},
-	{EP92_CEC_EVENT_PARAM_2,                0x00},
-	{EP92_CEC_EVENT_PARAM_3,                0x00},
-	{EP92_CEC_EVENT_PARAM_4,                0x00},
-	{EP92_AUDIO_INFO_SYSTEM_STATUS_0,       0x00},
-	{EP92_AUDIO_INFO_SYSTEM_STATUS_1,       0x00},
-	{EP92_AUDIO_INFO_AUDIO_STATUS,          0x00},
-	{EP92_AUDIO_INFO_CHANNEL_STATUS_0,      0x00},
-	{EP92_AUDIO_INFO_CHANNEL_STATUS_1,      0x00},
-	{EP92_AUDIO_INFO_CHANNEL_STATUS_2,      0x00},
-	{EP92_AUDIO_INFO_CHANNEL_STATUS_3,      0x00},
-	{EP92_AUDIO_INFO_CHANNEL_STATUS_4,      0x00},
-	{EP92_AUDIO_INFO_ADO_INFO_FRAME_0,      0x00},
-	{EP92_AUDIO_INFO_ADO_INFO_FRAME_1,      0x00},
-	{EP92_AUDIO_INFO_ADO_INFO_FRAME_2,      0x00},
-	{EP92_AUDIO_INFO_ADO_INFO_FRAME_3,      0x00},
-	{EP92_AUDIO_INFO_ADO_INFO_FRAME_4,      0x00},
-	{EP92_AUDIO_INFO_ADO_INFO_FRAME_5,      0x00},
-	{EP92_OTHER_PACKETS_HDMI_VS_0,          0x00},
-	{EP92_OTHER_PACKETS_HDMI_VS_1,          0x00},
-	{EP92_OTHER_PACKETS_ACP_PACKET,         0x00},
-	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_0,   0x00},
-	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_1,   0x00},
-	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_2,   0x00},
-	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_3,   0x00},
-	{EP92_OTHER_PACKETS_AVI_INFO_FRAME_4,   0x00},
-	{EP92_OTHER_PACKETS_GC_PACKET_0,        0x00},
-	{EP92_OTHER_PACKETS_GC_PACKET_1,        0x00},
-	{EP92_OTHER_PACKETS_GC_PACKET_2,        0x00},
-};
-
-
 /* shift/masks for register bits
  * GI = General Info
  * GC = General Control
@@ -211,4 +154,6 @@ enum {
 	EP92_KCTL_MAX
 };
 
+int ep92_set_ext_mclk(struct snd_soc_codec *codec, uint32_t mclk_freq);
+
 #endif /* __EP92_H__ */

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

@@ -108,6 +108,7 @@ struct rouleur_pdata {
 	int num_supplies;
 	int reset_reg;
 	int foundry_id_reg;
+	u32 soc_threshold_val;
 };
 
 struct wcd_ctrl_platform_data {

+ 19 - 9
asoc/codecs/rouleur/rouleur.c

@@ -2087,7 +2087,7 @@ static void rouleur_evaluate_soc(struct work_struct *work)
 		return;
 	}
 
-	if (soc_val < SOC_THRESHOLD_LEVEL) {
+	if (soc_val < pdata->soc_threshold_val) {
 		dev_dbg(rouleur->dev,
 			"%s battery SoC less than threshold soc_val = %d\n",
 			__func__, soc_val);
@@ -2224,14 +2224,6 @@ static int rouleur_soc_codec_probe(struct snd_soc_component *component)
 	}
 	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;
 }
@@ -2471,6 +2463,16 @@ struct rouleur_pdata *rouleur_populate_dt_data(struct device *dev)
 	else
 		pdata->foundry_id_reg = reg;
 
+	if (of_property_read_u32(dev->of_node, "qcom,soc-threshold-voltage"
+	    , &reg)) {
+		dev_dbg(dev, "%s: Looking up %s property in node %s failed\n",
+			__func__, "qcom,soc-threshold-voltage",
+			dev->of_node->full_name);
+		pdata->soc_threshold_val = SOC_THRESHOLD_LEVEL;
+	} else {
+		pdata->soc_threshold_val = reg;
+	}
+
 	/* Parse power supplies */
 	msm_cdc_get_power_supplies(dev, &pdata->regulator,
 				   &pdata->num_supplies);
@@ -2688,6 +2690,14 @@ static int rouleur_bind(struct device *dev)
 		goto err_irq;
 	}
 
+	/* 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);
 	return ret;
 err_irq:
 	wcd_irq_exit(&rouleur->irq_info, rouleur->virq);

+ 13 - 12
asoc/codecs/swr-dmic.c

@@ -67,7 +67,6 @@ struct swr_dmic_priv {
 	struct device_node *wcd_handle;
 	bool is_wcd_supply;
 	int is_en_supply;
-	int port_type;
 	u8 tx_master_port_map[SWR_DMIC_MAX_PORTS];
 	struct notifier_block nblock;
 };
@@ -141,7 +140,6 @@ static int swr_dmic_tx_master_port_get(struct snd_kcontrol *kcontrol,
 		dev_dbg(component->dev, "%s: invalid port string\n", __func__);
 		return ret;
 	}
-	swr_dmic->port_type = slave_port_idx;
 
 	ucontrol->value.integer.value[0] =
 			swr_dmic_get_master_port_val(
@@ -168,7 +166,6 @@ static int swr_dmic_tx_master_port_put(struct snd_kcontrol *kcontrol,
 		dev_dbg(component->dev, "%s: invalid port string\n", __func__);
 		return ret;
 	}
-	swr_dmic->port_type = slave_port_idx;
 
 	swr_dmic->tx_master_port_map[slave_port_idx] =
 		swr_master_channel_map[ucontrol->value.enumerated.item[0]];
@@ -188,9 +185,9 @@ static int swr_dmic_port_enable(struct snd_soc_dapm_widget *w,
 	struct swr_dmic_priv *swr_dmic =
 			snd_soc_component_get_drvdata(component);
 
-	u8 ch_mask = 0x01; // only DpnChannelEN1 register is available
+	u8 ch_mask = 0x01; /* only DpnChannelEN1 register is available */
 	u8 num_port = 1;
-	u8 port_id = swr_dmic->port_type;
+	u8 port_id = w->shift;
 	u8 port_type = swr_dmic->tx_master_port_map[port_id];
 
 	switch (event) {
@@ -217,17 +214,17 @@ static int dmic_swr_ctrl(struct snd_soc_dapm_widget *w,
 			snd_soc_component_get_drvdata(component);
 
 	u8 num_ch = 1;
-	u8 ch_mask = 0x01; // only DpnChannelEN1 register is available
+	u8 ch_mask = 0x01; /* only DpnChannelEN1 register is available */
 	u32 ch_rate = SWR_CLK_RATE_4P8MHZ;
 	u8 num_port = 1;
 	u8 port_type = 0;
-	u8 port_id = swr_dmic->port_type;
+	u8 port_id = w->shift;
 
 	/*
 	 * Port 1 is high quality / 2.4 or 3.072 Mbps
 	 * Port 2 is listen low power / 0.6 or 0.768 Mbps
 	 */
-	if(swr_dmic->port_type == SWR_DMIC_HIFI_PORT)
+	if(port_id == SWR_DMIC_HIFI_PORT)
 		ch_rate = SWR_CLK_RATE_2P4MHZ;
 	else
 		ch_rate = SWR_CLK_RATE_0P6MHZ;
@@ -279,22 +276,26 @@ static const struct snd_kcontrol_new va_dmic_switch[] = {
 };
 
 static const struct snd_soc_dapm_widget swr_dmic_dapm_widgets[] = {
-	SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_MIXER_E("SWR_DMIC_MIXER", SND_SOC_NOPM,
+			SWR_DMIC_HIFI_PORT, 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,
+	SND_SOC_DAPM_MIXER_E("SWR_DMIC_VA_MIXER", SND_SOC_NOPM,
+			SWR_DMIC_LP_PORT, 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,
+	SND_SOC_DAPM_OUT_DRV_E("SMIC_PORT_EN", SND_SOC_NOPM,
+				SWR_DMIC_HIFI_PORT, 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,
+	SND_SOC_DAPM_OUT_DRV_E("SMIC_VA_PORT_EN", SND_SOC_NOPM,
+				SWR_DMIC_LP_PORT, 0, NULL, 0,
 				swr_dmic_port_enable,
 				SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
 

+ 4 - 2
asoc/codecs/wcd-mbhc-adc.c

@@ -885,8 +885,10 @@ correct_plug_type:
 		 */
 		if ((plug_type == MBHC_PLUG_TYPE_HEADSET) ||
 		    (plug_type == MBHC_PLUG_TYPE_ANC_HEADPHONE)) {
-			pr_debug("%s: plug_type:0x%x already reported\n",
-				 __func__, mbhc->current_plug);
+			pr_debug("%s: plug_type:0x%x current_plug: 0x%x already reported\n",
+				 __func__, plug_type, mbhc->current_plug);
+			if (mbhc->current_plug != plug_type)
+				goto report;
 			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_MODE, 0);
 			WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ADC_EN, 0);
 			goto enable_supply;

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

@@ -515,6 +515,15 @@ static void wcd_mbhc_set_and_turnoff_hph_padac(struct wcd_mbhc *mbhc)
 int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
 			uint32_t *zr)
 {
+	int detection_type = -EINVAL;
+
+	WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type);
+	/* Call compute impedance only when accessory is inserted */
+	if (!detection_type) {
+		if (mbhc->mbhc_cb->compute_impedance)
+			mbhc->mbhc_cb->compute_impedance(mbhc,
+						&mbhc->zl, &mbhc->zr);
+	}
 	*zl = mbhc->zl;
 	*zr = mbhc->zr;
 

+ 26 - 22
asoc/codecs/wcd937x/wcd937x.c

@@ -719,9 +719,6 @@ static int wcd937x_codec_enable_hphr_pa(struct snd_soc_dapm_widget *w,
 					0x10, 0x10);
 		usleep_range(100, 110);
 		set_bit(HPH_PA_DELAY, &wcd937x->status_mask);
-		ret = swr_slvdev_datapath_control(wcd937x->rx_swr_dev,
-					    wcd937x->rx_swr_dev->dev_num,
-					    true);
 		snd_soc_component_update_bits(component,
 				WCD937X_DIGITAL_PDM_WD_CTL1, 0x17, 0x13);
 		break;
@@ -1214,7 +1211,9 @@ static int wcd937x_codec_enable_dmic(struct snd_soc_dapm_widget *w,
 			dmic_clk_reg, 0x08, 0x08);
 		snd_soc_component_update_bits(component,
 			dmic_clk_reg, 0x70, 0x20);
-		wcd937x_tx_connect_port(component, DMIC0 + (w->shift), true);
+		ret = swr_slvdev_datapath_control(wcd937x->tx_swr_dev,
+		    wcd937x->tx_swr_dev->dev_num,
+		    true);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		wcd937x_tx_connect_port(component, DMIC0 + (w->shift), false);
@@ -1330,9 +1329,17 @@ static int wcd937x_tx_swr_ctrl(struct snd_soc_dapm_widget *w,
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		ret = swr_slvdev_datapath_control(wcd937x->tx_swr_dev,
-		    wcd937x->tx_swr_dev->dev_num,
-		    true);
+		if (strnstr(w->name, "ADC", sizeof("ADC"))) {
+			/* Enable BCS for Headset mic */
+			if (w->shift == 1 && !(snd_soc_component_read32(component,
+				WCD937X_TX_NEW_TX_CH2_SEL) & 0x80)) {
+				wcd937x_tx_connect_port(component, MBHC, true);
+				set_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask);
+			}
+			wcd937x_tx_connect_port(component, ADC1 + (w->shift), true);
+		} else {
+			wcd937x_tx_connect_port(component, DMIC0 + (w->shift), true);
+		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		ret = swr_slvdev_datapath_control(wcd937x->tx_swr_dev,
@@ -1352,6 +1359,7 @@ static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w,
 			snd_soc_dapm_to_component(w->dapm);
 	struct wcd937x_priv *wcd937x =
 			snd_soc_component_get_drvdata(component);
+	int ret = 0;
 
 	dev_dbg(component->dev, "%s wname: %s event: %d\n", __func__,
 		w->name, event);
@@ -1367,13 +1375,9 @@ static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w,
 				WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x08, 0x08);
 		snd_soc_component_update_bits(component,
 				WCD937X_DIGITAL_CDC_ANA_CLK_CTL, 0x10, 0x10);
-		/* Enable BCS for Headset mic */
-		if (w->shift == 1 && !(snd_soc_component_read32(component,
-				WCD937X_TX_NEW_TX_CH2_SEL) & 0x80)) {
-			wcd937x_tx_connect_port(component, MBHC, true);
-			set_bit(AMIC2_BCS_ENABLE, &wcd937x->status_mask);
-		}
-		wcd937x_tx_connect_port(component, ADC1 + (w->shift), true);
+		ret = swr_slvdev_datapath_control(wcd937x->tx_swr_dev,
+		    wcd937x->tx_swr_dev->dev_num,
+		    true);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		wcd937x_tx_connect_port(component, ADC1 + (w->shift), false);
@@ -1387,7 +1391,7 @@ static int wcd937x_codec_enable_adc(struct snd_soc_dapm_widget *w,
 		break;
 	};
 
-	return 0;
+	return ret;
 }
 
 static int wcd937x_enable_req(struct snd_soc_dapm_widget *w,
@@ -2263,7 +2267,7 @@ static const struct snd_soc_dapm_widget wcd937x_dapm_widgets[] = {
 				adc1_switch, ARRAY_SIZE(adc1_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 0, 0,
+	SND_SOC_DAPM_MIXER_E("ADC2_MIXER", SND_SOC_NOPM, 1, 0,
 				adc2_switch, ARRAY_SIZE(adc2_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
@@ -2414,27 +2418,27 @@ static const struct snd_soc_dapm_widget wcd9375_dapm_widgets[] = {
 				0, dmic1_switch, ARRAY_SIZE(dmic1_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_MIXER_E("DMIC2_MIXER", SND_SOC_NOPM, 1,
 				0, dmic2_switch, ARRAY_SIZE(dmic2_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_MIXER_E("DMIC3_MIXER", SND_SOC_NOPM, 2,
 				0, dmic3_switch, ARRAY_SIZE(dmic3_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_MIXER_E("DMIC4_MIXER", SND_SOC_NOPM, 3,
 				0, dmic4_switch, ARRAY_SIZE(dmic4_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_MIXER_E("DMIC5_MIXER", SND_SOC_NOPM, 4,
 				0, dmic5_switch, ARRAY_SIZE(dmic5_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 0,
+	SND_SOC_DAPM_MIXER_E("DMIC6_MIXER", SND_SOC_NOPM, 5,
 				0, dmic6_switch, ARRAY_SIZE(dmic6_switch),
 				wcd937x_tx_swr_ctrl, SND_SOC_DAPM_PRE_PMU |
 				SND_SOC_DAPM_POST_PMD),
-	SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 0, 0, adc3_switch,
+	SND_SOC_DAPM_MIXER_E("ADC3_MIXER", SND_SOC_NOPM, 2, 0, adc3_switch,
 				ARRAY_SIZE(adc3_switch), wcd937x_tx_swr_ctrl,
 				SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
 

+ 15 - 2
asoc/codecs/wsa883x/wsa883x.c

@@ -97,11 +97,13 @@ static const struct wsa_reg_mask_val reg_init[] = {
 	{WSA883X_CDC_SPK_DSM_R5, 0xFF, 0x8B},
 	{WSA883X_CDC_SPK_DSM_R6, 0xFF, 0x9B},
 	{WSA883X_CDC_SPK_DSM_R7, 0xFF, 0x3F},
+	{WSA883X_VBAT_SNS, 0x60, 0x20},
 	{WSA883X_DRE_CTL_0, 0xF0, 0x90},
 	{WSA883X_DRE_IDLE_DET_CTL, 0x10, 0x00},
-	{WSA883X_CURRENT_LIMIT, 0x78, 0x20},
+	{WSA883X_CURRENT_LIMIT, 0x78, 0x40},
 	{WSA883X_DRE_CTL_0, 0x07, 0x02},
 	{WSA883X_VAGC_TIME, 0x0F, 0x0F},
+	{WSA883X_VAGC_ATTN_LVL_1_2, 0x70, 0x10},
 	{WSA883X_VAGC_ATTN_LVL_3, 0x07, 0x02},
 	{WSA883X_VAGC_CTL, 0x01, 0x01},
 	{WSA883X_TAGC_CTL, 0x0E, 0x0A},
@@ -121,7 +123,6 @@ static const struct wsa_reg_mask_val reg_init[] = {
 	{WSA883X_DRE_CTL_1, 0x3E, 0x20},
 	{WSA883X_CKWD_CTL_1, 0x1F, 0x1B},
 	{WSA883X_GMAMP_SUP1, 0x60, 0x60},
-	{WSA883X_OVERRIDE2, 0x02, 0x02},
 };
 
 static int wsa883x_handle_post_irq(void *data);
@@ -1052,6 +1053,12 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
 		/* Force remove group */
 		swr_remove_from_group(wsa883x->swr_slave,
 				      wsa883x->swr_slave->dev_num);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x0E, 0x06);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x01, 0x01);
 		if (test_bit(SPKR_ADIE_LB, &wsa883x->status_mask))
 			snd_soc_component_update_bits(component,
 				WSA883X_PA_FSM_CTL, 0x01, 0x01);
@@ -1060,6 +1067,12 @@ static int wsa883x_spkr_event(struct snd_soc_dapm_widget *w,
 		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_VBAT_ADC_FLT_CTL,
+				0x01, 0x00);
+		snd_soc_component_update_bits(component,
+				WSA883X_VBAT_ADC_FLT_CTL,
+				0x0E, 0x00);
 		snd_soc_component_update_bits(component, WSA883X_PA_FSM_CTL,
 				0x01, 0x00);
 		snd_soc_component_update_bits(component, WSA883X_PDM_WD_CTL,

+ 4 - 4
asoc/holi-port-config.h

@@ -41,19 +41,19 @@ static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
 };
 
 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, 0, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX1 */
+	{3, 1, 0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 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},
+	{VA_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},
+	{VA_MACRO, SWR_UC0, tx_frame_params_wcd937x},
 	{RX_MACRO, SWR_UC0, rx_frame_params_default},
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 };

+ 11 - 3
asoc/holi.c

@@ -6368,6 +6368,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 	struct snd_info_entry *entry;
 	struct snd_card *card = NULL;
 	struct msm_asoc_mach_data *pdata;
+	bool is_wcd938x = false;
 
 	pdata = snd_soc_card_get_drvdata(rtd->card);
 	if(!pdata)
@@ -6387,9 +6388,11 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 	}
 
 	component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME);
-	if (!component) {
+	if (!component)
 		component = snd_soc_rtdcom_lookup(rtd, WCD937X_DRV_NAME);
-	}
+	else
+		is_wcd938x = true;
+
 	if (!component) {
 		pr_err("%s component is NULL\n", __func__);
 		return -EINVAL;
@@ -6460,7 +6463,12 @@ mbhc_cfg_cal:
 	if (!mbhc_calibration)
 		return -ENOMEM;
 	wcd_mbhc_cfg.calibration = mbhc_calibration;
-	ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
+
+	if (is_wcd938x)
+		ret = wcd938x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
+	else
+		ret = wcd937x_mbhc_hs_detect(component, &wcd_mbhc_cfg);
+
 	if (ret) {
 		dev_err(component->dev, "%s: mbhc hs detect failed, err:%d\n",
 			__func__, ret);

+ 27 - 3
asoc/lahaina-port-config.h

@@ -53,21 +53,43 @@ static struct port_params tx_frame_params_default[SWR_MSTR_PORT_LEN] = {
 
 /* 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 */
+	{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,  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 */
+	{7,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
 	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX2 */
 	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
 };
 
+/* 0.6 MHz clock */
+static struct port_params tx_frame_params_0p6MHz[SWR_MSTR_PORT_LEN] = {
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+/* 4.8 MHz clock */
+static struct port_params tx_frame_params_shima_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,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+};
+
+/* 0.6 MHz clock */
+static struct port_params tx_frame_params_shima_0p6MHz[SWR_MSTR_PORT_LEN] = {
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{1,  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},
 	{TX_MACRO, SWR_UC1, tx_frame_params_4p8MHz},
+	{TX_MACRO, SWR_UC2, tx_frame_params_0p6MHz},
 	{RX_MACRO, SWR_UC0, rx_frame_params_default},
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},
@@ -75,6 +97,8 @@ static struct swr_mstr_port_map sm_port_map[] = {
 
 static struct swr_mstr_port_map sm_port_map_shima[] = {
 	{TX_MACRO, SWR_UC0, tx_frame_params_shima},
+	{TX_MACRO, SWR_UC1, tx_frame_params_shima_4p8MHz},
+	{TX_MACRO, SWR_UC2, tx_frame_params_shima_0p6MHz},
 	{RX_MACRO, SWR_UC0, rx_frame_params_default},
 	{RX_MACRO, SWR_UC1, rx_frame_params_dsd},
 	{WSA_MACRO, SWR_UC0, wsa_frame_params_default},

+ 53 - 81
asoc/lahaina.c

@@ -884,8 +884,8 @@ 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*);
+static int msm_rx_tx_codec_init(struct snd_soc_pcm_runtime*);
+static int msm_int_wsa_init(struct snd_soc_pcm_runtime*);
 
 /*
  * Need to report LINEIN
@@ -917,24 +917,23 @@ static struct wcd_mbhc_config wcd_mbhc_cfg = {
 /* 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 struct dev_pm_qos_request *msm_audio_req;
+static unsigned int qos_client_active_cnt;
 
-static void msm_audio_add_qos_request()
+static void msm_audio_add_qos_request(void)
 {
 	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__);
+	msm_audio_req = kcalloc(num_possible_cpus(),
+		sizeof(struct dev_pm_qos_request), GFP_KERNEL);
+	if (!msm_audio_req)
 		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]);
+		if (audio_core_list[i] >= num_possible_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);
 	}
@@ -948,7 +947,7 @@ static void msm_audio_add_qos_request()
 	}
 }
 
-static void msm_audio_remove_qos_request()
+static void msm_audio_remove_qos_request(void)
 {
 	int cpu = 0;
 
@@ -956,7 +955,8 @@ static void msm_audio_remove_qos_request()
 		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);
+			pr_debug("%s remove cpu affinity of core %d.\n",
+				__func__, cpu);
 		}
 		kfree(msm_audio_req);
 	}
@@ -970,7 +970,8 @@ static void msm_audio_update_qos_request(u32 latency)
 		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);
+			pr_debug("%s update latency of core %d to %ul.\n",
+				__func__, cpu, latency);
 		}
 	}
 }
@@ -5020,14 +5021,12 @@ static int msm_snd_cdc_dma_startup(struct snd_pcm_substream *substream)
 	return ret;
 }
 
-static int send_cps_config(struct snd_soc_pcm_runtime *rtd,
+static void set_cps_config(struct snd_soc_pcm_runtime *rtd,
 				u32 num_ch, u32 ch_mask)
 {
 	int i = 0;
-	int ret = 0;
 	int val = 0;
 	u8 dev_num = 0;
-	int param_size = 0;
 	int ch_configured = 0;
 	char wsa_cdc_name[DEV_NAME_STR_LEN];
 	struct snd_soc_component *component = NULL;
@@ -5037,29 +5036,29 @@ static int send_cps_config(struct snd_soc_pcm_runtime *rtd,
 
 	if (!pdata) {
 		pr_err("%s: pdata is NULL\n", __func__);
-		return -EINVAL;
+		return;
 	}
 
 	if (!num_ch) {
 		pr_err("%s: channel count is 0\n", __func__);
-		return -EINVAL;
+		return;
 	}
 
 	if (!pdata->get_wsa_dev_num) {
 		pr_err("%s: get_wsa_dev_num is NULL\n", __func__);
-		return -EINVAL;
+		return;
 	}
 
 	if (!pdata->cps_config.spkr_dep_cfg) {
 		pr_err("%s: spkr_dep_cfg is NULL\n", __func__);
-		return -EINVAL;
+		return;
 	}
 
 	if (!pdata->cps_config.hw_reg_cfg.lpass_wr_cmd_reg_phy_addr ||
 	   !pdata->cps_config.hw_reg_cfg.lpass_rd_cmd_reg_phy_addr ||
 	   !pdata->cps_config.hw_reg_cfg.lpass_rd_fifo_reg_phy_addr) {
 		pr_err("%s: cps static configuration is not set\n", __func__);
-		return -EINVAL;
+		return;
 	}
 
 	pdata->cps_config.lpass_hw_intf_cfg_mode = 1;
@@ -5077,14 +5076,14 @@ static int send_cps_config(struct snd_soc_pcm_runtime *rtd,
 		if (!component) {
 			pr_err("%s: %s component is NULL\n", __func__,
 				wsa_cdc_name);
-			return -EINVAL;
+			return;
 		}
 
 		dev_num = pdata->get_wsa_dev_num(component);
 		if (dev_num < 0 || dev_num > SWR_MAX_SLAVE_DEVICES) {
 			pr_err("%s: invalid slave dev num : %d\n", __func__,
 				dev_num);
-			return -EINVAL;
+			return;
 		}
 
 		/* Clear stale dev num info */
@@ -5106,18 +5105,8 @@ static int send_cps_config(struct snd_soc_pcm_runtime *rtd,
 		ch_configured++;
 	}
 
-	param_size = sizeof(struct afe_cps_hw_intf_cfg) -
-			sizeof(pdata->cps_config.spkr_dep_cfg) +
-			(sizeof(struct lpass_swr_spkr_dep_cfg_t)
-				* pdata->cps_config.hw_reg_cfg.num_spkr);
-
-	ret = afe_send_cps_config(msm_get_port_id(dai_link->id),
-					&pdata->cps_config, param_size);
-	if (ret) {
-		pr_err("%s: afe_send_cps_cfg failed\n", __func__);
-	}
-
-	return ret;
+	afe_set_cps_config(msm_get_port_id(dai_link->id),
+					&pdata->cps_config, ch_mask);
 }
 
 static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream,
@@ -5170,7 +5159,7 @@ static int msm_snd_cdc_dma_hw_params(struct snd_pcm_substream *substream,
 
 			if (dai_link->id == MSM_BACKEND_DAI_WSA_CDC_DMA_RX_0 ||
 			    dai_link->id == MSM_BACKEND_DAI_WSA_CDC_DMA_RX_1) {
-				send_cps_config(rtd, user_set_rx_ch,
+				set_cps_config(rtd, user_set_rx_ch,
 						rx_ch_cdc_dma);
 			}
 		}
@@ -6929,7 +6918,7 @@ static struct snd_soc_dai_link msm_wsa_cdc_dma_be_dai_links[] = {
 		.ignore_suspend = 1,
 		.ops = &msm_cdc_dma_be_ops,
 		SND_SOC_DAILINK_REG(wsa_dma_rx0),
-		.init = &msm_int_audrx_init,
+		.init = &msm_int_wsa_init,
 	},
 	{
 		.name = LPASS_BE_WSA_CDC_DMA_RX_1,
@@ -6983,7 +6972,7 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
 		.ignore_suspend = 1,
 		.ops = &msm_cdc_dma_be_ops,
 		SND_SOC_DAILINK_REG(rx_dma_rx0),
-		.init = &msm_aux_codec_init,
+		.init = &msm_rx_tx_codec_init,
 	},
 	{
 		.name = LPASS_BE_RX_CDC_DMA_RX_1,
@@ -6999,7 +6988,6 @@ static struct snd_soc_dai_link msm_rx_tx_cdc_dma_be_dai_links[] = {
 		.ignore_suspend = 1,
 		.ops = &msm_cdc_dma_be_ops,
 		SND_SOC_DAILINK_REG(rx_dma_rx1),
-		.init = &msm_int_audrx_init,
 	},
 	{
 		.name = LPASS_BE_RX_CDC_DMA_RX_2,
@@ -7624,7 +7612,7 @@ static struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
 	return card;
 }
 
-static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
+static int msm_int_wsa_init(struct snd_soc_pcm_runtime *rtd)
 {
 	u8 spkleft_ports[WSA883X_MAX_SWR_PORTS] = {0, 1, 2, 3};
 	u8 spkright_ports[WSA883X_MAX_SWR_PORTS] = {0, 1, 2, 3};
@@ -7637,16 +7625,10 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 	unsigned int ch_mask[WSA883X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3};
 	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;
 	int wsa_active_devs = 0;
 
-	if (codec_reg_done) {
-		return 0;
-	}
         if (pdata->wsa_max_devs > 0) {
 		component = snd_soc_rtdcom_lookup(rtd, "wsa-codec.1");
 		if (component) {
@@ -7684,6 +7666,23 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 							component);
 	}
 
+	return 0;
+}
+
+static int msm_rx_tx_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+	struct snd_soc_component *component = NULL;
+	struct snd_soc_dapm_context *dapm = NULL;
+	int ret = 0;
+	int codec_variant = -1;
+	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;
+
 	component = snd_soc_rtdcom_lookup(rtd, "bolero_codec");
 	if (!component) {
 		pr_err("%s: could not find component for bolero_codec\n",
@@ -7735,7 +7734,7 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 
 	card = rtd->card->snd_card;
 
-	if (strnstr(rtd->card->name, "shima", 5) != NULL)
+	if (strnstr(rtd->card->name, "shima", strlen(rtd->card->name)) != NULL)
 		bolero_set_port_map(component, ARRAY_SIZE(sm_port_map_shima),
 				sm_port_map_shima);
 	else
@@ -7748,35 +7747,17 @@ static int msm_int_audrx_init(struct snd_soc_pcm_runtime *rtd)
 		if (!entry) {
 			pr_debug("%s: Cannot create codecs module entry\n",
 				 __func__);
-			ret = 0;
-			goto err;
+			return 0;
 		}
 		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 *component = NULL;
-	struct snd_soc_dapm_context *dapm = NULL;
-	int ret = 0;
-	int codec_variant = -1;
-	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;
-
-	if (pdata->wcd_disabled)
+	if (pdata->wcd_disabled) {
+		codec_reg_done = true;
 		return 0;
+	}
 	component = snd_soc_rtdcom_lookup(rtd, WCD938X_DRV_NAME);
 	if (!component) {
 		pr_err("%s component is NULL\n", __func__);
@@ -7795,16 +7776,6 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 	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__);
-			 return 0;
-		}
-		pdata->codec_root = entry;
-	}
 	wcd938x_info_create_codec_entry(pdata->codec_root, component);
 
 	codec_variant = wcd938x_get_codec_variant(component);
@@ -7824,6 +7795,7 @@ static int msm_aux_codec_init(struct snd_soc_pcm_runtime *rtd)
 		return ret;
 	}
 
+	codec_reg_done = true;
 	return 0;
 }
 

+ 2 - 2
asoc/msm-compress-q6-v2.c

@@ -3092,9 +3092,9 @@ static int msm_compr_pointer(struct snd_compr_stream *cstream,
 		pr_err_ratelimited("%s Got RESET EVENTS notification, return error\n",
 				   __func__);
 		if (cstream->direction == SND_COMPRESS_PLAYBACK)
-			runtime->total_bytes_transferred = tstamp.copied_total;
+			runtime->total_bytes_transferred = prtd->copied_total;
 		else
-			runtime->total_bytes_available = tstamp.copied_total;
+			runtime->total_bytes_available = prtd->received_total;
 		tstamp.pcm_io_frames = 0;
 		memcpy(arg, &tstamp, sizeof(struct snd_compr_tstamp));
 		spin_unlock_irqrestore(&prtd->lock, flags);

+ 50 - 4
asoc/msm-pcm-routing-v2.c

@@ -25359,10 +25359,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
 				&cdc_dma_rx_1_switch_mixer_controls),
 
 	/* Mixer definitions */
-	SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
-	pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
-	SND_SOC_DAPM_MIXER("SEC_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
-	sec_i2s_rx_mixer_controls, ARRAY_SIZE(sec_i2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_2_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -25925,6 +25921,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets_mi2s[] = {
 				&quin_mi2s_rx_switch_mixer_controls),
 	SND_SOC_DAPM_SWITCH("SEN_MI2S_RX_DL_HL", SND_SOC_NOPM, 0, 0,
 				&sen_mi2s_rx_switch_mixer_controls),
+	SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+	pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SEC_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+	sec_i2s_rx_mixer_controls, ARRAY_SIZE(sec_i2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
 	mi2s_rx_mixer_controls, ARRAY_SIZE(mi2s_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("QUAT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
@@ -32126,6 +32126,50 @@ static const struct snd_kcontrol_new
 	},
 };
 
+static int msm_routing_put_mclk_src_cfg(struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	u16 port_id = 0;
+	int32_t mclk_src_id = 0;
+	uint32_t mclk_freq = 0;
+	int be_idx, ret = -EINVAL;
+
+	be_idx = ucontrol->value.integer.value[0];
+	mclk_src_id = ucontrol->value.integer.value[1];
+	mclk_freq = ucontrol->value.integer.value[2];
+
+	if (be_idx < 0 && be_idx >= MSM_BACKEND_DAI_MAX) {
+		pr_err("%s: Invalid be id %d\n", __func__, be_idx);
+		return -EINVAL;
+	}
+
+	if (mclk_src_id < MCLK_SRC_INT && mclk_src_id >= MCLK_SRC_MAX) {
+		pr_err("%s: Invalid MCLK src %d\n", __func__, mclk_src_id);
+		return -EINVAL;
+	}
+
+	if (msm_bedais[be_idx].active) {
+		pr_err("%s:BE is active %d, cannot set mclk clock src\n",
+			__func__, be_idx);
+		return -EINVAL;
+	}
+
+	port_id = msm_bedais[be_idx].port_id;
+	pr_debug("%s: be idx %d mclk_src id %d mclk_freq %d port id 0x%x\n",
+		  __func__, be_idx, mclk_src_id, mclk_freq, port_id);
+	ret = afe_set_mclk_src_cfg(port_id, mclk_src_id, mclk_freq);
+	if (ret < 0)
+		pr_err("%s: failed to set mclk src cfg\n", __func__);
+
+	return ret;
+
+}
+
+static const struct snd_kcontrol_new mclk_src_controls[] = {
+	SOC_SINGLE_MULTI_EXT("MCLK_SRC CFG", SND_SOC_NOPM, 0, 24576000, 0, 3,
+					NULL, msm_routing_put_mclk_src_cfg),
+};
+
 static int msm_routing_stereo_channel_reverse_control_get(
 			struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
@@ -32418,6 +32462,8 @@ static int msm_routing_probe(struct snd_soc_component *component)
 	snd_soc_add_component_controls(component, pll_clk_drift_controls,
 				      ARRAY_SIZE(pll_clk_drift_controls));
 
+	snd_soc_add_component_controls(component, mclk_src_controls,
+				      ARRAY_SIZE(mclk_src_controls));
 	return 0;
 }
 

+ 2 - 2
asoc/msm-pcm-routing-v2.h

@@ -297,8 +297,8 @@ enum {
 	MSM_FRONTEND_DAI_MAX,
 };
 
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA32 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA32
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MAX + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MAX
 
 enum {
 	MSM_BACKEND_DAI_PRI_I2S_RX = 0,

+ 13 - 1
asoc/sa6155.c

@@ -627,7 +627,7 @@ static char const *tdm_ch_text[] = {
 static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
 static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32",
 					     "KHZ_48", "KHZ_176P4",
-					     "KHZ_352P8"};
+					     "KHZ_352P8", "KHZ_44P1", "KHZ_96"};
 static const char *const tdm_slot_num_text[] = {"One", "Two", "Four",
 	"Eight", "Sixteen", "ThirtyTwo"};
 static const char *const tdm_slot_width_text[] = {"16", "24", "32"};
@@ -1334,6 +1334,12 @@ static int tdm_get_sample_rate(int value)
 	case 5:
 		sample_rate = SAMPLING_RATE_352P8KHZ;
 		break;
+	case 6:
+		sample_rate = SAMPLING_RATE_44P1KHZ:
+		break;
+	case 7:
+		sample_rate = SAMPLING_RATE_96KHZ;
+		break;
 	default:
 		sample_rate = SAMPLING_RATE_48KHZ;
 		break;
@@ -1380,6 +1386,12 @@ static int tdm_get_sample_rate_val(int sample_rate)
 	case SAMPLING_RATE_352P8KHZ:
 		sample_rate_val = 5;
 		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 7;
+		break;
 	default:
 		sample_rate_val = 3;
 		break;

+ 13 - 1
asoc/sa8155.c

@@ -631,7 +631,7 @@ static char const *tdm_ch_text[] = {
 static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
 static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32",
 					     "KHZ_48", "KHZ_176P4",
-					     "KHZ_352P8"};
+					     "KHZ_352P8", "KHZ_44P1", "KHZ_96"};
 static const char *const tdm_slot_num_text[] = {"One", "Two", "Four",
 	"Eight", "Sixteen", "ThirtyTwo"};
 static const char *const tdm_slot_width_text[] = {"16", "24", "32"};
@@ -1338,6 +1338,12 @@ static int tdm_get_sample_rate(int value)
 	case 5:
 		sample_rate = SAMPLING_RATE_352P8KHZ;
 		break;
+	case 6:
+		sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 7:
+		sample_rate = SAMPLING_RATE_96KHZ;
+		break;
 	default:
 		sample_rate = SAMPLING_RATE_48KHZ;
 		break;
@@ -1384,6 +1390,12 @@ static int tdm_get_sample_rate_val(int sample_rate)
 	case SAMPLING_RATE_352P8KHZ:
 		sample_rate_val = 5;
 		break;
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 6;
+		break;
+	case SAMPLING_RATE_96KHZ:
+		sample_rate_val = 7;
+		break;
 	default:
 		sample_rate_val = 3;
 		break;

+ 1 - 0
config/gvmauto.conf

@@ -13,3 +13,4 @@ CONFIG_SND_SOC_MSM_STUB=m
 CONFIG_SND_SOC_MSM_HDMI_CODEC_RX=m
 CONFIG_MSM_QDSP6V2_CODECS=m
 CONFIG_SND_EVENT=m
+CONFIG_SND_SOC_SA8155=m

+ 1 - 0
config/gvmautoconf.h

@@ -25,3 +25,4 @@
 #define CONFIG_SND_SOC_MSM_HDMI_CODEC_RX 1
 #define CONFIG_MSM_QDSP6V2_CODECS 1
 #define CONFIG_SND_EVENT 1
+#define CONFIG_SND_SOC_SA8155 1

+ 3 - 0
config/holiauto.conf

@@ -31,4 +31,7 @@ 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_TDM_DISABLE=m
+export CONFIG_MI2S_DISABLE=m
+export CONFIG_AUXPCM_DISABLE=m
 export CONFIG_DIGITAL_CDC_RSC_MGR=m

+ 3 - 0
config/holiautoconf.h

@@ -35,4 +35,7 @@
 #define CONFIG_SND_SOC_WSA881X_ANALOG 1
 #define CONFIG_SND_SOC_HOLI 1
 #define CONFIG_SND_EVENT 1
+#define CONFIG_TDM_DISABLE 1
+#define CONFIG_MI2S_DISABLE 1
+#define CONFIG_AUXPCM_DISABLE 1
 #define CONFIG_DIGITAL_CDC_RSC_MGR 1

+ 14 - 3
dsp/Kbuild

@@ -13,6 +13,18 @@ ifeq ($(KERNEL_BUILD), 1)
 	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
 endif
 
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+else
 ifeq ($(KERNEL_BUILD), 0)
 	ifeq ($(CONFIG_ARCH_SM6150), y)
 		ifdef CONFIG_SND_SOC_SA6155
@@ -71,14 +83,13 @@ ifeq ($(KERNEL_BUILD), 0)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
 	endif
-	ifeq ($(CONFIG_QTI_GVM), y)
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
 		include $(AUDIO_ROOT)/config/gvmauto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
 	endif
 endif
-
-
+endif
 
 # As per target team, build is done as follows:
 # Defconfig : build with default flags

+ 1 - 1
dsp/codecs/Kbuild

@@ -53,7 +53,7 @@ ifeq ($(KERNEL_BUILD), 0)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
 	endif
-	ifeq ($(CONFIG_QTI_GVM), y)
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
 		include $(AUDIO_ROOT)/config/gvmauto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h

+ 135 - 189
dsp/msm_audio_ion_vm.c

@@ -12,17 +12,14 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/dma-mapping.h>
-#include <linux/dma-contiguous.h>
 #include <linux/dma-buf.h>
 #include <linux/iommu.h>
 #include <linux/platform_device.h>
 #include <linux/of_device.h>
 #include <linux/export.h>
-#include <linux/ion_kernel.h>
+#include <linux/ion.h>
 #include <ipc/apr.h>
-#include <asm/dma-iommu.h>
 #include <dsp/msm_audio_ion.h>
-#include <soc/qcom/secure_buffer.h>
 #include <linux/habmm.h>
 
 #define MSM_AUDIO_ION_PROBED (1 << 0)
@@ -34,11 +31,6 @@
 #define MSM_AUDIO_SMMU_VM_CMD_UNMAP 0x00000002
 #define MSM_AUDIO_SMMU_VM_HAB_MINOR_ID 1
 
-enum msm_audio_mem_type{
-	MSM_AUDIO_MEM_TYPE_ION,
-	MSM_AUDIO_MEM_TYPE_DMA,
-};
-
 struct msm_audio_ion_private {
 	bool smmu_enabled;
 	struct device *cb_dev;
@@ -50,12 +42,10 @@ struct msm_audio_ion_private {
 struct msm_audio_alloc_data {
 	size_t len;
 	void *vaddr;
-	void *handle;
+	struct dma_buf *dma_buf;
 	struct dma_buf_attachment *attach;
 	struct sg_table *table;
 	struct list_head list;
-	dma_addr_t *paddr;
-	enum msm_audio_mem_type type;
 	u32 export_id;
 };
 
@@ -97,30 +87,7 @@ static void msm_audio_ion_add_allocation(
 	mutex_unlock(&(msm_audio_ion_data->list_mutex));
 }
 
-static int msm_audio_dma_buf_map(void *handle, void *vaddr,
-					  dma_addr_t *paddr,
-					  size_t *len)
-{
-	struct msm_audio_alloc_data *alloc_data;
-
-	/* Data required per buffer mapping */
-	alloc_data = kzalloc(sizeof(*alloc_data), GFP_KERNEL);
-	if (!alloc_data)
-		return -ENOMEM;
-
-	alloc_data->handle = handle;
-	alloc_data->len = *len;
-	alloc_data->vaddr = vaddr;
-	alloc_data->paddr = paddr;
-	alloc_data->type = MSM_AUDIO_MEM_TYPE_DMA;
-
-	msm_audio_ion_add_allocation(&msm_audio_ion_data,
-				     alloc_data);
-
-	return 0;
-}
-
-static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf,
+static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
 				 dma_addr_t *addr, size_t *len)
 {
 
@@ -136,13 +103,13 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf,
 	if (!alloc_data)
 		return -ENOMEM;
 
-	alloc_data->handle = (void*)dma_buf;
+	alloc_data->dma_buf = dma_buf;
 	alloc_data->len = dma_buf->size;
-	alloc_data->type = MSM_AUDIO_MEM_TYPE_ION;
 	*len = dma_buf->size;
 
 	/* Attach the dma_buf to context bank device */
-	alloc_data->attach = dma_buf_attach(dma_buf, cb_dev);
+	alloc_data->attach = dma_buf_attach(alloc_data->dma_buf,
+					    cb_dev);
 	if (IS_ERR(alloc_data->attach)) {
 		rc = PTR_ERR(alloc_data->attach);
 		dev_err(cb_dev,
@@ -152,7 +119,7 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf,
 	}
 
 	/* For uncached buffers, avoid cache maintanance */
-	rc = dma_buf_get_flags(dma_buf, &ionflag);
+	rc = dma_buf_get_flags(alloc_data->dma_buf, &ionflag);
 	if (rc) {
 		dev_err(cb_dev, "%s: dma_buf_get_flags failed: %d\n",
 			__func__, rc);
@@ -180,46 +147,21 @@ static int msm_audio_ion_dma_buf_map(struct dma_buf *dma_buf,
 
 	/* physical address from mapping */
 	*addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data);
-	alloc_data->paddr = addr;
+
 	msm_audio_ion_add_allocation(&msm_audio_ion_data,
 				     alloc_data);
 	return rc;
 
 detach_dma_buf:
-	dma_buf_detach(dma_buf, alloc_data->attach);
+	dma_buf_detach(alloc_data->dma_buf,
+		       alloc_data->attach);
 free_alloc_data:
 	kfree(alloc_data);
 
 	return rc;
 }
 
-static int msm_audio_ion_unmap_kernel(void *vaddr, void *handle)
-{
-	int rc = 0;
-	struct device *cb_dev = msm_audio_ion_data.cb_dev;
-
-	if (!vaddr) {
-		dev_err(cb_dev,
-			"%s: cannot find allocation for handle %pK\n",
-			__func__, handle);
-		rc = -EINVAL;
-		goto err;
-	}
-
-	dma_buf_vunmap((struct dma_buf*)handle, vaddr);
-
-	rc = dma_buf_end_cpu_access((struct dma_buf*)handle, DMA_BIDIRECTIONAL);
-	if (rc) {
-		dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n",
-			__func__);
-		goto err;
-	}
-
-err:
-	return rc;
-}
-
-static int msm_audio_dma_buf_unmap(void *handle)
+static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
 {
 	int rc = 0;
 	struct msm_audio_alloc_data *alloc_data = NULL;
@@ -233,68 +175,41 @@ static int msm_audio_dma_buf_unmap(void *handle)
 	 * on adding elements to the list.
 	 */
 	mutex_lock(&(msm_audio_ion_data.list_mutex));
-	list_for_each_safe(ptr, next, &(msm_audio_ion_data.alloc_list)) {
-
-		alloc_data = list_entry(ptr, struct msm_audio_alloc_data, list);
-		if(alloc_data->type == MSM_AUDIO_MEM_TYPE_ION) {
-			if (alloc_data->handle == handle) {
-				rc = msm_audio_ion_unmap_kernel(
-							alloc_data->vaddr,
-							handle);
-			if(rc) {
-				pr_err("%s: Unable to unmap ion mem rc: %d\n",
-				       __func__, rc);
-				mutex_unlock(&(msm_audio_ion_data.list_mutex));
-				return rc;
-			}
-
-				found = true;
-				dma_buf_unmap_attachment(alloc_data->attach,
-							 alloc_data->table,
-							 DMA_BIDIRECTIONAL);
-
-				dma_buf_detach((struct dma_buf*)
-						alloc_data->handle,
-					       alloc_data->attach);
+	list_for_each_safe(ptr, next,
+			    &(msm_audio_ion_data.alloc_list)) {
 
-				dma_buf_put((struct dma_buf*)
-					    alloc_data->handle);
+		alloc_data = list_entry(ptr, struct msm_audio_alloc_data,
+					list);
 
-				list_del(&(alloc_data->list));
-				kfree(alloc_data);
-				break;
-			}
-		} else {
-			alloc_data = list_entry(ptr,
-						struct msm_audio_alloc_data,
-						list);
+		if (alloc_data->dma_buf == dma_buf) {
+			found = true;
+			dma_buf_unmap_attachment(alloc_data->attach,
+						 alloc_data->table,
+						 DMA_BIDIRECTIONAL);
 
-			if (alloc_data->handle == handle) {
-				found = true;
+			dma_buf_detach(alloc_data->dma_buf,
+				       alloc_data->attach);
 
-				dma_free_coherent(cb_dev, alloc_data->len,
-						  alloc_data->vaddr,
-						  *(alloc_data->paddr));
+			dma_buf_put(alloc_data->dma_buf);
 
-				list_del(&(alloc_data->list));
-				kfree(alloc_data);
-				break;
-			}
+			list_del(&(alloc_data->list));
+			kfree(alloc_data);
+			break;
 		}
 	}
 	mutex_unlock(&(msm_audio_ion_data.list_mutex));
 
 	if (!found) {
 		dev_err(cb_dev,
-			"%s: cannot find allocation, handle %pK",
-			__func__, handle);
+			"%s: cannot find allocation, dma_buf %pK",
+			__func__, dma_buf);
 		rc = -EINVAL;
 	}
 
 	return rc;
 }
 
-static int msm_audio_ion_smmu_map(void *handle,
+static int msm_audio_ion_smmu_map(struct dma_buf *dma_buf,
 		dma_addr_t *paddr, size_t *len)
 {
 	int rc;
@@ -307,20 +222,20 @@ static int msm_audio_ion_smmu_map(void *handle,
 	struct msm_audio_alloc_data *alloc_data = NULL;
 	unsigned long delay = jiffies + (HZ / 2);
 
-	*len = ((struct dma_buf*)handle)->size;
+	*len = dma_buf->size;
 
 	mutex_lock(&(msm_audio_ion_data.list_mutex));
 	list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
 			    list) {
-		if (alloc_data->handle == handle) {
+		if (alloc_data->dma_buf == dma_buf) {
 			found = true;
 
 			/* Export the buffer to physical VM */
-			rc = habmm_export(msm_audio_ion_hab_handle, handle, *len,
+			rc = habmm_export(msm_audio_ion_hab_handle, dma_buf, *len,
 				&export_id, HABMM_EXPIMP_FLAGS_DMABUF);
 			if (rc) {
-				pr_err("%s: habmm_export failed handle = %pK, len = %zd, rc = %d\n",
-					__func__, handle, *len, rc);
+				pr_err("%s: habmm_export failed dma_buf = %pK, len = %zd, rc = %d\n",
+					__func__, dma_buf, *len, rc);
 				goto err;
 			}
 
@@ -374,7 +289,7 @@ static int msm_audio_ion_smmu_map(void *handle,
 	mutex_unlock(&(msm_audio_ion_data.list_mutex));
 
 	if (!found) {
-		pr_err("%s: cannot find allocation, handle %pK\n", __func__, handle);
+		pr_err("%s: cannot find allocation, dma_buf %pK", __func__, dma_buf);
 		return -EINVAL;
 	}
 
@@ -388,7 +303,7 @@ err:
 	return rc;
 }
 
-static int msm_audio_ion_smmu_unmap(void *handle)
+static int msm_audio_ion_smmu_unmap(struct dma_buf *dma_buf)
 {
 	int rc;
 	bool found = false;
@@ -407,7 +322,7 @@ static int msm_audio_ion_smmu_unmap(void *handle)
 	list_for_each_entry_safe(alloc_data, next,
 		&(msm_audio_ion_data.alloc_list), list) {
 
-		if (alloc_data->handle == handle) {
+		if (alloc_data->dma_buf == dma_buf) {
 			found = true;
 			smmu_unmap_cmd.cmd_id = MSM_AUDIO_SMMU_VM_CMD_UNMAP;
 			smmu_unmap_cmd.export_id = alloc_data->export_id;
@@ -463,7 +378,7 @@ static int msm_audio_ion_smmu_unmap(void *handle)
 	mutex_unlock(&(msm_audio_ion_data.list_mutex));
 
 	if (!found) {
-		pr_err("%s: cannot find allocation, handle %pK\n", __func__, handle);
+		pr_err("%s: cannot find allocation, dma_buf %pK\n", __func__, dma_buf);
 		rc = -EINVAL;
 	}
 
@@ -486,32 +401,31 @@ static int msm_audio_ion_get_phys(struct dma_buf *dma_buf,
 {
 	int rc = 0;
 
-	rc = msm_audio_ion_dma_buf_map(dma_buf, addr, len);
+	rc = msm_audio_dma_buf_map(dma_buf, addr, len);
 	if (rc) {
 		pr_err("%s: failed to map DMA buf, err = %d\n",
 			__func__, rc);
 		goto err;
 	}
 
-	pr_debug("phys=%pK, len=%zd, rc=%d\n", addr, *len, rc);
+	pr_debug("phys=%pK, len=%zd, rc=%d\n", &(*addr), *len, rc);
 err:
 	return rc;
 }
 
-static void *msm_audio_ion_map_kernel(void *handle)
+static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf)
 {
 	int rc = 0;
 	void *addr = NULL;
 	struct msm_audio_alloc_data *alloc_data = NULL;
 
-	rc = dma_buf_begin_cpu_access((struct dma_buf*)handle,
-				      DMA_BIDIRECTIONAL);
+	rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
 	if (rc) {
 		pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__);
 		goto exit;
 	}
 
-	addr = dma_buf_vmap((struct dma_buf*)handle);
+	addr = dma_buf_vmap(dma_buf);
 	if (!addr) {
 		pr_err("%s: kernel mapping of dma_buf failed\n",
 		       __func__);
@@ -525,7 +439,7 @@ static void *msm_audio_ion_map_kernel(void *handle)
 	mutex_lock(&(msm_audio_ion_data.list_mutex));
 	list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
 			    list) {
-		if (alloc_data->handle == handle) {
+		if (alloc_data->dma_buf == dma_buf) {
 			alloc_data->vaddr = addr;
 			break;
 		}
@@ -536,12 +450,54 @@ exit:
 	return addr;
 }
 
-static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr,
+static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
+{
+	int rc = 0;
+	void *vaddr = NULL;
+	struct msm_audio_alloc_data *alloc_data = NULL;
+	struct device *cb_dev = msm_audio_ion_data.cb_dev;
+
+	/*
+	 * TBD: remove the below section once new API
+	 * for unmapping kernel virtual address is available.
+	 */
+	mutex_lock(&(msm_audio_ion_data.list_mutex));
+	list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
+			    list) {
+		if (alloc_data->dma_buf == dma_buf) {
+			vaddr = alloc_data->vaddr;
+			break;
+		}
+	}
+	mutex_unlock(&(msm_audio_ion_data.list_mutex));
+
+	if (!vaddr) {
+		dev_err(cb_dev,
+			"%s: cannot find allocation for dma_buf %pK",
+			__func__, dma_buf);
+		rc = -EINVAL;
+		goto err;
+	}
+
+	dma_buf_vunmap(dma_buf, vaddr);
+
+	rc = dma_buf_end_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
+	if (rc) {
+		dev_err(cb_dev, "%s: kmap dma_buf_end_cpu_access fail\n",
+			__func__);
+		goto err;
+	}
+
+err:
+	return rc;
+}
+
+static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
 				 size_t *plen, void **vaddr)
 {
 	int rc = 0;
 
-	rc = msm_audio_ion_get_phys((struct dma_buf*) handle, paddr, plen);
+	rc = msm_audio_ion_get_phys(dma_buf, paddr, plen);
 	if (rc) {
 		pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
 				__func__, rc);
@@ -549,7 +505,7 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr,
 		goto err;
 	}
 
-	*vaddr = msm_audio_ion_map_kernel(handle);
+	*vaddr = msm_audio_ion_map_kernel(dma_buf);
 	if (IS_ERR_OR_NULL(*vaddr)) {
 		pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
 		rc = -ENOMEM;
@@ -558,11 +514,11 @@ static int msm_audio_ion_map_buf(void *handle, dma_addr_t *paddr,
 	}
 
 	if (msm_audio_ion_data.smmu_enabled) {
-		rc = msm_audio_ion_smmu_map(handle, paddr, plen);
+		rc = msm_audio_ion_smmu_map(dma_buf, paddr, plen);
 		if (rc) {
 			pr_err("%s: failed to do smmu map, err = %d\n",
 				__func__, rc);
-			msm_audio_dma_buf_unmap((struct dma_buf *) handle);
+			msm_audio_dma_buf_unmap(dma_buf);
 			goto err;
 		}
 	}
@@ -574,8 +530,7 @@ err:
  * msm_audio_ion_alloc -
  *        Allocs ION memory for given client name
  *
- * @handle: generic handle to the memory allocation
- *          dma_buf for the system heap memory. vaddr for audio heap memory.
+ * @dma_buf: dma_buf for the ION memory
  * @bufsz: buffer size
  * @paddr: Physical address to be assigned with allocated region
  * @plen: length of allocated region to be assigned
@@ -583,7 +538,7 @@ err:
  *
  * Returns 0 on success or error on failure
  */
-int msm_audio_ion_alloc(void **handle, size_t bufsz,
+int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
 			dma_addr_t *paddr, size_t *plen, void **vaddr)
 {
 	int rc = -EINVAL;
@@ -593,54 +548,41 @@ int msm_audio_ion_alloc(void **handle, size_t bufsz,
 		pr_debug("%s:probe is not done, deferred\n", __func__);
 		return -EPROBE_DEFER;
 	}
-	if (!handle || !paddr || !vaddr || !bufsz || !plen) {
+	if (!dma_buf || !paddr || !vaddr || !bufsz || !plen) {
 		pr_err("%s: Invalid params\n", __func__);
 		return -EINVAL;
 	}
 
 	if (msm_audio_ion_data.smmu_enabled == true) {
 		pr_debug("%s: system heap is used\n", __func__);
-		*handle = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
+		*dma_buf = ion_alloc(bufsz, ION_HEAP(ION_SYSTEM_HEAP_ID), 0);
 	} else {
 		pr_debug("%s: audio heap is used\n", __func__);
-		*vaddr = *handle = dma_alloc_coherent(
-						      msm_audio_ion_data.cb_dev,
-						      bufsz, paddr, GFP_KERNEL);
-		if(*vaddr != NULL) {
-			pr_err("%s: vaddr = %pK, size=%zd\n", __func__, *vaddr,
-			       bufsz);
-			rc = 0;
-		}
+		*dma_buf = ion_alloc(bufsz, ION_HEAP(ION_AUDIO_HEAP_ID), 0);
 	}
-	if (IS_ERR_OR_NULL((void *)(*handle))) {
-		if (IS_ERR((void *)(*handle)))
-			err_ion_ptr = PTR_ERR((int *)(*handle));
+	if (IS_ERR_OR_NULL((void *)(*dma_buf))) {
+		if (IS_ERR((void *)(*dma_buf)))
+			err_ion_ptr = PTR_ERR((int *)(*dma_buf));
 		pr_err("%s: ION alloc fail err ptr=%ld, smmu_enabled=%d\n",
 		       __func__, err_ion_ptr, msm_audio_ion_data.smmu_enabled);
 		rc = -ENOMEM;
 		goto err;
 	}
-	if (msm_audio_ion_data.smmu_enabled) {
-		rc = msm_audio_ion_map_buf(*handle, paddr, plen, vaddr);
-		if (rc) {
-			pr_err("%s: failed to map ION buf, rc = %d\n", __func__,
-			       rc);
-		}
-	} else {
-		rc = msm_audio_dma_buf_map(*handle, *vaddr, paddr,
-						    &bufsz);
-		if (rc) {
-			pr_err("%s: failed to map ION buf, rc = %d\n", __func__,
-				rc);
-			dma_free_coherent(msm_audio_ion_data.cb_dev,
-					  bufsz, vaddr, *paddr);
-		}
+
+	rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr);
+	if (rc) {
+		pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
+		goto err_dma_buf;
 	}
 	pr_debug("%s: mapped address = %pK, size=%zd\n", __func__,
 		*vaddr, bufsz);
 
 	memset(*vaddr, 0, bufsz);
 
+	return rc;
+
+err_dma_buf:
+	dma_buf_put(*dma_buf);
 err:
 	return rc;
 }
@@ -675,8 +617,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported);
  * msm_audio_ion_import-
  *        Import ION buffer with given file descriptor
  *
- * @handle: generic handle to the memory allocation
- *          dma_buf for the system heap memory. vaddr for audio heap memory.
+ * @dma_buf: dma_buf for the ION memory
  * @fd: file descriptor for the ION memory
  * @ionflag: flags associated with ION buffer
  * @bufsz: buffer size
@@ -686,7 +627,7 @@ EXPORT_SYMBOL(msm_audio_is_hypervisor_supported);
  *
  * Returns 0 on success or error on failure
  */
-int msm_audio_ion_import(void **handle, int fd,
+int msm_audio_ion_import(struct dma_buf **dma_buf, int fd,
 			unsigned long *ionflag, size_t bufsz,
 			dma_addr_t *paddr, size_t *plen, void **vaddr)
 {
@@ -697,22 +638,22 @@ int msm_audio_ion_import(void **handle, int fd,
 		return -EPROBE_DEFER;
 	}
 
-	if (!handle || !paddr || !vaddr || !plen) {
+	if (!dma_buf || !paddr || !vaddr || !plen) {
 		pr_err("%s: Invalid params\n", __func__);
 		return -EINVAL;
 	}
 
 	/* bufsz should be 0 and fd shouldn't be 0 as of now */
-	*handle = dma_buf_get(fd);
-	pr_debug("%s: handle =%pK, fd=%d\n", __func__, *handle, fd);
-	if (IS_ERR_OR_NULL((void *)(*handle))) {
+	*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((struct dma_buf*)*handle, ionflag);
+		rc = dma_buf_get_flags(*dma_buf, ionflag);
 		if (rc) {
 			pr_err("%s: could not get flags for the dma_buf\n",
 				__func__);
@@ -720,7 +661,7 @@ int msm_audio_ion_import(void **handle, int fd,
 		}
 	}
 
-	rc = msm_audio_ion_map_buf(*handle, paddr, plen, vaddr);
+	rc = msm_audio_ion_map_buf(*dma_buf, paddr, plen, vaddr);
 	if (rc) {
 		pr_err("%s: failed to map ION buf, rc = %d\n", __func__, rc);
 		goto err;
@@ -731,9 +672,9 @@ int msm_audio_ion_import(void **handle, int fd,
 	return 0;
 
 err_ion_flag:
-	dma_buf_put((struct dma_buf*) *handle);
+	dma_buf_put(*dma_buf);
 err:
-	*handle = NULL;
+	*dma_buf = NULL;
 	return rc;
 }
 EXPORT_SYMBOL(msm_audio_ion_import);
@@ -742,28 +683,31 @@ EXPORT_SYMBOL(msm_audio_ion_import);
  * msm_audio_ion_free -
  *        fress ION memory for given client and handle
  *
- * @handle: generic handle to the memory allocation
- *          dma_buf for the system heap memory. vaddr for audio heap memory.
+ * @dma_buf: dma_buf for the ION memory
  *
  * Returns 0 on success or error on failure
  */
-int msm_audio_ion_free(void *handle)
+int msm_audio_ion_free(struct dma_buf *dma_buf)
 {
 	int ret = 0;
 
-	if (!handle) {
-		pr_err("%s: handle invalid\n", __func__);
+	if (!dma_buf) {
+		pr_err("%s: dma_buf invalid\n", __func__);
 		return -EINVAL;
 	}
 
+	ret = msm_audio_ion_unmap_kernel(dma_buf);
+	if (ret)
+		return ret;
+
 	if (msm_audio_ion_data.smmu_enabled) {
-		ret = msm_audio_ion_smmu_unmap(handle);
+		ret = msm_audio_ion_smmu_unmap(dma_buf);
 		if (ret)
 			pr_err("%s: smmu unmap failed with ret %d\n",
 				__func__, ret);
 	}
 
-	msm_audio_dma_buf_unmap(handle);
+	msm_audio_dma_buf_unmap(dma_buf);
 
 	return 0;
 }
@@ -795,7 +739,7 @@ int msm_audio_ion_mmap(struct audio_buffer *abuff,
 	mutex_lock(&(msm_audio_ion_data.list_mutex));
 	list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
 			    list) {
-		if (alloc_data->handle == abuff->mem_handle) {
+		if (alloc_data->dma_buf == abuff->dma_buf) {
 			found = true;
 			table = alloc_data->table;
 			break;
@@ -806,7 +750,7 @@ int msm_audio_ion_mmap(struct audio_buffer *abuff,
 	if (!found) {
 		dev_err(cb_dev,
 			"%s: cannot find allocation, dma_buf %pK",
-			__func__, abuff->mem_handle);
+			__func__, abuff->dma_buf);
 		return -EINVAL;
 	}
 	/* uncached */
@@ -912,13 +856,14 @@ static int msm_audio_ion_probe(struct platform_device *pdev)
 	dev_info(dev, "%s: msm_audio_ion_hab_handle %x\n",
 		__func__, msm_audio_ion_hab_handle);
 
+	INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
+	mutex_init(&(msm_audio_ion_data.list_mutex));
+
 exit:
 	if (!rc)
 		msm_audio_ion_data.device_status |= MSM_AUDIO_ION_PROBED;
 
 	msm_audio_ion_data.cb_dev = dev;
-	INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
-	mutex_init(&(msm_audio_ion_data.list_mutex));
 
 	return rc;
 }
@@ -928,10 +873,11 @@ static int msm_audio_ion_remove(struct platform_device *pdev)
 	if (msm_audio_ion_data.smmu_enabled) {
 		if (msm_audio_ion_hab_handle)
 			habmm_socket_close(msm_audio_ion_hab_handle);
+
+		mutex_destroy(&(msm_audio_ion_data.list_mutex));
 	}
 	msm_audio_ion_data.smmu_enabled = 0;
 	msm_audio_ion_data.device_status = 0;
-	mutex_destroy(&(msm_audio_ion_data.list_mutex));
 	return 0;
 }
 

+ 380 - 53
dsp/q6afe.c

@@ -247,45 +247,77 @@ struct afe_ctl {
 	uint32_t initial_cal;
 	uint32_t v_vali_flag;
 	uint32_t num_spkrs;
+	uint32_t cps_ch_mask;
+	struct afe_cps_hw_intf_cfg *cps_config;
 };
 
 struct afe_clkinfo_per_port {
 	u16 port_id; /* AFE port ID */
 	uint32_t clk_id; /* Clock ID */
+	uint32_t mclk_src_id; /* MCLK SRC ID */
+	uint32_t mclk_freq; /* MCLK_FREQ */
 };
 
-struct afe_clkinfo_per_port clkinfo_per_port[] = {
-	{ AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
-	{ AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT},
-	{ AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT},
-	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT},
-	{ AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT},
-	{ AFE_PORT_ID_SENARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT},
-	{ AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT},
-	{ AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT},
-	{ AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT},
-	{ AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT},
-	{ AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT},
-	{ AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT},
-	{ AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT},
-	{ AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT},
-	{ AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT},
-	{ AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT},
-	{ AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT},
+struct afe_ext_mclk_cb_info {
+	afe_enable_mclk_and_get_info_cb_func ext_mclk_cb;
+	void *private_data;
+};
+
+static struct afe_clkinfo_per_port clkinfo_per_port[] = {
+	{ AFE_PORT_ID_PRIMARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_SECONDARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_TERTIARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_QUATERNARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_QUINARY_MI2S_RX, Q6AFE_LPASS_CLK_ID_QUI_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_SENARY_MI2S_TX, Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_PRIMARY_PCM_RX, Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_SECONDARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEC_PCM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_TERTIARY_PCM_RX, Q6AFE_LPASS_CLK_ID_TER_PCM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_QUATERNARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUAD_PCM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_QUINARY_PCM_RX, Q6AFE_LPASS_CLK_ID_QUIN_PCM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_SENARY_PCM_RX, Q6AFE_LPASS_CLK_ID_SEN_PCM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_PRIMARY_TDM_RX, Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_SECONDARY_TDM_RX, Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_TERTIARY_TDM_RX, Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_QUATERNARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_QUINARY_TDM_RX, Q6AFE_LPASS_CLK_ID_QUIN_TDM_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
 	{ AFE_PORT_ID_PRIMARY_SPDIF_RX,
-		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE},
+		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_OUTPUT_CORE,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
 	{ AFE_PORT_ID_PRIMARY_SPDIF_TX,
-		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE},
+		AFE_CLOCK_SET_CLOCK_ID_PRI_SPDIF_INPUT_CORE,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
 	{ AFE_PORT_ID_SECONDARY_SPDIF_RX,
-		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE},
+		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_OUTPUT_CORE,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
 	{ AFE_PORT_ID_SECONDARY_SPDIF_TX,
-		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE},
-	{ AFE_PORT_ID_PRIMARY_META_MI2S_RX,
-		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
-	{ AFE_PORT_ID_SECONDARY_META_MI2S_RX,
-		Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT},
+		AFE_CLOCK_SET_CLOCK_ID_SEC_SPDIF_INPUT_CORE,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_PRIMARY_META_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
+	{ AFE_PORT_ID_SECONDARY_META_MI2S_RX, Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
+		MCLK_SRC_INT, Q6AFE_EXT_MCLK_FREQ_DEFAULT},
 };
 
+static struct afe_ext_mclk_cb_info afe_ext_mclk;
+
 static atomic_t afe_ports_mad_type[SLIMBUS_PORT_LAST - SLIMBUS_0_RX];
 static unsigned long afe_configured_cmd;
 
@@ -425,6 +457,37 @@ static int afe_get_cal_hw_delay(int32_t path,
 				struct audio_cal_hw_delay_entry *entry);
 static int remap_cal_data(struct cal_block_data *cal_block, int cal_index);
 
+/**
+ * afe_register_ext_mclk_cb - register callback for external mclk
+ *
+ * @fn - external mclk callback function
+ * @private_data - external mclk callback specific data
+ *
+ * Returns 0 in case of success and -EINVAL for failure
+ */
+int afe_register_ext_mclk_cb(afe_enable_mclk_and_get_info_cb_func fn,
+				void *private_data)
+{
+	if (fn && private_data) {
+		afe_ext_mclk.ext_mclk_cb = fn;
+		afe_ext_mclk.private_data = private_data;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL(afe_register_ext_mclk_cb);
+
+/**
+ * afe_unregister_ext_mclk_cb - unregister external mclk callback
+ */
+void afe_unregister_ext_mclk_cb(void)
+{
+	afe_ext_mclk.ext_mclk_cb = NULL;
+	afe_ext_mclk.private_data = NULL;
+}
+EXPORT_SYMBOL(afe_unregister_ext_mclk_cb);
+
 int afe_get_spk_initial_cal(void)
 {
 	return this_afe.initial_cal;
@@ -2179,46 +2242,53 @@ fail_cmd:
 	return ret;
 }
 
-/**
- * afe_send_cps_config -
- *         to send cps speaker protection configuration
- *
- * @src_port: source port to send configuration to
- * @cps_config: cps speaker protection v4 configuration
- * @param_size: size of payload
- *
- * Returns 0 on success or error value on failure.
- */
-int afe_send_cps_config(int src_port,
-			struct afe_cps_hw_intf_cfg *cps_config,
-			int param_size)
+static int afe_send_cps_config(int src_port)
 {
+	int i = 0;
 	struct param_hdr_v3 param_info;
 	int ret = -EINVAL;
 	u8 *packed_payload = NULL;
 	int cpy_size = 0;
+	int ch_copied = 0;
+	size_t param_size = 0;
 
-	ret = q6audio_validate_port(src_port);
-	if (ret < 0) {
-		pr_err("%s: Invalid src port 0x%x ret %d", __func__,
-		       src_port, ret);
+	if ((-1 == this_afe.vi_tx_port) || (!this_afe.cps_ch_mask) ||
+	    (!this_afe.cps_config)) {
+		pr_err("%s: speaker prot not configured for 0x%x\n", __func__,
+		       src_port);
 		return -EINVAL;
 	}
 
+	param_size = sizeof(struct afe_cps_hw_intf_cfg) -
+			sizeof(this_afe.cps_config->spkr_dep_cfg) +
+			(sizeof(struct lpass_swr_spkr_dep_cfg_t)
+				* this_afe.num_spkrs);
+
+	this_afe.cps_config->hw_reg_cfg.num_spkr = this_afe.num_spkrs;
 	packed_payload = kzalloc(param_size, GFP_KERNEL);
 	if (packed_payload == NULL)
 		return -ENOMEM;
 
 	cpy_size = sizeof(struct afe_cps_hw_intf_cfg) -
-			sizeof(cps_config->spkr_dep_cfg);
-	memcpy(packed_payload, cps_config, cpy_size);
-	memcpy(packed_payload + cpy_size, cps_config->spkr_dep_cfg,
-		sizeof(struct lpass_swr_spkr_dep_cfg_t)
-			* cps_config->hw_reg_cfg.num_spkr);
+			sizeof(this_afe.cps_config->spkr_dep_cfg);
+	memcpy(packed_payload, this_afe.cps_config, cpy_size);
+
+	while (ch_copied < this_afe.num_spkrs) {
+		if (!(this_afe.cps_ch_mask & (1 << i))) {
+			i++;
+			continue;
+		}
+
+		memcpy(packed_payload + cpy_size,
+			&this_afe.cps_config->spkr_dep_cfg[i],
+			sizeof(struct lpass_swr_spkr_dep_cfg_t));
+		cpy_size += sizeof(struct lpass_swr_spkr_dep_cfg_t);
+		ch_copied++;
+		i++;
+	}
 
 	memset(&param_info, 0, sizeof(param_info));
 
-	mutex_lock(&this_afe.afe_cmd_lock);
 	param_info.module_id = AFE_MODULE_SPEAKER_PROTECTION_V4_RX;
 	param_info.instance_id = INSTANCE_ID_0;
 	param_info.param_id = AFE_PARAM_ID_CPS_LPASS_HW_INTF_CFG;
@@ -2231,13 +2301,11 @@ int afe_send_cps_config(int src_port,
 		pr_err("%s: port = 0x%x param = 0x%x failed %d\n", __func__,
 		       src_port, param_info.param_id, ret);
 
-	mutex_unlock(&this_afe.afe_cmd_lock);
 	pr_debug("%s: config.pdata.param_id 0x%x status %d 0x%x\n", __func__,
 		 param_info.param_id, ret, src_port);
 	kfree(packed_payload);
 	return ret;
 }
-EXPORT_SYMBOL(afe_send_cps_config);
 
 static int afe_spk_prot_prepare(int src_port, int dst_port, int param_id,
 		union afe_spkr_prot_config *prot_config, uint32_t param_size)
@@ -3036,6 +3104,63 @@ unlock:
 	return ret;
 }
 
+static int afe_port_topology_deregister(u16 port_id)
+{
+	struct param_hdr_v3 param_info;
+	int ret = 0;
+	uint32_t build_major_version = 0;
+	uint32_t build_minor_version = 0;
+	uint32_t build_branch_version = 0;
+	uint32_t afe_api_version = 0;
+
+	ret = q6core_get_avcs_avs_build_version_info(&build_major_version,
+						     &build_minor_version,
+						     &build_branch_version);
+	if (ret < 0) {
+		pr_err("%s: get AVS build versions failed %d\n",
+		       __func__, ret);
+		goto done;
+	}
+
+	afe_api_version = q6core_get_avcs_api_version_per_service(
+					APRV2_IDS_SERVICE_ID_ADSP_AFE_V);
+	if (afe_api_version < 0) {
+		ret = -EINVAL;
+		goto done;
+	}
+	pr_debug("%s: major: %u, minor: %u, branch: %u, afe_api: %u\n",
+		 __func__, build_major_version, build_minor_version,
+		 build_branch_version, afe_api_version);
+
+	if (build_major_version != AVS_BUILD_MAJOR_VERSION_V2 ||
+	    build_minor_version != AVS_BUILD_MINOR_VERSION_V9 ||
+	    (build_branch_version != AVS_BUILD_BRANCH_VERSION_V0 &&
+	     build_branch_version != AVS_BUILD_BRANCH_VERSION_V3) ||
+	    afe_api_version < AFE_API_VERSION_V9) {
+		ret = -EINVAL;
+		pr_err("%s: AVS build versions mismatched %d\n",
+		       __func__, ret);
+		goto done;
+	}
+
+	memset(&param_info, 0, sizeof(param_info));
+	param_info.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
+	param_info.instance_id = INSTANCE_ID_0;
+	param_info.param_id = AFE_PARAM_ID_DEREGISTER_TOPOLOGY;
+	param_info.param_size =  0;
+	ret = q6afe_pack_and_set_param_in_band(port_id,
+					q6audio_get_port_index(port_id),
+					param_info, NULL);
+	if (ret < 0)
+		pr_err("%s: AFE deregister topology for port 0x%x failed %d\n",
+		       __func__, port_id, ret);
+
+done:
+	pr_debug("%s: AFE port 0x%x deregister topology, ret %d\n",
+		 __func__, port_id, ret);
+	return ret;
+}
+
 static int afe_send_port_topology_id(u16 port_id)
 {
 	struct afe_param_id_set_topology_cfg topology;
@@ -5517,11 +5642,24 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
 	if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE)) {
 		/* One time call: only for first time */
 		afe_send_custom_topology();
+		/*
+		 * Deregister existing afe topology before
+		 * sending a new one for VA use cases only
+		 */
+		if (port_id == AFE_PORT_ID_VA_CODEC_DMA_TX_0 ||
+		    port_id == AFE_PORT_ID_VA_CODEC_DMA_TX_1 ||
+		    port_id == AFE_PORT_ID_VA_CODEC_DMA_TX_2)
+			afe_port_topology_deregister(port_id);
 		afe_send_port_topology_id(port_id);
 		afe_send_cal(port_id);
 		afe_send_hw_delay(port_id, rate);
 	}
 
+	if ((this_afe.cps_config) &&
+	    (this_afe.vi_rx_port == port_id)) {
+		afe_send_cps_config(port_id);
+	}
+
 	/* Start SW MAD module */
 	mad_type = afe_port_get_mad_type(port_id);
 	pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id,
@@ -8980,6 +9118,89 @@ int afe_set_pll_clk_drift(u16 port_id, int32_t set_clk_drift,
 }
 EXPORT_SYMBOL(afe_set_pll_clk_drift);
 
+static int afe_set_lpass_clk_cfg_ext_mclk(int index, struct afe_clk_set *cfg,
+							uint32_t mclk_freq)
+{
+	struct param_hdr_v3 param_hdr;
+	struct afe_param_id_clock_set_v2_t dyn_mclk_cfg;
+	int ret = 0;
+
+	if (!cfg) {
+		pr_err("%s: clock cfg is NULL\n", __func__);
+		ret = -EINVAL;
+		return ret;
+	}
+
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: index[%d] invalid!\n", __func__, index);
+		return -EINVAL;
+	}
+
+	memset(&param_hdr, 0, sizeof(param_hdr));
+	param_hdr.module_id = AFE_MODULE_CLOCK_SET;
+	param_hdr.instance_id = INSTANCE_ID_0;
+	param_hdr.param_id = AFE_PARAM_ID_CLOCK_SET_V2;
+	param_hdr.param_size = sizeof(struct afe_param_id_clock_set_v2_t);
+
+	memset(&dyn_mclk_cfg, 0, sizeof(dyn_mclk_cfg));
+	dyn_mclk_cfg.clk_freq_in_hz = cfg->clk_freq_in_hz;
+	if (afe_ext_mclk.ext_mclk_cb) {
+		ret =  afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
+			cfg->enable, mclk_freq, &dyn_mclk_cfg);
+		if (ret) {
+			pr_err_ratelimited("%s: get mclk cfg failed %d\n",
+					__func__, ret);
+			return ret;
+		}
+	} else {
+		pr_err_ratelimited("%s: mclk callback not registered\n",
+					__func__);
+		return -EINVAL;
+	}
+
+	dyn_mclk_cfg.clk_set_minor_version = 1;
+	dyn_mclk_cfg.clk_id = cfg->clk_id;
+	dyn_mclk_cfg.clk_attri = cfg->clk_attri;
+	dyn_mclk_cfg.enable = cfg->enable;
+
+	pr_debug("%s: Minor version =0x%x clk id = %d\n", __func__,
+		dyn_mclk_cfg.clk_set_minor_version, dyn_mclk_cfg.clk_id);
+	pr_debug("%s: clk freq (Hz) = %d, clk attri = 0x%x\n", __func__,
+		dyn_mclk_cfg.clk_freq_in_hz, dyn_mclk_cfg.clk_attri);
+	pr_debug("%s: clk root = 0x%x clk enable = 0x%x\n", __func__,
+		dyn_mclk_cfg.clk_root, dyn_mclk_cfg.enable);
+	pr_debug("%s: divider_2x =%d m = %d n = %d, d =%d\n", __func__,
+		dyn_mclk_cfg.divider_2x, dyn_mclk_cfg.m, dyn_mclk_cfg.n,
+		dyn_mclk_cfg.d);
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0) {
+		pr_err_ratelimited("%s: Q6 interface prepare failed %d\n",
+				__func__, ret);
+		goto stop_mclk;
+	}
+
+	mutex_lock(&this_afe.afe_cmd_lock);
+	ret = q6afe_svc_pack_and_set_param_in_band(index, param_hdr,
+						   (u8 *) &dyn_mclk_cfg);
+	if (ret < 0)
+		pr_err_ratelimited("%s: ext MCLK clk cfg failed with ret %d\n",
+				__func__, ret);
+
+	mutex_unlock(&this_afe.afe_cmd_lock);
+
+	if (ret >= 0)
+		return ret;
+
+stop_mclk:
+	if (afe_ext_mclk.ext_mclk_cb && cfg->enable) {
+		afe_ext_mclk.ext_mclk_cb(afe_ext_mclk.private_data,
+				cfg->enable, mclk_freq, &dyn_mclk_cfg);
+	}
+
+	return ret;
+}
+
 /**
  * afe_set_lpass_clk_cfg - Set AFE clk config
  *
@@ -9052,6 +9273,11 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
 {
 	int index = 0;
 	int ret = 0;
+	u16 idx = 0;
+	uint32_t build_major_version = 0;
+	uint32_t build_minor_version = 0;
+	uint32_t build_branch_version = 0;
+	int afe_api_version = 0;
 
 	index = q6audio_get_port_index(port_id);
 	if (index < 0 || index >= AFE_MAX_PORTS) {
@@ -9068,9 +9294,49 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
 
 	ret = afe_set_clk_id(port_id, cfg->clk_id);
 	if (ret < 0)
-		pr_debug("%s: afe_set_clk_id fail %d\n", __func__, ret);
+		pr_err("%s: afe_set_clk_id fail %d\n", __func__, ret);
+
+	idx = afe_get_port_idx(port_id);
+	if (idx < 0) {
+		pr_err("%s: cannot get clock id for port id 0x%x\n", __func__,
+			port_id);
+		return -EINVAL;
+	}
+
+	if (clkinfo_per_port[idx].mclk_src_id != MCLK_SRC_INT) {
+		pr_debug("%s: ext MCLK src %d\n",
+			__func__, clkinfo_per_port[idx].mclk_src_id);
+
+		ret = q6core_get_avcs_avs_build_version_info(
+			&build_major_version, &build_minor_version,
+						&build_branch_version);
+		if (ret < 0)
+			return ret;
+
+		ret = q6core_get_avcs_api_version_per_service(
+					APRV2_IDS_SERVICE_ID_ADSP_AFE_V);
+		if (ret < 0)
+			return ret;
+
+		afe_api_version = ret;
+
+		pr_debug("%s: mjor: %u, mnor: %u, brnch: %u, afe_api: %u\n",
+			__func__, build_major_version, build_minor_version,
+			build_branch_version, afe_api_version);
+		if ((build_major_version != AVS_BUILD_MAJOR_VERSION_V2) ||
+		    (build_minor_version != AVS_BUILD_MINOR_VERSION_V9) ||
+		    (build_branch_version != AVS_BUILD_BRANCH_VERSION_V3) ||
+		    (afe_api_version < AFE_API_VERSION_V8)) {
+			pr_err("%s: ext mclk not supported by AVS\n", __func__);
+			return -EINVAL;
+		}
+
+		ret = afe_set_lpass_clk_cfg_ext_mclk(index, cfg,
+					clkinfo_per_port[idx].mclk_freq);
+	} else {
+		ret = afe_set_lpass_clk_cfg(index, cfg);
+	}
 
-	ret = afe_set_lpass_clk_cfg(index, cfg);
 	if (ret)
 		pr_err("%s: afe_set_lpass_clk_cfg_v2 failed %d\n",
 			__func__, ret);
@@ -9079,6 +9345,36 @@ int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg)
 }
 EXPORT_SYMBOL(afe_set_lpass_clock_v2);
 
+/**
+ * afe_set_mclk_src_cfg - Set audio interface MCLK source configuration
+ *
+ * @port_id: AFE port id
+ * @mclk_src_id: mclk id to represent internal or one of external MCLK
+ * @mclk_freq: frequency of the MCLK
+ *
+ * Returns 0 on success, appropriate error code otherwise
+ */
+int afe_set_mclk_src_cfg(u16 port_id, uint32_t mclk_src_id, uint32_t mclk_freq)
+{
+	int idx = 0;
+
+	idx = afe_get_port_idx(port_id);
+	if (idx < 0) {
+		pr_err("%s: cannot get clock id for port id 0x%x\n",
+			__func__, port_id);
+		return -EINVAL;
+	}
+
+	clkinfo_per_port[idx].mclk_src_id = mclk_src_id;
+	clkinfo_per_port[idx].mclk_freq = mclk_freq;
+
+	pr_debug("%s: mclk src id 0x%x mclk_freq %d port id 0x%x\n",
+		__func__, mclk_src_id, mclk_freq, port_id);
+
+	return 0;
+}
+EXPORT_SYMBOL(afe_set_mclk_src_cfg);
+
 int afe_set_lpass_internal_digital_codec_clock(u16 port_id,
 			struct afe_digital_clk_cfg *cfg)
 {
@@ -11082,3 +11378,34 @@ done:
 	return ret;
 }
 EXPORT_SYMBOL(afe_unvote_lpass_core_hw);
+
+/**
+ * afe_set_cps_config -
+ *         to set cps speaker protection configuration
+ *
+ * @src_port: source port to send configuration to
+ * @cps_config: cps speaker protection v4 configuration
+ * @ch_mask: channel mask
+ *
+ */
+void afe_set_cps_config(int src_port,
+			struct afe_cps_hw_intf_cfg *cps_config,
+			u32 ch_mask)
+{
+	this_afe.cps_config = NULL;
+	this_afe.cps_ch_mask = 0;
+
+	if (!cps_config) {
+		pr_err("%s: cps config is NULL\n", __func__);
+		return;
+	}
+
+	if (q6audio_validate_port(src_port) < 0) {
+		pr_err("%s: Invalid src port 0x%x\n", __func__, src_port);
+		return;
+	}
+
+	this_afe.cps_ch_mask = ch_mask;
+	this_afe.cps_config = cps_config;
+}
+EXPORT_SYMBOL(afe_set_cps_config);

+ 38 - 0
dsp/q6core.c

@@ -737,6 +737,44 @@ int q6core_get_avcs_api_version_per_service(uint32_t service_id)
 }
 EXPORT_SYMBOL(q6core_get_avcs_api_version_per_service);
 
+/**
+ * q6core_get_avcs_avs_build_version_info - Get AVS build version information
+ *
+ * @build_major_version - pointer to build major version
+ * @build_minor_version - pointer to build minor version
+ * @build_branch_version - pointer to build branch version
+ *
+ * Returns 0 on success and error on failure
+ */
+int q6core_get_avcs_avs_build_version_info(
+	uint32_t *build_major_version, uint32_t *build_minor_version,
+					uint32_t *build_branch_version)
+{
+
+	struct avcs_fwk_ver_info *cached_ver_info = NULL;
+	int ret = 0;
+
+	if (!build_major_version || !build_minor_version ||
+		!build_branch_version)
+		return -EINVAL;
+
+	ret = q6core_get_avcs_fwk_version();
+	if (ret < 0)
+		return ret;
+
+	cached_ver_info = q6core_lcl.q6core_avcs_ver_info.ver_info;
+
+	*build_major_version =
+			cached_ver_info->avcs_fwk_version.build_major_version;
+	*build_minor_version =
+			cached_ver_info->avcs_fwk_version.build_minor_version;
+	*build_branch_version =
+			cached_ver_info->avcs_fwk_version.build_branch_version;
+
+	return ret;
+}
+EXPORT_SYMBOL(q6core_get_avcs_avs_build_version_info);
+
 /**
  * core_set_license -
  *       command to set license for module

+ 82 - 38
dsp/q6voice.c

@@ -1291,6 +1291,7 @@ static int voice_unmap_cal_block(struct voice_data *v, int cal_index)
 		if (cal_block->cal_data.paddr == 0 ||
 		    cal_block->map_data.map_size <= 0) {
 			pr_err("%s: No address to map!\n", __func__);
+			cal_block->map_data.q6map_handle = 0;
 			result = -EINVAL;
 			goto unlock;
 		}
@@ -1301,6 +1302,7 @@ static int voice_unmap_cal_block(struct voice_data *v, int cal_index)
 			pr_err("%s: hyp_assign_phys failed result = %d addr = 0x%pK size = %d\n",
 				__func__, result, cal_block->cal_data.paddr,
 				cal_block->map_data.map_size);
+			cal_block->map_data.q6map_handle = 0;
 			result = -EINVAL;
 			goto unlock;
 		}
@@ -1337,42 +1339,6 @@ static int voice_destroy_mvm_cvs_session(struct voice_data *v)
 	if (!apr_mvm || !apr_cvs) {
 		pr_err("%s: apr_mvm or apr_cvs is NULL\n", __func__);
 		ret = -EINVAL;
-
-		pr_debug("%s: use hyp assigned %d\n",__func__, hyp_assigned);
-		if (hyp_assigned) {
-			mutex_lock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
-			cal_block = cal_utils_get_only_cal_block(
-					common.cal_data[CVP_VOCPROC_CAL]);
-			if (cal_block == NULL) {
-				pr_err("%s: Cal block NULL, CVP_VOCPROC_CAL!\n",
-					__func__);
-				mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
-				goto fail;
-			}
-			if (cal_block->cma_mem) {
-				if (cal_block->cal_data.paddr == 0 ||
-				    cal_block->map_data.map_size <= 0) {
-					pr_err("%s: No address to map!\n", __func__);
-					mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
-					goto fail;
-				}
-				result = hyp_assign_phys(
-						cal_block->cal_data.paddr,
-						cal_block->map_data.map_size,
-						source_vm, 2, dest_vm, dest_perms, 1);
-				if (result < 0) {
-					pr_err("%s: hyp_assign_phys failed result = %d addr = 0x%pK size = %d\n",
-						__func__, result,
-						cal_block->cal_data.paddr,
-						cal_block->map_data.map_size);
-					mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
-					goto fail;
-				}
-				hyp_assigned = false;
-				pr_debug("%s: hyp_assign_phys success\n", __func__);
-				mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
-			}
-		}
 		goto fail;
 	}
 	mvm_handle = voice_get_mvm_handle(v);
@@ -1547,6 +1513,41 @@ static int voice_destroy_mvm_cvs_session(struct voice_data *v)
 	}
 	return 0;
 fail:
+	pr_debug("%s: use hyp assigned %d\n",__func__, hyp_assigned);
+	if (hyp_assigned) {
+		mutex_lock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+		cal_block = cal_utils_get_only_cal_block(
+				common.cal_data[CVP_VOCPROC_CAL]);
+		if (cal_block == NULL) {
+			pr_err("%s: Cal block NULL, CVP_VOCPROC_CAL!\n",
+				__func__);
+			mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+			return -EINVAL;
+		}
+		if (cal_block->cma_mem) {
+			if (cal_block->cal_data.paddr == 0 ||
+			    cal_block->map_data.map_size <= 0) {
+				pr_err("%s: No address to map!\n", __func__);
+				mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+				return -EINVAL;
+			}
+			result = hyp_assign_phys(
+					cal_block->cal_data.paddr,
+					cal_block->map_data.map_size,
+					source_vm, 2, dest_vm, dest_perms, 1);
+			if (result < 0) {
+				pr_err("%s: hyp_assign_phys failed result = %d addr = 0x%pK size = %d\n",
+					__func__, result,
+					cal_block->cal_data.paddr,
+					cal_block->map_data.map_size);
+				mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+				return -EINVAL;
+			}
+			hyp_assigned = false;
+			pr_debug("%s: hyp_assign_phys success\n", __func__);
+			mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+		}
+	}
 	return ret;
 }
 
@@ -7209,7 +7210,11 @@ EXPORT_SYMBOL(voc_standby_voice_call);
 int voc_disable_device(uint32_t session_id)
 {
 	struct voice_data *v = voice_get_session(session_id);
-	int ret = 0;
+	int ret = 0, result = 0;
+	struct cal_block_data *cal_block;
+	int dest_perms[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
+	int source_vm[2] = {VMID_LPASS, VMID_ADSP_HEAP};
+	int dest_vm[1] = {VMID_HLOS};
 
 	if (v == NULL) {
 		pr_err("%s: v is NULL\n", __func__);
@@ -7224,7 +7229,7 @@ int voc_disable_device(uint32_t session_id)
 		if (ret < 0) {
 			pr_err("%s: Pause Voice Call failed for session 0x%x, err %d!\n",
 			       __func__, v->session_id, ret);
-			goto done;
+			goto fail;
 		}
 		rtac_remove_voice(voice_get_cvs_handle(v));
 		voice_send_cvp_deregister_vol_cal_cmd(v);
@@ -7240,6 +7245,45 @@ int voc_disable_device(uint32_t session_id)
 			 __func__, v->voc_state);
 	}
 
+fail:
+	if (hyp_assigned) {
+		mutex_lock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+		cal_block = cal_utils_get_only_cal_block(
+				common.cal_data[CVP_VOCPROC_CAL]);
+		if (cal_block == NULL) {
+			pr_err("%s: Cal block NULL, CVP_VOCPROC_CAL!\n",
+				__func__);
+			ret = -EINVAL;
+			mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+			goto done;
+		}
+		if (cal_block->cma_mem) {
+			if (cal_block->cal_data.paddr == 0 ||
+			    cal_block->map_data.map_size <= 0) {
+				pr_err("%s: No address to map!\n", __func__);
+				ret = -EINVAL;
+				mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+				goto done;
+			}
+			result = hyp_assign_phys(
+					cal_block->cal_data.paddr,
+					cal_block->map_data.map_size,
+					source_vm, 2, dest_vm, dest_perms, 1);
+			if (result < 0) {
+				pr_err("%s: hyp_assign_phys failed result = %d addr = 0x%pK size = %d\n",
+					__func__,
+					result,
+					cal_block->cal_data.paddr,
+					cal_block->map_data.map_size);
+				ret = -EINVAL;
+				mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+				goto done;
+			}
+			hyp_assigned = false;
+			pr_debug("%s: hyp_assign_phys success\n", __func__);
+			mutex_unlock(&common.cal_data[CVP_VOCPROC_CAL]->lock);
+		}
+	}
 done:
 	mutex_unlock(&v->lock);
 

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

@@ -3965,6 +3965,7 @@ struct afe_param_id_device_hw_delay_cfg {
 } __packed;
 
 #define AFE_PARAM_ID_SET_TOPOLOGY    0x0001025A
+#define AFE_PARAM_ID_DEREGISTER_TOPOLOGY	0x000102E8
 #define AFE_API_VERSION_TOPOLOGY_V1 0x1
 
 struct afe_param_id_set_topology_cfg {
@@ -12190,6 +12191,28 @@ struct afe_clk_set {
 	uint32_t enable;
 };
 
+#define AVS_BUILD_MAJOR_VERSION_V2		2
+#define AVS_BUILD_MINOR_VERSION_V9		9
+#define AVS_BUILD_BRANCH_VERSION_V0		0
+#define AVS_BUILD_BRANCH_VERSION_V3		3
+
+#define AFE_PARAM_ID_CLOCK_SET_V2		0x000102E6
+
+#define AFE_API_VERSION_CLOCK_SET_V2		0x1
+
+struct afe_param_id_clock_set_v2_t {
+	uint32_t	clk_set_minor_version;
+	uint32_t	clk_id;
+	uint32_t	clk_freq_in_hz;
+	uint16_t	clk_attri;
+	uint16_t	clk_root;
+	uint32_t	enable;
+	uint32_t	divider_2x;
+	uint32_t	m;
+	uint32_t	n;
+	uint32_t	d;
+};
+
 struct afe_clk_cfg {
 /* Minor version used for tracking the version of the I2S
  * configuration interface.

+ 36 - 2
include/dsp/q6afe-v2.h

@@ -50,6 +50,9 @@
 #define AFE_API_VERSION_V6		6
 /* for Speaker Protection V4 */
 #define AFE_API_VERSION_V9		9
+/* for external mclk dynamic switch */
+#define AFE_API_VERSION_V8		8
+
 
 typedef int (*routing_cb)(int port);
 
@@ -319,6 +322,24 @@ struct vad_config {
 	u32 pre_roll;
 };
 
+enum afe_mclk_src_id {
+	MCLK_SRC_INT = 0x00,
+	MCLK_SRC_EXT_0 = 0x01,
+	MCLK_SRC_MAX,
+};
+
+enum afe_mclk_freq {
+	MCLK_FREQ_MIN = 0,
+	MCLK_FREQ_11P2896_MHZ = MCLK_FREQ_MIN,
+	MCLK_FREQ_12P288_MHZ,
+	MCLK_FREQ_16P384_MHZ,
+	MCLK_FREQ_22P5792_MHZ,
+	MCLK_FREQ_24P576_MHZ,
+	MCLK_FREQ_MAX,
+};
+
+#define Q6AFE_EXT_MCLK_FREQ_DEFAULT 0
+
 struct afe_audio_buffer {
 	dma_addr_t phys;
 	void       *data;
@@ -438,9 +459,9 @@ int afe_pseudo_port_start_nowait(u16 port_id);
 int afe_pseudo_port_stop_nowait(u16 port_id);
 int afe_set_lpass_clock(u16 port_id, struct afe_clk_cfg *cfg);
 int afe_set_lpass_clock_v2(u16 port_id, struct afe_clk_set *cfg);
-int afe_send_cps_config(int src_port,
+void afe_set_cps_config(int src_port,
 			struct afe_cps_hw_intf_cfg *cps_config,
-			int param_size);
+			u32 ch_mask);
 int afe_set_lpass_clk_cfg(int index, struct afe_clk_set *cfg);
 int afe_set_digital_codec_core_clock(u16 port_id,
 			struct afe_digital_clk_cfg *cfg);
@@ -515,6 +536,19 @@ enum {
 	AFE_LPASS_CORE_HW_DCODEC_BLOCK,
 	AFE_LPASS_CORE_HW_VOTE_MAX
 };
+int afe_set_mclk_src_cfg(u16 port_id, uint32_t mclk_src_id, uint32_t mclk_freq);
+
+typedef int (*afe_enable_mclk_and_get_info_cb_func) (void *private_data,
+			uint32_t enable, uint32_t mclk_freq,
+			struct afe_param_id_clock_set_v2_t *dyn_mclk_cfg);
+
+int afe_register_ext_mclk_cb(afe_enable_mclk_and_get_info_cb_func fn1,
+				void *private_data);
+void afe_unregister_ext_mclk_cb(void);
+
+#define AFE_LPASS_CORE_HW_BLOCK_ID_NONE                        0
+#define AFE_LPASS_CORE_HW_BLOCK_ID_AVTIMER                     2
+#define AFE_LPASS_CORE_HW_MACRO_BLOCK                          3
 
 /* Handles audio-video timer (avtimer) and BTSC vote requests from clients.
  */

+ 3 - 0
include/dsp/q6core.h

@@ -435,4 +435,7 @@ int q6core_destroy_lpass_npa_client(uint32_t client_handle);
 int q6core_request_island_transition(uint32_t client_handle,
 				     uint32_t island_allow_mode);
 
+int q6core_get_avcs_avs_build_version_info(
+	uint32_t *build_major_version, uint32_t *build_minor_version,
+					uint32_t *build_branch_version);
 #endif /* __Q6CORE_H__ */

+ 1 - 0
include/soc/swr-common.h

@@ -13,6 +13,7 @@
 enum {
 	SWR_UC0 = 0,
 	SWR_UC1,
+	SWR_UC2,
 	SWR_UC_MAX,
 };
 

+ 14 - 1
ipc/Kbuild

@@ -14,6 +14,18 @@ ifeq ($(KERNEL_BUILD), 1)
 	AUDIO_ROOT := $(KDIR)/techpack/audio
 endif
 
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+else
 ifeq ($(KERNEL_BUILD), 0)
         ifeq ($(CONFIG_ARCH_SM6150), y)
 		ifdef CONFIG_SND_SOC_SA6155
@@ -72,12 +84,13 @@ ifeq ($(KERNEL_BUILD), 0)
 			INCS    +=  -include $(AUDIO_ROOT)/config/sm8150autoconf.h
 		endif
 	endif
-	ifeq ($(CONFIG_QTI_GVM), y)
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
 		include $(AUDIO_ROOT)/config/gvmauto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
 	endif
 endif
+endif
 
 # As per target team, build is done as follows:
 # Defconfig : build with default flags

+ 2 - 0
ipc/apr.c

@@ -432,6 +432,8 @@ int apr_send_pkt(void *handle, uint32_t *buf)
 		if (rc == -ECONNRESET) {
 			pr_err_ratelimited("%s: Received reset error from tal\n",
 					__func__);
+			if (svc->dest_id == APR_DEST_QDSP6)
+				apr_set_q6_state(APR_SUBSYS_DOWN);
 			rc = -ENETRESET;
 		}
 		if (rc == -EAGAIN || rc == -ETIMEDOUT) {

+ 21 - 1
ipc/apr_vm.c

@@ -23,7 +23,6 @@
 #include <linux/ipc_logging.h>
 #include <linux/of_platform.h>
 #include <soc/qcom/subsystem_restart.h>
-#include <soc/qcom/scm.h>
 #include <soc/snd_event.h>
 #include <dsp/apr_audio-v2.h>
 #include <dsp/audio_notifier.h>
@@ -31,6 +30,7 @@
 #include <ipc/apr_tal.h>
 #include <ipc/aprv2_vm.h>
 #include <linux/habmm.h>
+#include <uapi/linux/sched/types.h>
 
 #define APR_PKT_IPC_LOG_PAGE_CNT 2
 #define APR_VM_CB_THREAD_NAME "apr_vm_cb_thread"
@@ -581,10 +581,15 @@ static int apr_vm_cb_process_evt(char *buf, int len)
 static int apr_vm_cb_thread(void *data)
 {
 	uint32_t apr_rx_buf_len;
+#ifdef APRV2_VM_BE_ASYNC_SEND_RSP
 	struct aprv2_vm_ack_rx_pkt_available_t apr_ack;
+#endif
 	unsigned long delay = jiffies + (HZ / 2);
 	int status = 0;
 	int ret = 0;
+	struct sched_param param = {.sched_priority = 1};
+
+	sched_setscheduler(current, SCHED_FIFO, &param);
 
 	while (1) {
 		do {
@@ -604,11 +609,15 @@ static int apr_vm_cb_thread(void *data)
 
 		status = apr_vm_cb_process_evt(apr_rx_buf, apr_rx_buf_len);
 
+#ifdef APRV2_VM_BE_ASYNC_SEND_RSP
 		apr_ack.status = status;
 		ret = habmm_socket_send(hab_handle_rx,
 				(void *)&apr_ack,
 				sizeof(apr_ack),
 				0);
+#else
+		ret = status;
+#endif
 		if (ret) {
 			pr_err("%s: habmm_socket_send failed %d\n",
 					__func__, ret);
@@ -827,8 +836,10 @@ int apr_send_pkt(void *handle, uint32_t *buf)
 		(struct aprv2_vm_cmd_async_send_t *)(apr_tx_buf +
 			sizeof(uint32_t));
 	uint32_t apr_send_len;
+#ifdef APRV2_VM_BE_ASYNC_SEND_RSP
 	struct aprv2_vm_cmd_async_send_rsp_t apr_rsp;
 	uint32_t apr_rsp_len;
+#endif
 	int ret = 0;
 
 	if (!handle || !buf) {
@@ -894,6 +905,7 @@ int apr_send_pkt(void *handle, uint32_t *buf)
 				__func__, ret);
 		goto done;
 	}
+#ifdef APRV2_VM_BE_ASYNC_SEND_RSP
 	/* wait for response */
 	apr_rsp_len = sizeof(apr_rsp);
 	ret = apr_vm_nb_receive(hab_handle_tx,
@@ -912,6 +924,7 @@ int apr_send_pkt(void *handle, uint32_t *buf)
 		ret = -ECOMM;
 		goto done;
 	}
+#endif
 
 	/* upon successful send, return packet size */
 	ret = hdr->pkt_size;
@@ -1061,6 +1074,13 @@ static void apr_reset_deregister(struct work_struct *work)
 	kfree(apr_reset);
 }
 
+void apr_register_adsp_state_cb(void *adsp_cb, void *client_handle)
+{
+	q6.state_notify_cb = adsp_cb;
+	q6.client_handle = client_handle;
+}
+EXPORT_SYMBOL(apr_register_adsp_state_cb);
+
 /**
  * apr_start_rx_rt - Clients call to vote for thread
  * priority upgrade whenever needed.

+ 14 - 1
soc/Kbuild

@@ -13,6 +13,18 @@ ifeq ($(KERNEL_BUILD), 1)
 	AUDIO_ROOT := $(AUDIO_BLD_DIR)/techpack/audio
 endif
 
+ifeq ($(CONFIG_SND_SOC_AUTO), y)
+	ifdef CONFIG_SND_SOC_SA8155
+		include $(AUDIO_ROOT)/config/sa8155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa8155autoconf.h
+	endif
+	ifdef CONFIG_SND_SOC_SA6155
+		include $(AUDIO_ROOT)/config/sa6155auto.conf
+		export
+		INCS    +=  -include $(AUDIO_ROOT)/config/sa6155autoconf.h
+	endif
+else
 ifeq ($(KERNEL_BUILD), 0)
 	ifeq ($(CONFIG_ARCH_SM8150), y)
 		ifdef CONFIG_SND_SOC_SA8155
@@ -71,12 +83,13 @@ ifeq ($(KERNEL_BUILD), 0)
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/qcs405autoconf.h
 	endif
-	ifeq ($(CONFIG_QTI_GVM), y)
+	ifeq ($(CONFIG_QTI_QUIN_GVM), y)
 		include $(AUDIO_ROOT)/config/gvmauto.conf
 		export
 		INCS    +=  -include $(AUDIO_ROOT)/config/gvmautoconf.h
 	endif
 endif
+endif
 
 # As per target team, build is done as follows:
 # Defconfig : build with default flags

+ 44 - 19
soc/swr-mstr-ctrl.c

@@ -755,6 +755,8 @@ static int swrm_get_port_config(struct swr_mstr_ctrl *swrm)
 
 	if (swrm->bus_clk == SWR_CLK_RATE_4P8MHZ)
 		usecase = 1;
+	else if (swrm->bus_clk == SWR_CLK_RATE_0P6MHZ)
+		usecase = 2;
 
 	params = swrm->port_param[usecase];
 	copy_port_tables(swrm, params);
@@ -1366,11 +1368,14 @@ static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm,
 
 	if ((swrm->master_id == MASTER_ID_TX) &&
 		((swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) ||
+		 (swrm->bus_clk == SWR_CLK_RATE_0P6MHZ) ||
 		 (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 if (swrm->bus_clk == SWR_CLK_RATE_0P6MHZ)
+			pp_dev = swrdev_frame_params_0p6MHz[dev_num].pp;
 		else
 			pp_dev = swrdev_frame_params_4p8MHz[dev_num].pp;
 		pp_port = &pp_dev[port_id];
@@ -1759,6 +1764,7 @@ static int swrm_connect_port(struct swr_master *master,
 	mutex_lock(&swrm->mlock);
 	mutex_lock(&swrm->devlock);
 	if (!swrm->dev_up) {
+		swr_port_response(master, portinfo->tid);
 		mutex_unlock(&swrm->devlock);
 		mutex_unlock(&swrm->mlock);
 		return -EINVAL;
@@ -1827,6 +1833,7 @@ static int swrm_connect_port(struct swr_master *master,
 
 port_fail:
 mem_fail:
+	swr_port_response(master, portinfo->tid);
 	/* cleanup  port reqs in error condition */
 	swrm_cleanup_disabled_port_reqs(master);
 	mutex_unlock(&swrm->mlock);
@@ -1863,8 +1870,7 @@ static int swrm_disconnect_port(struct swr_master *master,
 			dev_err(&master->dev,
 				"%s: mstr portid for slv port %d not found\n",
 				__func__, portinfo->port_id[i]);
-			mutex_unlock(&swrm->mlock);
-			return -EINVAL;
+			goto err;
 		}
 		mport = &(swrm->mport_cfg[mstr_port_id]);
 		/* get port req */
@@ -1874,8 +1880,7 @@ static int swrm_disconnect_port(struct swr_master *master,
 		if (!port_req) {
 			dev_err(&master->dev, "%s:port not enabled : port %d\n",
 					 __func__, portinfo->port_id[i]);
-			mutex_unlock(&swrm->mlock);
-			return -EINVAL;
+			goto err;
 		}
 		port_req->req_ch &= ~portinfo->ch_en[i];
 		mport->req_ch &= ~mstr_ch_mask;
@@ -1892,6 +1897,11 @@ static int swrm_disconnect_port(struct swr_master *master,
 	mutex_unlock(&swrm->mlock);
 
 	return 0;
+
+err:
+	swr_port_response(master, portinfo->tid);
+	mutex_unlock(&swrm->mlock);
+	return -EINVAL;
 }
 
 static int swrm_find_alert_slave(struct swr_mstr_ctrl *swrm,
@@ -2165,20 +2175,21 @@ handle_irq:
 		case SWRM_INTERRUPT_STATUS_CLK_STOP_FINISHED:
 			break;
 		case SWRM_INTERRUPT_STATUS_EXT_CLK_STOP_WAKEUP:
-			if (swrm->state == SWR_MSTR_UP)
+			if (swrm->state == SWR_MSTR_UP) {
 				dev_dbg(swrm->dev,
 					"%s:SWR Master is already up\n",
 					__func__);
-			else
+			} else {
 				dev_err_ratelimited(swrm->dev,
 					"%s: SWR wokeup during clock stop\n",
 					__func__);
-			/* It might be possible the slave device gets reset
-			 * and slave interrupt gets missed. So re-enable
-			 * Host IRQ and process slave pending
-			 * interrupts, if any.
-			 */
-			swrm_enable_slave_irq(swrm);
+				/* It might be possible the slave device gets
+				 * reset and slave interrupt gets missed. So
+				 * re-enable Host IRQ and process slave pending
+				 * interrupts, if any.
+				 */
+				swrm_enable_slave_irq(swrm);
+			}
 			break;
 		default:
 			dev_err_ratelimited(swrm->dev,
@@ -2482,9 +2493,6 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
 	reg[len] = SWRM_COMP_CFG;
 	value[len++] = 0x02;
 
-	reg[len] = SWRM_COMP_CFG;
-	value[len++] = 0x03;
-
 	reg[len] = SWRM_INTERRUPT_CLEAR;
 	value[len++] = 0xFFFFFFFF;
 
@@ -2496,6 +2504,9 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm)
 	reg[len] = SWRM_CPU1_INTERRUPT_EN;
 	value[len++] = swrm->intr_mask;
 
+	reg[len] = SWRM_COMP_CFG;
+	value[len++] = 0x03;
+
 	swr_master_bulk_write(swrm, reg, value, len);
 
 	if (!swrm_check_link_status(swrm, 0x1)) {
@@ -2572,6 +2583,7 @@ static int swrm_probe(struct platform_device *pdev)
 	int ret = 0;
 	struct clk *lpass_core_hw_vote = NULL;
 	struct clk *lpass_core_audio = NULL;
+	u32 is_wcd937x = 0;
 
 	/* Allocate soundwire master driver structure */
 	swrm = devm_kzalloc(&pdev->dev, sizeof(struct swr_mstr_ctrl),
@@ -2604,6 +2616,14 @@ static int swrm_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "%s: failed to get master id\n", __func__);
 		goto err_pdata_fail;
 	}
+	/* update the physical device address if wcd937x. */
+	ret = of_property_read_u32(pdev->dev.of_node, "qcom,is_wcd937x",
+				&is_wcd937x);
+	if (ret)
+		dev_dbg(&pdev->dev, "%s: failed to get wcd info\n", __func__);
+	else if (is_wcd937x)
+		swrm_phy_dev[1] = 0xa01170223;
+
 	ret = of_property_read_u32(pdev->dev.of_node, "qcom,dynamic-port-map-supported",
 				&swrm->dynamic_port_map_supported);
 	if (ret) {
@@ -2674,6 +2694,8 @@ static int swrm_probe(struct platform_device *pdev)
 				SWRM_NUM_AUTO_ENUM_SLAVES);
 			ret = -EINVAL;
 			goto err_pdata_fail;
+		} else {
+			swrm->master.num_dev = swrm->num_dev;
 		}
 	}
 
@@ -3221,16 +3243,19 @@ static int swrm_runtime_suspend(struct device *dev)
 				swrm->ipc_wakeup_triggered = false;
 			}
 		}
-
 	}
-	if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false))
-		dev_dbg(dev, "%s:lpass audio hw enable failed\n",
-			__func__);
 
 	/* Retain  SSR state until resume */
 	if (current_state != SWR_MSTR_SSR)
 		swrm->state = SWR_MSTR_DOWN;
+
 exit:
+	if (current_state != SWR_MSTR_UP) {
+		if (swrm_request_hw_vote(swrm, LPASS_AUDIO_CORE, false))
+			dev_dbg(dev, "%s:lpass audio hw enable failed\n",
+			__func__);
+	}
+
 	if (!hw_core_err)
 		swrm_request_hw_vote(swrm, LPASS_HW_CORE, false);
 	mutex_unlock(&swrm->reslock);

+ 59 - 8
soc/swr-slave-port-config.h

@@ -23,12 +23,21 @@ static struct port_params tx_dummy[SWR_MSTR_PORT_LEN] = {
 };
 
 /* AMIC 9.6 MHz clock */
+#ifdef CONFIG_SND_SOC_HOLI
+static struct port_params tx_wcd_9p6MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  0,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 1, 0x00, 0x00}, /* TX1 */
+	{3,  1,  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 */
+};
+#else
 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 */
 };
+#endif
 
 /* AMIC 4.8 MHz clock */
 static struct port_params tx_wcd_4p8MHz[SWR_MSTR_PORT_LEN] = {
@@ -38,6 +47,14 @@ static struct port_params tx_wcd_4p8MHz[SWR_MSTR_PORT_LEN] = {
 	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX4 */
 };
 
+/* AMIC 0.6 MHz clock, single channel */
+static struct port_params tx_wcd_0p6MHz[SWR_MSTR_PORT_LEN] = {
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX3 */
+	{1,  1,  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] = {
@@ -63,29 +80,54 @@ static struct port_params tx_top_mic_9p6MHz[SWR_MSTR_PORT_LEN] = {
 	{7,  5,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
 };
 
-/* 3 Channel configuration */
+/* 4 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 */
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  5,  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 */
+	{3,  3,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  6,  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 */
+	{3,  3,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  7,  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,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{7,  4,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* 1 Channel configuration */
+/* SWR DMIC0 */
+static struct port_params tx_bottom_mic_0p6MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC1 */
+static struct port_params tx_receiver_mic_0p6MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC2 */
+static struct port_params tx_back_mic_0p6MHz[SWR_MSTR_PORT_LEN] = {
+	{3,  2,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX1 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
+};
+
+/* SWR DMIC3 */
+static struct port_params tx_top_mic_0p6MHz[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 */
+	{1,  1,  0,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0, 0x00, 0x00}, /* TX2 */
 };
 
 struct swr_dev_frame_config {
@@ -110,4 +152,13 @@ static struct swr_dev_frame_config swrdev_frame_params_4p8MHz[] = {
 	{tx_bottom_mic_4p8MHz},
 };
 
+static struct swr_dev_frame_config swrdev_frame_params_0p6MHz[] = {
+	{tx_dummy},
+	{tx_wcd_0p6MHz},
+	{tx_top_mic_0p6MHz},
+	{tx_back_mic_0p6MHz},
+	{tx_receiver_mic_0p6MHz},
+	{tx_bottom_mic_0p6MHz},
+};
+
 #endif /* _LAHAINA_PORT_CONFIG */