Merge "asoc: sdm660: update cpu_dai_name for quin_tdm"
diff --git a/asoc/Makefile b/asoc/Makefile
index cc28148..4d3839d 100644
--- a/asoc/Makefile
+++ b/asoc/Makefile
@@ -15,19 +15,9 @@
 snd-soc-msm8998-objs := msm8998.o
 obj-$(CONFIG_SND_SOC_MACHINE_MSM8998) += snd-soc-msm8998.o
 
-# for SDM660 sound card driver
-snd-soc-sdm660-common-objs := sdm660-common.o
-obj-$(CONFIG_SND_SOC_SDM670) += snd-soc-sdm660-common.o
-
-# for SDM660 sound card driver
-snd-soc-int-codec-objs := sdm660-internal.o
-obj-$(CONFIG_SND_SOC_INT_CODEC) += snd-soc-sdm660-common.o
-obj-$(CONFIG_SND_SOC_INT_CODEC) += snd-soc-int-codec.o
-
-# for SDM660 sound card driver
-snd-soc-ext-codec-objs := sdm660-external.o sdm660-ext-dai-links.o
-obj-$(CONFIG_SND_SOC_EXT_CODEC) += snd-soc-sdm660-common.o
-obj-$(CONFIG_SND_SOC_EXT_CODEC) += snd-soc-ext-codec.o
+# for SDM670 sound card driver
+snd-soc-sdm670-objs := sdm660-common.o sdm660-internal.o sdm660-external.o sdm660-ext-dai-links.o
+obj-$(CONFIG_SND_SOC_SDM670) += snd-soc-sdm670.o
 
 # for SDM845 sound card driver
 snd-soc-sdm845-objs := sdm845.o
diff --git a/asoc/codecs/msm_hdmi_codec_rx.c b/asoc/codecs/msm_hdmi_codec_rx.c
index 46cfe7d..3a48f53 100644
--- a/asoc/codecs/msm_hdmi_codec_rx.c
+++ b/asoc/codecs/msm_hdmi_codec_rx.c
@@ -489,7 +489,8 @@
 			.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
 				 SNDRV_PCM_RATE_192000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE |
-				   SNDRV_PCM_FMTBIT_S24_LE,
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S24_3LE,
 		},
 		.ops = &msm_ext_disp_audio_codec_rx_dai_ops,
 	},
diff --git a/asoc/codecs/wcd9335.c b/asoc/codecs/wcd9335.c
index 19877b9..8ade82b 100644
--- a/asoc/codecs/wcd9335.c
+++ b/asoc/codecs/wcd9335.c
@@ -87,6 +87,8 @@
 #define TASHA_NUM_INTERPOLATORS 9
 #define TASHA_NUM_DECIMATORS 9
 
+#define WCD9335_CHILD_DEVICES_MAX	6
+
 #define BYTE_BIT_MASK(nr) (1 << ((nr) % BITS_PER_BYTE))
 #define TASHA_MAD_AUDIO_FIRMWARE_PATH "wcd9335/wcd9335_mad_audio.bin"
 #define TASHA_CPE_SS_ERR_STATUS_MEM_ACCESS (1 << 0)
@@ -829,6 +831,10 @@
 	u32 ref_count;
 	/* Lock to protect mclk enablement */
 	struct mutex mclk_lock;
+
+	struct platform_device *pdev_child_devices
+			[WCD9335_CHILD_DEVICES_MAX];
+	int child_count;
 };
 
 static int tasha_codec_vote_max_bw(struct snd_soc_codec *codec,
@@ -13576,11 +13582,14 @@
 	struct wcd9xxx *control;
 
 	control = dev_get_drvdata(codec->dev->parent);
+	control->num_rx_port = 0;
+	control->num_tx_port = 0;
 	control->rx_chs = NULL;
 	control->tx_chs = NULL;
 
 	tasha_cleanup_irqs(tasha);
 	/* Cleanup MBHC */
+	wcd_mbhc_deinit(&tasha->mbhc);
 	/* Cleanup resmgr */
 
 	return 0;
@@ -13920,6 +13929,7 @@
 	}
 
 	platdata = &tasha->swr_plat_data;
+	tasha->child_count = 0;
 
 	for_each_child_of_node(wcd9xxx->dev->of_node, node) {
 		if (!strcmp(node->name, "swr_master"))
@@ -13980,6 +13990,11 @@
 			tasha->nr = ctrl_num;
 			tasha->swr_ctrl_data = swr_ctrl_data;
 		}
+
+		if (tasha->child_count < WCD9335_CHILD_DEVICES_MAX)
+			tasha->pdev_child_devices[tasha->child_count++] = pdev;
+		else
+			goto err;
 	}
 
 	return;
