ASoC: msm: Support DS1 processing controls

Add support to send parameters to enable DS1 processing in LPASS

Change-Id: I22d3f8a4618b69dbc86077acb436f90fc1431c5c
Signed-off-by: Subhash Chandra Bose Naripeddy <snariped@codeaurora.org>
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 04e683f..f0c224d 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -335,6 +335,7 @@
 /*  Payload an #ADM_CMD_GET_PP_PARAMS_V5 command.
 */
 struct adm_cmd_get_pp_params_v5 {
+	struct apr_hdr hdr;
 	u32                  data_payload_addr_lsw;
 	/* LSW of parameter data payload address.*/
 
@@ -6913,4 +6914,7 @@
 	struct afe_port_cmd_set_param_v2 param;
 } __packed;
 
+/* Dolby DAP topology */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
+
 #endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 77a805c..4bea1e1 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -32,6 +32,12 @@
 int adm_open(int port, int path, int rate, int mode, int topology,
 				bool perf_mode, uint16_t bits_per_sample);
 
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+			uint32_t params_length, char *params);
+
+int adm_dolby_dap_send_params(int port_id, char *params,
+				 uint32_t params_length);
+
 int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
 			int topology, bool perf_mode, uint16_t bits_per_sample);
 
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 35a9646..66c475f 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -163,6 +163,16 @@
 	 OCMEM gets exercised for low-power
 	 audio and voice use cases.
 
+config DOLBY_DAP
+	bool "Enable Dolby DAP"
+	depends on SND_SOC_MSM8974
+	help
+	 To add support for dolby DAP post processing.
+	 This support is to configure the post processing parameters
+	 to DSP. The configuration includes sending the end point
+	 device, end point dependent post processing parameters and
+	 the various posrt processing parameters
+
 config SND_SOC_MSM8974
 	tristate "SoC Machine driver for MSM8974 boards"
 	depends on ARCH_MSM8974
@@ -173,6 +183,7 @@
 	select SND_SOC_MSM_HDMI_CODEC_RX
 	select SND_DYNAMIC_MINORS
 	select AUDIO_OCMEM
+	select DOLBY_DAP
 	help
 	 To add support for SoC audio on MSM8974.
 	 This will enable sound soc drivers which
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 391b3da..f3dcf95 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -5,6 +5,7 @@
 			msm-lsm-client.o
 obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
 				 msm-dai-stub-v2.o
+obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o
 obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o \
 	 rtac.o q6lsm.o
 ocmem-audio-objs += audio_ocmem.o
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
new file mode 100644
index 0000000..b43c3bd
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -0,0 +1,707 @@
+/* Copyright (c) 2013, 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
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/q6adm-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/q6afe-v2.h>
+
+#include "msm-dolby-dap-config.h"
+
+/* dolby endp based parameters */
+struct dolby_dap_endp_params_s {
+	int device;
+	int device_ch_caps;
+	int dap_device;
+	int params_id[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+	int params_len[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+	int params_offset[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+	int params_val[DOLBY_ENDDEP_PARAM_LENGTH];
+};
+
+const struct dolby_dap_endp_params_s
+			dolby_dap_endp_params[NUM_DOLBY_ENDP_DEVICE] = {
+	{EARPIECE,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{SPEAKER,			2, DOLBY_ENDP_INT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{WIRED_HEADSET,			2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{WIRED_HEADPHONE,		2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_SCO,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_SCO_HEADSET,		2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_SCO_CARKIT,		2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_A2DP,		2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_A2DP_HEADPHONES,	2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{BLUETOOTH_A2DP_SPEAKER,	2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{AUX_DIGITAL,			2, DOLBY_ENDP_HDMI,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+	{AUX_DIGITAL,			6, DOLBY_ENDP_HDMI,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+	{AUX_DIGITAL,			8, DOLBY_ENDP_HDMI,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+	{ANLG_DOCK_HEADSET,		2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{DGTL_DOCK_HEADSET,		2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{USB_ACCESSORY,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{USB_DEVICE,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{REMOTE_SUBMIX,			2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{ANC_HEADSET,			2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{ANC_HEADPHONE,			2, DOLBY_ENDP_HEADPHONES,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{PROXY,				2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{FM,				2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+	{FM_TX,				2, DOLBY_ENDP_EXT_SPEAKERS,
+		{DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+		{DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+};
+
+/* dolby param ids to/from dsp */
+static uint32_t	dolby_dap_params_id[ALL_DOLBY_PARAMS] = {
+	DOLBY_PARAM_ID_VDHE, DOLBY_PARAM_ID_VSPE, DOLBY_PARAM_ID_DSSF,
+	DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLE,
+	DOLBY_PARAM_ID_DVMC, DOLBY_PARAM_ID_DVME, DOLBY_PARAM_ID_IENB,
+	DOLBY_PARAM_ID_IEBF, DOLBY_PARAM_ID_IEON, DOLBY_PARAM_ID_DEON,
+	DOLBY_PARAM_ID_NGON, DOLBY_PARAM_ID_GEON, DOLBY_PARAM_ID_GENB,
+	DOLBY_PARAM_ID_GEBF, DOLBY_PARAM_ID_AONB, DOLBY_PARAM_ID_AOBF,
+	DOLBY_PARAM_ID_AOBG, DOLBY_PARAM_ID_AOON, DOLBY_PARAM_ID_ARNB,
+	DOLBY_PARAM_ID_ARBF, DOLBY_PARAM_ID_PLB,  DOLBY_PARAM_ID_PLMD,
+	DOLBY_PARAM_ID_DHSB, DOLBY_PARAM_ID_DHRG, DOLBY_PARAM_ID_DSSB,
+	DOLBY_PARAM_ID_DSSA, DOLBY_PARAM_ID_DVLA, DOLBY_PARAM_ID_IEBT,
+	DOLBY_PARAM_ID_IEA,  DOLBY_PARAM_ID_DEA,  DOLBY_PARAM_ID_DED,
+	DOLBY_PARAM_ID_GEBG, DOLBY_PARAM_ID_AOCC, DOLBY_PARAM_ID_ARBI,
+	DOLBY_PARAM_ID_ARBL, DOLBY_PARAM_ID_ARBH, DOLBY_PARAM_ID_AROD,
+	DOLBY_PARAM_ID_ARTP, DOLBY_PARAM_ID_VMON, DOLBY_PARAM_ID_VMB,
+	DOLBY_PARAM_ID_VCNB, DOLBY_PARAM_ID_VCBF, DOLBY_PARAM_ID_PREG,
+	DOLBY_PARAM_ID_VEN,  DOLBY_PARAM_ID_PSTG, DOLBY_COMMIT_ALL_TO_DSP,
+	DOLBY_COMMIT_TO_DSP, DOLBY_USE_CACHE, DOLBY_AUTO_ENDP,
+	DOLBY_AUTO_ENDDEP_PARAMS
+};
+
+/* modifed state:	0x00000000 - Not updated
+*			> 0x00000000 && < 0x00010000
+*				Updated and not commited to DSP
+*			0x00010001 - Updated and commited to DSP
+*			> 0x00010001 - Modified the commited value
+*/
+static int dolby_dap_params_modified[MAX_DOLBY_PARAMS] = { 0 };
+/* param offset */
+static uint32_t	dolby_dap_params_offset[MAX_DOLBY_PARAMS] = {
+	DOLBY_PARAM_VDHE_OFFSET, DOLBY_PARAM_VSPE_OFFSET,
+	DOLBY_PARAM_DSSF_OFFSET, DOLBY_PARAM_DVLI_OFFSET,
+	DOLBY_PARAM_DVLO_OFFSET, DOLBY_PARAM_DVLE_OFFSET,
+	DOLBY_PARAM_DVMC_OFFSET, DOLBY_PARAM_DVME_OFFSET,
+	DOLBY_PARAM_IENB_OFFSET, DOLBY_PARAM_IEBF_OFFSET,
+	DOLBY_PARAM_IEON_OFFSET, DOLBY_PARAM_DEON_OFFSET,
+	DOLBY_PARAM_NGON_OFFSET, DOLBY_PARAM_GEON_OFFSET,
+	DOLBY_PARAM_GENB_OFFSET, DOLBY_PARAM_GEBF_OFFSET,
+	DOLBY_PARAM_AONB_OFFSET, DOLBY_PARAM_AOBF_OFFSET,
+	DOLBY_PARAM_AOBG_OFFSET, DOLBY_PARAM_AOON_OFFSET,
+	DOLBY_PARAM_ARNB_OFFSET, DOLBY_PARAM_ARBF_OFFSET,
+	DOLBY_PARAM_PLB_OFFSET,  DOLBY_PARAM_PLMD_OFFSET,
+	DOLBY_PARAM_DHSB_OFFSET, DOLBY_PARAM_DHRG_OFFSET,
+	DOLBY_PARAM_DSSB_OFFSET, DOLBY_PARAM_DSSA_OFFSET,
+	DOLBY_PARAM_DVLA_OFFSET, DOLBY_PARAM_IEBT_OFFSET,
+	DOLBY_PARAM_IEA_OFFSET,  DOLBY_PARAM_DEA_OFFSET,
+	DOLBY_PARAM_DED_OFFSET,  DOLBY_PARAM_GEBG_OFFSET,
+	DOLBY_PARAM_AOCC_OFFSET, DOLBY_PARAM_ARBI_OFFSET,
+	DOLBY_PARAM_ARBL_OFFSET, DOLBY_PARAM_ARBH_OFFSET,
+	DOLBY_PARAM_AROD_OFFSET, DOLBY_PARAM_ARTP_OFFSET,
+	DOLBY_PARAM_VMON_OFFSET, DOLBY_PARAM_VMB_OFFSET,
+	DOLBY_PARAM_VCNB_OFFSET, DOLBY_PARAM_VCBF_OFFSET,
+	DOLBY_PARAM_PREG_OFFSET, DOLBY_PARAM_VEN_OFFSET,
+	DOLBY_PARAM_PSTG_OFFSET
+};
+/* param_length */
+static uint32_t	dolby_dap_params_length[MAX_DOLBY_PARAMS] = {
+	DOLBY_PARAM_VDHE_LENGTH, DOLBY_PARAM_VSPE_LENGTH,
+	DOLBY_PARAM_DSSF_LENGTH, DOLBY_PARAM_DVLI_LENGTH,
+	DOLBY_PARAM_DVLO_LENGTH, DOLBY_PARAM_DVLE_LENGTH,
+	DOLBY_PARAM_DVMC_LENGTH, DOLBY_PARAM_DVME_LENGTH,
+	DOLBY_PARAM_IENB_LENGTH, DOLBY_PARAM_IEBF_LENGTH,
+	DOLBY_PARAM_IEON_LENGTH, DOLBY_PARAM_DEON_LENGTH,
+	DOLBY_PARAM_NGON_LENGTH, DOLBY_PARAM_GEON_LENGTH,
+	DOLBY_PARAM_GENB_LENGTH, DOLBY_PARAM_GEBF_LENGTH,
+	DOLBY_PARAM_AONB_LENGTH, DOLBY_PARAM_AOBF_LENGTH,
+	DOLBY_PARAM_AOBG_LENGTH, DOLBY_PARAM_AOON_LENGTH,
+	DOLBY_PARAM_ARNB_LENGTH, DOLBY_PARAM_ARBF_LENGTH,
+	DOLBY_PARAM_PLB_LENGTH,  DOLBY_PARAM_PLMD_LENGTH,
+	DOLBY_PARAM_DHSB_LENGTH, DOLBY_PARAM_DHRG_LENGTH,
+	DOLBY_PARAM_DSSB_LENGTH, DOLBY_PARAM_DSSA_LENGTH,
+	DOLBY_PARAM_DVLA_LENGTH, DOLBY_PARAM_IEBT_LENGTH,
+	DOLBY_PARAM_IEA_LENGTH,  DOLBY_PARAM_DEA_LENGTH,
+	DOLBY_PARAM_DED_LENGTH,  DOLBY_PARAM_GEBG_LENGTH,
+	DOLBY_PARAM_AOCC_LENGTH, DOLBY_PARAM_ARBI_LENGTH,
+	DOLBY_PARAM_ARBL_LENGTH, DOLBY_PARAM_ARBH_LENGTH,
+	DOLBY_PARAM_AROD_LENGTH, DOLBY_PARAM_ARTP_LENGTH,
+	DOLBY_PARAM_VMON_LENGTH, DOLBY_PARAM_VMB_LENGTH,
+	DOLBY_PARAM_VCNB_LENGTH, DOLBY_PARAM_VCBF_LENGTH,
+	DOLBY_PARAM_PREG_LENGTH, DOLBY_PARAM_VEN_LENGTH,
+	DOLBY_PARAM_PSTG_LENGTH
+};
+
+/* param_value */
+static uint32_t	dolby_dap_params_value[TOTAL_LENGTH_DOLBY_PARAM] = {0};
+
+struct dolby_dap_params_get_s {
+	int32_t  port_id;
+	uint32_t device_id;
+	uint32_t param_id;
+	uint32_t offset;
+	uint32_t length;
+};
+
+struct dolby_dap_params_states_s {
+	bool use_cache;
+	bool auto_endp;
+	bool enddep_params;
+	int  port_id;
+	int  port_open_count;
+	int  port_ids_dolby_can_be_enabled;
+	int  device;
+};
+
+static struct dolby_dap_params_get_s dolby_dap_params_get = {-1, DEVICE_OUT_ALL,
+								 0, 0, 0};
+static struct dolby_dap_params_states_s dolby_dap_params_states = { true, true,
+						true, DOLBY_INVALID_PORT_ID,
+						0, DEVICE_OUT_ALL, 0 };
+/*
+port_ids_dolby_can_be_enabled is set to 0x7FFFFFFF.
+this needs to be removed after interface validation
+*/
+
+static int map_device_to_dolby_endpoint(int device)
+{
+	int i, dolby_dap_device = DOLBY_ENDP_INT_SPEAKERS;
+	for (i = 0; i < NUM_DOLBY_ENDP_DEVICE; i++) {
+		if (dolby_dap_endp_params[i].device == device) {
+			dolby_dap_device = dolby_dap_endp_params[i].dap_device;
+			break;
+		}
+	}
+	/* default the endpoint to speaker if corresponding device entry */
+	/* not found */
+	if (i >= NUM_DOLBY_ENDP_DEVICE)
+		dolby_dap_params_states.device = SPEAKER;
+	return dolby_dap_device;
+}
+
+static int dolby_dap_send_end_point(int port_id)
+{
+	int rc = 0;
+	char *params_value;
+	int *update_params_value;
+	uint32_t params_length = (DOLBY_PARAM_INT_ENDP_LENGTH +
+				DOLBY_PARAM_PAYLOAD_SIZE) * sizeof(uint32_t);
+
+	pr_debug("%s\n", __func__);
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+	update_params_value = (int *)params_value;
+	*update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+	*update_params_value++ = DOLBY_PARAM_ID_INIT_ENDP;
+	*update_params_value++ = DOLBY_PARAM_INT_ENDP_LENGTH * sizeof(uint32_t);
+	*update_params_value++ =
+		 map_device_to_dolby_endpoint(dolby_dap_params_states.device);
+	rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+	if (rc) {
+		pr_err("%s: send dolby params failed\n", __func__);
+		rc = -EINVAL;
+	}
+	kfree(params_value);
+	return rc;
+}
+
+static int dolby_dap_send_enddep_params(int port_id, int device_channels)
+{
+	int i, j, rc = 0, idx, offset;
+	char *params_value;
+	int *update_params_value;
+	uint32_t params_length = (DOLBY_ENDDEP_PARAM_LENGTH +
+					DOLBY_NUM_ENDP_DEPENDENT_PARAMS *
+					DOLBY_PARAM_PAYLOAD_SIZE) *
+				sizeof(uint32_t);
+
+	pr_debug("%s\n", __func__);
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+	update_params_value = (int *)params_value;
+	for (idx = 0; idx < NUM_DOLBY_ENDP_DEVICE; idx++) {
+		if (dolby_dap_endp_params[idx].device ==
+			dolby_dap_params_states.device) {
+			if (dolby_dap_params_states.device == AUX_DIGITAL) {
+				if (dolby_dap_endp_params[idx].device_ch_caps ==
+					device_channels)
+					break;
+			} else {
+				break;
+			}
+		}
+	}
+	if (idx >= NUM_DOLBY_ENDP_DEVICE) {
+		pr_err("%s: device is not set accordingly\n", __func__);
+		return -EINVAL;
+	}
+	for (i = 0; i < DOLBY_ENDDEP_PARAM_LENGTH; i++) {
+		*update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+		*update_params_value++ =
+				dolby_dap_endp_params[idx].params_id[i];
+		*update_params_value++ =
+			dolby_dap_endp_params[idx].params_len[i] *
+				sizeof(uint32_t);
+		offset = dolby_dap_endp_params[idx].params_offset[i];
+		for (j = 0; j < dolby_dap_endp_params[idx].params_len[i]; j++)
+			*update_params_value++ =
+				dolby_dap_endp_params[idx].params_val[offset+j];
+	}
+	rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+	if (rc) {
+		pr_err("%s: send dolby params failed\n", __func__);
+		rc = -EINVAL;
+	}
+	kfree(params_value);
+	return rc;
+}
+
+static int dolby_dap_send_cached_params(int port_id, int commit)
+{
+	char *params_value;
+	int *update_params_value, rc = 0;
+	uint32_t index_offset, i, j;
+	uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
+				MAX_DOLBY_PARAMS * DOLBY_PARAM_PAYLOAD_SIZE) *
+				sizeof(uint32_t);
+
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	update_params_value = (int *)params_value;
+	params_length = 0;
+	for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+		if ((dolby_dap_params_modified[i] == 0) ||
+		    ((commit) &&
+		     ((dolby_dap_params_modified[i] & 0x00010000) &&
+		     ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))))
+			continue;
+		*update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+		*update_params_value++ = dolby_dap_params_id[i];
+		*update_params_value++ = dolby_dap_params_length[i] *
+						sizeof(uint32_t);
+		index_offset = dolby_dap_params_offset[i];
+		for (j = 0; j < dolby_dap_params_length[i]; j++)
+			*update_params_value++ =
+				dolby_dap_params_value[index_offset+j];
+		params_length += (DOLBY_PARAM_PAYLOAD_SIZE +
+				dolby_dap_params_length[i]) * sizeof(uint32_t);
+	}
+	pr_debug("%s, valid param length: %d", __func__, params_length);
+	if (params_length) {
+		rc = adm_dolby_dap_send_params(port_id, params_value,
+						params_length);
+		if (rc) {
+			pr_err("%s: send dolby params failed\n", __func__);
+			return -EINVAL;
+		}
+		for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+			if ((dolby_dap_params_modified[i] == 0) ||
+			    ((commit) &&
+			     ((dolby_dap_params_modified[i] & 0x00010000) &&
+			     ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))
+			    ))
+				continue;
+			dolby_dap_params_modified[i] = 0x00010001;
+		}
+	}
+	kfree(params_value);
+	return 0;
+}
+
+int dolby_dap_init(int port_id, int channels)
+{
+	int ret = 0;
+	if ((port_id != DOLBY_INVALID_PORT_ID) &&
+		(port_id &
+		 dolby_dap_params_states.port_ids_dolby_can_be_enabled)) {
+		dolby_dap_params_states.port_id = port_id;
+		dolby_dap_params_states.port_open_count++;
+		if (dolby_dap_params_states.auto_endp) {
+			ret = dolby_dap_send_end_point(port_id);
+			if (ret) {
+				pr_err("%s: err sending endppoint\n", __func__);
+				return ret;
+			}
+		}
+		if (dolby_dap_params_states.use_cache) {
+			ret = dolby_dap_send_cached_params(port_id, 0);
+			if (ret) {
+				pr_err("%s: err sending cached params\n",
+					__func__);
+				return ret;
+			}
+		}
+		if (dolby_dap_params_states.enddep_params) {
+			dolby_dap_send_enddep_params(port_id,
+				channels);
+			if (ret) {
+				pr_err("%s: err sending endp dependent params\n",
+					__func__);
+				return ret;
+			}
+		}
+	}
+	return ret;
+}
+
+void dolby_dap_deinit(int port_id)
+{
+	dolby_dap_params_states.port_open_count--;
+	if ((dolby_dap_params_states.port_id == port_id) &&
+		(!dolby_dap_params_states.port_open_count))
+		dolby_dap_params_states.port_id = DOLBY_INVALID_PORT_ID;
+}
+
+static int map_device_to_port_id(int device)
+{
+	int port_id = SLIMBUS_0_RX;
+	device = DEVICE_OUT_ALL;
+	/*update the device when single stream to multiple device is handled*/
+	if (device == DEVICE_OUT_ALL) {
+		port_id = PRIMARY_I2S_RX | SLIMBUS_0_RX | HDMI_RX |
+				INT_BT_SCO_RX | INT_FM_RX |
+				RT_PROXY_PORT_001_RX | PCM_RX |
+				MI2S_RX | SECONDARY_I2S_RX |
+				SLIMBUS_1_RX | SLIMBUS_4_RX | SLIMBUS_3_RX |
+				AFE_PORT_ID_SECONDARY_MI2S_RX;
+	} else {
+		/* update port_id based on the device */
+	}
+	return port_id;
+}
+
+int msm_routing_get_dolby_dap_param_to_set_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while setting the parameters */
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_set_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int rc = 0;
+	uint32_t idx, j;
+	uint32_t device = ucontrol->value.integer.value[0];
+	uint32_t param_id = ucontrol->value.integer.value[1];
+	uint32_t offset = ucontrol->value.integer.value[2];
+	uint32_t length = ucontrol->value.integer.value[3];
+
+	int port_id = dolby_dap_params_states.port_id;
+
+	dolby_dap_params_states.port_ids_dolby_can_be_enabled =
+						map_device_to_port_id(device);
+	for (idx = 0; idx < ALL_DOLBY_PARAMS; idx++) {
+		/*paramid from user space*/
+		if (param_id == dolby_dap_params_id[idx])
+			break;
+	}
+	if (idx > ALL_DOLBY_PARAMS-1) {
+		pr_err("%s: invalid param id 0x%x to set\n", __func__,
+			param_id);
+		return -EINVAL;
+	}
+	switch (idx) {
+		case DOLBY_COMMIT_ALL_IDX: {
+			/* COMIIT ALL: Send all parameters to DSP */
+			pr_debug("%s: COMMIT_ALL recvd\n", __func__);
+			if (port_id != DOLBY_INVALID_PORT_ID)
+				rc = dolby_dap_send_cached_params(port_id, 0);
+		}
+		break;
+		case DOLBY_COMMIT_IDX: {
+			pr_debug("%s: COMMIT recvd\n", __func__);
+			/* COMMIT: Send only modified paramters to DSP */
+			if (port_id != DOLBY_INVALID_PORT_ID)
+				rc = dolby_dap_send_cached_params(port_id, 1);
+		}
+		break;
+		case DOLBY_USE_CACHE_IDX: {
+			pr_debug("%s: USE CACHE recvd val: %ld\n", __func__,
+				ucontrol->value.integer.value[4]);
+			dolby_dap_params_states.use_cache =
+				ucontrol->value.integer.value[4];
+		}
+		break;
+		case DOLBY_AUTO_ENDP_IDX: {
+			pr_debug("%s: AUTO_ENDP recvd val: %ld\n", __func__,
+				ucontrol->value.integer.value[4]);
+			dolby_dap_params_states.auto_endp =
+				ucontrol->value.integer.value[4];
+		}
+		break;
+		case DOLBY_AUTO_ENDDEP_IDX: {
+			pr_debug("%s: USE_ENDDEP_PARAMS recvd val: %ld\n",
+				__func__, ucontrol->value.integer.value[4]);
+			dolby_dap_params_states.enddep_params =
+				ucontrol->value.integer.value[4];
+		}
+		break;
+		default: {
+			/* cache the parameters */
+			dolby_dap_params_modified[idx] += 1;
+			dolby_dap_params_length[idx] = length;
+			pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n",
+				__func__, device, param_id, offset, length);
+			for (j = 0; j < length; j++) {
+				dolby_dap_params_value[
+					dolby_dap_params_offset[idx] +
+					offset + j]
+				= ucontrol->value.integer.value[4+j];
+				pr_debug("value[%d]: %ld\n", j,
+					ucontrol->value.integer.value[4+j]);
+			}
+		}
+	}
+
+	return rc;
+}
+
+int msm_routing_get_dolby_dap_param_to_get_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int rc = 0, i;
+	char *params_value;
+	int *update_params_value;
+	uint32_t params_length = DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM *
+					sizeof(uint32_t);
+	uint32_t param_payload_len =
+			DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+	int port_id = dolby_dap_params_states.port_id;
+
+	if (port_id == DOLBY_INVALID_PORT_ID) {
+		pr_err("%s, port_id not set, returning error", __func__);
+		return -EINVAL;
+	}
+	params_value = kzalloc(params_length, GFP_KERNEL);
+	if (!params_value) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
+		rc = adm_dolby_dap_get_params(dolby_dap_params_get.port_id,
+						DOLBY_BUNDLE_MODULE_ID,
+						DOLBY_PARAM_ID_VER,
+						params_length +
+							param_payload_len,
+						params_value);
+	} else {
+		for (i = 0; i < MAX_DOLBY_PARAMS; i++)
+			if (dolby_dap_params_id[i] ==
+				dolby_dap_params_get.param_id)
+				break;
+		if (i > MAX_DOLBY_PARAMS-1) {
+			pr_err("%s: invalid param id to set", __func__);
+			rc = -EINVAL;
+		} else {
+			params_length = (dolby_dap_params_length[i] +
+						DOLBY_PARAM_PAYLOAD_SIZE) *
+						sizeof(uint32_t);
+			rc = adm_dolby_dap_get_params(
+						dolby_dap_params_get.port_id,
+						DOLBY_BUNDLE_MODULE_ID,
+						dolby_dap_params_id[i],
+						params_length +
+						 param_payload_len,
+						params_value);
+		}
+	}
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(params_value);
+		rc = -EINVAL;
+	}
+	update_params_value = (int *)params_value;
+	ucontrol->value.integer.value[0] = dolby_dap_params_get.device_id;
+	ucontrol->value.integer.value[1] = dolby_dap_params_get.param_id;
+	ucontrol->value.integer.value[2] = dolby_dap_params_get.offset;
+	ucontrol->value.integer.value[3] = dolby_dap_params_get.length;
+
+	pr_debug("%s: FROM DSP value[0] 0x%x value[1] %d value[2] 0x%x\n",
+			__func__, update_params_value[0],
+			update_params_value[1], update_params_value[2]);
+	for (i = 0; i < dolby_dap_params_get.length; i++) {
+		ucontrol->value.integer.value[DOLBY_PARAM_PAYLOAD_SIZE+i] =
+			update_params_value[i];
+		pr_debug("value[%d]:%d\n", i, update_params_value[i]);
+	}
+	pr_debug("%s: Returning param_id=0x%x offset=%d length=%d\n",
+			__func__, dolby_dap_params_get.param_id,
+			dolby_dap_params_get.offset,
+			dolby_dap_params_get.length);
+	kfree(params_value);
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_get_control(
+					struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol) {
+	dolby_dap_params_get.device_id = ucontrol->value.integer.value[0];
+	dolby_dap_params_get.port_id =
+			(dolby_dap_params_get.device_id == DEVICE_OUT_ALL) ?
+			dolby_dap_params_states.port_id :
+			map_device_to_port_id(dolby_dap_params_get.device_id);
+	dolby_dap_params_get.param_id = ucontrol->value.integer.value[1];
+	dolby_dap_params_get.offset = ucontrol->value.integer.value[2];
+	dolby_dap_params_get.length = ucontrol->value.integer.value[3];
+	pr_debug("%s: param_id=0x%x offset=%d length=%d\n", __func__,
+		dolby_dap_params_get.param_id, dolby_dap_params_get.offset,
+		dolby_dap_params_get.length);
+	return 0;
+}
+
+int msm_routing_get_dolby_dap_param_visualizer_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	uint32_t length = dolby_dap_params_value[DOLBY_PARAM_VCNB_OFFSET];
+	char *visualizer_data;
+	int i, rc;
+	int *update_visualizer_data;
+	uint32_t offset, params_length =
+		(2*length + DOLBY_VIS_PARAM_HEADER_SIZE)*sizeof(uint32_t);
+	uint32_t param_payload_len =
+		DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+	int port_id = dolby_dap_params_states.port_id;
+	if (port_id == DOLBY_INVALID_PORT_ID) {
+		pr_err("%s, port_id not set, returning error", __func__);
+		ucontrol->value.integer.value[0] = 0;
+		return -EINVAL;
+	}
+	visualizer_data = kzalloc(params_length, GFP_KERNEL);
+	if (!visualizer_data) {
+		pr_err("%s, params memory alloc failed\n", __func__);
+		return -ENOMEM;
+	}
+	offset = 0;
+	params_length = length * sizeof(uint32_t);
+	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+					DOLBY_BUNDLE_MODULE_ID,
+					DOLBY_PARAM_ID_VCBG,
+					params_length + param_payload_len,
+					visualizer_data + offset);
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(visualizer_data);
+		return -EINVAL;
+	}
+
+	offset = length * sizeof(uint32_t);
+	rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+					DOLBY_BUNDLE_MODULE_ID,
+					DOLBY_PARAM_ID_VCBE,
+					params_length + param_payload_len,
+					visualizer_data + offset);
+	if (rc) {
+		pr_err("%s: get parameters failed\n", __func__);
+		kfree(visualizer_data);
+		return -EINVAL;
+	}
+
+	ucontrol->value.integer.value[0] = 2*length;
+	pr_debug("%s: visualizer data length %ld\n", __func__,
+			ucontrol->value.integer.value[0]);
+	update_visualizer_data = (int *)visualizer_data;
+	for (i = 0; i < 2*length; i++) {
+		ucontrol->value.integer.value[1+i] = update_visualizer_data[i];
+		pr_debug("value[%d] %d\n", i, update_visualizer_data[i]);
+	}
+	kfree(visualizer_data);
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_param_visualizer_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while getting the visualizer data */
+	return 0;
+}
+
+int msm_routing_get_dolby_dap_endpoint_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	/* not used while setting the endpoint */
+	return 0;
+}
+
+int msm_routing_put_dolby_dap_endpoint_control(
+		struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol) {
+	int device = ucontrol->value.integer.value[0];
+	dolby_dap_params_states.device = device;
+	return 0;
+}
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
new file mode 100644
index 0000000..58ea36d
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
@@ -0,0 +1,348 @@
+/* Copyright (c) 2013, 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
+* only version 2 as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*/
+
+#ifndef _MSM_DOLBY_DAP_CONFIG_H_
+#define _MSM_DOLBY_DAP_CONFIG_H_
+
+#ifdef CONFIG_DOLBY_DAP
+/* DOLBY DOLBY GUIDS */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID	0x0001033B
+#define DOLBY_BUNDLE_MODULE_ID		0x00010723
+#define DOLBY_VISUALIZER_MODULE_ID	0x0001072B
+
+#define DOLBY_PARAM_ID_VDHE		0x0001074D
+#define DOLBY_PARAM_ID_VSPE		0x00010750
+#define DOLBY_PARAM_ID_DSSF		0x00010753
+#define DOLBY_PARAM_ID_DVLI		0x0001073E
+#define DOLBY_PARAM_ID_DVLO		0x0001073F
+#define DOLBY_PARAM_ID_DVLE		0x0001073C
+#define DOLBY_PARAM_ID_DVMC		0x00010741
+#define DOLBY_PARAM_ID_DVME		0x00010740
+#define DOLBY_PARAM_ID_IENB		0x00010744
+#define DOLBY_PARAM_ID_IEBF		0x00010745
+#define DOLBY_PARAM_ID_IEON		0x00010743
+#define DOLBY_PARAM_ID_DEON		0x00010738
+#define DOLBY_PARAM_ID_NGON		0x00010736
+#define DOLBY_PARAM_ID_GEON		0x00010748
+#define DOLBY_PARAM_ID_GENB		0x00010749
+#define DOLBY_PARAM_ID_GEBF		0x0001074A
+#define DOLBY_PARAM_ID_AONB		0x0001075B
+#define DOLBY_PARAM_ID_AOBF		0x0001075C
+#define DOLBY_PARAM_ID_AOBG		0x0001075D
+#define DOLBY_PARAM_ID_AOON		0x00010759
+#define DOLBY_PARAM_ID_ARNB		0x0001075F
+#define DOLBY_PARAM_ID_ARBF		0x00010760
+#define DOLBY_PARAM_ID_PLB		0x00010768
+#define DOLBY_PARAM_ID_PLMD		0x00010767
+#define DOLBY_PARAM_ID_DHSB		0x0001074E
+#define DOLBY_PARAM_ID_DHRG		0x0001074F
+#define DOLBY_PARAM_ID_DSSB		0x00010751
+#define DOLBY_PARAM_ID_DSSA		0x00010752
+#define DOLBY_PARAM_ID_DVLA		0x0001073D
+#define DOLBY_PARAM_ID_IEBT		0x00010746
+#define DOLBY_PARAM_ID_IEA		0x0001076A
+#define DOLBY_PARAM_ID_DEA		0x00010739
+#define DOLBY_PARAM_ID_DED		0x0001073A
+#define DOLBY_PARAM_ID_GEBG		0x0001074B
+#define DOLBY_PARAM_ID_AOCC		0x0001075A
+#define DOLBY_PARAM_ID_ARBI		0x00010761
+#define DOLBY_PARAM_ID_ARBL		0x00010762
+#define DOLBY_PARAM_ID_ARBH		0x00010763
+#define DOLBY_PARAM_ID_AROD		0x00010764
+#define DOLBY_PARAM_ID_ARTP		0x00010765
+#define DOLBY_PARAM_ID_VMON		0x00010756
+#define DOLBY_PARAM_ID_VMB		0x00010757
+#define DOLBY_PARAM_ID_VCNB		0x00010733
+#define DOLBY_PARAM_ID_VCBF		0x00010734
+#define DOLBY_PARAM_ID_PREG		0x00010728
+#define DOLBY_PARAM_ID_VEN		0x00010732
+#define DOLBY_PARAM_ID_PSTG		0x00010729
+#define DOLBY_PARAM_ID_INIT_ENDP		0x00010727
+
+/* Not Used with Set Param kcontrol, only to query using Get Param */
+#define DOLBY_PARAM_ID_VER                0x00010726
+
+#define DOLBY_PARAM_ID_VCBG		0x00010730
+#define DOLBY_PARAM_ID_VCBE		0x00010731
+
+/* DOLBY DAP control params */
+#define DOLBY_COMMIT_ALL_TO_DSP		0x70000001
+#define DOLBY_COMMIT_TO_DSP		0x70000002
+#define DOLBY_USE_CACHE			0x70000003
+#define DOLBY_AUTO_ENDP			0x70000004
+#define DOLBY_AUTO_ENDDEP_PARAMS		0x70000005
+
+/* DOLBY DAP offsets start */
+#define DOLBY_PARAM_VDHE_LENGTH   1
+#define DOLBY_PARAM_VDHE_OFFSET   0
+#define DOLBY_PARAM_VSPE_LENGTH   1
+#define DOLBY_PARAM_VSPE_OFFSET   (DOLBY_PARAM_VDHE_OFFSET + \
+					DOLBY_PARAM_VDHE_LENGTH)
+#define DOLBY_PARAM_DSSF_LENGTH   1
+#define DOLBY_PARAM_DSSF_OFFSET   (DOLBY_PARAM_VSPE_OFFSET + \
+					DOLBY_PARAM_VSPE_LENGTH)
+#define DOLBY_PARAM_DVLI_LENGTH   1
+#define DOLBY_PARAM_DVLI_OFFSET   (DOLBY_PARAM_DSSF_OFFSET + \
+					DOLBY_PARAM_DSSF_LENGTH)
+#define DOLBY_PARAM_DVLO_LENGTH   1
+#define DOLBY_PARAM_DVLO_OFFSET   (DOLBY_PARAM_DVLI_OFFSET + \
+					DOLBY_PARAM_DVLI_LENGTH)
+#define DOLBY_PARAM_DVLE_LENGTH   1
+#define DOLBY_PARAM_DVLE_OFFSET   (DOLBY_PARAM_DVLO_OFFSET + \
+					DOLBY_PARAM_DVLO_LENGTH)
+#define DOLBY_PARAM_DVMC_LENGTH   1
+#define DOLBY_PARAM_DVMC_OFFSET   (DOLBY_PARAM_DVLE_OFFSET + \
+					DOLBY_PARAM_DVLE_LENGTH)
+#define DOLBY_PARAM_DVME_LENGTH   1
+#define DOLBY_PARAM_DVME_OFFSET   (DOLBY_PARAM_DVMC_OFFSET + \
+					DOLBY_PARAM_DVMC_LENGTH)
+#define DOLBY_PARAM_IENB_LENGTH   1
+#define DOLBY_PARAM_IENB_OFFSET   (DOLBY_PARAM_DVME_OFFSET + \
+					DOLBY_PARAM_DVME_LENGTH)
+#define DOLBY_PARAM_IEBF_LENGTH   40
+#define DOLBY_PARAM_IEBF_OFFSET   (DOLBY_PARAM_IENB_OFFSET + \
+					DOLBY_PARAM_IENB_LENGTH)
+#define DOLBY_PARAM_IEON_LENGTH   1
+#define DOLBY_PARAM_IEON_OFFSET   (DOLBY_PARAM_IEBF_OFFSET + \
+					DOLBY_PARAM_IEBF_LENGTH)
+#define DOLBY_PARAM_DEON_LENGTH   1
+#define DOLBY_PARAM_DEON_OFFSET   (DOLBY_PARAM_IEON_OFFSET + \
+					DOLBY_PARAM_IEON_LENGTH)
+#define DOLBY_PARAM_NGON_LENGTH   1
+#define DOLBY_PARAM_NGON_OFFSET   (DOLBY_PARAM_DEON_OFFSET + \
+					DOLBY_PARAM_DEON_LENGTH)
+#define DOLBY_PARAM_GEON_LENGTH   1
+#define DOLBY_PARAM_GEON_OFFSET   (DOLBY_PARAM_NGON_OFFSET + \
+					DOLBY_PARAM_NGON_LENGTH)
+#define DOLBY_PARAM_GENB_LENGTH   1
+#define DOLBY_PARAM_GENB_OFFSET   (DOLBY_PARAM_GEON_OFFSET + \
+					DOLBY_PARAM_GEON_LENGTH)
+#define DOLBY_PARAM_GEBF_LENGTH   40
+#define DOLBY_PARAM_GEBF_OFFSET   (DOLBY_PARAM_GENB_OFFSET + \
+					DOLBY_PARAM_GENB_LENGTH)
+#define DOLBY_PARAM_AONB_LENGTH   1
+#define DOLBY_PARAM_AONB_OFFSET   (DOLBY_PARAM_GEBF_OFFSET + \
+					DOLBY_PARAM_GEBF_LENGTH)
+#define DOLBY_PARAM_AOBF_LENGTH   40
+#define DOLBY_PARAM_AOBF_OFFSET   (DOLBY_PARAM_AONB_OFFSET + \
+					DOLBY_PARAM_AONB_LENGTH)
+#define DOLBY_PARAM_AOBG_LENGTH   329
+#define DOLBY_PARAM_AOBG_OFFSET   (DOLBY_PARAM_AOBF_OFFSET + \
+					DOLBY_PARAM_AOBF_LENGTH)
+#define DOLBY_PARAM_AOON_LENGTH   1
+#define DOLBY_PARAM_AOON_OFFSET   (DOLBY_PARAM_AOBG_OFFSET + \
+					DOLBY_PARAM_AOBG_LENGTH)
+#define DOLBY_PARAM_ARNB_LENGTH   1
+#define DOLBY_PARAM_ARNB_OFFSET   (DOLBY_PARAM_AOON_OFFSET + \
+					DOLBY_PARAM_AOON_LENGTH)
+#define DOLBY_PARAM_ARBF_LENGTH   40
+#define DOLBY_PARAM_ARBF_OFFSET   (DOLBY_PARAM_ARNB_OFFSET + \
+					DOLBY_PARAM_ARNB_LENGTH)
+#define DOLBY_PARAM_PLB_LENGTH    1
+#define DOLBY_PARAM_PLB_OFFSET    (DOLBY_PARAM_ARBF_OFFSET + \
+					DOLBY_PARAM_ARBF_LENGTH)
+#define DOLBY_PARAM_PLMD_LENGTH   1
+#define DOLBY_PARAM_PLMD_OFFSET   (DOLBY_PARAM_PLB_OFFSET + \
+					DOLBY_PARAM_PLB_LENGTH)
+#define DOLBY_PARAM_DHSB_LENGTH   1
+#define DOLBY_PARAM_DHSB_OFFSET   (DOLBY_PARAM_PLMD_OFFSET + \
+					DOLBY_PARAM_PLMD_LENGTH)
+#define DOLBY_PARAM_DHRG_LENGTH   1
+#define DOLBY_PARAM_DHRG_OFFSET   (DOLBY_PARAM_DHSB_OFFSET + \
+					DOLBY_PARAM_DHSB_LENGTH)
+#define DOLBY_PARAM_DSSB_LENGTH   1
+#define DOLBY_PARAM_DSSB_OFFSET   (DOLBY_PARAM_DHRG_OFFSET + \
+					DOLBY_PARAM_DHRG_LENGTH)
+#define DOLBY_PARAM_DSSA_LENGTH   1
+#define DOLBY_PARAM_DSSA_OFFSET   (DOLBY_PARAM_DSSB_OFFSET + \
+					DOLBY_PARAM_DSSB_LENGTH)
+#define DOLBY_PARAM_DVLA_LENGTH   1
+#define DOLBY_PARAM_DVLA_OFFSET   (DOLBY_PARAM_DSSA_OFFSET + \
+					DOLBY_PARAM_DSSA_LENGTH)
+#define DOLBY_PARAM_IEBT_LENGTH   40
+#define DOLBY_PARAM_IEBT_OFFSET   (DOLBY_PARAM_DVLA_OFFSET + \
+					DOLBY_PARAM_DVLA_LENGTH)
+#define DOLBY_PARAM_IEA_LENGTH    1
+#define DOLBY_PARAM_IEA_OFFSET    (DOLBY_PARAM_IEBT_OFFSET + \
+					DOLBY_PARAM_IEBT_LENGTH)
+#define DOLBY_PARAM_DEA_LENGTH    1
+#define DOLBY_PARAM_DEA_OFFSET    (DOLBY_PARAM_IEA_OFFSET + \
+					DOLBY_PARAM_IEA_LENGTH)
+#define DOLBY_PARAM_DED_LENGTH    1
+#define DOLBY_PARAM_DED_OFFSET    (DOLBY_PARAM_DEA_OFFSET + \
+					DOLBY_PARAM_DEA_LENGTH)
+#define DOLBY_PARAM_GEBG_LENGTH   40
+#define DOLBY_PARAM_GEBG_OFFSET   (DOLBY_PARAM_DED_OFFSET + \
+					DOLBY_PARAM_DED_LENGTH)
+#define DOLBY_PARAM_AOCC_LENGTH   1
+#define DOLBY_PARAM_AOCC_OFFSET   (DOLBY_PARAM_GEBG_OFFSET + \
+					DOLBY_PARAM_GEBG_LENGTH)
+#define DOLBY_PARAM_ARBI_LENGTH   40
+#define DOLBY_PARAM_ARBI_OFFSET   (DOLBY_PARAM_AOCC_OFFSET + \
+					DOLBY_PARAM_AOCC_LENGTH)
+#define DOLBY_PARAM_ARBL_LENGTH   40
+#define DOLBY_PARAM_ARBL_OFFSET   (DOLBY_PARAM_ARBI_OFFSET + \
+					DOLBY_PARAM_ARBI_LENGTH)
+#define DOLBY_PARAM_ARBH_LENGTH   40
+#define DOLBY_PARAM_ARBH_OFFSET   (DOLBY_PARAM_ARBL_OFFSET + \
+					DOLBY_PARAM_ARBL_LENGTH)
+#define DOLBY_PARAM_AROD_LENGTH   1
+#define DOLBY_PARAM_AROD_OFFSET   (DOLBY_PARAM_ARBH_OFFSET + \
+					DOLBY_PARAM_ARBH_LENGTH)
+#define DOLBY_PARAM_ARTP_LENGTH   1
+#define DOLBY_PARAM_ARTP_OFFSET   (DOLBY_PARAM_AROD_OFFSET + \
+					DOLBY_PARAM_AROD_LENGTH)
+#define DOLBY_PARAM_VMON_LENGTH   1
+#define DOLBY_PARAM_VMON_OFFSET   (DOLBY_PARAM_ARTP_OFFSET + \
+					DOLBY_PARAM_ARTP_LENGTH)
+#define DOLBY_PARAM_VMB_LENGTH    1
+#define DOLBY_PARAM_VMB_OFFSET    (DOLBY_PARAM_VMON_OFFSET + \
+					DOLBY_PARAM_VMON_LENGTH)
+#define DOLBY_PARAM_VCNB_LENGTH   1
+#define DOLBY_PARAM_VCNB_OFFSET   (DOLBY_PARAM_VMB_OFFSET + \
+					DOLBY_PARAM_VMB_LENGTH)
+#define DOLBY_PARAM_VCBF_LENGTH   20
+#define DOLBY_PARAM_VCBF_OFFSET   (DOLBY_PARAM_VCNB_OFFSET + \
+					DOLBY_PARAM_VCNB_LENGTH)
+#define DOLBY_PARAM_PREG_LENGTH   1
+#define DOLBY_PARAM_PREG_OFFSET   (DOLBY_PARAM_VCBF_OFFSET + \
+					DOLBY_PARAM_VCBF_LENGTH)
+#define DOLBY_PARAM_VEN_LENGTH    1
+#define DOLBY_PARAM_VEN_OFFSET    (DOLBY_PARAM_PREG_OFFSET + \
+					DOLBY_PARAM_PREG_LENGTH)
+#define DOLBY_PARAM_PSTG_LENGTH   1
+#define DOLBY_PARAM_PSTG_OFFSET   (DOLBY_PARAM_VEN_OFFSET + \
+					DOLBY_PARAM_VEN_LENGTH)
+
+#define DOLBY_PARAM_INT_ENDP_LENGTH		1
+#define DOLBY_PARAM_PAYLOAD_SIZE		4
+#define DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM	329
+
+#define DOLBY_NUM_ENDP_DEPENDENT_PARAMS		1
+#define DOLBY_ENDDEP_PARAM_DVLO_OFFSET		0
+#define DOLBY_ENDDEP_PARAM_DVLO_LENGTH		1
+#define DOLBY_ENDDEP_PARAM_LENGTH		DOLBY_ENDDEP_PARAM_DVLO_LENGTH
+
+#define MAX_DOLBY_PARAMS			47
+#define MAX_DOLBY_CTRL_PARAMS			5
+#define ALL_DOLBY_PARAMS			(MAX_DOLBY_PARAMS + \
+							MAX_DOLBY_CTRL_PARAMS)
+#define DOLBY_COMMIT_ALL_IDX			MAX_DOLBY_PARAMS
+#define DOLBY_COMMIT_IDX			(MAX_DOLBY_PARAMS+1)
+#define DOLBY_USE_CACHE_IDX			(MAX_DOLBY_PARAMS+2)
+#define DOLBY_AUTO_ENDP_IDX			(MAX_DOLBY_PARAMS+3)
+#define DOLBY_AUTO_ENDDEP_IDX			(MAX_DOLBY_PARAMS+4)
+
+#define TOTAL_LENGTH_DOLBY_PARAM		745
+#define NUM_DOLBY_ENDP_DEVICE			23
+#define DOLBY_VIS_PARAM_HEADER_SIZE		 25
+
+#define DOLBY_INVALID_PORT_ID			-1
+/* DOLBY device definitions */
+enum {
+	DOLBY_ENDP_INT_SPEAKERS = 0,
+	DOLBY_ENDP_EXT_SPEAKERS,
+	DOLBY_ENDP_HEADPHONES,
+	DOLBY_ENDP_HDMI,
+	DOLBY_ENDP_SPDIF,
+	DOLBY_ENDP_DLNA,
+	DOLBY_ENDP_ANALOG,
+};
+
+enum {
+	DEVICE_NONE			= 0x0,
+	/* output devices */
+	EARPIECE			= 0x1,
+	SPEAKER				= 0x2,
+	WIRED_HEADSET			= 0x4,
+	WIRED_HEADPHONE			= 0x8,
+	BLUETOOTH_SCO			= 0x10,
+	BLUETOOTH_SCO_HEADSET		= 0x20,
+	BLUETOOTH_SCO_CARKIT		= 0x40,
+	BLUETOOTH_A2DP			= 0x80,
+	BLUETOOTH_A2DP_HEADPHONES	= 0x100,
+	BLUETOOTH_A2DP_SPEAKER		= 0x200,
+	AUX_DIGITAL			= 0x400,
+	ANLG_DOCK_HEADSET		= 0x800,
+	DGTL_DOCK_HEADSET		= 0x1000,
+	USB_ACCESSORY			= 0x2000,
+	USB_DEVICE			= 0x4000,
+	REMOTE_SUBMIX			= 0x8000,
+	ANC_HEADSET			= 0x10000,
+	ANC_HEADPHONE			= 0x20000,
+	PROXY				= 0x40000,
+	FM				= 0x80000,
+	FM_TX				= 0x100000,
+	DEVICE_OUT_ALL			= 0x7FFFFFFF,
+};
+/* DOLBY device definitions end */
+
+struct dolby_dap_params {
+	uint32_t value[TOTAL_LENGTH_DOLBY_PARAM + MAX_DOLBY_PARAMS];
+} __packed;
+int dolby_dap_init(int port_id, int channels);
+int msm_routing_get_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol);
+void dolby_dap_deinit(int port_id);
+/* Dolby DOLBY end */
+#else
+int dolby_dap_init(int port_id, int channels) { return 0; }
+int msm_routing_get_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_set_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_get_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_visualizer_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_endpoint_control(
+			struct snd_kcontrol *kcontrol,
+			struct snd_ctl_elem_value *ucontrol) { return 0; }
+void dolby_dap_deinit(int port_id) { return; }
+#endif
+
+#endif
+
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 4e3a929..cb08ddc 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -10,7 +10,6 @@
  * GNU General Public License for more details.
  */
 
-
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/module.h>
@@ -34,6 +33,7 @@
 #include <mach/qdsp6v2/q6core.h>
 
 #include "msm-pcm-routing-v2.h"
+#include "msm-dolby-dap-config.h"
 #include "q6voice.h"
 
 struct msm_pcm_routing_bdai_data {
@@ -186,6 +186,20 @@
 	(void *)&msm_srs_trumedia_params[param_block_idx].srs_params.global);
 }
 
+int get_topology(int path_type)
+{
+	int topology_id = 0;
+	if (path_type == ADM_PATH_PLAYBACK)
+		topology_id = get_adm_rx_topology();
+	else
+		topology_id = get_adm_tx_topology();
+
+	if (topology_id  == 0)
+		topology_id = DEFAULT_COPP_TOPOLOGY;
+
+	return topology_id;
+}
+
 #define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
 static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
 	{ PRIMARY_I2S_RX, 0, 0, 0, 0, 0},
@@ -319,7 +333,7 @@
 void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
 					int dspst_id, int stream_type)
 {
-	int i, session_type, path_type, port_type;
+	int i, session_type, path_type, port_type, port_id, topology;
 	struct route_payload payload;
 	u32 channels;
 	uint16_t bits_per_sample = 16;
@@ -347,6 +361,7 @@
 	/* re-enable EQ if active */
 	if (eq_data[fedai_id].enable)
 		msm_send_eq_values(fedai_id);
+	topology = get_topology(path_type);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
 			msm_bedais[i].perf_mode = perf_mode;
@@ -362,27 +377,31 @@
 			else if (msm_bedais[i].format ==
 						SNDRV_PCM_FORMAT_S24_LE)
 				bits_per_sample = 24;
-
 			if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
 				(channels > 0))
 				adm_multi_ch_copp_open(msm_bedais[i].port_id,
 				path_type,
 				msm_bedais[i].sample_rate,
 				msm_bedais[i].channel,
-				DEFAULT_COPP_TOPOLOGY, msm_bedais[i].perf_mode,
+				topology, msm_bedais[i].perf_mode,
 				bits_per_sample);
 			else
 				adm_open(msm_bedais[i].port_id,
 				path_type,
 				msm_bedais[i].sample_rate,
 				msm_bedais[i].channel,
-				DEFAULT_COPP_TOPOLOGY, false,
+				topology, false,
 				bits_per_sample);
 
 			payload.copp_ids[payload.num_copps++] =
 				msm_bedais[i].port_id;