@@ -14179,17 +14194,25 @@
 static int tasha_remove(struct platform_device *pdev)
 {
 	struct tasha_priv *tasha;
+	int count = 0;
 
 	tasha = platform_get_drvdata(pdev);
 
+	if (!tasha)
+		return -EINVAL;
+
+	for (count = 0; count < tasha->child_count &&
+		count < WCD9335_CHILD_DEVICES_MAX; count++)
+		platform_device_unregister(tasha->pdev_child_devices[count]);
+
 	mutex_destroy(&tasha->codec_mutex);
 	clk_put(tasha->wcd_ext_clk);
 	if (tasha->wcd_native_clk)
 		clk_put(tasha->wcd_native_clk);
 	mutex_destroy(&tasha->mclk_lock);
-	devm_kfree(&pdev->dev, tasha);
-	snd_soc_unregister_codec(&pdev->dev);
 	mutex_destroy(&tasha->sb_clk_gear_lock);
+	snd_soc_unregister_codec(&pdev->dev);
+	devm_kfree(&pdev->dev, tasha);
 	return 0;
 }
 
diff --git a/asoc/msm-dai-q6-hdmi-v2.c b/asoc/msm-dai-q6-hdmi-v2.c
index 9c8d20a..212c4e3 100644
--- a/asoc/msm-dai-q6-hdmi-v2.c
+++ b/asoc/msm-dai-q6-hdmi-v2.c
@@ -217,6 +217,7 @@
 		dai_data->port_config.hdmi_multi_ch.bit_width = 16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
+	case SNDRV_PCM_FORMAT_S24_3LE:
 		dai_data->port_config.hdmi_multi_ch.bit_width = 24;
 		break;
 	}
@@ -435,7 +436,9 @@
 			 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
 			 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
 			 SNDRV_PCM_RATE_192000,
-		.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE |
+			   SNDRV_PCM_FMTBIT_S24_LE |
+			   SNDRV_PCM_FMTBIT_S24_3LE,
 		.channels_min = 2,
 		.channels_max = 8,
 		.rate_max = 192000,
@@ -457,7 +460,8 @@
 				 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
 				 SNDRV_PCM_RATE_192000,
 			.formats = SNDRV_PCM_FMTBIT_S16_LE |
-				   SNDRV_PCM_FMTBIT_S24_LE,
+				   SNDRV_PCM_FMTBIT_S24_LE |
+				   SNDRV_PCM_FMTBIT_S24_3LE,
 			.channels_min = 2,
 			.channels_max = 8,
 			.rate_max =     192000,
diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c
index 6011926..3338ac6 100644
--- a/asoc/msm-pcm-routing-v2.c
+++ b/asoc/msm-pcm-routing-v2.c
@@ -16533,7 +16533,7 @@
 	{"QUIN_TDM_RX_0 Port Mixer", "QUIN_TDM_TX_1", "QUIN_TDM_TX_1"},
 	{"QUIN_TDM_RX_0 Port Mixer", "QUIN_TDM_TX_2", "QUIN_TDM_TX_2"},
 	{"QUIN_TDM_RX_0 Port Mixer", "QUIN_TDM_TX_3", "QUIN_TDM_TX_3"},
-	{"QUIN_TDM_RX_0", NULL, "QUAT_TDM_RX_0 Port Mixer"},
+	{"QUIN_TDM_RX_0", NULL, "QUIN_TDM_RX_0 Port Mixer"},
 
 	{"QUIN_TDM_RX_1 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"QUIN_TDM_RX_1 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
@@ -16555,7 +16555,7 @@
 	{"QUIN_TDM_RX_1 Port Mixer", "QUIN_TDM_TX_1", "QUIN_TDM_TX_1"},
 	{"QUIN_TDM_RX_1 Port Mixer", "QUIN_TDM_TX_2", "QUIN_TDM_TX_2"},
 	{"QUIN_TDM_RX_1 Port Mixer", "QUIN_TDM_TX_3", "QUIN_TDM_TX_3"},
-	{"QUIN_TDM_RX_1", NULL, "QUAT_TDM_RX_1 Port Mixer"},
+	{"QUIN_TDM_RX_1", NULL, "QUIN_TDM_RX_1 Port Mixer"},
 
 	{"QUIN_TDM_RX_2 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"QUIN_TDM_RX_2 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
@@ -16577,7 +16577,7 @@
 	{"QUIN_TDM_RX_2 Port Mixer", "QUIN_TDM_TX_1", "QUIN_TDM_TX_1"},
 	{"QUIN_TDM_RX_2 Port Mixer", "QUIN_TDM_TX_2", "QUIN_TDM_TX_2"},
 	{"QUIN_TDM_RX_2 Port Mixer", "QUIN_TDM_TX_3", "QUIN_TDM_TX_3"},
-	{"QUIN_TDM_RX_2", NULL, "QUAT_TDM_RX_2 Port Mixer"},
+	{"QUIN_TDM_RX_2", NULL, "QUIN_TDM_RX_2 Port Mixer"},
 
 	{"QUIN_TDM_RX_3 Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"QUIN_TDM_RX_3 Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
@@ -16599,7 +16599,7 @@
 	{"QUIN_TDM_RX_3 Port Mixer", "QUIN_TDM_TX_1", "QUIN_TDM_TX_1"},
 	{"QUIN_TDM_RX_3 Port Mixer", "QUIN_TDM_TX_2", "QUIN_TDM_TX_2"},
 	{"QUIN_TDM_RX_3 Port Mixer", "QUIN_TDM_TX_3", "QUIN_TDM_TX_3"},
-	{"QUIN_TDM_RX_3", NULL, "QUAT_TDM_RX_3 Port Mixer"},
+	{"QUIN_TDM_RX_3", NULL, "QUIN_TDM_RX_3 Port Mixer"},
 
 	{"INT0_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
 	{"INT0_MI2S_RX Port Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h
index 479ba35..8f91e4f 100644
--- a/asoc/msm-pcm-routing-v2.h
+++ b/asoc/msm-pcm-routing-v2.h
@@ -58,8 +58,8 @@
 #define LPASS_BE_SEC_MI2S_TX "SEC_MI2S_TX"
 #define LPASS_BE_PRI_MI2S_RX "PRI_MI2S_RX"
 #define LPASS_BE_PRI_MI2S_TX "PRI_MI2S_TX"
-#define LPASS_BE_TERT_MI2S_RX "TERTIARY_MI2S_RX"
-#define LPASS_BE_TERT_MI2S_TX "TERTIARY_MI2S_TX"
+#define LPASS_BE_TERT_MI2S_RX "TERT_MI2S_RX"
+#define LPASS_BE_TERT_MI2S_TX "TERT_MI2S_TX"
 #define LPASS_BE_AUDIO_I2S_RX "AUDIO_I2S_RX"
 #define LPASS_BE_STUB_RX "STUB_RX"
 #define LPASS_BE_STUB_TX "STUB_TX"
diff --git a/asoc/sdm660-external.h b/asoc/sdm660-external.h
index 0648c01..b81e158 100644
--- a/asoc/sdm660-external.h
+++ b/asoc/sdm660-external.h
@@ -32,7 +32,7 @@
 			       struct snd_pcm_hw_params *params);
 int msm_snd_card_tavil_late_probe(struct snd_soc_card *card);
 int msm_snd_card_tasha_late_probe(struct snd_soc_card *card);
-#ifdef CONFIG_SND_SOC_EXT_CODEC
+#if IS_ENABLED(CONFIG_SND_SOC_EXT_CODEC)
 int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *,
 		     struct snd_soc_card **, struct wcd_mbhc_config *);
 void msm_ext_register_audio_notifier(struct platform_device *pdev);
diff --git a/asoc/sdm660-internal.h b/asoc/sdm660-internal.h
index ccc62b8..6918231 100644
--- a/asoc/sdm660-internal.h
+++ b/asoc/sdm660-internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,7 +15,7 @@
 
 #include <sound/soc.h>
 
-#ifdef CONFIG_SND_SOC_INT_CODEC
+#if IS_ENABLED(CONFIG_SND_SOC_INT_CODEC)
 int msm_int_cdc_init(struct platform_device *pdev,
 		     struct msm_asoc_mach_data *pdata,
 		     struct snd_soc_card **card,
diff --git a/asoc/sdm845.c b/asoc/sdm845.c
index 5721c32..0506636 100644
--- a/asoc/sdm845.c
+++ b/asoc/sdm845.c
@@ -408,7 +408,8 @@
 static const char *const vi_feed_ch_text[] = {"One", "Two"};
 static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
 					  "S32_LE"};
-static char const *ext_disp_bit_format_text[] = {"S16_LE", "S24_LE"};
+static char const *ext_disp_bit_format_text[] = {"S16_LE", "S24_LE",
+						 "S24_3LE"};
 static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
 					"KHZ_32", "KHZ_44P1", "KHZ_48",
 					"KHZ_88P2", "KHZ_96", "KHZ_176P4",
@@ -1420,10 +1421,12 @@
 		return idx;
 
 	switch (ext_disp_rx_cfg[idx].bit_format) {
+	case SNDRV_PCM_FORMAT_S24_3LE:
+		ucontrol->value.integer.value[0] = 2;
+		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
 		ucontrol->value.integer.value[0] = 1;
 		break;
-
 	case SNDRV_PCM_FORMAT_S16_LE:
 	default:
 		ucontrol->value.integer.value[0] = 0;
@@ -1445,6 +1448,9 @@
 		return idx;
 
 	switch (ucontrol->value.integer.value[0]) {
+	case 2:
+		ext_disp_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_3LE;
+		break;
 	case 1:
 		ext_disp_rx_cfg[idx].bit_format = SNDRV_PCM_FORMAT_S24_LE;
 		break;
diff --git a/dsp/codecs/audio_utils_aio.h b/dsp/codecs/audio_utils_aio.h
index 82374f9..e44f9d9 100644
--- a/dsp/codecs/audio_utils_aio.h
+++ b/dsp/codecs/audio_utils_aio.h
@@ -20,7 +20,6 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/wait.h>
-#include <linux/wakelock.h>
 #include <linux/msm_audio.h>
 #include <linux/debugfs.h>
 #include <linux/list.h>
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 0289144..a91e119 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -15,7 +15,6 @@
 #include <linux/kthread.h>
 #include <linux/uaccess.h>
 #include <linux/wait.h>
-#include <linux/wakelock.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
@@ -495,6 +494,7 @@
 	case AFE_PORT_ID_SECONDARY_PCM_RX:
 	case AFE_PORT_ID_TERTIARY_PCM_RX:
 	case AFE_PORT_ID_QUATERNARY_PCM_RX:
+	case AFE_PORT_ID_QUINARY_PCM_RX:
 	case AFE_PORT_ID_PRIMARY_TDM_RX:
 	case AFE_PORT_ID_PRIMARY_TDM_RX_1:
 	case AFE_PORT_ID_PRIMARY_TDM_RX_2:
@@ -527,6 +527,14 @@
 	case AFE_PORT_ID_QUATERNARY_TDM_RX_5:
 	case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
 	case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
+	case AFE_PORT_ID_QUINARY_TDM_RX:
+	case AFE_PORT_ID_QUINARY_TDM_RX_1:
+	case AFE_PORT_ID_QUINARY_TDM_RX_2:
+	case AFE_PORT_ID_QUINARY_TDM_RX_3:
+	case AFE_PORT_ID_QUINARY_TDM_RX_4:
+	case AFE_PORT_ID_QUINARY_TDM_RX_5:
+	case AFE_PORT_ID_QUINARY_TDM_RX_6:
+	case AFE_PORT_ID_QUINARY_TDM_RX_7:
 	case AFE_PORT_ID_USB_RX:
 	case AFE_PORT_ID_INT0_MI2S_RX:
 	case AFE_PORT_ID_INT1_MI2S_RX:
@@ -566,6 +574,7 @@
 	case AFE_PORT_ID_SECONDARY_PCM_TX:
 	case AFE_PORT_ID_TERTIARY_PCM_TX:
 	case AFE_PORT_ID_QUATERNARY_PCM_TX:
+	case AFE_PORT_ID_QUINARY_PCM_TX:
 	case AFE_PORT_ID_PRIMARY_TDM_TX:
 	case AFE_PORT_ID_PRIMARY_TDM_TX_1:
 	case AFE_PORT_ID_PRIMARY_TDM_TX_2:
@@ -598,6 +607,14 @@
 	case AFE_PORT_ID_QUATERNARY_TDM_TX_5:
 	case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
 	case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
+	case AFE_PORT_ID_QUINARY_TDM_TX:
+	case AFE_PORT_ID_QUINARY_TDM_TX_1:
+	case AFE_PORT_ID_QUINARY_TDM_TX_2:
+	case AFE_PORT_ID_QUINARY_TDM_TX_3:
+	case AFE_PORT_ID_QUINARY_TDM_TX_4:
+	case AFE_PORT_ID_QUINARY_TDM_TX_5:
+	case AFE_PORT_ID_QUINARY_TDM_TX_6:
+	case AFE_PORT_ID_QUINARY_TDM_TX_7:
 	case AFE_PORT_ID_USB_TX:
 	case AFE_PORT_ID_INT0_MI2S_TX:
 	case AFE_PORT_ID_INT1_MI2S_TX:
@@ -685,6 +702,8 @@
 	case AFE_PORT_ID_TERTIARY_PCM_TX:
 	case AFE_PORT_ID_QUATERNARY_PCM_RX:
 	case AFE_PORT_ID_QUATERNARY_PCM_TX:
+	case AFE_PORT_ID_QUINARY_PCM_RX:
+	case AFE_PORT_ID_QUINARY_PCM_TX:
 	default:
 		pr_debug("%s: default case 0x%x\n", __func__, port_id);
 		ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
@@ -3071,6 +3090,8 @@
 	case AFE_PORT_ID_TERTIARY_PCM_TX:
 	case AFE_PORT_ID_QUATERNARY_PCM_RX:
 	case AFE_PORT_ID_QUATERNARY_PCM_TX:
+	case AFE_PORT_ID_QUINARY_PCM_RX:
+	case AFE_PORT_ID_QUINARY_PCM_TX:
 		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
 		break;
 	case PRIMARY_I2S_RX:
@@ -3288,6 +3309,10 @@
 		return IDX_AFE_PORT_ID_QUATERNARY_PCM_RX;
 	case AFE_PORT_ID_QUATERNARY_PCM_TX:
 		return IDX_AFE_PORT_ID_QUATERNARY_PCM_TX;
+	case AFE_PORT_ID_QUINARY_PCM_RX:
+		return IDX_AFE_PORT_ID_QUINARY_PCM_RX;
+	case AFE_PORT_ID_QUINARY_PCM_TX:
+		return IDX_AFE_PORT_ID_QUINARY_PCM_TX;
 	case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
 	case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
 	case MI2S_RX: return IDX_MI2S_RX;
@@ -3481,6 +3506,38 @@
 		return IDX_AFE_PORT_ID_QUATERNARY_TDM_RX_7;
 	case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
 		return IDX_AFE_PORT_ID_QUATERNARY_TDM_TX_7;
+	case AFE_PORT_ID_QUINARY_TDM_RX:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_0;
+	case AFE_PORT_ID_QUINARY_TDM_TX:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_0;
+	case AFE_PORT_ID_QUINARY_TDM_RX_1:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_1;
+	case AFE_PORT_ID_QUINARY_TDM_TX_1:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_1;
+	case AFE_PORT_ID_QUINARY_TDM_RX_2:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_2;
+	case AFE_PORT_ID_QUINARY_TDM_TX_2:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_2;
+	case AFE_PORT_ID_QUINARY_TDM_RX_3:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_3;
+	case AFE_PORT_ID_QUINARY_TDM_TX_3:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_3;
+	case AFE_PORT_ID_QUINARY_TDM_RX_4:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_4;
+	case AFE_PORT_ID_QUINARY_TDM_TX_4:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_4;
+	case AFE_PORT_ID_QUINARY_TDM_RX_5:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_5;
+	case AFE_PORT_ID_QUINARY_TDM_TX_5:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_5;
+	case AFE_PORT_ID_QUINARY_TDM_RX_6:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_6;
+	case AFE_PORT_ID_QUINARY_TDM_TX_6:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_6;
+	case AFE_PORT_ID_QUINARY_TDM_RX_7:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_RX_7;
+	case AFE_PORT_ID_QUINARY_TDM_TX_7:
+		return IDX_AFE_PORT_ID_QUINARY_TDM_TX_7;
 	case AFE_PORT_ID_INT0_MI2S_RX:
 		return IDX_AFE_PORT_ID_INT0_MI2S_RX;
 	case AFE_PORT_ID_INT0_MI2S_TX:
@@ -3597,6 +3654,8 @@
 	case AFE_PORT_ID_TERTIARY_PCM_TX:
 	case AFE_PORT_ID_QUATERNARY_PCM_RX:
 	case AFE_PORT_ID_QUATERNARY_PCM_TX:
+	case AFE_PORT_ID_QUINARY_PCM_RX:
+	case AFE_PORT_ID_QUINARY_PCM_TX:
 		cfg_type = AFE_PARAM_ID_PCM_CONFIG;
 		break;
 	case SECONDARY_I2S_RX:
@@ -3980,6 +4039,8 @@
 	case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
 	case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
 	case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
+	case AFE_GROUP_DEVICE_ID_QUINARY_TDM_RX:
+	case AFE_GROUP_DEVICE_ID_QUINARY_TDM_TX:
 		cfg_type = AFE_PARAM_ID_GROUP_DEVICE_TDM_CONFIG;
 		break;
 	default:
@@ -5262,6 +5323,8 @@
 	case AFE_PORT_ID_TERTIARY_PCM_TX:
 	case AFE_PORT_ID_QUATERNARY_PCM_RX:
 	case AFE_PORT_ID_QUATERNARY_PCM_TX:
+	case AFE_PORT_ID_QUINARY_PCM_RX:
+	case AFE_PORT_ID_QUINARY_PCM_TX:
 	case SECONDARY_I2S_RX:
 	case SECONDARY_I2S_TX:
 	case MI2S_RX:
@@ -5376,6 +5439,22 @@
 	case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
 	case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
 	case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
+	case AFE_PORT_ID_QUINARY_TDM_RX:
+	case AFE_PORT_ID_QUINARY_TDM_TX:
+	case AFE_PORT_ID_QUINARY_TDM_RX_1:
+	case AFE_PORT_ID_QUINARY_TDM_TX_1:
+	case AFE_PORT_ID_QUINARY_TDM_RX_2:
+	case AFE_PORT_ID_QUINARY_TDM_TX_2:
+	case AFE_PORT_ID_QUINARY_TDM_RX_3:
+	case AFE_PORT_ID_QUINARY_TDM_TX_3:
+	case AFE_PORT_ID_QUINARY_TDM_RX_4:
+	case AFE_PORT_ID_QUINARY_TDM_TX_4:
+	case AFE_PORT_ID_QUINARY_TDM_RX_5:
+	case AFE_PORT_ID_QUINARY_TDM_TX_5:
+	case AFE_PORT_ID_QUINARY_TDM_RX_6:
+	case AFE_PORT_ID_QUINARY_TDM_TX_6:
+	case AFE_PORT_ID_QUINARY_TDM_RX_7:
+	case AFE_PORT_ID_QUINARY_TDM_TX_7:
 	case AFE_PORT_ID_INT0_MI2S_RX:
 	case AFE_PORT_ID_INT1_MI2S_RX:
 	case AFE_PORT_ID_INT2_MI2S_RX:
diff --git a/dsp/q6lsm.c b/dsp/q6lsm.c
index adc541a..848f2cd 100644
--- a/dsp/q6lsm.c
+++ b/dsp/q6lsm.c
@@ -148,6 +148,10 @@
 			 __func__, data->opcode, data->reset_event,
 			 data->reset_proc);
 
+		apr_reset(client->apr);
+		client->apr = NULL;
+		atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
+		wake_up(&client->cmd_wait);
 		cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
 			lsm_common.cal_data);
 		mutex_lock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
@@ -368,6 +372,11 @@
 	unsigned long flags = 0;
 	struct apr_hdr *msg_hdr = (struct apr_hdr *) data;
 
+	if (!handle) {
+		pr_err("%s: handle is NULL\n", __func__);
+		return -EINVAL;
+	}
+
 	pr_debug("%s: enter wait %d\n", __func__, wait);
 	if (wait)
 		mutex_lock(&lsm_common.apr_lock);
@@ -1341,6 +1350,10 @@
 		pr_debug("%s: SSR event received 0x%x, event 0x%x,\n"
 			 "proc 0x%x SID 0x%x\n", __func__, data->opcode,
 			 data->reset_event, data->reset_proc, sid);
+
+		apr_reset(lsm_common.apr);
+		lsm_common.apr = NULL;
+		atomic_set(&lsm_common.apr_users, 0);
 		lsm_common.common_client[sid].lsm_cal_phy_addr = 0;
 		cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
 			lsm_common.cal_data);
diff --git a/dsp/q6voice.c b/dsp/q6voice.c
index fa910ca..983e0a2 100644
--- a/dsp/q6voice.c
+++ b/dsp/q6voice.c
@@ -2368,6 +2368,9 @@
 			&cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
 			&cvp_setdev_cmd.cvp_set_device_v2.rx_topology_id);
 
+	voice_set_topology_specific_info(v, CVP_VOC_RX_TOPOLOGY_CAL);
+	voice_set_topology_specific_info(v, CVP_VOC_TX_TOPOLOGY_CAL);
+
 	cvp_setdev_cmd.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
 	cvp_setdev_cmd.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
 
@@ -2722,6 +2725,9 @@
 			&cvp_session_cmd.cvp_session.tx_topology_id,
 			&cvp_session_cmd.cvp_session.rx_topology_id);
 