-			srs_port_id = msm_bedais[i].port_id;
+			port_id = srs_port_id = msm_bedais[i].port_id;
 			srs_send_params(srs_port_id, 1, 0);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				if (dolby_dap_init(port_id,
+						msm_bedais[i].channel) < 0)
+					pr_err("%s: Err init dolby dap\n",
+						__func__);
 		}
 	}
 	if (payload.num_copps)
@@ -394,7 +413,7 @@
 
 void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
 {
-	int i, port_type, session_type;
+	int i, port_type, session_type, path_type, topology;
 
 	if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
 		/* bad ID assigned in machine driver */
@@ -405,19 +424,24 @@
 	if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
 		port_type = MSM_AFE_PORT_TYPE_RX;
 		session_type = SESSION_TYPE_RX;
+		path_type = ADM_PATH_PLAYBACK;
 	} else {
 		port_type = MSM_AFE_PORT_TYPE_TX;
 		session_type = SESSION_TYPE_TX;
+		path_type = ADM_PATH_LIVE_REC;
 	}
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
 		if (!is_be_dai_extproc(i) &&
 		   (afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
 		   (msm_bedais[i].active) &&
-		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
+		   (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
 			adm_close(msm_bedais[i].port_id);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				dolby_dap_deinit(msm_bedais[i].port_id);
+		}
 	}
 
 	fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
@@ -444,7 +468,7 @@
 
 static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
 {
-	int session_type, path_type;
+	int session_type, path_type, port_id, topology;
 	u32 channels;
 	uint16_t bits_per_sample = 16;
 
@@ -466,7 +490,7 @@
 	}
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	if (set) {
 		if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
 			(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
@@ -485,19 +509,23 @@
 				path_type,
 				msm_bedais[reg].sample_rate,
 				channels,
-				DEFAULT_COPP_TOPOLOGY,
+				topology,
 				msm_bedais[reg].perf_mode,
 				bits_per_sample);
 			} else
 				adm_open(msm_bedais[reg].port_id,
 				path_type,
 				msm_bedais[reg].sample_rate, channels,
-				DEFAULT_COPP_TOPOLOGY, false, bits_per_sample);
+				topology, false, bits_per_sample);
 
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type);
-			srs_port_id = msm_bedais[reg].port_id;
+			port_id = srs_port_id = msm_bedais[reg].port_id;
 			srs_send_params(srs_port_id, 1, 0);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				if (dolby_dap_init(port_id, channels) < 0)
+					pr_err("%s: Err init dolby dap\n",
+						__func__);
 		}
 	} else {
 		if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
@@ -507,6 +535,8 @@
 		if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
 			INVALID_SESSION) {
 			adm_close(msm_bedais[reg].port_id);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				dolby_dap_deinit(msm_bedais[reg].port_id);
 			msm_pcm_routing_build_matrix(val,
 				fe_dai_map[val][session_type], path_type);
 		}
@@ -2112,6 +2142,30 @@
 	msm_routing_put_dolby_security_control),
 };
 
+static const struct snd_kcontrol_new dolby_dap_param_to_set_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Set Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, 128, msm_routing_get_dolby_dap_param_to_set_control,
+	msm_routing_put_dolby_dap_param_to_set_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_get_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Get Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+	0, 128, msm_routing_get_dolby_dap_param_to_get_control,
+	msm_routing_put_dolby_dap_param_to_get_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_visualizer_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Get Visualizer", SND_SOC_NOPM, 0,
+	0xFFFFFFFF, 0, 41, msm_routing_get_dolby_dap_param_visualizer_control,
+	msm_routing_put_dolby_dap_param_visualizer_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_end_point_controls[] = {
+	SOC_SINGLE_MULTI_EXT("DS1 DAP Endpoint", SND_SOC_NOPM, 0,
+	0xFFFFFFFF, 0, 1, msm_routing_get_dolby_dap_endpoint_control,
+	msm_routing_put_dolby_dap_endpoint_control),
+};
+
 static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
 	SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
 	MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -2963,7 +3017,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	unsigned int be_id = rtd->dai_link->be_id;