+	voice_set_topology_specific_info(v, CVP_VOC_RX_TOPOLOGY_CAL);
+	voice_set_topology_specific_info(v, CVP_VOC_TX_TOPOLOGY_CAL);
+
 	cvp_session_cmd.cvp_session.direction = 2; /*tx and rx*/
 	cvp_session_cmd.cvp_session.tx_port_id = v->dev_tx.port_id;
 	cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.port_id;
@@ -3864,6 +3870,9 @@
 			VSS_PARAM_VOCPROC_RX_CHANNEL_INFO;
 		channel_info->num_channels = v->dev_rx.no_of_channels;
 		channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
+		memcpy(&channel_info->channel_mapping,
+		       v->dev_rx.channel_mapping,
+		       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 		break;
 
 	case TX_PATH:
@@ -3871,6 +3880,9 @@
 			VSS_PARAM_VOCPROC_TX_CHANNEL_INFO;
 		channel_info->num_channels = v->dev_tx.no_of_channels;
 		channel_info->bits_per_sample = v->dev_tx.bits_per_sample;
+		memcpy(&channel_info->channel_mapping,
+		       v->dev_tx.channel_mapping,
+		       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 		break;
 
 	case EC_REF_PATH:
@@ -3878,6 +3890,9 @@
 			VSS_PARAM_VOCPROC_EC_REF_CHANNEL_INFO;
 		channel_info->num_channels = v->dev_rx.no_of_channels;
 		channel_info->bits_per_sample = v->dev_rx.bits_per_sample;
+		memcpy(&channel_info->channel_mapping,
+		       v->dev_rx.channel_mapping,
+		       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 		break;
 	default:
 		pr_err("%s: Invalid param type\n",
@@ -3886,21 +3901,6 @@
 		goto done;
 	}
 
-	if (channel_info->num_channels == NUM_CHANNELS_MONO) {
-		channel_info->channel_mapping[0] = PCM_CHANNEL_FC;
-	} else if (channel_info->num_channels == NUM_CHANNELS_STEREO) {
-		channel_info->channel_mapping[0] = PCM_CHANNEL_FL;
-		channel_info->channel_mapping[1] = PCM_CHANNEL_FR;
-	} else if (channel_info->num_channels == NUM_CHANNELS_QUAD &&
-		   param_type == TX_PATH) {
-		channel_info->channel_mapping[0] = PCM_CHANNEL_FL;
-		channel_info->channel_mapping[1] = PCM_CHANNEL_FR;
-		channel_info->channel_mapping[2] = PCM_CHANNEL_LS;
-		channel_info->channel_mapping[3] = PCM_CHANNEL_RS;
-	} else {
-		pr_warn("%s: Unsupported num channels: %d for path: %d\n",
-			__func__, channel_info->num_channels, param_type);
-	}
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	v->async_err = 0;
@@ -4110,16 +4110,9 @@
 	mfc_config_info->num_channels = v->dev_rx.no_of_channels;
 	mfc_config_info->bits_per_sample = 16;
 	mfc_config_info->sample_rate = v->dev_rx.sample_rate;
-
-	if (mfc_config_info->num_channels == NUM_CHANNELS_MONO) {
-		mfc_config_info->channel_type[0] = PCM_CHANNEL_FC;
-	} else if (mfc_config_info->num_channels == NUM_CHANNELS_STEREO) {
-		mfc_config_info->channel_type[0] = PCM_CHANNEL_FL;
-		mfc_config_info->channel_type[1] = PCM_CHANNEL_FR;
-	} else {
-		pr_warn("%s: Unsupported num channels: %d\n",
-			__func__, mfc_config_info->num_channels);
-	}
+	memcpy(&mfc_config_info->channel_type,
+	       v->dev_rx.channel_mapping,
+	       VSS_NUM_CHANNELS_MAX * sizeof(uint8_t));
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	v->async_err = 0;
@@ -8183,6 +8176,96 @@
 	return topology;
 }
 
+int voice_set_topology_specific_info(struct voice_data *v,
+				     uint32_t topology_idx)
+{
+	struct cal_block_data *cal_block = NULL;
+	int ret = 0;
+	uint32_t topo_channels;
+
+	if (common.cal_data[topology_idx] == NULL) {
+		pr_err("%s: cal type is NULL for cal index %x\n",
+			__func__, topology_idx);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&common.cal_data[topology_idx]->lock);
+	cal_block = cal_utils_get_only_cal_block(
+		common.cal_data[topology_idx]);
+	if (cal_block == NULL) {
+		pr_debug("%s: cal_block not found for cal index %x\n",
+			__func__, topology_idx);
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	if (topology_idx == CVP_VOC_RX_TOPOLOGY_CAL) {
+		topo_channels = ((struct audio_cal_info_voc_top *)
+				cal_block->cal_info)->num_channels;
+		if (topo_channels > 0) {
+			v->dev_rx.no_of_channels = topo_channels;
+			pr_debug("%s: Topology Rx no of channels: %d",
+				 __func__, v->dev_rx.no_of_channels);
+			memcpy(&v->dev_rx.channel_mapping,
+			       &((struct audio_cal_info_voc_top *)
+			       cal_block->cal_info)->channel_mapping,
+			       VSS_CHANNEL_MAPPING_SIZE);
+		} else {
+			pr_debug("%s: cal data is zero, default to Rx backend config\n",
+				 __func__);
+			if (v->dev_rx.no_of_channels == NUM_CHANNELS_MONO) {
+				v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FC;
+			} else if (v->dev_rx.no_of_channels ==
+							NUM_CHANNELS_STEREO) {
+				v->dev_rx.channel_mapping[0] = PCM_CHANNEL_FL;
+				v->dev_rx.channel_mapping[1] = PCM_CHANNEL_FR;
+			} else {
+				pr_warn("%s: Unsupported Rx num channels: %d\n",
+					__func__, v->dev_rx.no_of_channels);
+			}
+		}
+	} else if (topology_idx == CVP_VOC_TX_TOPOLOGY_CAL) {
+		topo_channels = ((struct audio_cal_info_voc_top *)
+				cal_block->cal_info)->num_channels;
+		if (topo_channels > 0) {
+			v->dev_tx.no_of_channels = topo_channels;
+			pr_debug("%s: Topology Tx no of channels: %d",
+				 __func__, v->dev_tx.no_of_channels);
+			memcpy(&v->dev_tx.channel_mapping,
+			       &((struct audio_cal_info_voc_top *)
+			       cal_block->cal_info)->channel_mapping,
+			       VSS_CHANNEL_MAPPING_SIZE);
+		} else {
+			pr_debug("%s: cal data is zero, default to Tx backend config\n",
+				 __func__);
+			if (v->dev_tx.no_of_channels == NUM_CHANNELS_MONO) {
+				v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FC;
+			} else if (v->dev_tx.no_of_channels ==
+							NUM_CHANNELS_STEREO) {
+				v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
+				v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
+			} else if (v->dev_tx.no_of_channels ==
+							NUM_CHANNELS_QUAD) {
+				v->dev_tx.channel_mapping[0] = PCM_CHANNEL_FL;
+				v->dev_tx.channel_mapping[1] = PCM_CHANNEL_FR;
+				v->dev_tx.channel_mapping[2] = PCM_CHANNEL_LS;
+				v->dev_tx.channel_mapping[3] = PCM_CHANNEL_RS;
+			} else {
+				pr_warn("%s: Unsupported Tx num channels: %d\n",
+					__func__, v->dev_tx.no_of_channels);
+			}
+		}
+	} else {
+		pr_err("%s: topology index %x is invalid\n",
+		       __func__, topology_idx);
+	}
+unlock:
+	mutex_unlock(&common.cal_data[topology_idx]->lock);
+done:
+	return ret;
+}
+
 static int get_cal_type_index(int32_t cal_type)
 {
 	int ret = -EINVAL;
diff --git a/dsp/rtac.c b/dsp/rtac.c
index 456ac57..84ef835 100644
--- a/dsp/rtac.c
+++ b/dsp/rtac.c
@@ -909,6 +909,14 @@
 		bytes_returned = ((u32 *)rtac_cal[ADM_RTAC_CAL].cal_data.
 			kvaddr)[2] + 3 * sizeof(u32);
 
+		if (bytes_returned > rtac_cal[ADM_RTAC_CAL].
+			map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, bytes_returned);
+			result = -EINVAL;
+			goto err;
+		}
+
 		if (bytes_returned > user_buf_size) {
 			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
 				__func__, user_buf_size, bytes_returned);
@@ -1132,6 +1140,14 @@
 		bytes_returned = ((u32 *)rtac_cal[ASM_RTAC_CAL].cal_data.
 			kvaddr)[2] + 3 * sizeof(u32);
 
+		if (bytes_returned > rtac_cal[ASM_RTAC_CAL].
+			map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, bytes_returned);
+			result = -EINVAL;
+			goto err;
+		}
+
 		if (bytes_returned > user_buf_size) {
 			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
 				__func__, user_buf_size, bytes_returned);
@@ -1392,6 +1408,14 @@
 		bytes_returned = get_resp->param_size +
 				sizeof(struct afe_port_param_data_v2);
 
+		if (bytes_returned > rtac_cal[AFE_RTAC_CAL].
+			map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, bytes_returned);
+			result = -EINVAL;
+			goto err;
+		}
+
 		if (bytes_returned > user_afe_buf.buf_size) {
 			pr_err("%s: user size = 0x%x, returned size = 0x%x\n",
 				__func__, user_afe_buf.buf_size,
@@ -1617,6 +1641,14 @@
 		bytes_returned = ((u32 *)rtac_cal[VOICE_RTAC_CAL].cal_data.
 			kvaddr)[2] + 3 * sizeof(u32);
 
+		if (bytes_returned > rtac_cal[VOICE_RTAC_CAL].
+			map_data.map_size) {
+			pr_err("%s: Invalid data size = %d\n",
+				__func__, bytes_returned);
+			result = -EINVAL;
+			goto err;
+		}
+
 		if (bytes_returned > user_buf_size) {
 			pr_err("%s: User buf not big enough, size = 0x%x, returned size = 0x%x\n",
 				__func__, user_buf_size, bytes_returned);
diff --git a/dsp/usf.c b/dsp/usf.c
index dfa2097..f75439d 100644
--- a/dsp/usf.c
+++ b/dsp/usf.c
@@ -22,7 +22,6 @@
 #include <linux/uaccess.h>
 #include <linux/time.h>
 #include <linux/kmemleak.h>
-#include <linux/wakelock.h>
 #include <linux/mutex.h>
 #include <dsp/apr_audio-v2.h>
 #include "q6usm.h"
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 7df993e..8fb480b 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -205,6 +205,25 @@
 	IDX_AFE_PORT_ID_INT5_MI2S_TX,
 	IDX_AFE_PORT_ID_INT6_MI2S_RX,
 	IDX_AFE_PORT_ID_INT6_MI2S_TX,
+	/* IDX 143-> 160 */
+	IDX_AFE_PORT_ID_QUINARY_PCM_RX,
+	IDX_AFE_PORT_ID_QUINARY_PCM_TX,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_0,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_0,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_1,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_1,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_2,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_2,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_3,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_3,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_4,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_4,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_5,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_5,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_6,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_6,
+	IDX_AFE_PORT_ID_QUINARY_TDM_RX_7,
+	IDX_AFE_PORT_ID_QUINARY_TDM_TX_7,
 	AFE_MAX_PORTS
 };
 
diff --git a/include/dsp/q6voice.h b/include/dsp/q6voice.h
index af7995a..a41a2db 100644
--- a/include/dsp/q6voice.h
+++ b/include/dsp/q6voice.h
@@ -2063,6 +2063,8 @@
 int voc_set_device_config(uint32_t session_id, uint8_t path_dir,
 			  struct media_format_info *finfo);
 uint32_t voice_get_topology(uint32_t topology_idx);
+int voice_set_topology_specific_info(struct voice_data *v,
+				     uint32_t topology_idx);
 int voc_set_sound_focus(struct sound_focus_param sound_focus_param);
 int voc_get_sound_focus(struct sound_focus_param *soundFocusData);
 int voc_get_source_tracking(struct source_tracking_param *sourceTrackingData);
diff --git a/include/soc/swr-wcd.h b/include/soc/swr-wcd.h
index 041b901..f6ff61a 100644
--- a/include/soc/swr-wcd.h
+++ b/include/soc/swr-wcd.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,6 +30,13 @@
 	u8 *port;
 };
 
+#if IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL)
 extern int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data);
-
+#else /* CONFIG_SOUNDWIRE_WCD_CTRL */
+static inline int swrm_wcd_notify(struct platform_device *pdev, u32 id,
+				  void *data)
+{
+	return 0;
+}
+#endif /* CONFIG_SOUNDWIRE_WCD_CTRL */
 #endif /* _LINUX_SWR_WCD_H */
diff --git a/include/uapi/linux/msm_audio_calibration.h b/include/uapi/linux/msm_audio_calibration.h
index 5a0b860..1696ae5 100644
--- a/include/uapi/linux/msm_audio_calibration.h
+++ b/include/uapi/linux/msm_audio_calibration.h
@@ -107,6 +107,8 @@
 
 #define AFE_SIDETONE_IIR_CAL_TYPE AFE_SIDETONE_IIR_CAL_TYPE
 
+#define TOPOLOGY_SPECIFIC_CHANNEL_INFO
+
 enum {
 	VERSION_0_0,
 };
@@ -376,9 +378,15 @@
 	int32_t		app_type;
 };
 
+#define VSS_NUM_CHANNELS_MAX	8
+
 struct audio_cal_info_voc_top {
 	int32_t		topology;
 	int32_t		acdb_id;
+#ifdef TOPOLOGY_SPECIFIC_CHANNEL_INFO
+	uint32_t	num_channels;
+	uint8_t		channel_mapping[VSS_NUM_CHANNELS_MAX];
+#endif
 };
 
 struct audio_cal_info_vocproc {
diff --git a/soc/pinctrl-lpi.c b/soc/pinctrl-lpi.c
index 0fa7b60..07a582e 100644
--- a/soc/pinctrl-lpi.c
+++ b/soc/pinctrl-lpi.c
@@ -622,6 +622,7 @@
 {
 	struct lpi_gpio_state *state = platform_get_drvdata(pdev);
 
+	audio_notifier_deregister("lpi_tlmm");
 	gpiochip_remove(&state->chip);
 	return 0;
 }