-	int i, session_type;
+	int i, session_type, path_type, topology;
 	struct msm_pcm_routing_bdai_data *bedai;
 
 	if (be_id >= MSM_BACKEND_DAI_MAX) {
@@ -2974,13 +3028,20 @@
 	bedai = &msm_bedais[be_id];
 	session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
 		0 : 1);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		path_type = ADM_PATH_PLAYBACK;
+	else
+		path_type = ADM_PATH_LIVE_REC;
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
-		if (fe_dai_map[i][session_type] != INVALID_SESSION)
+		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 			adm_close(bedai->port_id);
 			srs_port_id = -1;
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				dolby_dap_deinit(bedai->port_id);
+		}
 	}
 
 	bedai->active = 0;
@@ -2996,7 +3057,7 @@
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
 	unsigned int be_id = rtd->dai_link->be_id;
-	int i, path_type, session_type;
+	int i, path_type, session_type, port_id, topology;
 	struct msm_pcm_routing_bdai_data *bedai;
 	u32 channels;
 	bool playback, capture;
@@ -3018,7 +3079,7 @@
 	}
 
 	mutex_lock(&routing_lock);
-
+	topology = get_topology(path_type);
 	if (bedai->active == 1)
 		goto done; /* Ignore prepare if back-end already active */
 
@@ -3043,21 +3104,25 @@
 					path_type,
 					bedai->sample_rate,
 					channels,
-					DEFAULT_COPP_TOPOLOGY, bedai->perf_mode,
+					topology, bedai->perf_mode,
 					bits_per_sample);
 			} else if (capture) {
 				adm_open(bedai->port_id,
 				path_type,
 				bedai->sample_rate,
 				channels,
-				DEFAULT_COPP_TOPOLOGY, false,
+				topology, false,
 				bits_per_sample);
 			}
 
 			msm_pcm_routing_build_matrix(i,
 				fe_dai_map[i][session_type], path_type);
-			srs_port_id = bedai->port_id;
+			port_id = srs_port_id = bedai->port_id;
 			srs_send_params(srs_port_id, 1, 0);
+			if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+				if (dolby_dap_init(port_id, channels) < 0)
+					pr_err("%s: Err init dolby dap\n",
+						__func__);
 		}
 	}
 
@@ -3157,6 +3222,22 @@
 				dolby_security_controls,
 			ARRAY_SIZE(dolby_security_controls));
 
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_to_set_controls,
+			ARRAY_SIZE(dolby_dap_param_to_set_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_to_get_controls,
+			ARRAY_SIZE(dolby_dap_param_to_get_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_visualizer_controls,
+			ARRAY_SIZE(dolby_dap_param_visualizer_controls));
+
+	snd_soc_add_platform_controls(platform,
+				dolby_dap_param_end_point_controls,
+			ARRAY_SIZE(dolby_dap_param_end_point_controls));
+
 	return 0;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 1c1029c..bd5821f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -141,4 +141,7 @@
 
 int compressed_set_volume(unsigned volume);
 
+uint32_t get_adm_rx_topology(void);
+
+uint32_t get_adm_tx_topology(void);
 #endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index b1db277..1bd3eac 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -33,6 +33,7 @@
 
 #define RESET_COPP_ID 99
 #define INVALID_COPP_ID 0xFF
+#define ADM_GET_PARAMETER_LENGTH 350
 
 struct adm_ctl {
 	void *apr;
@@ -64,6 +65,8 @@
 						{0, 0, 0, 0, 0, 0, 0, 0}
 					      };
 
+static int adm_dolby_get_parameters[ADM_GET_PARAMETER_LENGTH];
+
 int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
 {
 	struct adm_cmd_set_pp_params_inband_v5 *adm_params = NULL;
@@ -266,6 +269,134 @@
 	return ret;
 }
 
+int adm_dolby_dap_send_params(int port_id, char *params, uint32_t params_length)
+{
+	struct adm_cmd_set_pp_params_v5	*adm_params = NULL;
+	int sz, rc = 0, index = afe_get_port_index(port_id);
+
+	pr_debug("%s\n", __func__);
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d portid %#x\n",
+			__func__, index, port_id);
+		return -EINVAL;
+	}
+	sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+	adm_params = kzalloc(sz, GFP_KERNEL);
+	if (!adm_params) {
+		pr_err("%s, adm params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+			params, params_length);
+	adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	adm_params->hdr.pkt_size = sz;
+	adm_params->hdr.src_svc = APR_SVC_ADM;
+	adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+	adm_params->hdr.src_port = port_id;
+	adm_params->hdr.dest_svc = APR_SVC_ADM;
+	adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+	adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+	adm_params->hdr.token = port_id;
+	adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
+	adm_params->payload_addr_lsw = 0;
+	adm_params->payload_addr_msw = 0;
+	adm_params->mem_map_handle = 0;
+	adm_params->payload_size = params_length;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+	if (rc < 0) {
+		pr_err("%s: Set params failed port = %#x\n",
+			__func__, port_id);
+		rc = -EINVAL;
+		goto dolby_dap_send_param_return;
+	}
+	/* Wait for the callback */
+	rc = wait_event_timeout(this_adm.wait[index],
+		atomic_read(&this_adm.copp_stat[index]),
+		msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("%s: Set params timed out port = %#x\n",
+			 __func__, port_id);
+		rc = -EINVAL;
+		goto dolby_dap_send_param_return;
+	}
+	rc = 0;
+dolby_dap_send_param_return:
+	kfree(adm_params);
+	return rc;
+}
+
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+				uint32_t params_length, char *params)
+{
+	struct adm_cmd_get_pp_params_v5	*adm_params = NULL;
+	int sz, rc = 0, i = 0, index = afe_get_port_index(port_id);
+	int *params_data = (int *)params;
+
+	if (index < 0 || index >= AFE_MAX_PORTS) {
+		pr_err("%s: invalid port idx %d portid %#x\n",
+			__func__, index, port_id);
+		return -EINVAL;
+	}
+	sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+	adm_params = kzalloc(sz, GFP_KERNEL);
+	if (!adm_params) {
+		pr_err("%s, adm params memory alloc failed", __func__);
+		return -ENOMEM;
+	}
+
+	memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+			params, params_length);
+	adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	adm_params->hdr.pkt_size = sz;
+	adm_params->hdr.src_svc = APR_SVC_ADM;
+	adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+	adm_params->hdr.src_port = port_id;
+	adm_params->hdr.dest_svc = APR_SVC_ADM;
+	adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+	adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+	adm_params->hdr.token = port_id;
+	adm_params->hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
+	adm_params->data_payload_addr_lsw = 0;
+	adm_params->data_payload_addr_msw = 0;
+	adm_params->mem_map_handle = 0;
+	adm_params->module_id = module_id;
+	adm_params->param_id = param_id;
+	adm_params->param_max_size = params_length;
+	adm_params->reserved = 0;
+
+	atomic_set(&this_adm.copp_stat[index], 0);
+	rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+	if (rc < 0) {
+		pr_err("%s: Failed to Get DOLBY Params on port %d\n", __func__,
+			port_id);
+		rc = -EINVAL;
+		goto dolby_dap_get_param_return;
+	}
+	/* Wait for the callback with copp id */
+	rc = wait_event_timeout(this_adm.wait[index],
+			atomic_read(&this_adm.copp_stat[index]),
+			msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("%s: DOLBY get params timed out port = %d\n", __func__,
+			port_id);
+		rc = -EINVAL;
+		goto dolby_dap_get_param_return;
+	}
+	if (params_data) {
+		for (i = 0; i < adm_dolby_get_parameters[0]; i++)
+			params_data[i] = adm_dolby_get_parameters[1+i];
+	}
+	rc = 0;
+dolby_dap_get_param_return:
+	kfree(adm_params);
+	return rc;
+}
+
 static void adm_callback_debug_print(struct apr_client_data *data)
 {
 	uint32_t *payload;
@@ -428,6 +559,13 @@
 					__func__, payload[0]);
 			rtac_make_adm_callback(payload,
 				data->payload_size);
+			adm_dolby_get_parameters[0] = payload[3];
+			pr_debug("GET_PP PARAM:received parameter length: %x\n",
+					adm_dolby_get_parameters[0]);
+			for (i = 0; i < payload[3]; i++)
+				adm_dolby_get_parameters[1+i] = payload[4+i];
+			atomic_set(&this_adm.copp_stat[index], 1);
+			wake_up(&this_adm.wait[index]);
 			break;
 		case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
 			pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
@@ -807,20 +945,10 @@
 		open.endpoint_id_1 = tmp_port;
 		open.endpoint_id_2 = 0xFFFF;
 
-		/* convert path to acdb path */
-		if (path == ADM_PATH_PLAYBACK)
-			open.topology_id = get_adm_rx_topology();
-		else {
-			open.topology_id = get_adm_tx_topology();
-			if ((open.topology_id ==
-				VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
-			    (open.topology_id ==
-				VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+		open.topology_id = topology;
+		if ((open.topology_id == VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+			(open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
 				rate = 16000;
-		}
-
-		if (open.topology_id  == 0)
-			open.topology_id = topology;
 
 		open.dev_num_channel = channel_mode & 0x00FF;
 		open.bit_width = bits_per_sample;