Merge changes Ia0648af6,Ie257475a into msm-3.0

* changes:
  msm: kgsl: add a225-specific registers to dumps
  msm: kgsl: fix format of the rbbm read error message
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 9952818..bc350a7 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -220,7 +220,7 @@
 # CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
 CONFIG_DIAG_CHAR=y
 # CONFIG_HW_RANDOM is not set
-CONFIG_DCC_TTY=y
+# CONFIG_DCC_TTY is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_MSM is not set
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 0419929..e6b7b79 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -180,10 +180,8 @@
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
-CONFIG_HVC_DCC=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
-CONFIG_DCC_TTY=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 # CONFIG_I2C_MSM is not set
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 6f33d86..c294d59 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -242,6 +242,8 @@
 	select FIX_MOVABLE_ZONE if ENABLE_DMM
 	select CLEANCACHE
 	select QCACHE
+	select MIGHT_HAVE_PCI
+	select ARCH_SUPPORTS_MSI
 
 config ARCH_MSMCOPPER
 	bool "MSM Copper"
@@ -1216,6 +1218,13 @@
 	    prompt "Package 4"
 endchoice
 
+config MSM_PCIE
+	bool "MSM PCIe Controller driver"
+	depends on PCI && PCI_MSI
+	help
+	  Enables the PCIe functionality by configures PCIe core on
+	  MSM chipset and by enabling the ARM PCI framework extension.
+
 config MSM_RPC_SDIO_XPRT
 	depends on MSM_SDIO_AL
 	default y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index c5b0081..000cf43 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -156,6 +156,8 @@
 obj-$(CONFIG_MSM_PM) += pm.o
 obj-$(CONFIG_MSM_NOPM) += no-pm.o
 
+obj-$(CONFIG_MSM_PCIE) += pcie.o pcie_irq.o
+
 obj-$(CONFIG_MSM_SPM_V1) += spm.o
 obj-$(CONFIG_MSM_SPM_V2) += spm-v2.o spm_devices.o
 
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ceae29c..df041f0 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2139,6 +2139,7 @@
 	&apq_cpudai_slimbus_1_rx,
 	&apq_cpudai_slimbus_1_tx,
 	&apq_cpudai_slimbus_2_tx,
+	&apq_cpudai_slimbus_3_rx,
 	&apq8064_rpm_device,
 	&apq8064_rpm_log_device,
 	&apq8064_rpm_stat_device,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 6fd0f1b..f52d312 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -41,6 +41,7 @@
 #include <linux/i2c/isa1200.h>
 #include <linux/gpio_keys.h>
 #include <linux/memory.h>
+#include <linux/memblock.h>
 
 #include <linux/slimbus/slimbus.h>
 #include <linux/mfd/wcd9xxx/core.h>
@@ -76,6 +77,7 @@
 #include <mach/ion.h>
 #include <mach/mdm2.h>
 #include <mach/msm_rtb.h>
+#include <linux/fmem.h>
 
 #include "timer.h"
 #include "devices.h"
@@ -122,17 +124,29 @@
 #else
 #define MSM_PMEM_SIZE 0x2800000 /* 40 Mbytes */
 #endif
-
+#define MSM_LIQUID_PMEM_SIZE 0x4000000 /* 64 Mbytes */
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x65000
 #define MSM_ION_SF_SIZE		MSM_PMEM_SIZE
-#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MM_SIZE		MSM_PMEM_ADSP_SIZE
 #define MSM_ION_QSECOM_SIZE	0x300000 /* (3MB) */
+#define MSM_ION_HEAP_NUM	8
+
+
+#define MSM_ION_MM_FW_SIZE	0x200000 /* (2MB) */
 #define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_AUDIO_SIZE	MSM_PMEM_AUDIO_SIZE
-#define MSM_ION_HEAP_NUM	8
+
+#define MSM_LIQUID_ION_MM_SIZE (MSM_ION_MM_SIZE + 0x600000)
+#define MSM_LIQUID_ION_SF_SIZE MSM_LIQUID_PMEM_SIZE
+#define MSM_HDMI_PRIM_ION_SF_SIZE MSM_HDMI_PRIM_PMEM_SIZE
+
+#define MSM8930_FIXED_AREA_START 0xa0000000
+#define MAX_FIXED_AREA_SIZE	0x10000000
+#define MSM_MM_FW_SIZE		0x200000
+#define MSM8930_FW_START	(MSM8930_FIXED_AREA_START - MSM_MM_FW_SIZE)
+
 #else
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
 #define MSM_ION_HEAP_NUM	1
@@ -218,6 +232,9 @@
 #endif /* CONFIG_MSM_MULTIMEDIA_USE_ION */
 #endif /* CONFIG_ANDROID_PMEM */
 
+struct fmem_platform_data msm8930_fmem_pdata = {
+};
+
 #define DSP_RAM_BASE_8960 0x8da00000
 #define DSP_RAM_SIZE_8960 0x1800000
 static int dspcrashd_pdata_8960 = 0xDEADDEAD;
@@ -294,24 +311,36 @@
 	return MEMTYPE_EBI1;
 }
 
+#define FMEM_ENABLED 1
 #ifdef CONFIG_ION_MSM
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 static struct ion_cp_heap_pdata cp_mm_msm8930_ion_pdata = {
 	.permission_type = IPT_TYPE_MM_CARVEOUT,
 	.align = PAGE_SIZE,
+	.reusable = FMEM_ENABLED,
+	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_MIDDLE,
 };
 
 static struct ion_cp_heap_pdata cp_mfc_msm8930_ion_pdata = {
 	.permission_type = IPT_TYPE_MFC_SHAREDMEM,
 	.align = PAGE_SIZE,
+	.reusable = 0,
+	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_HIGH,
 };
+
 static struct ion_co_heap_pdata co_msm8930_ion_pdata = {
 	.adjacent_mem_id = INVALID_HEAP_ID,
 	.align = PAGE_SIZE,
+	.mem_is_fmem = 0,
 };
+
 static struct ion_co_heap_pdata fw_co_msm8930_ion_pdata = {
 	.adjacent_mem_id = ION_CP_MM_HEAP_ID,
 	.align = SZ_128K,
+	.mem_is_fmem = FMEM_ENABLED,
+	.fixed_position = FIXED_LOW,
 };
 #endif
 
@@ -399,15 +428,180 @@
 };
 #endif
 
+struct platform_device msm8930_fmem_device = {
+	.name = "fmem",
+	.id = 1,
+	.dev = { .platform_data = &msm8930_fmem_pdata },
+};
+
+static void __init reserve_mem_for_ion(enum ion_memory_types mem_type,
+				      unsigned long size)
+{
+	msm8930_reserve_table[mem_type].size += size;
+}
+
+static void __init msm8930_reserve_fixed_area(unsigned long fixed_area_size)
+{
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	int ret;
+
+	if (fixed_area_size > MAX_FIXED_AREA_SIZE)
+		panic("fixed area size is larger than %dM\n",
+			MAX_FIXED_AREA_SIZE >> 20);
+
+	reserve_info->fixed_area_size = fixed_area_size;
+	reserve_info->fixed_area_start = MSM8930_FW_START;
+
+	ret = memblock_remove(reserve_info->fixed_area_start,
+		reserve_info->fixed_area_size);
+	BUG_ON(ret);
+#endif
+}
+
+/**
+ * Reserve memory for ION and calculate amount of reusable memory for fmem.
+ * We only reserve memory for heaps that are not reusable. However, we only
+ * support one reusable heap at the moment so we ignore the reusable flag for
+ * other than the first heap with reusable flag set. Also handle special case
+ * for video heaps (MM,FW, and MFC). Video requires heaps MM and MFC to be
+ * at a higher address than FW in addition to not more than 256MB away from the
+ * base address of the firmware. This means that if MM is reusable the other
+ * two heaps must be allocated in the same region as FW. This is handled by the
+ * mem_is_fmem flag in the platform data. In addition the MM heap must be
+ * adjacent to the FW heap for content protection purposes.
+ */
 static void __init reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_SIZE;
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MM_FW_SIZE;
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_QSECOM_SIZE;
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
+	unsigned int i;
+	unsigned int reusable_count = 0;
+	unsigned int fixed_size = 0;
+	unsigned int fixed_low_size, fixed_middle_size, fixed_high_size;
+	unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
+
+	msm8930_fmem_pdata.size = 0;
+	msm8930_fmem_pdata.reserved_size_low = 0;
+	msm8930_fmem_pdata.reserved_size_high = 0;
+	fixed_low_size = 0;
+	fixed_middle_size = 0;
+	fixed_high_size = 0;
+
+	/* We only support 1 reusable heap. Check if more than one heap
+	 * is specified as reusable and set as non-reusable if found.
+	 */
+	for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap =
+						&(msm8930_ion_pdata.heaps[i]);
+
+		if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
+			struct ion_cp_heap_pdata *data = heap->extra_data;
+
+			reusable_count += (data->reusable) ? 1 : 0;
+
+			if (data->reusable && reusable_count > 1) {
+				pr_err("%s: Too many heaps specified as "
+					"reusable. Heap %s was not configured "
+					"as reusable.\n", __func__, heap->name);
+				data->reusable = 0;
+			}
+		}
+	}
+
+	for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
+		const struct ion_platform_heap *heap =
+						&(msm8930_ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			int fixed_position = NOT_FIXED;
+			int mem_is_fmem = 0;
+
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				mem_is_fmem = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->mem_is_fmem;
+				fixed_position = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				mem_is_fmem = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->mem_is_fmem;
+				fixed_position = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			default:
+				break;
+			}
+
+			if (fixed_position != NOT_FIXED)
+				fixed_size += heap->size;
+			else
+				reserve_mem_for_ion(MEMTYPE_EBI1, heap->size);
+
+			if (fixed_position == FIXED_LOW)
+				fixed_low_size += heap->size;
+			else if (fixed_position == FIXED_MIDDLE)
+				fixed_middle_size += heap->size;
+			else if (fixed_position == FIXED_HIGH)
+				fixed_high_size += heap->size;
+
+			if (mem_is_fmem)
+				msm8930_fmem_pdata.size += heap->size;
+		}
+	}
+
+	if (!fixed_size)
+		return;
+
+	if (msm8930_fmem_pdata.size) {
+		msm8930_fmem_pdata.reserved_size_low = fixed_low_size;
+		msm8930_fmem_pdata.reserved_size_high = fixed_high_size;
+	}
+
+	/* Since the fixed area may be carved out of lowmem,
+	 * make sure the length is a multiple of 1M.
+	 */
+	fixed_size = (fixed_size + MSM_MM_FW_SIZE + SECTION_SIZE - 1)
+		& SECTION_MASK;
+	msm8930_reserve_fixed_area(fixed_size);
+
+	fixed_low_start = MSM8930_FIXED_AREA_START;
+	fixed_middle_start = fixed_low_start + fixed_low_size;
+	fixed_high_start = fixed_middle_start + fixed_middle_size;
+
+	for (i = 0; i < msm8930_ion_pdata.nr; ++i) {
+		struct ion_platform_heap *heap = &(msm8930_ion_pdata.heaps[i]);
+
+		if (heap->extra_data) {
+			int fixed_position = NOT_FIXED;
+
+			switch (heap->type) {
+			case ION_HEAP_TYPE_CP:
+				fixed_position = ((struct ion_cp_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			case ION_HEAP_TYPE_CARVEOUT:
+				fixed_position = ((struct ion_co_heap_pdata *)
+					heap->extra_data)->fixed_position;
+				break;
+			default:
+				break;
+			}
+
+			switch (fixed_position) {
+			case FIXED_LOW:
+				heap->base = fixed_low_start;
+				break;
+			case FIXED_MIDDLE:
+				heap->base = fixed_middle_start;
+				break;
+			case FIXED_HIGH:
+				heap->base = fixed_high_start;
+				break;
+			default:
+				break;
+			}
+		}
+	}
 #endif
 }
 
@@ -428,6 +622,7 @@
 static struct reserve_info msm8930_reserve_info __initdata = {
 	.memtype_reserve_table = msm8930_reserve_table,
 	.calculate_reserve_sizes = msm8930_calculate_reserve_sizes,
+	.reserve_fixed_area = msm8930_reserve_fixed_area,
 	.paddr_to_memtype = msm8930_paddr_to_memtype,
 };
 
@@ -448,12 +643,15 @@
 
 	/* Check if 32 bit overflow occured */
 	if (high < mb->start)
-		high = ~0UL;
+		high -= PAGE_SIZE;
+
+	if (high < MAX_FIXED_AREA_SIZE + MSM8930_FIXED_AREA_START)
+		panic("fixed area extends beyond end of memory\n");
 
 	low &= ~(bank_size - 1);
 
 	if (high - low <= bank_size)
-		return;
+		goto no_dmm;
 
 	msm8930_reserve_info.bank_size = bank_size;
 #ifdef CONFIG_ENABLE_DMM
@@ -464,10 +662,11 @@
 		msm8930_reserve_info.low_unstable_address,
 		msm8930_reserve_info.max_unstable_size,
 		msm8930_reserve_info.bank_size);
-#else
-	msm8930_reserve_info.low_unstable_address = 0;
-	msm8930_reserve_info.max_unstable_size = 0;
+	return;
 #endif
+no_dmm:
+	msm8930_reserve_info.low_unstable_address = high;
+	msm8930_reserve_info.max_unstable_size = 0;
 }
 
 static void __init place_movable_zone(void)
@@ -490,6 +689,18 @@
 static void __init msm8930_reserve(void)
 {
 	msm_reserve();
+	if (msm8930_fmem_pdata.size) {
+#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+		if (reserve_info->fixed_area_size) {
+			msm8930_fmem_pdata.phys =
+				reserve_info->fixed_area_start + MSM_MM_FW_SIZE;
+		pr_info("mm fw at %lx (fixed) size %x\n",
+			reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
+		pr_info("fmem start %lx (fixed) size %lx\n",
+			msm8930_fmem_pdata.phys, msm8930_fmem_pdata.size);
+		}
+#endif
+	}
 }
 
 static int msm8930_change_memory_power(u64 start, u64 size,
@@ -1740,6 +1951,7 @@
 	&msm8930_android_pmem_audio_device,
 #endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 #endif /*CONFIG_ANDROID_PMEM*/
+	&msm8930_fmem_device,
 	&msm_device_bam_dmux,
 	&msm_fm_platform_init,
 
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index e97fdad..bd89e34 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -120,14 +120,38 @@
 
 static struct msm_camera_sensor_info msm_camera_sensor_s5k4e1_data;
 
-struct msm_camera_device_platform_data msm_camera_device_data_csi1 = {
-	.csid_core = 1,
-	.is_csic = 1,
+struct msm_camera_device_platform_data msm_camera_device_data_csi1[] = {
+	{
+		.csid_core = 1,
+		.is_csic = 1,
+		.ioclk = {
+			.vfe_clk_rate = 192000000,
+		},
+	},
+	{
+		.csid_core = 1,
+		.is_csic = 1,
+		.ioclk = {
+			.vfe_clk_rate = 266667000,
+		},
+	},
 };
 
-struct msm_camera_device_platform_data msm_camera_device_data_csi0 = {
-	.csid_core = 0,
-	.is_csic = 1,
+struct msm_camera_device_platform_data msm_camera_device_data_csi0[] = {
+	{
+		.csid_core = 0,
+		.is_csic = 1,
+		.ioclk = {
+			.vfe_clk_rate = 192000000,
+		},
+	},
+	{
+		.csid_core = 0,
+		.is_csic = 1,
+		.ioclk = {
+			.vfe_clk_rate = 266667000,
+		},
+	},
 };
 
 static struct i2c_board_info msm_act_main_cam_i2c_info = {
@@ -159,7 +183,7 @@
 	.sensor_name    = "s5k4e1",
 	.sensor_reset_enable = 1,
 	.pmic_gpio_enable    = 0,
-	.pdata                  = &msm_camera_device_data_csi1,
+	.pdata                  = &msm_camera_device_data_csi1[0],
 	.flash_data             = &flash_s5k4e1,
 	.sensor_platform_info   = &sensor_board_info_s5k4e1,
 	.csi_if                 = 1,
@@ -187,7 +211,7 @@
 	.pmic_gpio_enable  = 1,
 	.sensor_reset	   = GPIO_SKU1_CAM_VGA_RESET_N,
 	.sensor_pwd	     = GPIO_SKU1_CAM_VGA_SHDN,
-	.pdata			= &msm_camera_device_data_csi0,
+	.pdata			= &msm_camera_device_data_csi0[0],
 	.flash_data	     = &flash_ov7692,
 	.sensor_platform_info   = &sensor_board_info_ov7692,
 	.csi_if		 = 1,
@@ -230,7 +254,7 @@
 	.pmic_gpio_enable  = 1,
 	.sensor_reset   = GPIO_SKU3_CAM_5MP_CAMIF_RESET,
 	.sensor_pwd     = GPIO_SKU3_CAM_5MP_SHDN_N,
-	.pdata          = &msm_camera_device_data_csi1,
+	.pdata          = &msm_camera_device_data_csi1[0],
 	.flash_data     = &flash_ov5647,
 	.sensor_platform_info   = &sensor_board_info_ov5647,
 	.csi_if                 = 1,
@@ -257,7 +281,7 @@
 	.sensor_name    = "mt9e013",
 	.sensor_reset_enable = 1,
 	.pmic_gpio_enable    = 0,
-	.pdata                  = &msm_camera_device_data_csi1,
+	.pdata                  = &msm_camera_device_data_csi1[1],
 	.flash_data             = &flash_mt9e013,
 	.sensor_platform_info   = &sensor_board_info_mt9e013,
 	.csi_if                 = 1,
@@ -283,7 +307,7 @@
 	.sensor_name    = "ov9726",
 	.sensor_reset_enable = 0,
 	.pmic_gpio_enable  = 0,
-	.pdata                  = &msm_camera_device_data_csi0,
+	.pdata                  = &msm_camera_device_data_csi0[0],
 	.flash_data             = &flash_ov9726,
 	.sensor_platform_info   = &sensor_board_info_ov9726,
 	.csi_if                 = 1,
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 4df2232..49945d0 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -186,6 +186,56 @@
 
 #define MXT_TS_IRQ_GPIO         48
 #define MXT_TS_RESET_GPIO       26
+#define MAX_VKEY_LEN		100
+
+static ssize_t mxt_virtual_keys_register(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	char *virtual_keys = __stringify(EV_KEY) ":" __stringify(KEY_MENU) \
+		":60:840:120:80" ":" __stringify(EV_KEY) \
+		":" __stringify(KEY_HOME)   ":180:840:120:80" \
+		":" __stringify(EV_KEY) ":" \
+		__stringify(KEY_BACK) ":300:840:120:80" \
+		":" __stringify(EV_KEY) ":" \
+		__stringify(KEY_SEARCH)   ":420:840:120:80" "\n";
+
+	return snprintf(buf, strnlen(virtual_keys, MAX_VKEY_LEN) + 1 , "%s",
+			virtual_keys);
+}
+
+static struct kobj_attribute mxt_virtual_keys_attr = {
+	.attr = {
+		.name = "virtualkeys.atmel_mxt_ts",
+		.mode = S_IRUGO,
+	},
+	.show = &mxt_virtual_keys_register,
+};
+
+static struct attribute *mxt_virtual_key_properties_attrs[] = {
+	&mxt_virtual_keys_attr.attr,
+	NULL,
+};
+
+static struct attribute_group mxt_virtual_key_properties_attr_group = {
+	.attrs = mxt_virtual_key_properties_attrs,
+};
+
+struct kobject *mxt_virtual_key_properties_kobj;
+
+static int mxt_vkey_setup(void)
+{
+	int retval;
+
+	mxt_virtual_key_properties_kobj =
+		kobject_create_and_add("board_properties", NULL);
+	if (mxt_virtual_key_properties_kobj)
+		retval = sysfs_create_group(mxt_virtual_key_properties_kobj,
+				&mxt_virtual_key_properties_attr_group);
+	if (!mxt_virtual_key_properties_kobj || retval)
+		pr_err("failed to create mxt board_properties\n");
+
+	return retval;
+}
 
 static const u8 mxt_config_data[] = {
 	/* T6 Object */
@@ -232,6 +282,51 @@
 	80, 100, 15, 3,
 };
 
+static const u8 mxt_config_data_evt[] = {
+	/* T6 Object */
+	0, 0, 0, 0, 0, 0,
+	/* T38 Object */
+	20, 0, 0, 0, 0, 0, 0, 0,
+	/* T7 Object */
+	24, 12, 10,
+	/* T8 Object */
+	30, 0, 20, 20, 0, 0, 9, 45, 10, 192,
+	/* T9 Object */
+	3, 0, 0, 18, 11, 0, 16, 60, 3, 1,
+	0, 1, 1, 0, 10, 10, 10, 10, 107, 3,
+	223, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+	20, 15, 0, 0, 2,
+	/* T15 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0,
+	/* T18 Object */
+	0, 0,
+	/* T19 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0,
+	/* T23 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0,
+	/* T25 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+	/* T40 Object */
+	17, 0, 0, 30, 30,
+	/* T42 Object */
+	3, 20, 45, 40, 128, 0, 0, 0,
+	/* T46 Object */
+	0, 2, 16, 16, 0, 0, 0, 0, 0,
+	/* T47 Object */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	/* T48 Object */
+	1, 128, 96, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 6, 6, 0, 0, 63, 4, 64,
+	10, 0, 32, 5, 0, 38, 0, 8, 0, 0,
+	0, 0, 0, 0, 16, 65, 3, 1, 1, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0,
+};
+
 static struct mxt_config_info mxt_config_array[] = {
 	{
 		.config		= mxt_config_data,
@@ -715,7 +810,17 @@
 		i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
 					synaptic_i2c_clearpad3k,
 					ARRAY_SIZE(synaptic_i2c_clearpad3k));
-	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
+	} else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
+			machine_is_msm8625_evt()) {
+		/* Use configuration data for EVT */
+		if (machine_is_msm8625_evt()) {
+			mxt_config_array[0].config = mxt_config_data_evt;
+			mxt_config_array[0].config_length =
+					ARRAY_SIZE(mxt_config_data_evt);
+			mxt_platform_data.panel_maxy = 875;
+			mxt_vkey_setup();
+		}
+
 		rc = gpio_tlmm_config(GPIO_CFG(MXT_TS_IRQ_GPIO, 0,
 				GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,
 				GPIO_CFG_8MA), GPIO_CFG_ENABLE);
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 13866e7..e5a31f2a 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -7517,7 +7517,7 @@
 					"msm_ebi2", "mem_clk");
 		return;
 	}
-	clk_enable(mem_clk);
+	clk_prepare_enable(mem_clk);
 	clk_put(mem_clk);
 
 	ebi2_cfg_ptr = ioremap_nocache(0x1a100000, sizeof(uint32_t));
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 9ada0dd..2c533d9 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -582,6 +582,11 @@
 	.id = 0x4005,
 };
 
+struct platform_device apq_cpudai_slimbus_3_rx = {
+	.name = "msm-dai-q6",
+	.id = 0x4006,
+};
+
 static struct resource resources_ssbi_pmic1[] = {
 	{
 		.start  = MSM_PMIC1_SSBI_CMD_PHYS,
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 6a03a77..f8cb345 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -690,7 +690,7 @@
 	.memtype = MEMTYPE_EBI1,
 	.enable_ion = 0,
 #endif
-	.disable_dmx = 0,
+	.disable_dmx = 1,
 	.disable_fullhd = 0,
 };
 
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 6a56c04..31142c1 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -264,6 +264,7 @@
 extern struct platform_device apq_cpudai_slimbus_1_rx;
 extern struct platform_device apq_cpudai_slimbus_1_tx;
 extern struct platform_device apq_cpudai_slimbus_2_tx;
+extern struct platform_device apq_cpudai_slimbus_3_rx;
 extern struct platform_device apq_cpudai_slim_4_rx;
 extern struct platform_device apq_cpudai_slim_4_tx;
 
diff --git a/arch/arm/mach-msm/include/mach/hardware.h b/arch/arm/mach-msm/include/mach/hardware.h
index 2d12609..f1095af 100644
--- a/arch/arm/mach-msm/include/mach/hardware.h
+++ b/arch/arm/mach-msm/include/mach/hardware.h
@@ -1,6 +1,7 @@
 /* arch/arm/mach-msm/include/mach/hardware.h
  *
  * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -14,5 +15,10 @@
  */
 
 #ifndef __ASM_ARCH_MSM_HARDWARE_H
+#define __ASM_ARCH_MSM_HARDWARE_H
+
+#define PCIBIOS_MIN_IO                  0x10000000
+#define PCIBIOS_MIN_MEM                 0x10000000
+#define pcibios_assign_all_busses()     1
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index ff011a8..e3904b4 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -45,8 +45,14 @@
 #define NR_WCD9XXX_IRQS 49
 #define NR_TABLA_IRQS NR_WCD9XXX_IRQS
 #define NR_GPIO_EXPANDER_IRQS 64
+#ifdef CONFIG_PCI_MSI
+#define NR_PCIE_MSI_IRQS 256
+#define NR_BOARD_IRQS (NR_PM8921_IRQS + NR_PM8821_IRQS + \
+		NR_WCD9XXX_IRQS + NR_GPIO_EXPANDER_IRQS + NR_PCIE_MSI_IRQS)
+#else
 #define NR_BOARD_IRQS (NR_PM8921_IRQS + NR_PM8821_IRQS + \
 		NR_WCD9XXX_IRQS + NR_GPIO_EXPANDER_IRQS)
+#endif
 #define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
 #define NR_MSM_GPIOS NR_GPIO_IRQS
 
@@ -85,4 +91,9 @@
 #define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
 #define MSM_INT_TO_REG(base, irq) (base + irq / 32)
 
+#if defined(CONFIG_PCI_MSI) && defined(CONFIG_MSM_PCIE)
+#define MSM_PCIE_MSI_INT(n) (NR_MSM_IRQS + NR_GPIO_IRQS + NR_PM8921_IRQS +  \
+		NR_PM8821_IRQS + NR_TABLA_IRQS + NR_GPIO_EXPANDER_IRQS + (n))
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_pcie.h b/arch/arm/mach-msm/include/mach/msm_pcie.h
new file mode 100644
index 0000000..008c984
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_pcie.h
@@ -0,0 +1,37 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 __ASM_ARCH_MSM_PCIE_H
+#define __ASM_ARCH_MSM_PCIE_H
+
+#include <linux/types.h>
+
+/* gpios */
+enum msm_pcie_gpio {
+	MSM_PCIE_GPIO_RST_N,
+	MSM_PCIE_GPIO_PWR_EN,
+	MSM_PCIE_MAX_GPIO
+};
+
+/* gpio info structrue */
+struct msm_pcie_gpio_info_t {
+	char      *name;
+	uint32_t   num;
+	uint32_t   on;
+};
+
+/* msm pcie platfrom data */
+struct msm_pcie_platform {
+	struct msm_pcie_gpio_info_t  *gpio;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/pcie.c b/arch/arm/mach-msm/pcie.c
new file mode 100644
index 0000000..4e2b1083
--- /dev/null
+++ b/arch/arm/mach-msm/pcie.c
@@ -0,0 +1,669 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*
+ * MSM PCIe controller driver.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+#include <asm/mach/pci.h>
+#include <mach/gpiomux.h>
+#include <mach/hardware.h>
+#include <mach/msm_iomap.h>
+
+#include "pcie.h"
+
+/* Root Complex Port vendor/device IDs */
+#define PCIE_VENDOR_ID_RCP             0x17cb
+#define PCIE_DEVICE_ID_RCP             0x0101
+
+#define PCIE20_PARF_PCS_DEEMPH         0x34
+#define PCIE20_PARF_PCS_SWING          0x38
+#define PCIE20_PARF_PHY_CTRL           0x40
+#define PCIE20_PARF_PHY_REFCLK         0x4C
+#define PCIE20_PARF_CONFIG_BITS        0x50
+
+#define PCIE20_ELBI_SYS_CTRL           0x04
+
+#define PCIE20_CAP                     0x70
+#define PCIE20_CAP_LINKCTRLSTATUS      (PCIE20_CAP + 0x10)
+
+#define PCIE20_COMMAND_STATUS          0x04
+#define PCIE20_BUSNUMBERS              0x18
+#define PCIE20_MEMORY_BASE_LIMIT       0x20
+
+#define PCIE20_PLR_IATU_VIEWPORT       0x900
+#define PCIE20_PLR_IATU_CTRL1          0x904
+#define PCIE20_PLR_IATU_CTRL2          0x908
+#define PCIE20_PLR_IATU_LBAR           0x90C
+#define PCIE20_PLR_IATU_UBAR           0x910
+#define PCIE20_PLR_IATU_LAR            0x914
+#define PCIE20_PLR_IATU_LTAR           0x918
+#define PCIE20_PLR_IATU_UTAR           0x91c
+
+#define PCIE_RESET                     (MSM_CLK_CTL_BASE + 0x22dc)
+#define PCIE_SFAB_AXI_S5_FCLK_CTL      (MSM_CLK_CTL_BASE + 0x2154)
+
+#define MSM_PCIE_DEV_BAR_ADDR          PCIBIOS_MIN_MEM
+#define MSM_PCIE_DEV_CFG_ADDR          0x01000000
+
+#define RD 0
+#define WR 1
+
+/* debug mask sys interface */
+static int msm_pcie_debug_mask;
+module_param_named(debug_mask, msm_pcie_debug_mask,
+			    int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+/* resources from device file */
+enum msm_pcie_res {
+	MSM_PCIE_RES_PARF,
+	MSM_PCIE_RES_ELBI,
+	MSM_PCIE_RES_PCIE20,
+	MSM_PCIE_RES_AXI_BAR,
+	MSM_PCIE_RES_AXI_CONF,
+	MSM_PCIE_MAX_RES
+};
+
+/* msm pcie device data */
+static struct msm_pcie_dev_t msm_pcie_dev;
+
+/* regulators */
+static struct msm_pcie_vreg_info_t msm_pcie_vreg_info[MSM_PCIE_MAX_VREG] = {
+	{NULL, "vp_pcie",      1050000, 1050000, 40900},
+	{NULL, "vptx_pcie",    1050000, 1050000, 18200},
+	{NULL, "vdd_pcie_vph",       0,       0,     0},
+	{NULL, "pcie_ext_3p3v",      0,       0,     0}
+};
+
+/* clocks */
+static struct msm_pcie_clk_info_t msm_pcie_clk_info[MSM_PCIE_MAX_CLK] = {
+	{NULL, "bus_clk"},
+	{NULL, "iface_clk"},
+	{NULL, "ref_clk"}
+};
+
+/* resources */
+static struct msm_pcie_res_info_t msm_pcie_res_info[MSM_PCIE_MAX_RES] = {
+	{"parf",     0, 0, 0},
+	{"elbi",     0, 0, 0},
+	{"pcie20",   0, 0, 0},
+	{"axi_bar",  0, 0, 0},
+	{"axi_conf", 0, 0, 0},
+};
+
+int msm_pcie_get_debug_mask(void)
+{
+	return msm_pcie_debug_mask;
+}
+
+static void msm_pcie_write_mask(void __iomem *addr,
+				uint32_t clear_mask, uint32_t set_mask)
+{
+	uint32_t val;
+
+	val = (readl_relaxed(addr) & ~clear_mask) | set_mask;
+	writel_relaxed(val, addr);
+	wmb();  /* ensure data is written to hardware register */
+}
+
+static int msm_pcie_is_link_up(void)
+{
+	return readl_relaxed(msm_pcie_dev.pcie20 + PCIE20_CAP_LINKCTRLSTATUS) &
+				BIT(29);
+}
+
+static inline int msm_pcie_oper_conf(struct pci_bus *bus, u32 devfn, int oper,
+				     int where, int size, u32 *val)
+{
+	uint32_t word_offset, byte_offset, mask;
+	uint32_t rd_val, wr_val;
+	struct msm_pcie_dev_t *dev = &msm_pcie_dev;
+	void __iomem *config_base;
+
+	/*
+	 * Only buses 0 and 1 are supported. RC port on bus 0 and EP in bus 1.
+	 * For downstream bus (1), make sure link is up
+	 */
+	if ((bus->number > 1) || (devfn != 0)) {
+		PCIE_DBG("invalid %s - bus %d devfn %d\n",
+			 (oper == RD) ? "rd" : "wr", bus->number, devfn);
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	} else if ((bus->number != 0) && !msm_pcie_is_link_up()) {
+		PCIE_DBG("%s fail, link down - bus %d devfn %d\n",
+			 (oper == RD) ? "rd" : "wr", bus->number, devfn);
+		*val = ~0;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	word_offset = where & ~0x3;
+	byte_offset = where & 0x3;
+	mask = (~0 >> (8 * (4 - size))) << (8 * byte_offset);
+
+	config_base = (bus->number == 0) ? dev->pcie20 : dev->axi_conf;
+	rd_val = readl_relaxed(config_base + word_offset);
+
+	if (oper == RD) {
+		*val = ((rd_val & mask) >> (8 * byte_offset));
+
+		PCIE_DBG("%d:0x%02x + 0x%04x[%d] -> 0x%08x; rd 0x%08x\n",
+			 bus->number, devfn, where, size, *val, rd_val);
+	} else {
+		wr_val = (rd_val & ~mask) |
+				((*val << (8 * byte_offset)) & mask);
+		writel_relaxed(wr_val, config_base + word_offset);
+		wmb(); /* ensure config data is written to hardware register */
+
+		PCIE_DBG("%d:0x%02x + 0x%04x[%d] <- 0x%08x;"
+			 " rd 0x%08x val 0x%08x\n", bus->number,
+			 devfn, where, size, wr_val, rd_val, *val);
+	}
+
+	return 0;
+}
+
+static int msm_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+			    int size, u32 *val)
+{
+	return msm_pcie_oper_conf(bus, devfn, RD, where, size, val);
+}
+
+static int msm_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+			    int where, int size, u32 val)
+{
+	return msm_pcie_oper_conf(bus, devfn, WR, where, size, &val);
+}
+
+static struct pci_ops msm_pcie_ops = {
+	.read = msm_pcie_rd_conf,
+	.write = msm_pcie_wr_conf,
+};
+
+static int __devinit msm_pcie_gpio_init(void)
+{
+	int rc, i;
+	struct msm_pcie_gpio_info_t *info;
+
+	for (i = 0; i < MSM_PCIE_MAX_GPIO; i++) {
+		info = &msm_pcie_dev.gpio[i];
+
+		rc = gpio_request(info->num, info->name);
+		if (rc) {
+			pr_err("can't get gpio %s; %d\n", info->name, rc);
+			break;
+		}
+
+		rc = gpio_direction_output(info->num, 0);
+		if (rc) {
+			pr_err("can't set gpio direction %s; %d\n",
+			       info->name, rc);
+			gpio_free(info->num);
+			break;
+		}
+	}
+
+	if (rc)
+		while (i--)
+			gpio_free(msm_pcie_dev.gpio[i].num);
+
+	return rc;
+}
+
+static void msm_pcie_gpio_deinit(void)
+{
+	int i;
+
+	for (i = 0; i < MSM_PCIE_MAX_GPIO; i++)
+		gpio_free(msm_pcie_dev.gpio[i].num);
+}
+
+static int __devinit msm_pcie_vreg_init(struct device *dev)
+{
+	int i, rc = 0;
+	struct regulator *vreg;
+	struct msm_pcie_vreg_info_t *info;
+
+	for (i = 0; i < MSM_PCIE_MAX_VREG; i++) {
+		info = &msm_pcie_dev.vreg[i];
+
+		vreg = regulator_get(dev, info->name);
+		if (!vreg || IS_ERR(vreg)) {
+			rc = (PTR_ERR(vreg)) ? PTR_ERR(vreg) : -ENODEV;
+			pr_err("can't get %s; %d\n", info->name, rc);
+			break;
+		}
+
+		if (info->max_v) {
+			rc = regulator_set_voltage(vreg,
+						   info->min_v, info->max_v);
+			if (rc) {
+				pr_err("can't set voltage %s; %d\n",
+				       info->name, rc);
+				regulator_put(vreg);
+				break;
+			}
+		}
+
+		if (info->opt_mode) {
+			rc = regulator_set_optimum_mode(vreg, info->opt_mode);
+			if (rc < 0) {
+				pr_err("can't set mode %s; %d\n",
+				       info->name, rc);
+				regulator_put(vreg);
+				break;
+			}
+		}
+
+		rc = regulator_enable(vreg);
+		if (rc) {
+			pr_err("can't enable %s, %d\n", info->name, rc);
+			regulator_put(vreg);
+			break;
+		}
+		info->hdl = vreg;
+	}
+
+	if (rc)
+		while (i--) {
+			regulator_disable(msm_pcie_dev.vreg[i].hdl);
+			regulator_put(msm_pcie_dev.vreg[i].hdl);
+			msm_pcie_dev.vreg[i].hdl = NULL;
+		}
+
+	return rc;
+}
+
+static void msm_pcie_vreg_deinit(void)
+{
+	int i;
+
+	for (i = 0; i < MSM_PCIE_MAX_VREG; i++) {
+		regulator_disable(msm_pcie_dev.vreg[i].hdl);
+		regulator_put(msm_pcie_dev.vreg[i].hdl);
+		msm_pcie_dev.vreg[i].hdl = NULL;
+	}
+}
+
+static int __devinit msm_pcie_clk_init(struct device *dev)
+{
+	int i, rc = 0;
+	struct clk *clk_hdl;
+	struct msm_pcie_clk_info_t *info;
+
+	for (i = 0; i < MSM_PCIE_MAX_CLK; i++) {
+		info = &msm_pcie_dev.clk[i];
+
+		clk_hdl = clk_get(dev, info->name);
+		if (!clk_hdl || IS_ERR(clk_hdl)) {
+			rc = (PTR_ERR(clk_hdl)) ? PTR_ERR(clk_hdl) : -ENODEV;
+			pr_err("can't get clk %s; %d\n", info->name, rc);
+			break;
+		}
+		clk_prepare_enable(clk_hdl);
+		info->hdl = clk_hdl;
+	}
+
+	if (rc)
+		while (i--) {
+			clk_disable_unprepare(msm_pcie_dev.clk[i].hdl);
+			clk_put(msm_pcie_dev.clk[i].hdl);
+			msm_pcie_dev.clk[i].hdl = NULL;
+		}
+
+	return rc;
+}
+
+static void msm_pcie_clk_deinit(void)
+{
+	int i;
+
+	for (i = 0; i < MSM_PCIE_MAX_CLK; i++) {
+		clk_disable_unprepare(msm_pcie_dev.clk[i].hdl);
+		clk_put(msm_pcie_dev.clk[i].hdl);
+		msm_pcie_dev.clk[i].hdl = NULL;
+	}
+}
+
+static void __devinit msm_pcie_config_controller(void)
+{
+	struct msm_pcie_dev_t *dev = &msm_pcie_dev;
+	struct msm_pcie_res_info_t *axi_bar = &dev->res[MSM_PCIE_RES_AXI_BAR];
+	struct msm_pcie_res_info_t *axi_conf = &dev->res[MSM_PCIE_RES_AXI_CONF];
+
+	/*
+	 * program and enable address translation region 0 (device config
+	 * address space); region type config;
+	 * axi config address range to device config address range
+	 */
+	writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_VIEWPORT);
+	/* ensure that hardware locks the region before programming it */
+	wmb();
+
+	writel_relaxed(4, dev->pcie20 + PCIE20_PLR_IATU_CTRL1);
+	writel_relaxed(BIT(31), dev->pcie20 + PCIE20_PLR_IATU_CTRL2);
+	writel_relaxed(axi_conf->start, dev->pcie20 + PCIE20_PLR_IATU_LBAR);
+	writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UBAR);
+	writel_relaxed(axi_conf->end, dev->pcie20 + PCIE20_PLR_IATU_LAR);
+	writel_relaxed(MSM_PCIE_DEV_CFG_ADDR,
+		       dev->pcie20 + PCIE20_PLR_IATU_LTAR);
+	writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UTAR);
+	/* ensure that hardware registers the configuration */
+	wmb();
+
+	/*
+	 * program and enable address translation region 2 (device resource
+	 * address space); region type memory;
+	 * axi device bar address range to device bar address range
+	 */
+	writel_relaxed(2, dev->pcie20 + PCIE20_PLR_IATU_VIEWPORT);
+	/* ensure that hardware locks the region before programming it */
+	wmb();
+
+	writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_CTRL1);
+	writel_relaxed(BIT(31), dev->pcie20 + PCIE20_PLR_IATU_CTRL2);
+	writel_relaxed(axi_bar->start, dev->pcie20 + PCIE20_PLR_IATU_LBAR);
+	writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UBAR);
+	writel_relaxed(axi_bar->end, dev->pcie20 + PCIE20_PLR_IATU_LAR);
+	writel_relaxed(MSM_PCIE_DEV_BAR_ADDR,
+		       dev->pcie20 + PCIE20_PLR_IATU_LTAR);
+	writel_relaxed(0, dev->pcie20 + PCIE20_PLR_IATU_UTAR);
+	/* ensure that hardware registers the configuration */
+	wmb();
+}
+
+static int __devinit msm_pcie_get_resources(struct platform_device *pdev)
+{
+	int i, rc = 0;
+	struct resource *res;
+	struct msm_pcie_res_info_t *info;
+	struct msm_pcie_dev_t *dev = &msm_pcie_dev;
+
+	for (i = 0; i < MSM_PCIE_MAX_RES; i++) {
+		info = &dev->res[i];
+
+		res = platform_get_resource_byname(pdev,
+						   IORESOURCE_MEM, info->name);
+		if (!res) {
+			pr_err("can't get %s resource\n", info->name);
+			rc = -ENOMEM;
+			break;
+		}
+
+		info->base = ioremap(res->start, resource_size(res));
+		if (!info->base) {
+			pr_err("can't remap %s\n", info->name);
+			rc = -ENOMEM;
+			break;
+		}
+
+		info->start = res->start;
+		info->end = res->end;
+	}
+
+	if (rc) {
+		while (i--) {
+			iounmap(dev->res[i].base);
+			dev->res[i].base = NULL;
+		}
+	} else {
+		dev->parf = dev->res[MSM_PCIE_RES_PARF].base;
+		dev->elbi = dev->res[MSM_PCIE_RES_ELBI].base;
+		dev->pcie20 = dev->res[MSM_PCIE_RES_PCIE20].base;
+		dev->axi_conf = dev->res[MSM_PCIE_RES_AXI_CONF].base;
+	}
+
+	return rc;
+}
+
+static void __devexit msm_pcie_release_resources(void)
+{
+	int i;
+
+	for (i = 0; i < MSM_PCIE_MAX_RES; i++) {
+		iounmap(msm_pcie_dev.res[i].base);
+		msm_pcie_dev.res[i].base = NULL;
+	}
+
+	msm_pcie_dev.parf = NULL;
+	msm_pcie_dev.elbi = NULL;
+	msm_pcie_dev.pcie20 = NULL;
+	msm_pcie_dev.axi_conf = NULL;
+}
+
+static int __devinit msm_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	int rc;
+	struct msm_pcie_dev_t *dev = &msm_pcie_dev;
+	uint32_t val;
+
+	PCIE_DBG("bus %d\n", nr);
+	if (nr != 0)
+		return 0;
+
+	/* assert PCIe reset link to keep EP in reset */
+	gpio_set_value_cansleep(dev->gpio[MSM_PCIE_GPIO_RST_N].num,
+				dev->gpio[MSM_PCIE_GPIO_RST_N].on);
+
+	/* enable power */
+	rc = msm_pcie_vreg_init(&dev->pdev->dev);
+	if (rc)
+		goto out;
+
+	/* assert PCIe PARF reset while powering the core */
+	msm_pcie_write_mask(PCIE_RESET, 0, BIT(2));
+
+	/* enable clocks */
+	rc = msm_pcie_clk_init(&dev->pdev->dev);
+	if (rc)
+		goto clk_fail;
+
+	/* enable pcie power; wait 3ms for clock to stabilize */
+	gpio_set_value_cansleep(dev->gpio[MSM_PCIE_GPIO_PWR_EN].num,
+				dev->gpio[MSM_PCIE_GPIO_PWR_EN].on);
+	usleep(3000);
+
+	/*
+	 * de-assert PCIe PARF reset;
+	 * wait 1us before accessing PARF registers
+	 */
+	msm_pcie_write_mask(PCIE_RESET, BIT(2), 0);
+	udelay(1);
+
+	/* enable PCIe clocks and resets */
+	msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_CTRL, BIT(0), 0);
+
+	/* PARF programming */
+	writel_relaxed(0x282828, dev->parf + PCIE20_PARF_PCS_DEEMPH);
+	writel_relaxed(0x7F7F, dev->parf + PCIE20_PARF_PCS_SWING);
+	writel_relaxed((4<<24), dev->parf + PCIE20_PARF_CONFIG_BITS);
+	/* ensure that hardware registers the PARF configuration */
+	wmb();
+
+	/* enable reference clock */
+	msm_pcie_write_mask(dev->parf + PCIE20_PARF_PHY_REFCLK, 0, BIT(16));
+
+	/* enable access to PCIe slave port on system fabric */
+	writel_relaxed(BIT(4), PCIE_SFAB_AXI_S5_FCLK_CTL);
+	/* ensure that access is enabled before proceeding */
+	wmb();
+
+	/* de-assert PICe PHY, Core, POR and AXI clk domain resets */
+	msm_pcie_write_mask(PCIE_RESET, BIT(5), 0);
+	msm_pcie_write_mask(PCIE_RESET, BIT(4), 0);
+	msm_pcie_write_mask(PCIE_RESET, BIT(3), 0);
+	msm_pcie_write_mask(PCIE_RESET, BIT(0), 0);
+
+	/* wait 150ms for clock acquisition */
+	udelay(150);
+
+	/* de-assert PCIe reset link to bring EP out of reset */
+	gpio_set_value_cansleep(dev->gpio[MSM_PCIE_GPIO_RST_N].num,
+				!dev->gpio[MSM_PCIE_GPIO_RST_N].on);
+
+	/* enable link training */
+	msm_pcie_write_mask(dev->elbi + PCIE20_ELBI_SYS_CTRL, 0, BIT(0));
+
+	/* poll for link to come up for upto 100ms */
+	rc = readl_poll_timeout(
+			(msm_pcie_dev.pcie20 + PCIE20_CAP_LINKCTRLSTATUS),
+			val, (val & BIT(29)), 10000, 100000);
+	if (rc) {
+		pr_err("link initialization failed\n");
+		goto link_fail;
+	} else
+		pr_info("link initialized\n");
+
+	msm_pcie_config_controller();
+	rc = msm_pcie_irq_init(dev);
+	if (!rc)
+		goto out;
+
+link_fail:
+	msm_pcie_clk_deinit();
+clk_fail:
+	msm_pcie_vreg_deinit();
+out:
+	return (rc) ? 0 : 1;
+}
+
+static struct pci_bus __devinit *msm_pcie_scan_bus(int nr,
+						   struct pci_sys_data *sys)
+{
+	struct pci_bus *bus = NULL;
+
+	PCIE_DBG("bus %d\n", nr);
+	if (nr == 0)
+		bus = pci_scan_bus(sys->busnr, &msm_pcie_ops, sys);
+
+	return bus;
+}
+
+static int __devinit msm_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	PCIE_DBG("slot %d pin %d\n", slot, pin);
+	return (pin <= 4) ? (PCIE20_INTA + pin - 1) : 0;
+}
+
+static struct hw_pci msm_pci __devinitdata = {
+	.nr_controllers = 1,
+	.swizzle = pci_std_swizzle,
+	.setup = msm_pcie_setup,
+	.scan = msm_pcie_scan_bus,
+	.map_irq = msm_pcie_map_irq,
+};
+
+static int __devinit msm_pcie_probe(struct platform_device *pdev)
+{
+	const struct msm_pcie_platform *pdata;
+	int rc;
+
+	PCIE_DBG("\n");
+
+	msm_pcie_dev.pdev = pdev;
+	pdata = pdev->dev.platform_data;
+	msm_pcie_dev.gpio = pdata->gpio;
+	msm_pcie_dev.vreg = msm_pcie_vreg_info;
+	msm_pcie_dev.clk = msm_pcie_clk_info;
+	msm_pcie_dev.res = msm_pcie_res_info;
+
+	rc = msm_pcie_get_resources(msm_pcie_dev.pdev);
+	if (rc)
+		return rc;
+
+	rc = msm_pcie_gpio_init();
+	if (rc) {
+		msm_pcie_release_resources();
+		return rc;
+	}
+
+	/* kick start ARM PCI configuration framework */
+	pci_common_init(&msm_pci);
+	return 0;
+}
+
+static int __devexit msm_pcie_remove(struct platform_device *pdev)
+{
+	PCIE_DBG("\n");
+
+	msm_pcie_irq_deinit(&msm_pcie_dev);
+	msm_pcie_vreg_deinit();
+	msm_pcie_clk_deinit();
+	msm_pcie_gpio_deinit();
+	msm_pcie_release_resources();
+
+	msm_pcie_dev.pdev = NULL;
+	msm_pcie_dev.vreg = NULL;
+	msm_pcie_dev.clk = NULL;
+	msm_pcie_dev.gpio = NULL;
+	return 0;
+}
+
+static struct platform_driver msm_pcie_driver = {
+	.probe = msm_pcie_probe,
+	.remove = __devexit_p(msm_pcie_remove),
+	.driver = {
+		.name = "msm_pcie",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_pcie_init(void)
+{
+	PCIE_DBG("\n");
+	return platform_driver_register(&msm_pcie_driver);
+}
+subsys_initcall(msm_pcie_init);
+
+/* RC do not represent the right class; set it to PCI_CLASS_BRIDGE_PCI */
+static void __devinit msm_pcie_fixup_header(struct pci_dev *dev)
+{
+	PCIE_DBG("hdr_type %d\n", dev->hdr_type);
+	if (dev->hdr_type == 1)
+		dev->class = (dev->class & 0xff) | (PCI_CLASS_BRIDGE_PCI << 8);
+}
+DECLARE_PCI_FIXUP_HEADER(PCIE_VENDOR_ID_RCP, PCIE_DEVICE_ID_RCP,
+			 msm_pcie_fixup_header);
+
+/*
+ * actual physical (BAR) address of the device resources starts from 0x10xxxxxx;
+ * the system axi address for the device resources starts from 0x08xxxxxx;
+ * correct the device resource structure here; address translation unit handles
+ * the required translations
+ */
+static void __devinit msm_pcie_fixup_final(struct pci_dev *dev)
+{
+	int i;
+
+	PCIE_DBG("vendor 0x%x 0x%x\n", dev->vendor, dev->device);
+	for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+		if (dev->resource[i].start & 0xFF000000) {
+			dev->resource[i].start &= 0x00FFFFFF;
+			dev->resource[i].start |= 0x08000000;
+			dev->resource[i].end &= 0x00FFFFFF;
+			dev->resource[i].end |= 0x08000000;
+		}
+	}
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, msm_pcie_fixup_final);
diff --git a/arch/arm/mach-msm/pcie.h b/arch/arm/mach-msm/pcie.h
new file mode 100644
index 0000000..4866ec5
--- /dev/null
+++ b/arch/arm/mach-msm/pcie.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 __ARCH_ARM_MACH_MSM_PCIE_H
+#define __ARCH_ARM_MACH_MSM_PCIE_H
+
+#include <linux/clk.h>
+#include <linux/compiler.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+#include <mach/msm_pcie.h>
+
+#define MSM_PCIE_MAX_VREG 4
+#define MSM_PCIE_MAX_CLK  3
+
+#define PCIE_DBG(x...) do {              \
+	if (msm_pcie_get_debug_mask())   \
+		pr_info(x);              \
+	} while (0)
+
+/* voltage regulator info structrue */
+struct msm_pcie_vreg_info_t {
+	struct regulator  *hdl;
+	char              *name;
+	uint32_t           max_v;
+	uint32_t           min_v;
+	uint32_t           opt_mode;
+};
+
+/* clock info structure */
+struct msm_pcie_clk_info_t {
+	struct clk  *hdl;
+	char        *name;
+};
+
+/* resource info structure */
+struct msm_pcie_res_info_t {
+	char          *name;
+	uint32_t       start;
+	uint32_t       end;
+	void __iomem  *base;
+};
+
+/* msm pcie device structure */
+struct msm_pcie_dev_t {
+	struct platform_device       *pdev;
+
+	struct msm_pcie_vreg_info_t  *vreg;
+	struct msm_pcie_gpio_info_t  *gpio;
+	struct msm_pcie_clk_info_t   *clk;
+	struct msm_pcie_res_info_t   *res;
+
+	void __iomem                 *parf;
+	void __iomem                 *elbi;
+	void __iomem                 *pcie20;
+	void __iomem                 *axi_conf;
+};
+
+extern uint32_t msm_pcie_irq_init(struct msm_pcie_dev_t *dev);
+extern void msm_pcie_irq_deinit(struct msm_pcie_dev_t *dev);
+extern int msm_pcie_get_debug_mask(void);
+
+#endif
diff --git a/arch/arm/mach-msm/pcie_irq.c b/arch/arm/mach-msm/pcie_irq.c
new file mode 100644
index 0000000..df100db
--- /dev/null
+++ b/arch/arm/mach-msm/pcie_irq.c
@@ -0,0 +1,170 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+/*
+ * MSM PCIe controller IRQ driver.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/bitops.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/msi.h>
+#include <linux/pci.h>
+#include <mach/irqs.h>
+
+#include "pcie.h"
+
+/* Any address will do here, as it won't be dereferenced */
+#define MSM_PCIE_MSI_PHY 0xa0000000
+
+#define PCIE20_MSI_CTRL_ADDR            (0x820)
+#define PCIE20_MSI_CTRL_UPPER_ADDR      (0x824)
+#define PCIE20_MSI_CTRL_INTR_EN         (0x828)
+#define PCIE20_MSI_CTRL_INTR_MASK       (0x82C)
+#define PCIE20_MSI_CTRL_INTR_STATUS     (0x830)
+
+#define PCIE20_MSI_CTRL_MAX 8
+
+static DECLARE_BITMAP(msi_irq_in_use, NR_PCIE_MSI_IRQS);
+
+irqreturn_t handle_msi_irq(int irq, void *data)
+{
+	int i, j;
+	unsigned long val;
+	struct msm_pcie_dev_t *dev = data;
+	void __iomem *ctrl_status;
+
+	/* check for set bits, clear it by setting that bit
+	   and trigger corresponding irq */
+	for (i = 0; i < PCIE20_MSI_CTRL_MAX; i++) {
+		ctrl_status = dev->pcie20 +
+				PCIE20_MSI_CTRL_INTR_STATUS + (i * 12);
+
+		val = readl_relaxed(ctrl_status);
+		while (val) {
+			j = find_first_bit(&val, 32);
+			writel_relaxed(BIT(j), ctrl_status);
+			/* ensure that interrupt is cleared (acked) */
+			wmb();
+
+			generic_handle_irq(MSM_PCIE_MSI_INT(j + (32 * i)));
+			val = readl_relaxed(ctrl_status);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+uint32_t __devinit msm_pcie_irq_init(struct msm_pcie_dev_t *dev)
+{
+	int i, rc;
+
+	PCIE_DBG("\n");
+
+	/* program MSI controller and enable all interrupts */
+	writel_relaxed(MSM_PCIE_MSI_PHY, dev->pcie20 + PCIE20_MSI_CTRL_ADDR);
+	writel_relaxed(0, dev->pcie20 + PCIE20_MSI_CTRL_UPPER_ADDR);
+
+	for (i = 0; i < PCIE20_MSI_CTRL_MAX; i++)
+		writel_relaxed(~0, dev->pcie20 +
+			       PCIE20_MSI_CTRL_INTR_EN + (i * 12));
+
+	/* ensure that hardware is configured before proceeding */
+	wmb();
+
+	/* register handler for physical MSI interrupt line */
+	rc = request_irq(PCIE20_INT_MSI, handle_msi_irq, IRQF_TRIGGER_RISING,
+			 "msm_pcie_msi", dev);
+	if (rc)
+		pr_err("Unable to allocate msi interrupt\n");
+
+	return rc;
+}
+
+void msm_pcie_irq_deinit(struct msm_pcie_dev_t *dev)
+{
+	free_irq(PCIE20_INT_MSI, dev);
+}
+
+void msm_pcie_destroy_irq(unsigned int irq)
+{
+	int pos = irq - MSM_PCIE_MSI_INT(0);
+
+	dynamic_irq_cleanup(irq);
+	clear_bit(pos, msi_irq_in_use);
+}
+
+/* hookup to linux pci msi framework */
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	PCIE_DBG("irq %d deallocated\n", irq);
+	msm_pcie_destroy_irq(irq);
+}
+
+static void msm_pcie_msi_nop(struct irq_data *d)
+{
+	return;
+}
+
+static struct irq_chip pcie_msi_chip = {
+	.name = "msm-pcie-msi",
+	.irq_ack = msm_pcie_msi_nop,
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
+};
+
+static int msm_pcie_create_irq(void)
+{
+	int irq, pos;
+
+again:
+	pos = find_first_zero_bit(msi_irq_in_use, NR_PCIE_MSI_IRQS);
+	irq = MSM_PCIE_MSI_INT(pos);
+	if (irq >= (MSM_PCIE_MSI_INT(0) + NR_PCIE_MSI_IRQS))
+		return -ENOSPC;
+
+	if (test_and_set_bit(pos, msi_irq_in_use))
+		goto again;
+
+	dynamic_irq_init(irq);
+	return irq;
+}
+
+/* hookup to linux pci msi framework */
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	int irq;
+	struct msi_msg msg;
+
+	irq = msm_pcie_create_irq();
+	if (irq < 0)
+		return irq;
+
+	PCIE_DBG("irq %d allocated\n", irq);
+
+	irq_set_msi_desc(irq, desc);
+
+	/* write msi vector and data */
+	msg.address_hi = 0;
+	msg.address_lo = MSM_PCIE_MSI_PHY;
+	msg.data = irq - MSM_PCIE_MSI_INT(0);
+	write_msi_msg(irq, &msg);
+
+	irq_set_chip_and_handler(irq, &pcie_msi_chip, handle_simple_irq);
+	set_irq_flags(irq, IRQF_VALID);
+	return 0;
+}
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index fa9159e..0ecea85 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -350,13 +350,14 @@
 	}
 
 	mutex_lock(&pil->lock);
-	if (!pil->count++) {
+	if (!pil->count) {
 		ret = load_image(pil);
 		if (ret) {
 			retval = ERR_PTR(ret);
 			goto err_load;
 		}
 	}
+	pil->count++;
 	pil_set_state(pil, PIL_ONLINE);
 	mutex_unlock(&pil->lock);
 out:
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index c888815..0eabd1b 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -214,9 +214,9 @@
 		global*global_timer_offset;
 
 	if (!(clock->flags & MSM_CLOCK_FLAGS_UNSTABLE_COUNT))
-		return __raw_readl(addr);
+		return __raw_readl_no_log(addr);
 
-	t1 = __raw_readl(addr);
+	t1 = __raw_readl_no_log(addr);
 	t2 = __raw_readl_no_log(addr);
 	if ((t2-t1) <= 1)
 		return t2;
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index d889c4d..7f57fe6 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -620,7 +620,7 @@
 }
 
 static int iommu_map_all(unsigned long domain_num, struct ion_cp_heap *cp_heap,
-			int partition, unsigned long prot, unsigned long align)
+			int partition, unsigned long prot)
 {
 	unsigned long left_to_map = cp_heap->total_size;
 	unsigned long order = get_order(SZ_64K);
@@ -718,8 +718,7 @@
 		data->iova_addr = cp_heap->iommu_iova[domain_num] + offset;
 		return 0;
 	} else if (cp_heap->iommu_map_all) {
-		ret = iommu_map_all(domain_num, cp_heap, partition_num,
-				    align, prot);
+		ret = iommu_map_all(domain_num, cp_heap, partition_num, prot);
 		if (!ret) {
 			unsigned long offset =
 					buffer->priv_phys - cp_heap->base;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 9f80a73..da3e4b2 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -44,7 +44,7 @@
 #define KGSL_PAGETABLE_ENTRY_SIZE  4
 
 /* Pagetable Virtual Address base */
-#define KGSL_PAGETABLE_BASE	0x66000000
+#define KGSL_PAGETABLE_BASE	0x10000000
 
 /* Extra accounting entries needed in the pagetable */
 #define KGSL_PT_EXTRA_ENTRIES      16
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index b4dcf7c..880fde1 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -518,14 +518,6 @@
 			"for GPUMMU: %x\n", CONFIG_MSM_KGSL_PAGE_TABLE_SIZE);
 			return -EINVAL;
 		}
-
-		/* allocate memory used for completing r/w operations that
-		 * cannot be mapped by the MMU
-		 */
-		status = kgsl_allocate_contiguous(&mmu->setstate_memory, 64);
-		if (!status)
-			kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
-					   mmu->setstate_memory.size);
 	}
 
 	dev_info(mmu->device->dev, "|%s| MMU type set for device is GPUMMU\n",
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 99acccb..4f27e6c 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -297,6 +297,61 @@
 	return ret;
 }
 
+/*
+ * kgsl_set_register_map - Map the IOMMU regsiters in the memory descriptors
+ * of the respective iommu units
+ * @mmu - Pointer to mmu structure
+ *
+ * Return - 0 on success else error code
+ */
+static int kgsl_set_register_map(struct kgsl_mmu *mmu)
+{
+	struct platform_device *pdev =
+		container_of(mmu->device->parentdev, struct platform_device,
+				dev);
+	struct kgsl_device_platform_data *pdata_dev = pdev->dev.platform_data;
+	struct kgsl_iommu *iommu = mmu->device->mmu.priv;
+	struct kgsl_iommu_unit *iommu_unit;
+	int i = 0, ret = 0;
+
+	for (; i < pdata_dev->iommu_count; i++) {
+		struct kgsl_device_iommu_data data = pdata_dev->iommu_data[i];
+		iommu_unit = &iommu->iommu_units[i];
+		/* set up the IOMMU register map for the given IOMMU unit */
+		if (!data.physstart || !data.physend) {
+			KGSL_CORE_ERR("The register range for IOMMU unit not"
+					" specified\n");
+			ret = -EINVAL;
+			goto err;
+		}
+		iommu_unit->reg_map.hostptr = ioremap(data.physstart,
+					data.physend - data.physstart + 1);
+		if (!iommu_unit->reg_map.hostptr) {
+			KGSL_CORE_ERR("Failed to map SMMU register address "
+				"space from %x to %x\n", data.physstart,
+				data.physend - data.physstart + 1);
+			ret = -ENOMEM;
+			i--;
+			goto err;
+		}
+		iommu_unit->reg_map.size = data.physend - data.physstart + 1;
+		iommu_unit->reg_map.physaddr = data.physstart;
+		memdesc_sg_phys(&iommu_unit->reg_map, data.physstart,
+				iommu_unit->reg_map.size);
+	}
+	iommu->unit_count = pdata_dev->iommu_count;
+	return ret;
+err:
+	/* Unmap any mapped IOMMU regions */
+	for (; i >= 0; i--) {
+		iommu_unit = &iommu->iommu_units[i];
+		iounmap(iommu_unit->reg_map.hostptr);
+		iommu_unit->reg_map.size = 0;
+		iommu_unit->reg_map.physaddr = 0;
+	}
+	return ret;
+}
+
 static void kgsl_iommu_setstate(struct kgsl_mmu *mmu,
 				struct kgsl_pagetable *pagetable)
 {
@@ -335,6 +390,9 @@
 	status = kgsl_get_iommu_ctxt(mmu);
 	if (status)
 		goto done;
+	status = kgsl_set_register_map(mmu);
+	if (status)
+		goto done;
 
 	dev_info(mmu->device->dev, "|%s| MMU type set for device is IOMMU\n",
 			__func__);
@@ -346,6 +404,53 @@
 	return status;
 }
 
+/*
+ * kgsl_iommu_setup_defaultpagetable - Setup the initial defualtpagetable
+ * for iommu. This function is only called once during first start, successive
+ * start do not call this funciton.
+ * @mmu - Pointer to mmu structure
+ *
+ * Create the  initial defaultpagetable and setup the iommu mappings to it
+ * Return - 0 on success else error code
+ */
+static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu)
+{
+	int status = 0;
+	int i = 0;
+	struct kgsl_iommu *iommu = mmu->priv;
+
+	mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
+	/* Return error if the default pagetable doesn't exist */
+	if (mmu->defaultpagetable == NULL) {
+		status = -ENOMEM;
+		goto err;
+	}
+	/* Map the IOMMU regsiters to only defaultpagetable */
+	for (i = 0; i < iommu->unit_count; i++) {
+		iommu->iommu_units[i].reg_map.priv |= KGSL_MEMFLAGS_GLOBAL;
+		status = kgsl_mmu_map(mmu->defaultpagetable,
+			&(iommu->iommu_units[i].reg_map),
+			GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+		if (status) {
+			iommu->iommu_units[i].reg_map.priv &=
+							~KGSL_MEMFLAGS_GLOBAL;
+			goto err;
+		}
+	}
+	return status;
+err:
+	for (i--; i >= 0; i--) {
+		kgsl_mmu_unmap(mmu->defaultpagetable,
+				&(iommu->iommu_units[i].reg_map));
+		iommu->iommu_units[i].reg_map.priv &= ~KGSL_MEMFLAGS_GLOBAL;
+	}
+	if (mmu->defaultpagetable) {
+		kgsl_mmu_putpagetable(mmu->defaultpagetable);
+		mmu->defaultpagetable = NULL;
+	}
+	return status;
+}
+
 static int kgsl_iommu_start(struct kgsl_mmu *mmu)
 {
 	int status;
@@ -353,13 +458,13 @@
 	if (mmu->flags & KGSL_FLAGS_STARTED)
 		return 0;
 
+	if (mmu->defaultpagetable == NULL) {
+		status = kgsl_iommu_setup_defaultpagetable(mmu);
+		if (status)
+			return -ENOMEM;
+	}
 	kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
-	if (mmu->defaultpagetable == NULL)
-		mmu->defaultpagetable =
-			kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT);
-	/* Return error if the default pagetable doesn't exist */
-	if (mmu->defaultpagetable == NULL)
-		return -ENOMEM;
+
 	mmu->hwpagetable = mmu->defaultpagetable;
 
 	status = kgsl_attach_pagetable_iommu_domain(mmu);
@@ -455,6 +560,17 @@
 
 static int kgsl_iommu_close(struct kgsl_mmu *mmu)
 {
+	struct kgsl_iommu *iommu = mmu->priv;
+	int i;
+	for (i = 0; i < iommu->unit_count; i++) {
+		if (iommu->iommu_units[i].reg_map.gpuaddr)
+			kgsl_mmu_unmap(mmu->defaultpagetable,
+			&(iommu->iommu_units[i].reg_map));
+		if (iommu->iommu_units[i].reg_map.hostptr)
+			iounmap(iommu->iommu_units[i].reg_map.hostptr);
+		kgsl_sg_free(iommu->iommu_units[i].reg_map.sg,
+				iommu->iommu_units[i].reg_map.sglen);
+	}
 	if (mmu->defaultpagetable)
 		kgsl_mmu_putpagetable(mmu->defaultpagetable);
 
@@ -464,11 +580,16 @@
 static unsigned int
 kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu)
 {
-	/* Current base is always the hwpagetables domain as we
-	 * do not use per process pagetables right not for iommu.
-	 * This will change when we switch to per process pagetables.
-	 */
-	return (unsigned int)mmu->hwpagetable->priv;
+	unsigned int pt_base;
+	struct kgsl_iommu *iommu = mmu->priv;
+	/* Return the current pt base by reading IOMMU pt_base register */
+	kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER);
+	pt_base = readl_relaxed(iommu->iommu_units[0].reg_map.hostptr +
+			(KGSL_IOMMU_CONTEXT_USER << KGSL_IOMMU_CTX_SHIFT) +
+			KGSL_IOMMU_TTBR0);
+	kgsl_iommu_disable_clk(mmu);
+	return pt_base & (KGSL_IOMMU_TTBR0_PA_MASK <<
+				KGSL_IOMMU_TTBR0_PA_SHIFT);
 }
 
 struct kgsl_mmu_ops iommu_ops = {
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index e2033c5..5a92f513 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -15,6 +15,17 @@
 
 #include <mach/iommu.h>
 
+/* IOMMU registers and masks */
+#define KGSL_IOMMU_TTBR0			0x10
+#define KGSL_IOMMU_TTBR1			0x14
+#define KGSL_IOMMU_TTBR0_PA_MASK		0x0003FFFF
+#define KGSL_IOMMU_TTBR0_PA_SHIFT		14
+#define KGSL_IOMMU_CTX_TLBIALL			0x800
+#define KGSL_IOMMU_CONTEXTIDR			0x8
+#define KGSL_IOMMU_CONTEXTIDR_ASID_MASK		0xFF
+#define KGSL_IOMMU_CONTEXTIDR_ASID_SHIFT	0
+#define KGSL_IOMMU_CTX_TLBIASID			0x804
+#define KGSL_IOMMU_CTX_SHIFT			12
 /*
  * Max number of iommu units that the gpu core can have
  * On APQ8064, KGSL can control a maximum of 2 IOMMU units.
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 4ba9e7f..5fdc182 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -343,26 +343,30 @@
 
 int kgsl_mmu_init(struct kgsl_device *device)
 {
+	int status = 0;
 	struct kgsl_mmu *mmu = &device->mmu;
 
 	mmu->device = device;
+	status = kgsl_allocate_contiguous(&mmu->setstate_memory, PAGE_SIZE);
+	if (status)
+		return status;
+	kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
+				mmu->setstate_memory.size);
 
 	if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) {
-		int status = 0;
-		status = kgsl_allocate_contiguous(&mmu->setstate_memory, 64);
-		if (!status) {
-			kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0,
-					mmu->setstate_memory.size);
-			dev_info(device->dev, "|%s| MMU type set for device is "
+		dev_info(device->dev, "|%s| MMU type set for device is "
 				"NOMMU\n", __func__);
-		}
-		return status;
+		goto done;
 	} else if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
 		mmu->mmu_ops = &gpummu_ops;
 	else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
 		mmu->mmu_ops = &iommu_ops;
 
-	return mmu->mmu_ops->mmu_init(mmu);
+	status =  mmu->mmu_ops->mmu_init(mmu);
+done:
+	if (status)
+		kgsl_sharedmem_free(&mmu->setstate_memory);
+	return status;
 }
 EXPORT_SYMBOL(kgsl_mmu_init);
 
@@ -734,12 +738,11 @@
 {
 	struct kgsl_mmu *mmu = &device->mmu;
 
-	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
-		kgsl_sharedmem_free(&mmu->setstate_memory);
+	kgsl_sharedmem_free(&mmu->setstate_memory);
+	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
 		return 0;
-	} else {
+	else
 		return mmu->mmu_ops->mmu_close(mmu);
-	}
 }
 EXPORT_SYMBOL(kgsl_mmu_close);
 
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index e643def..c04ece2 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -211,10 +211,11 @@
 
 	init_completion(&csid_dev->reset_complete);
 
-	enable_irq(csid_dev->irq->start);
+	rc = request_irq(csid_dev->irq->start, msm_csid_irq,
+		IRQF_TRIGGER_RISING, "csid", csid_dev);
 
 	msm_csid_reset(csid_dev);
-	return 0;
+	return rc;
 
 clk_enable_failed:
 	msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
@@ -230,10 +231,15 @@
 
 static int msm_csid_release(struct v4l2_subdev *sd)
 {
+	uint32_t irq;
 	struct csid_device *csid_dev;
 	csid_dev = v4l2_get_subdevdata(sd);
 
-	disable_irq(csid_dev->irq->start);
+	irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
+	msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
+	msm_camera_io_w(0, csid_dev->base + CSID_IRQ_MASK_ADDR);
+
+	free_irq(csid_dev->irq->start, csid_dev);
 
 	msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
 		csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
@@ -328,17 +334,6 @@
 		goto csid_no_resource;
 	}
 
-	rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
-		IRQF_TRIGGER_RISING, "csid", new_csid_dev);
-	if (rc < 0) {
-		release_mem_region(new_csid_dev->mem->start,
-			resource_size(new_csid_dev->mem));
-		pr_err("%s: irq request fail\n", __func__);
-		rc = -EBUSY;
-		goto csid_no_resource;
-	}
-	disable_irq(new_csid_dev->irq->start);
-
 	new_csid_dev->pdev = pdev;
 	msm_cam_register_subdev_node(&new_csid_dev->subdev, CSID_DEV, pdev->id);
 	return 0;
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 254cf3a..8720d70 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1568,6 +1568,7 @@
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
 	struct msm_cam_v4l2_dev_inst *pcam_inst;
 	struct msm_cam_media_controller *pmctl = NULL;
+	struct msm_cam_server_queue *queue = NULL;
 
 	D("%s\n", __func__);
 
@@ -1609,12 +1610,11 @@
 			pcam->vnode_id, pcam->use_count);
 	pcam->use_count++;
 	if (pcam->use_count == 1) {
-		struct msm_cam_server_queue *queue;
 		pcam->server_queue_idx = server_q_idx;
 		queue = &g_server_dev.server_queue[server_q_idx];
 		queue->ctrl = NULL;
 		queue->ctrl_data = kzalloc(sizeof(uint8_t) *
-				max_control_command_size, GFP_KERNEL);
+			max_control_command_size, GFP_KERNEL);
 		msm_queue_init(&queue->ctrl_q, "control");
 		msm_queue_init(&queue->eventData_q, "eventdata");
 		queue->queue_active = 1;
@@ -1623,7 +1623,7 @@
 		if (rc < 0) {
 			pr_err("%s: cam_server_open_session failed %d\n",
 			__func__, rc);
-			goto err;
+			goto msm_cam_server_open_session_failed;
 		}
 
 		pmctl = msm_camera_get_mctl(pcam->mctl_handle);
@@ -1636,26 +1636,26 @@
 
 		/* Should be set to sensor ops if any but right now its OK!! */
 		if (!pmctl->mctl_open) {
-			D("%s: media contoller is not inited\n",
-				 __func__);
+			D("%s: media contoller is not inited\n", __func__);
 			rc = -ENODEV;
-			goto err;
+			goto mctl_open_failed;
 		}
 
 		/* Now we really have to activate the camera */
 		D("%s: call mctl_open\n", __func__);
 		rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
-
 		if (rc < 0) {
 			pr_err("%s: HW open failed rc = 0x%x\n",  __func__, rc);
-			goto err;
+			goto mctl_open_failed;
 		}
 		pmctl->pcam_ptr = pcam;
 
 		rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
-							pcam->pvdev);
+			pcam->pvdev);
 		if (rc < 0) {
-			goto err;
+			pr_err("%s: msm_setup_v4l2_event_queue failed %d",
+				__func__, rc);
+			goto mctl_event_q_setup_failed;
 		}
 	}
 	pcam_inst->vbqueue_initialized = 0;
@@ -1666,21 +1666,26 @@
 	D("f->private_data = 0x%x, pcam = 0x%x\n",
 		(u32)f->private_data, (u32)pcam_inst);
 
-
 	if (pcam->use_count == 1) {
 		rc = msm_send_open_server(pcam);
 		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
-			pr_err("%s failed\n", __func__);
-			return rc;
+			pr_err("%s: msm_send_open_server failed %d\n",
+				__func__, rc);
+			goto msm_send_open_server_failed;
 		}
 	}
 	mutex_unlock(&pcam->vid_lock);
 	D("%s: end", __func__);
-	/* rc = msm_cam_server_open_session(g_server_dev, pcam);*/
 	return rc;
 
-err:
+msm_send_open_server_failed:
+	v4l2_fh_del(&pcam_inst->eventHandle);
+	v4l2_fh_exit(&pcam_inst->eventHandle);
+mctl_event_q_setup_failed:
+	if (pmctl->mctl_release)
+		if (pmctl->mctl_release(pmctl) < 0)
+			pr_err("%s: mctl_release failed\n", __func__);
+mctl_open_failed:
 	if (pcam->use_count == 1) {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		if (ion_client_created) {
@@ -1688,6 +1693,20 @@
 			kref_put(&pmctl->refcount, msm_release_ion_client);
 		}
 #endif
+		if (msm_cam_server_close_session(&g_server_dev, pcam) < 0)
+			pr_err("%s: msm_cam_server_close_session failed\n",
+				__func__);
+	}
+msm_cam_server_open_session_failed:
+	if (pcam->use_count == 1) {
+		queue->queue_active = 0;
+		msm_drain_eventq(&queue->eventData_q);
+		kfree(queue->ctrl_data);
+		queue->ctrl_data = NULL;
+		msm_queue_drain(&queue->ctrl_q, list_control);
+		msm_drain_eventq(&queue->eventData_q);
+		queue = NULL;
+
 		pcam->dev_inst[i] = NULL;
 		pcam->use_count = 0;
 	}
@@ -1909,16 +1928,18 @@
 	switch (cmd) {
 	case MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO:
 		if (copy_from_user(&temp_cam_info,
-				(void __user *)ioctl_ptr->ioctl_ptr,
-				sizeof(struct msm_camera_info))) {
+			(void __user *)ioctl_ptr->ioctl_ptr,
+			sizeof(struct msm_camera_info))) {
 			rc = -EINVAL;
 			return rc;
 		}
 		for (i = 0; i < g_server_dev.camera_info.num_cameras; i++) {
 			if (copy_to_user((void __user *)
-			temp_cam_info.video_dev_name[i],
-			 g_server_dev.camera_info.video_dev_name[i],
-			strlen(g_server_dev.camera_info.video_dev_name[i]))) {
+				temp_cam_info.video_dev_name[i],
+				g_server_dev.camera_info.video_dev_name[i],
+				strnlen(
+				g_server_dev.camera_info.video_dev_name[i],
+				MAX_DEV_NAME_LEN))) {
 				rc = -EINVAL;
 				return rc;
 			}
@@ -2059,6 +2080,7 @@
 		break;
 	}
 	default:
+		pr_err("%s: Invalid IOCTL = %d", __func__, cmd);
 		break;
 	}
 	return rc;
@@ -2152,7 +2174,7 @@
 	D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
 
 	switch (cmd) {
-		/* memory management shall be handeld here*/
+	/* memory management shall be handeld here*/
 	case MSM_CAM_IOCTL_REGISTER_PMEM:
 		return msm_register_pmem(
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
@@ -2164,31 +2186,38 @@
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
 			(void __user *)arg, config_cam->p_mctl->client);
 		break;
+
 	case VIDIOC_SUBSCRIBE_EVENT:
 		if (copy_from_user(&temp_sub,
 			(void __user *)arg,
 			sizeof(struct v4l2_event_subscription))) {
-				rc = -EINVAL;
-				return rc;
+			rc = -EINVAL;
+			return rc;
 		}
 		rc = msm_server_v4l2_subscribe_event
 			(&config_cam->config_stat_event_queue.eventHandle,
-				 &temp_sub);
-		if (rc < 0)
+			&temp_sub);
+		if (rc < 0) {
+			pr_err("%s: cam_v4l2_subscribe_event failed rc=%d\n",
+				__func__, rc);
 			return rc;
+		}
 		break;
 
 	case VIDIOC_UNSUBSCRIBE_EVENT:
 		if (copy_from_user(&temp_sub, (void __user *)arg,
-			  sizeof(struct v4l2_event_subscription))) {
+			sizeof(struct v4l2_event_subscription))) {
 			rc = -EINVAL;
 			return rc;
 		}
 		rc = msm_server_v4l2_unsubscribe_event
 			(&config_cam->config_stat_event_queue.eventHandle,
-			 &temp_sub);
-		if (rc < 0)
+			&temp_sub);
+		if (rc < 0) {
+			pr_err("%s: server_unsubscribe_event failed rc=%d\n",
+				__func__, rc);
 			return rc;
+		}
 		break;
 
 	case VIDIOC_DQEVENT: {
@@ -2334,8 +2363,8 @@
 static int msm_open_config(struct inode *inode, struct file *fp)
 {
 	int rc;
-	struct msm_cam_config_dev *config_cam =
-	container_of(inode->i_cdev, struct msm_cam_config_dev, config_cdev);
+	struct msm_cam_config_dev *config_cam = container_of(inode->i_cdev,
+		struct msm_cam_config_dev, config_cdev);
 
 	D("%s: open %s\n", __func__, fp->f_path.dentry->d_name.name);
 
@@ -2404,7 +2433,7 @@
 };
 
 int msm_setup_v4l2_event_queue(struct v4l2_fh *eventHandle,
-					struct video_device *pvdev)
+	struct video_device *pvdev)
 {
 	int rc = 0;
 	/* v4l2_fh support */
@@ -2414,6 +2443,7 @@
 	rc = v4l2_fh_init(eventHandle, pvdev);
 	if (rc < 0)
 		return rc;
+
 	if (eventHandle->events == NULL) {
 		rc = v4l2_event_init(eventHandle);
 		if (rc < 0)
@@ -2427,7 +2457,6 @@
 
 	v4l2_fh_add(eventHandle);
 	return rc;
-
 }
 
 static int msm_setup_config_dev(int node, char *device_name)
@@ -2448,8 +2477,8 @@
 	D("%s\n", __func__);
 
 	devno = MKDEV(MAJOR(msm_devno), dev_num+1);
-	device_config = device_create(msm_class, NULL, devno, NULL,
-					"%s%d", device_name, dev_num);
+	device_config = device_create(msm_class, NULL, devno, NULL, "%s%d",
+		device_name, dev_num);
 
 	if (IS_ERR(device_config)) {
 		rc = PTR_ERR(device_config);
@@ -2457,8 +2486,7 @@
 		goto config_setup_fail;
 	}
 
-	cdev_init(&config_cam->config_cdev,
-			&msm_fops_config);
+	cdev_init(&config_cam->config_cdev, &msm_fops_config);
 	config_cam->config_cdev.owner = THIS_MODULE;
 
 	rc = cdev_add(&config_cam->config_cdev, devno, 1);
@@ -2467,12 +2495,12 @@
 		device_destroy(msm_class, devno);
 		goto config_setup_fail;
 	}
-	g_server_dev.config_info.config_dev_name[dev_num]
-		= dev_name(device_config);
+
+	g_server_dev.config_info.config_dev_name[dev_num] =
+		dev_name(device_config);
 	D("%s Connected config device %s\n", __func__,
 		g_server_dev.config_info.config_dev_name[dev_num]);
-	g_server_dev.config_info.config_dev_id[dev_num]
-		= dev_num;
+	g_server_dev.config_info.config_dev_id[dev_num] = dev_num;
 
 	config_cam->config_stat_event_queue.pvdev = video_device_alloc();
 	if (config_cam->config_stat_event_queue.pvdev == NULL) {
@@ -2485,6 +2513,7 @@
 		config_cam->config_stat_event_queue.pvdev);
 	if (rc < 0) {
 		pr_err("%s failed to initialize event queue\n", __func__);
+		video_device_release(config_cam->config_stat_event_queue.pvdev);
 		goto config_setup_fail;
 	}
 
@@ -2493,7 +2522,6 @@
 config_setup_fail:
 	kfree(config_cam);
 	return rc;
-
 }
 
 static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
@@ -2697,13 +2725,13 @@
 	video_set_drvdata(g_server_dev.video_dev, &g_server_dev);
 
 	strlcpy(g_server_dev.media_dev.model, "qcamera",
-			sizeof(g_server_dev.media_dev.model));
+		sizeof(g_server_dev.media_dev.model));
 	g_server_dev.media_dev.dev = &pdev->dev;
 	rc = media_device_register(&g_server_dev.media_dev);
 	g_server_dev.v4l2_dev.mdev = &g_server_dev.media_dev;
 
 	rc = video_register_device(g_server_dev.video_dev,
-			VFL_TYPE_GRABBER, 100);
+		VFL_TYPE_GRABBER, 100);
 
 	mutex_init(&g_server_dev.server_lock);
 	mutex_init(&g_server_dev.server_queue_lock);
@@ -2719,8 +2747,11 @@
 		&g_server_dev.server_command_queue.eventHandle,
 		g_server_dev.server_command_queue.pvdev);
 
-	if (rc < 0)
+	if (rc < 0) {
 		pr_err("%s failed to initialize event queue\n", __func__);
+		video_device_release(g_server_dev.server_command_queue.pvdev);
+		return rc;
+	}
 
 	for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
 		struct msm_cam_server_queue *queue;
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 671dfd7..04e224c 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -244,7 +244,7 @@
 	struct v4l2_subdev *ispif_sdev; /* ispif sub device */
 	struct v4l2_subdev *gemini_sdev; /* gemini sub device */
 	struct v4l2_subdev *vpe_sdev; /* vpe sub device */
-	struct v4l2_subdev *axi_sdev; /* vpe sub device */
+	struct v4l2_subdev *axi_sdev; /* axi sub device */
 	struct v4l2_subdev *eeprom_sdev; /* eeprom sub device */
 
 	struct msm_isp_ops *isp_sdev;    /* isp sub device : camif/VFE */
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index d791771..e878063 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -583,23 +583,22 @@
 		if (rc < 0) {
 			pr_err("%s: msm_mctl_register_subdevs failed:%d\n",
 				__func__, rc);
-			goto msm_open_done;
+			goto register_sdev_failed;
 		}
 
-		/* then sensor - move sub dev later*/
+		/* then sensor - move sub dev later */
 		rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 1);
-
 		if (rc < 0) {
-			pr_err("%s: isp init failed: %d\n", __func__, rc);
-			goto msm_open_done;
+			pr_err("%s: sensor powerup failed: %d\n", __func__, rc);
+			goto sensor_sdev_failed;
 		}
+
 		if (p_mctl->act_sdev)
 			rc = v4l2_subdev_call(p_mctl->act_sdev,
-					core, s_power, 1);
-
+				core, s_power, 1);
 		if (rc < 0) {
 			pr_err("%s: act power failed:%d\n", __func__, rc);
-			goto msm_open_done;
+			goto act_power_up_failed;
 		}
 
 		if (camdev->is_csiphy) {
@@ -607,8 +606,8 @@
 				VIDIOC_MSM_CSIPHY_INIT, NULL);
 			if (rc < 0) {
 				pr_err("%s: csiphy initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto csiphy_init_failed;
 			}
 		}
 
@@ -617,17 +616,18 @@
 				VIDIOC_MSM_CSID_INIT, &csid_version);
 			if (rc < 0) {
 				pr_err("%s: csid initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto csid_init_failed;
 			}
 		}
+
 		if (camdev->is_csic) {
 			rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
 				VIDIOC_MSM_CSIC_INIT, &csid_version);
 			if (rc < 0) {
 				pr_err("%s: csic initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto csic_init_failed;
 			}
 		}
 
@@ -638,7 +638,7 @@
 			if (rc < 0) {
 				pr_err("%s: isp init failed: %d\n",
 					__func__, rc);
-				goto msm_open_done;
+				goto isp_open_failed;
 			}
 		}
 
@@ -646,9 +646,9 @@
 			rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
 				VIDIOC_MSM_AXI_INIT, p_mctl);
 			if (rc < 0) {
-				pr_err("%s: vpe initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+				pr_err("%s: axi initialization failed %d\n",
+					__func__, rc);
+				goto axi_init_failed;
 			}
 		}
 
@@ -658,7 +658,7 @@
 			if (rc < 0) {
 				pr_err("%s: vpe initialization failed %d\n",
 				__func__, rc);
-				goto msm_open_done;
+				goto vpe_init_failed;
 			}
 		}
 
@@ -667,23 +667,65 @@
 				VIDIOC_MSM_ISPIF_INIT, &csid_version);
 			if (rc < 0) {
 				pr_err("%s: ispif initialization failed %d\n",
-				__func__, rc);
-				goto msm_open_done;
+					__func__, rc);
+				goto ispif_init_failed;
 			}
 		}
 
 		if (camdev->is_ispif) {
 			pm_qos_add_request(&p_mctl->pm_qos_req_list,
-					PM_QOS_CPU_DMA_LATENCY,
-					PM_QOS_DEFAULT_VALUE);
+				PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE);
 			pm_qos_update_request(&p_mctl->pm_qos_req_list,
-					MSM_V4L2_SWFI_LATENCY);
+				MSM_V4L2_SWFI_LATENCY);
 		}
 		p_mctl->apps_id = apps_id;
 		p_mctl->opencnt++;
+	} else {
+		D("%s: camera is already open", __func__);
 	}
+	mutex_unlock(&p_mctl->lock);
 
-msm_open_done:
+	return rc;
+
+ispif_init_failed:
+	if (camdev->is_vpe)
+		if (v4l2_subdev_call(p_mctl->vpe_sdev, core, ioctl,
+			VIDIOC_MSM_VPE_RELEASE, NULL) < 0)
+			pr_err("%s: vpe release failed %d\n", __func__, rc);
+vpe_init_failed:
+	if (p_mctl->axi_sdev)
+		if (v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+			VIDIOC_MSM_AXI_RELEASE, NULL) < 0)
+			pr_err("%s: axi release failed %d\n", __func__, rc);
+axi_init_failed:
+	if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
+		p_mctl->isp_sdev->isp_release(p_mctl->isp_sdev->sd);
+isp_open_failed:
+	if (camdev->is_csic)
+		if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
+			VIDIOC_MSM_CSIC_RELEASE, NULL) < 0)
+			pr_err("%s: csic release failed %d\n", __func__, rc);
+csic_init_failed:
+	if (camdev->is_csid)
+		if (v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
+			VIDIOC_MSM_CSID_RELEASE, NULL) < 0)
+			pr_err("%s: csid release failed %d\n", __func__, rc);
+csid_init_failed:
+	if (camdev->is_csiphy)
+		if (v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
+			VIDIOC_MSM_CSIPHY_RELEASE, NULL) < 0)
+			pr_err("%s: csiphy release failed %d\n", __func__, rc);
+csiphy_init_failed:
+	if (p_mctl->act_sdev)
+		if (v4l2_subdev_call(p_mctl->act_sdev, core,
+			s_power, 0) < 0)
+			pr_err("%s: act power down failed:%d\n", __func__, rc);
+act_power_up_failed:
+	if (v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0) < 0)
+		pr_err("%s: sensor powerdown failed: %d\n", __func__, rc);
+sensor_sdev_failed:
+register_sdev_failed:
+	wake_unlock(&p_mctl->wake_lock);
 	mutex_unlock(&p_mctl->lock);
 	return rc;
 }
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index e265b25..becdd95 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4177,16 +4177,18 @@
 	switch (cmd) {
 	case VIDIOC_MSM_AXI_INIT:
 		rc = msm_axi_subdev_init(sd,
-				(struct msm_cam_media_controller *)arg);
+			(struct msm_cam_media_controller *)arg);
 		break;
 	case VIDIOC_MSM_AXI_CFG:
 		rc = msm_axi_config(sd, arg);
 		break;
 	case VIDIOC_MSM_AXI_IRQ:
 		msm_axi_process_irq(sd, arg);
+		rc = 0;
 		break;
 	case VIDIOC_MSM_AXI_RELEASE:
 		msm_axi_subdev_release(sd);
+		rc = 0;
 		break;
 	default:
 		pr_err("%s: command not found\n", __func__);
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index 40154ef..d9d315e 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -22,6 +22,7 @@
 #include <media/v4l2-subdev.h>
 #include <media/msm_isp.h>
 #include <mach/msm_adsp.h>
+#include <linux/clk.h>
 #include <mach/clk.h>
 #include <mach/camera.h>
 #include "msm_vfe7x27a_v4l2.h"
@@ -1729,12 +1730,38 @@
 	return;
 }
 
+static int msm_vfe_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+	u32 freq, u32 flags)
+{
+	int rc = 0;
+	int round_rate;
+
+	round_rate = clk_round_rate(vfe2x_ctrl->vfe_clk[0], freq);
+	if (rc < 0) {
+		pr_err("%s: clk_round_rate failed %d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	rc = clk_set_rate(vfe2x_ctrl->vfe_clk[0], round_rate);
+	if (rc < 0)
+		pr_err("%s: clk_set_rate failed %d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static const struct v4l2_subdev_video_ops msm_vfe_subdev_video_ops = {
+	.s_crystal_freq = msm_vfe_subdev_s_crystal_freq,
+};
+
 static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
 	.ioctl = msm_vfe_subdev_ioctl,
 };
 
 static const struct v4l2_subdev_ops msm_vfe_subdev_ops = {
 	.core = &msm_vfe_subdev_core_ops,
+	.video = &msm_vfe_subdev_video_ops,
 };
 
 static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index d4d07cd..ff5bb49 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -587,6 +587,7 @@
 		msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
 
 	return rc;
+
 enable_clk_failed:
 		msm_camera_config_gpio_table(data, 0);
 config_gpio_failed:
@@ -643,13 +644,14 @@
 			s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
 			MSM_CAMERA_I2C_WORD_DATA);
 	if (rc < 0) {
-		CDBG("%s: read id failed\n", __func__);
+		pr_err("%s: %s: read id failed\n", __func__,
+			s_ctrl->sensordata->sensor_name);
 		return rc;
 	}
 
 	CDBG("msm_sensor id: %d\n", chipid);
 	if (chipid != s_ctrl->sensor_id_info->sensor_id) {
-		CDBG("msm_sensor_match_id chip id doesnot match\n");
+		pr_err("msm_sensor_match_id chip id doesnot match\n");
 		return -ENODEV;
 	}
 	return rc;
@@ -726,10 +728,30 @@
 	int rc = 0;
 	struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
 	mutex_lock(s_ctrl->msm_sensor_mutex);
-	if (on)
+	if (on) {
 		rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
-	else
+		if (rc < 0) {
+			pr_err("%s: %s power_up failed rc = %d\n", __func__,
+				s_ctrl->sensordata->sensor_name, rc);
+		} else {
+			if (s_ctrl->func_tbl->sensor_match_id)
+				rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+			else
+				rc = msm_sensor_match_id(s_ctrl);
+			if (rc < 0) {
+				pr_err("%s: %s match_id failed  rc=%d\n",
+					__func__,
+					s_ctrl->sensordata->sensor_name, rc);
+				if (s_ctrl->func_tbl->sensor_power_down(s_ctrl)
+					< 0)
+					pr_err("%s: %s power_down failed\n",
+					__func__,
+					s_ctrl->sensordata->sensor_name);
+			}
+		}
+	} else {
 		rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+	}
 	mutex_unlock(s_ctrl->msm_sensor_mutex);
 	return rc;
 }
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index ca2bb98..83c83d1 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -100,6 +100,65 @@
 	{0x4004, 0x04},
 };
 
+static struct msm_camera_i2c_reg_conf ov5647_video_60fps_settings[] = {
+	{0x3035, 0x21},
+	{0x3036, 0x38},
+	{0x3821, 0x07},
+	{0x3820, 0x41},
+	{0x3612, 0x49},
+	{0x3618, 0x00},
+	{0x380c, 0x07},
+	{0x380d, 0x30},
+	{0x380e, 0x01},
+	{0x380f, 0xf8},
+	{0x3814, 0x71},
+	{0x3815, 0x71},
+	{0x3709, 0x52},
+	{0x3808, 0x02},
+	{0x3809, 0x80},
+	{0x380a, 0x01},
+	{0x380b, 0xe0},
+	{0x3800, 0x00},
+	{0x3801, 0x10},
+	{0x3802, 0x00},
+	{0x3803, 0x00},
+	{0x3804, 0x0a},
+	{0x3805, 0x2f},
+	{0x3806, 0x07},
+	{0x3807, 0x9f},
+	{0x4004, 0x02},
+};
+
+static struct msm_camera_i2c_reg_conf ov5647_video_90fps_settings[] = {
+	{0x3035, 0x11},
+	{0x3036, 0x2a},
+	{0x3821, 0x07},
+	{0x3820, 0x41},
+	{0x3612, 0x49},
+	{0x3618, 0x00},
+	{0x380c, 0x07},
+	{0x380d, 0x30},
+	{0x380e, 0x01},
+	{0x380f, 0xf8},
+	{0x3814, 0x71},
+	{0x3815, 0x71},
+	{0x3709, 0x52},
+	{0x3808, 0x02},
+	{0x3809, 0x80},
+	{0x380a, 0x01},
+	{0x380b, 0xe0},
+	{0x3800, 0x00},
+	{0x3801, 0x10},
+	{0x3802, 0x00},
+	{0x3803, 0x00},
+	{0x3804, 0x0a},
+	{0x3805, 0x2f},
+	{0x3806, 0x07},
+	{0x3807, 0x9f},
+	{0x4004, 0x02},
+};
+
+
 static struct msm_camera_i2c_reg_conf ov5647_recommend_settings[] = {
 	{0x3035, 0x11},
 	{0x303c, 0x11},
@@ -247,6 +306,10 @@
 	ARRAY_SIZE(ov5647_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 	{&ov5647_prev_settings[0],
 	ARRAY_SIZE(ov5647_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&ov5647_video_60fps_settings[0],
+	ARRAY_SIZE(ov5647_video_60fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
+	{&ov5647_video_90fps_settings[0],
+	ARRAY_SIZE(ov5647_video_90fps_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
 };
 
 static struct msm_camera_csi_params ov5647_csi_params = {
@@ -286,6 +349,25 @@
 		.op_pixel_clk = 159408000,
 		.binning_factor = 0x0,
 	},
+	{ /* For 60fps */
+		.x_output = 0x280,  /*640*/
+		.y_output = 0x1E0,   /*480*/
+		.line_length_pclk = 0x73C,
+		.frame_length_lines = 0x1F8,
+		.vt_pixel_clk = 56004480,
+		.op_pixel_clk = 159408000,
+		.binning_factor = 0x0,
+	},
+	{ /* For 90fps */
+		.x_output = 0x280,  /*640*/
+		.y_output = 0x1E0,   /*480*/
+		.line_length_pclk = 0x73C,
+		.frame_length_lines = 0x1F8,
+		.vt_pixel_clk = 56004480,
+		.op_pixel_clk = 159408000,
+		.binning_factor = 0x0,
+	},
+
 };
 
 static struct msm_sensor_output_reg_addr_t ov5647_reg_addr = {
@@ -298,6 +380,8 @@
 static struct msm_camera_csi_params *ov5647_csi_params_array[] = {
 	&ov5647_csi_params,
 	&ov5647_csi_params,
+	&ov5647_csi_params,
+	&ov5647_csi_params,
 };
 
 static struct msm_sensor_id_info_t ov5647_id_info = {
@@ -443,11 +527,12 @@
 	u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
 	uint8_t gain_lsb, gain_hsb;
 
-	pr_info(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
+	CDBG(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
 		 gain, line, line);
 
 	gain_lsb = (uint8_t) (gain);
 	gain_hsb = (uint8_t)((gain & 0x300)>>8);
+
 	/* adjust frame rate */
 	if (line > 980 && line <= 984) {
 
@@ -634,12 +719,12 @@
 {
 	int32_t rc = 0;
 	static int csi_config;
-
 	s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
 	if (csi_config == 0 || res == 0)
 		msleep(66);
 	else
 		msleep(266);
+
 	msm_camera_i2c_write(
 			s_ctrl->sensor_i2c_client,
 			0x4800, 0x25,
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index a311029..080a87c 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -145,6 +145,11 @@
 #define MP3_1_SHIFT	5
 #define MP3_2_SHIFT	2
 
+#define REG_HSED_BIAS0_CNTL2		0xA1
+#define REG_HSED_BIAS1_CNTL2		0x135
+#define REG_HSED_BIAS2_CNTL2		0x138
+#define HSED_EN_MASK			0xC0
+
 struct pm8xxx_misc_chip {
 	struct list_head			link;
 	struct pm8xxx_misc_platform_data	pdata;
@@ -1100,6 +1105,52 @@
 }
 EXPORT_SYMBOL_GPL(pm8xxx_aux_clk_control);
 
+int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias, bool enable)
+{
+	struct pm8xxx_misc_chip *chip;
+	unsigned long flags;
+	int rc = 0;
+	u16 addr;
+
+	switch (bias) {
+	case PM8XXX_HSED_BIAS0:
+		addr = REG_HSED_BIAS0_CNTL2;
+		break;
+	case PM8XXX_HSED_BIAS1:
+		addr = REG_HSED_BIAS1_CNTL2;
+		break;
+	case PM8XXX_HSED_BIAS2:
+		addr = REG_HSED_BIAS2_CNTL2;
+		break;
+	default:
+		pr_err("Invalid BIAS line\n");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+	/* Loop over all attached PMICs and call specific functions for them. */
+	list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+		switch (chip->version) {
+		case PM8XXX_VERSION_8058:
+		case PM8XXX_VERSION_8921:
+			rc = pm8xxx_misc_masked_write(chip, addr,
+				HSED_EN_MASK, enable ? HSED_EN_MASK : 0);
+			if (rc < 0)
+				pr_err("Enable HSED BIAS failed rc=%d\n", rc);
+			break;
+		default:
+			/* Functionality not supported */
+			break;
+		}
+	}
+
+	spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+	return rc;
+}
+EXPORT_SYMBOL(pm8xxx_hsed_bias_control);
+
 static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
 {
 	const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 28505636..d489233 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -31,6 +31,17 @@
 {
 	int i, ret, count;
 	unsigned char pending;
+	struct sdio_func *func;
+
+	/*
+	 * Optimization, if there is only 1 function interrupt registered
+	 * call irq handler directly
+	 */
+	func = card->sdio_single_irq;
+	if (func) {
+		func->irq_handler(func);
+		return 1;
+	}
 
 	ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending);
 	if (ret) {
@@ -42,7 +53,7 @@
 	count = 0;
 	for (i = 1; i <= 7; i++) {
 		if (pending & (1 << i)) {
-			struct sdio_func *func = card->sdio_func[i - 1];
+			func = card->sdio_func[i - 1];
 			if (!func) {
 				printk(KERN_WARNING "%s: pending IRQ for "
 					"non-existent function\n",
@@ -192,6 +203,24 @@
 	return 0;
 }
 
+/* If there is only 1 function registered set sdio_single_irq */
+static void sdio_single_irq_set(struct mmc_card *card)
+{
+	struct sdio_func *func;
+	int i;
+
+	card->sdio_single_irq = NULL;
+	if ((card->host->caps & MMC_CAP_SDIO_IRQ) &&
+			card->host->sdio_irqs == 1)
+		for (i = 0; i < card->sdio_funcs; i++) {
+			func = card->sdio_func[i];
+			if (func && func->irq_handler) {
+				card->sdio_single_irq = func;
+				break;
+			}
+		}
+}
+
 /**
  *	sdio_claim_irq - claim the IRQ for a SDIO function
  *	@func: SDIO function
@@ -233,6 +262,7 @@
 	ret = sdio_card_irq_get(func->card);
 	if (ret)
 		func->irq_handler = NULL;
+	sdio_single_irq_set(func->card);
 
 	return ret;
 }
@@ -257,6 +287,7 @@
 	if (func->irq_handler) {
 		func->irq_handler = NULL;
 		sdio_card_irq_put(func->card);
+		sdio_single_irq_set(func->card);
 	}
 
 	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 0d6c5f1..73a31716 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -79,6 +79,9 @@
 static int  msmsdcc_dbg_init(void);
 #endif
 
+static int msmsdcc_prep_xfer(struct msmsdcc_host *host, struct mmc_data
+			     *data);
+
 static u64 dma_mask = DMA_BIT_MASK(32);
 static unsigned int msmsdcc_pwrsave = 1;
 
@@ -482,8 +485,9 @@
 		if (!mrq->data->error)
 			mrq->data->error = -EIO;
 	}
-	dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
-		     host->dma.dir);
+	if (!mrq->data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
+			     host->dma.num_ents, host->dma.dir);
 
 	if (host->curr.user_pages) {
 		struct scatterlist *sg = host->dma.sg;
@@ -649,9 +653,9 @@
 	}
 
 	/* Unmap sg buffers */
-	dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
-			 host->sps.dir);
-
+	if (!mrq->data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg,
+			     host->sps.num_ents, host->sps.dir);
 	host->sps.sg = NULL;
 	host->sps.busy = 0;
 
@@ -720,8 +724,9 @@
 		mrq->data->error = -EIO;
 
 	/* Unmap sg buffers */
-	dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
-			 host->sps.dir);
+	if (!mrq->data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg,
+			     host->sps.num_ents, host->sps.dir);
 
 	host->sps.sg = NULL;
 	host->sps.busy = 0;
@@ -816,15 +821,13 @@
 	else
 		host->dma.dir = DMA_TO_DEVICE;
 
-	n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
-			host->dma.num_ents, host->dma.dir);
-
-	if (n != host->dma.num_ents) {
-		pr_err("%s: Unable to map in all sg elements\n",
-		       mmc_hostname(host->mmc));
-		host->dma.sg = NULL;
-		host->dma.num_ents = 0;
-		return -ENOMEM;
+	if (!data->host_cookie) {
+		n = msmsdcc_prep_xfer(host, data);
+		if (unlikely(n < 0)) {
+			host->dma.sg = NULL;
+			host->dma.num_ents = 0;
+			return -ENOMEM;
+		}
 	}
 
 	/* host->curr.user_pages = (data->flags & MMC_DATA_USERPAGE); */
@@ -893,8 +896,9 @@
 
 unmap:
 	if (err) {
-		dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
-				host->dma.num_ents, host->dma.dir);
+		if (!data->host_cookie)
+			dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg,
+				     host->dma.num_ents, host->dma.dir);
 		pr_err("%s: cannot do DMA, fall back to PIO mode err=%d\n",
 				mmc_hostname(host->mmc), err);
 	}
@@ -902,6 +906,44 @@
 	return err;
 }
 
+static int msmsdcc_prep_xfer(struct msmsdcc_host *host,
+			     struct mmc_data *data)
+{
+	int rc = 0;
+	unsigned int dir;
+
+	/* Prevent memory corruption */
+	BUG_ON(data->sg_len > msmsdcc_get_nr_sg(host));
+
+	if (data->flags & MMC_DATA_READ)
+		dir = DMA_FROM_DEVICE;
+	else
+		dir = DMA_TO_DEVICE;
+
+	/* Make sg buffers DMA ready */
+	rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			dir);
+
+	if (unlikely(rc != data->sg_len)) {
+		pr_err("%s: Unable to map in all sg elements, rc=%d\n",
+		       mmc_hostname(host->mmc), rc);
+		rc = -ENOMEM;
+		goto dma_map_err;
+	}
+
+	pr_debug("%s: %s: %s: sg_len=%d\n",
+		mmc_hostname(host->mmc), __func__,
+		dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
+		data->sg_len);
+
+	goto out;
+
+dma_map_err:
+	dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+		     data->flags);
+out:
+	return rc;
+}
 #ifdef CONFIG_MMC_MSM_SPS_SUPPORT
 /**
  * Submits data transfer request to SPS driver
@@ -916,7 +958,7 @@
  * @return 0 if success else negative value
  */
 static int msmsdcc_sps_start_xfer(struct msmsdcc_host *host,
-				struct mmc_data *data)
+				  struct mmc_data *data)
 {
 	int rc = 0;
 	u32 flags;
@@ -925,9 +967,6 @@
 	struct scatterlist *sg = data->sg;
 	struct sps_pipe *sps_pipe_handle;
 
-	/* Prevent memory corruption */
-	BUG_ON(data->sg_len > msmsdcc_get_nr_sg(host));
-
 	host->sps.sg = data->sg;
 	host->sps.num_ents = data->sg_len;
 	host->sps.xfer_req_cnt = 0;
@@ -939,24 +978,15 @@
 		sps_pipe_handle = host->sps.cons.pipe_handle;
 	}
 
-	/* Make sg buffers DMA ready */
-	rc = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-			host->sps.dir);
-
-	if (rc != data->sg_len) {
-		pr_err("%s: Unable to map in all sg elements, rc=%d\n",
-		       mmc_hostname(host->mmc), rc);
-		host->sps.sg = NULL;
-		host->sps.num_ents = 0;
-		rc = -ENOMEM;
-		goto dma_map_err;
+	if (!data->host_cookie) {
+		rc = msmsdcc_prep_xfer(host, data);
+		if (unlikely(rc < 0)) {
+			host->dma.sg = NULL;
+			host->dma.num_ents = 0;
+			goto out;
+		}
 	}
 
-	pr_debug("%s: %s: %s: pipe=0x%x, total_xfer=0x%x, sg_len=%d\n",
-		mmc_hostname(host->mmc), __func__,
-		host->sps.dir == DMA_FROM_DEVICE ? "READ" : "WRITE",
-		(u32)sps_pipe_handle, host->curr.xfer_size, data->sg_len);
-
 	for (i = 0; i < data->sg_len; i++) {
 		/*
 		 * Check if this is the last buffer to transfer?
@@ -993,8 +1023,9 @@
 
 dma_map_err:
 	/* unmap sg buffers */
-	dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg, host->sps.num_ents,
-			host->sps.dir);
+	if (!data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), host->sps.sg,
+			     host->sps.num_ents, host->sps.dir);
 out:
 	return rc;
 }
@@ -1833,6 +1864,63 @@
 }
 
 static void
+msmsdcc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+		bool is_first_request)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	struct mmc_data *data = mrq->data;
+	int rc = 0;
+
+	if (unlikely(!data)) {
+		pr_err("%s: %s cannot prepare null data\n", mmc_hostname(mmc),
+		       __func__);
+		return;
+	}
+	if (unlikely(data->host_cookie)) {
+		/* Very wrong */
+		data->host_cookie = 0;
+		pr_err("%s: %s Request reposted for prepare\n",
+		       mmc_hostname(mmc), __func__);
+		return;
+	}
+
+	if (!msmsdcc_is_dma_possible(host, data))
+		return;
+
+	rc = msmsdcc_prep_xfer(host, data);
+	if (unlikely(rc < 0)) {
+		data->host_cookie = 0;
+		return;
+	}
+
+	data->host_cookie = 1;
+}
+
+static void
+msmsdcc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err)
+{
+	struct msmsdcc_host *host = mmc_priv(mmc);
+	unsigned int dir;
+	struct mmc_data *data = mrq->data;
+
+	if (unlikely(!data)) {
+		pr_err("%s: %s cannot cleanup null data\n", mmc_hostname(mmc),
+		       __func__);
+		return;
+	}
+	if (data->flags & MMC_DATA_READ)
+		dir = DMA_FROM_DEVICE;
+	else
+		dir = DMA_TO_DEVICE;
+
+	if (data->host_cookie)
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+			     data->sg_len, dir);
+
+	data->host_cookie = 0;
+}
+
+static void
 msmsdcc_request_start(struct msmsdcc_host *host, struct mmc_request *mrq)
 {
 	if (mrq->data && mrq->data->flags & MMC_DATA_READ) {
@@ -3561,6 +3649,8 @@
 static const struct mmc_host_ops msmsdcc_ops = {
 	.enable		= msmsdcc_enable,
 	.disable	= msmsdcc_disable,
+	.pre_req        = msmsdcc_pre_req,
+	.post_req       = msmsdcc_post_req,
 	.request	= msmsdcc_request,
 	.set_ios	= msmsdcc_set_ios,
 	.get_ro		= msmsdcc_get_ro,
diff --git a/drivers/usb/gadget/msm72k_udc.c b/drivers/usb/gadget/msm72k_udc.c
index 0921b4f..35ea497 100644
--- a/drivers/usb/gadget/msm72k_udc.c
+++ b/drivers/usb/gadget/msm72k_udc.c
@@ -1109,6 +1109,7 @@
 	struct msm_endpoint *ept = ui->ept + bit;
 	struct msm_request *req;
 	unsigned long flags;
+	int req_dequeue = 1;
 	unsigned info;
 
 	/*
@@ -1128,12 +1129,23 @@
 			break;
 		}
 
+dequeue:
 		/* clean speculative fetches on req->item->info */
 		dma_coherent_post_ops();
 		info = req->item->info;
 		/* if the transaction is still in-flight, stop here */
-		if (info & INFO_ACTIVE)
-			break;
+		if (info & INFO_ACTIVE) {
+			if (req_dequeue) {
+				req_dequeue = 0;
+				ui->dTD_update_fail_count++;
+				ept->dTD_update_fail_count++;
+				udelay(10);
+				goto dequeue;
+			} else {
+				break;
+			}
+		}
+		req_dequeue = 0;
 
 		del_timer(&ept->prime_timer);
 		/* advance ept queue to the next request */
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 9794918..96e5a90 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -88,7 +88,8 @@
 		return;
 	}
 
-	cbs->read_complete_cb(cbs->ctxt,
+	if (cbs && cbs->read_complete_cb)
+		cbs->read_complete_cb(cbs->ctxt,
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
 			urb->status < 0 ? urb->status : urb->actual_length);
@@ -172,7 +173,8 @@
 		return;
 	}
 
-	cbs->write_complete_cb(cbs->ctxt,
+	if (cbs && cbs->write_complete_cb)
+		cbs->write_complete_cb(cbs->ctxt,
 			urb->transfer_buffer,
 			urb->transfer_buffer_length,
 			urb->status < 0 ? urb->status : urb->actual_length);
diff --git a/drivers/video/msm/mipi_toshiba.h b/drivers/video/msm/mipi_toshiba.h
index 632bbd3..4107161 100644
--- a/drivers/video/msm/mipi_toshiba.h
+++ b/drivers/video/msm/mipi_toshiba.h
@@ -21,9 +21,9 @@
 int mipi_toshiba_device_register(struct msm_panel_info *pinfo,
 					u32 channel, u32 panel);
 
-#define MIPI_TOSHIBA_PWM_FREQ_HZ 300
+#define MIPI_TOSHIBA_PWM_FREQ_HZ 3921
 #define MIPI_TOSHIBA_PWM_PERIOD_USEC (USEC_PER_SEC / MIPI_TOSHIBA_PWM_FREQ_HZ)
-#define MIPI_TOSHIBA_PWM_LEVEL 100
+#define MIPI_TOSHIBA_PWM_LEVEL 255
 #define MIPI_TOSHIBA_PWM_DUTY_LEVEL \
 	(MIPI_TOSHIBA_PWM_PERIOD_USEC / MIPI_TOSHIBA_PWM_LEVEL)
 
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index 77683ce..c4b0ea4 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -89,6 +89,12 @@
 	XO_DIV_64,
 };
 
+enum pm8xxx_hsed_bias {
+	PM8XXX_HSED_BIAS0,
+	PM8XXX_HSED_BIAS1,
+	PM8XXX_HSED_BIAS2,
+};
+
 #if defined(CONFIG_MFD_PM8XXX_MISC) || defined(CONFIG_MFD_PM8XXX_MISC_MODULE)
 
 /**
@@ -210,6 +216,14 @@
 				enum pm8xxx_aux_clk_div divider,
 				bool enable);
 
+/**
+ * pm8xxx_hsed_bias_control - Control the HSED_BIAS signal
+ * @bias: the bias line to be controlled (of the 3)
+ * @enable: enable/disable the bias line
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias, bool enable);
 #else
 
 static inline int pm8xxx_reset_pwr_off(int reset)
@@ -259,6 +273,11 @@
 {
 	return -ENODEV;
 }
+static inline int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias,
+							bool enable)
+{
+	return -ENODEV;
+}
 
 #endif
 
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 8a0c4d5..aa808dc 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -228,6 +228,7 @@
 	struct sdio_cccr	cccr;		/* common card info */
 	struct sdio_cis		cis;		/* common tuple info */
 	struct sdio_func	*sdio_func[SDIO_MAX_FUNCS]; /* SDIO functions (devices) */
+	struct sdio_func	*sdio_single_irq; /* SDIO function when only one IRQ active */
 	unsigned		num_info;	/* number of info strings */
 	const char		**info;		/* info strings */
 	struct sdio_func_tuple	*tuples;	/* unknown common tuples */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b920a72..f13b52b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1370,6 +1370,16 @@
 }
 #endif /* NET_SKBUFF_DATA_USES_OFFSET */
 
+static inline void skb_mac_header_rebuild(struct sk_buff *skb)
+{
+	if (skb_mac_header_was_set(skb)) {
+		const unsigned char *old_mac = skb_mac_header(skb);
+
+		skb_set_mac_header(skb, -skb->mac_len);
+		memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+	}
+}
+
 static inline int skb_checksum_start_offset(const struct sk_buff *skb)
 {
 	return skb->csum_start - skb_headroom(skb);
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index b806040..134d044 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -352,8 +352,53 @@
 	u16 reserved;
 } __attribute__ ((packed));
 
+/* Parameter ID used to configure and enable/disable the loopback path. The
+ * difference with respect to the existing API, AFE_PORT_CMD_LOOPBACK, is that
+ * it allows Rx port to be configured as source port in loopback path. Port-id
+ * in AFE_PORT_CMD_SET_PARAM cmd is the source port whcih can be Tx or Rx port.
+ * In addition, we can configure the type of routing mode to handle different
+ * use cases.
+*/
+enum {
+	/* Regular loopback from source to destination port */
+	LB_MODE_DEFAULT = 1,
+	/* Sidetone feed from Tx source to Rx destination port */
+	LB_MODE_SIDETONE,
+	/* Echo canceller reference, voice + audio + DTMF */
+	LB_MODE_EC_REF_VOICE_AUDIO,
+	/* Echo canceller reference, voice alone */
+	LB_MODE_EC_REF_VOICE
+};
+
+#define AFE_PARAM_ID_LOOPBACK_CONFIG 0x0001020B
+#define AFE_API_VERSION_LOOPBACK_CONFIG 0x1
+struct afe_param_loopback_cfg {
+	/* Minor version used for tracking the version of the configuration
+	 * interface.
+	 */
+	uint32_t loopback_cfg_minor_version;
+
+	/* Destination Port Id. */
+	uint16_t dst_port_id;
+
+	/* Specifies data path type from src to dest port. Supported values:
+	 * LB_MODE_DEFAULT
+	 * LB_MODE_SIDETONE
+	 * LB_MODE_EC_REF_VOICE_AUDIO
+	 * LB_MODE_EC_REF_VOICE
+	 */
+	uint16_t routing_mode;
+
+	/* Specifies whether to enable (1) or disable (0) an AFE loopback. */
+	uint16_t enable;
+
+	/* Reserved for 32-bit alignment. This field must be set to 0. */
+	uint16_t reserved;
+} __packed;
 
 #define AFE_MODULE_ID_PORT_INFO		0x00010200
+/* Module ID for the loopback-related parameters. */
+#define AFE_MODULE_LOOPBACK           0x00010205
 struct afe_param_payload {
 	u32 module_id;
 	u32 param_id;
@@ -364,6 +409,7 @@
 		struct afe_param_sampling_rate sampling_rate;
 		struct afe_param_channels      channels;
 		struct afe_param_loopback_gain loopback_gain;
+		struct afe_param_loopback_cfg loopback_cfg;
 	} __attribute__((packed)) param;
 } __attribute__ ((packed));
 
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 9893075..8cdcc18 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.h
@@ -74,6 +74,7 @@
 int afe_open(u16 port_id, union afe_port_config *afe_config, int rate);
 int afe_close(int port_id);
 int afe_loopback(u16 enable, u16 rx_port, u16 tx_port);
+int afe_loopback_cfg(u16 enable, u16 dst_port, u16 src_port, u16 mode);
 int afe_sidetone(u16 tx_port_id, u16 rx_port_id, u16 enable, uint16_t gain);
 int afe_loopback_gain(u16 port_id, u16 volume);
 int afe_validate_port(u16 port_id);
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 6341818..e3db3f9 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -110,10 +110,7 @@
 
 	skb_push(skb, sizeof(*iph));
 	skb_reset_network_header(skb);
-
-	memmove(skb->data - skb->mac_len, skb_mac_header(skb),
-		skb->mac_len);
-	skb_set_mac_header(skb, -skb->mac_len);
+	skb_mac_header_rebuild(skb);
 
 	xfrm4_beet_make_header(skb);
 
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 534972e..ed4bf11 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -66,7 +66,6 @@
 
 static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
-	const unsigned char *old_mac;
 	int err = -EINVAL;
 
 	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
@@ -84,10 +83,9 @@
 	if (!(x->props.flags & XFRM_STATE_NOECN))
 		ipip_ecn_decapsulate(skb);
 
-	old_mac = skb_mac_header(skb);
-	skb_set_mac_header(skb, -skb->mac_len);
-	memmove(skb_mac_header(skb), old_mac, skb->mac_len);
 	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+
 	err = 0;
 
 out:
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 3437d7d..f37cba9 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -80,7 +80,6 @@
 static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct ipv6hdr *ip6h;
-	const unsigned char *old_mac;
 	int size = sizeof(struct ipv6hdr);
 	int err;
 
@@ -90,10 +89,7 @@
 
 	__skb_push(skb, size);
 	skb_reset_network_header(skb);
-
-	old_mac = skb_mac_header(skb);
-	skb_set_mac_header(skb, -skb->mac_len);
-	memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+	skb_mac_header_rebuild(skb);
 
 	xfrm6_beet_make_header(skb);
 
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 4d6edff..23ecd68 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -63,7 +63,6 @@
 static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err = -EINVAL;
-	const unsigned char *old_mac;
 
 	if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
 		goto out;
@@ -80,10 +79,9 @@
 	if (!(x->props.flags & XFRM_STATE_NOECN))
 		ipip6_ecn_decapsulate(skb);
 
-	old_mac = skb_mac_header(skb);
-	skb_set_mac_header(skb, -skb->mac_len);
-	memmove(skb_mac_header(skb), old_mac, skb->mac_len);
 	skb_reset_network_header(skb);
+	skb_mac_header_rebuild(skb);
+
 	err = 0;
 
 out:
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index e5b9d16..94dd695 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -824,7 +824,7 @@
 
 #define ALL_INIT_DATA_SECTIONS \
 	".init.setup$", ".init.rodata$", \
-	".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$" \
+	".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$", \
 	".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
 #define ALL_EXIT_DATA_SECTIONS \
 	".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 4b6d83b..9041bd7 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1498,7 +1498,7 @@
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	unsigned int cfilt;
 
-	switch (sitar->micbias) {
+	switch (sitar->mbhc_cfg.micbias) {
 	case SITAR_MICBIAS1:
 		cfilt = sitar->pdata->micbias.bias1_cfilt_sel;
 		micbias_regs->mbhc_reg = SITAR_A_MICB_1_MBHC;
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index b0244af..c8ef419 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -62,7 +62,9 @@
 enum {
 	SLIM_1_RX_1 = 145, /* BT-SCO and USB TX */
 	SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
-	SLIM_2_RX_1 = 147, /* HDMI RX */
+	SLIM_3_RX_1 = 151, /* External echo-cancellation ref */
+	SLIM_3_RX_2 = 152, /* External echo-cancellation ref */
+	SLIM_3_TX_1 = 147, /* HDMI RX */
 	SLIM_4_TX_1 = 148, /* In-call recording RX */
 	SLIM_4_TX_2 = 149, /* In-call recording RX */
 	SLIM_4_RX_1 = 150, /* In-call music delivery TX */
@@ -80,6 +82,7 @@
 static int msm_ext_top_spk_pamp;
 static int msm_slim_0_rx_ch = 1;
 static int msm_slim_0_tx_ch = 1;
+static int msm_slim_3_rx_ch = 1;
 
 static int msm_btsco_rate = BTSCO_RATE_8KHZ;
 static int msm_btsco_ch = 1;
@@ -636,6 +639,25 @@
 	return 1;
 }
 
+static int msm_slim_3_rx_ch_get(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	pr_debug("%s: msm_slim_3_rx_ch  = %d\n", __func__,
+			msm_slim_3_rx_ch);
+	ucontrol->value.integer.value[0] = msm_slim_3_rx_ch - 1;
+	return 0;
+}
+
+static int msm_slim_3_rx_ch_put(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *ucontrol)
+{
+	msm_slim_3_rx_ch = ucontrol->value.integer.value[0] + 1;
+
+	pr_debug("%s: msm_slim_3_rx_ch = %d\n", __func__,
+			msm_slim_3_rx_ch);
+	return 1;
+}
+
 static int msm_btsco_rate_get(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -713,6 +735,24 @@
 	return 0;
 }
 
+static const struct snd_kcontrol_new slim_3_mixer_controls[] = {
+	SOC_ENUM_EXT("SLIM_3_RX Channels", msm_enum[1],
+		msm_slim_3_rx_ch_get, msm_slim_3_rx_ch_put),
+};
+
+static int msm_slim_3_init(struct snd_soc_pcm_runtime *rtd)
+{
+	int err = 0;
+	struct snd_soc_platform *platform = rtd->platform;
+
+	err = snd_soc_add_platform_controls(platform,
+			slim_3_mixer_controls,
+		ARRAY_SIZE(slim_3_mixer_controls));
+	if (err < 0)
+		return err;
+	return 0;
+}
+
 static int msm_incall_rec_init(struct snd_soc_pcm_runtime *rtd)
 {
 	int err = 0;
@@ -845,6 +885,13 @@
 			user_set_tx_ch =  msm_slim_0_tx_ch;
 		else if (codec_dai->id  == 4)
 			user_set_tx_ch =  params_channels(params);
+		else if (codec_dai->id == 5) {
+			/* DAI 5 is used for external EC reference from codec.
+			 * Since Rx is fed as reference for EC, the config of
+			 * this DAI is based on that of the Rx path.
+			 */
+			user_set_tx_ch =  msm_slim_0_rx_ch;
+		}
 
 		pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
 			codec_dai->name, codec_dai->id, user_set_tx_ch);
@@ -919,6 +966,35 @@
 	return ret;
 }
 
+static int msm_slimbus_3_hw_params(struct snd_pcm_substream *substream,
+				struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+	int ret = 0;
+	unsigned int rx_ch[2] = {SLIM_3_RX_1, SLIM_3_RX_2};
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		pr_debug("%s: slim_3_rx_ch %d, sch %d %d\n",
+			 __func__, msm_slim_3_rx_ch,
+				 rx_ch[0], rx_ch[1]);
+
+		ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+				msm_slim_3_rx_ch, rx_ch);
+		if (ret < 0) {
+			pr_err("%s: Erorr %d setting SLIM_3 RX channel map\n",
+				__func__, ret);
+
+			goto end;
+		}
+	} else {
+		pr_err("%s: SLIMBUS_3_TX not defined for this DAI\n", __func__);
+	}
+
+end:
+	return ret;
+}
+
 static int msm_slimbus_4_hw_params(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params)
 {
@@ -1093,6 +1169,22 @@
 	return 0;
 }
 
+static int msm_slim_3_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+	SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+			SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	pr_debug("%s()\n", __func__);
+	rate->min = rate->max = 48000;
+	channels->min = channels->max = msm_slim_3_rx_ch;
+
+	return 0;
+}
+
 static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
 			struct snd_pcm_hw_params *params)
 {
@@ -1257,6 +1349,12 @@
 	.shutdown = msm_shutdown,
 };
 
+static struct snd_soc_ops msm_slimbus_3_be_ops = {
+	.startup = msm_startup,
+	.hw_params = msm_slimbus_3_hw_params,
+	.shutdown = msm_shutdown,
+};
+
 static struct snd_soc_ops msm_slimbus_4_be_ops = {
 	.startup = msm_startup,
 	.hw_params = msm_slimbus_4_hw_params,
@@ -1505,7 +1603,7 @@
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_rx2",
 		.no_pcm = 1,
-		/* .be_id = do not care */
+		.be_id = MSM_BACKEND_DAI_EXTPROC_RX,
 		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
 		.init = &msm_stubrx_init,
 		.ops = &msm_be_ops,
@@ -1518,7 +1616,7 @@
 		.codec_name = "tabla_codec",
 		.codec_dai_name = "tabla_tx1",
 		.no_pcm = 1,
-		/* .be_id = do not care */
+		.be_id = MSM_BACKEND_DAI_EXTPROC_TX,
 		.be_hw_params_fixup = msm_slim_0_tx_be_hw_params_fixup,
 		.ops = &msm_be_ops,
 	},
@@ -1588,6 +1686,36 @@
 		.init = &msm_incall_rec_init,
 		.ops = &msm_slimbus_4_be_ops,
 	},
+	{
+		.name = LPASS_BE_STUB_1_TX,
+		.stream_name = "Stub1 Capture",
+		.cpu_dai_name = "msm-dai-stub",
+		.platform_name = "msm-pcm-routing",
+		.codec_name     = "tabla_codec",
+		.codec_dai_name	= "tabla_tx3",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_EXTPROC_EC_TX,
+		/* This BE is used for external EC reference from codec. Since
+		 * Rx is fed as reference for EC, the config of this DAI is
+		 * based on that of the Rx path.
+		 */
+		.be_hw_params_fixup = msm_slim_0_rx_be_hw_params_fixup,
+		.ops = &msm_be_ops,
+	},
+	{
+
+		.name = LPASS_BE_SLIMBUS_3_RX,
+		.stream_name = "Slimbus3 Playback",
+		.cpu_dai_name = "msm-dai-q6.16390",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.init = &msm_slim_3_init,
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+		.be_hw_params_fixup = msm_slim_3_rx_be_hw_params_fixup,
+		.ops = &msm_slimbus_3_be_ops,
+	},
 };
 
 struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 28d192e..fb7756c 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -590,6 +590,7 @@
 
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
+	case SLIMBUS_3_RX:
 	case SLIMBUS_0_TX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
@@ -1117,6 +1118,7 @@
 	switch (dai->id) {
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
+	case SLIMBUS_3_RX:
 	case SLIMBUS_4_RX:
 		/* channel number to be between 128 and 255. For RX port
 		 * use channel numbers from 138 to 144, for TX port
@@ -1466,6 +1468,21 @@
 	.remove = msm_dai_q6_dai_remove,
 };
 
+static struct snd_soc_dai_driver msm_dai_q6_slimbus_3_rx_dai = {
+	.playback = {
+		.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
+		SNDRV_PCM_RATE_48000,
+		.formats = SNDRV_PCM_FMTBIT_S16_LE,
+		.channels_min = 1,
+		.channels_max = 2,
+		.rate_min = 8000,
+		.rate_max = 48000,
+	},
+	.ops = &msm_dai_q6_ops,
+	.probe = msm_dai_q6_dai_probe,
+	.remove = msm_dai_q6_dai_remove,
+};
+
 /* To do: change to register DAIs as batch */
 static __devinit int msm_dai_q6_dev_probe(struct platform_device *pdev)
 {
@@ -1512,6 +1529,10 @@
 		rc = snd_soc_register_dai(&pdev->dev,
 				&msm_dai_q6_slimbus_2_tx_dai);
 		break;
+	case SLIMBUS_3_RX:
+		rc = snd_soc_register_dai(&pdev->dev,
+				&msm_dai_q6_slimbus_3_rx_dai);
+		break;
 	case INT_BT_SCO_RX:
 		rc = snd_soc_register_dai(&pdev->dev,
 					&msm_dai_q6_bt_sco_rx_dai);
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 39ce436..ec0d947 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -333,21 +333,20 @@
 			kfree(prtd);
 			return -ENOMEM;
 		}
+
+		pr_debug("%s: session ID %d\n", __func__,
+			prtd->audio_client->session);
+		prtd->session_id = prtd->audio_client->session;
+		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
+		prtd->cmd_ack = 1;
+
 	}
 	/* Capture path */
 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
 		runtime->hw = msm_pcm_hardware_capture;
 	}
 
-	pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
-
-	prtd->session_id = prtd->audio_client->session;
-	msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
-			prtd->session_id, substream->stream);
-
-	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-		prtd->cmd_ack = 1;
-
 	ret = snd_pcm_hw_constraint_list(runtime, 0,
 				SNDRV_PCM_HW_PARAM_RATE,
 				&constraints_sample_rates);
@@ -619,6 +618,7 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_audio *prtd = runtime->private_data;
 	struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
 	struct audio_buffer *buf;
 	int dir, ret;
 	int format = FORMAT_LINEAR_PCM;
@@ -641,6 +641,12 @@
 			kfree(prtd);
 			return -ENOMEM;
 		}
+
+		pr_debug("%s: session ID %d\n", __func__,
+			prtd->audio_client->session);
+		prtd->session_id = prtd->audio_client->session;
+		msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+			prtd->session_id, substream->stream);
 	}
 
 	ret = q6asm_audio_client_buf_alloc_contiguous(dir,
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 4f0e952..02cc6ce 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -134,6 +134,9 @@
 	{ SLIMBUS_1_TX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_4_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_3_RX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
+	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 	{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
 };
 
@@ -150,6 +153,16 @@
 	{INVALID_SESSION, INVALID_SESSION},
 };
 
+static uint8_t is_be_dai_extproc(int be_dai)
+{
+	if (be_dai == MSM_BACKEND_DAI_EXTPROC_RX ||
+	    be_dai == MSM_BACKEND_DAI_EXTPROC_TX ||
+	    be_dai == MSM_BACKEND_DAI_EXTPROC_EC_TX)
+		return 1;
+	else
+		return 0;
+}
+
 static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
 	int path_type)
 {
@@ -161,7 +174,7 @@
 		MSM_AFE_PORT_TYPE_RX : MSM_AFE_PORT_TYPE_TX);
 
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		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)))
@@ -200,7 +213,7 @@
 
 	fe_dai_map[fedai_id][session_type] = dspst_id;
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		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))) {
@@ -243,7 +256,7 @@
 	if (eq_data[fedai_id].enable)
 		msm_send_eq_values(fedai_id);
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		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))) {
@@ -296,7 +309,7 @@
 	mutex_lock(&routing_lock);
 
 	for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
-		if ((i != MSM_BACKEND_DAI_EXTPROC_RX) &&
+		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)))
@@ -1166,6 +1179,12 @@
 	msm_routing_put_voice_stub_mixer),
 };
 
+static const struct snd_kcontrol_new slimbus_3_rx_mixer_controls[] = {
+	SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_SLIMBUS_3_RX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
+};
+
 static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
 	SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
 	MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1227,7 +1246,7 @@
 };
 
 static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
-	SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_RX,
+	SOC_SINGLE_EXT("STUB_TX_HL", MSM_BACKEND_DAI_EXTPROC_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
 	SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
@@ -1236,6 +1255,9 @@
 	SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_SLIMBUS_1_TX,
 	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
 	msm_routing_put_voice_stub_mixer),
+	SOC_SINGLE_EXT("STUB_1_TX_HL", MSM_BACKEND_DAI_EXTPROC_EC_TX,
+	MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+	msm_routing_put_voice_stub_mixer),
 };
 
 static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
@@ -1268,6 +1290,11 @@
 	msm_routing_put_port_mixer),
 };
 
+static const struct snd_kcontrol_new sbus_3_rx_port_mixer_controls[] = {
+	SOC_SINGLE_EXT("INTERNAL_BT_SCO_RX", MSM_BACKEND_DAI_SLIMBUS_3_RX,
+	MSM_BACKEND_DAI_INT_BT_SCO_RX, 1, 0, msm_routing_get_port_mixer,
+	msm_routing_put_port_mixer),
+};
 static const struct snd_kcontrol_new bt_sco_rx_port_mixer_controls[] = {
 	SOC_SINGLE_EXT("SLIM_1_TX", MSM_BACKEND_DAI_INT_BT_SCO_RX,
 	MSM_BACKEND_DAI_SLIMBUS_1_TX, 1, 0, msm_routing_get_port_mixer,
@@ -1580,6 +1607,8 @@
 	SND_SOC_DAPM_AIF_IN("STUB_TX", "Stub Capture", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0),
 	SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_IN("STUB_1_TX", "Stub1 Capture", 0, 0, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
 
 	/* Switch Definitions */
 	SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
@@ -1659,6 +1688,8 @@
 	stub_rx_mixer_controls, ARRAY_SIZE(stub_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_1_RX Mixer", SND_SOC_NOPM, 0, 0,
 	slimbus_1_rx_mixer_controls, ARRAY_SIZE(slimbus_1_rx_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SLIMBUS_3_RX_Voice Mixer", SND_SOC_NOPM, 0, 0,
+	slimbus_3_rx_mixer_controls, ARRAY_SIZE(slimbus_3_rx_mixer_controls)),
 	SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
 	SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
 	ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
@@ -1680,6 +1711,9 @@
 	SND_SOC_DAPM_MIXER("SEC_I2S_RX Port Mixer",
 	SND_SOC_NOPM, 0, 0, sec_i2s_rx_port_mixer_controls,
 	ARRAY_SIZE(sec_i2s_rx_port_mixer_controls)),
+	SND_SOC_DAPM_MIXER("SLIMBUS_3_RX Port Mixer",
+	SND_SOC_NOPM, 0, 0, sbus_3_rx_port_mixer_controls,
+	ARRAY_SIZE(sbus_3_rx_port_mixer_controls)),
 };
 
 static const struct snd_soc_dapm_route intercon[] = {
@@ -1845,6 +1879,7 @@
 	{"Voice Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
 	{"Voice Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+	{"Voice Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
 	{"VOICE_STUB_UL", NULL, "Voice Stub Tx Mixer"},
 
 	{"STUB_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
@@ -1853,10 +1888,16 @@
 	{"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Mixer"},
 	{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
 
+	{"SLIMBUS_3_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
+	{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX_Voice Mixer"},
+
 	{"SLIMBUS_1_RX Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
 	{"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Port Mixer"},
 	{"INTERNAL_BT_SCO_RX Port Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
 	{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Port Mixer"},
+	{"SLIMBUS_3_RX Port Mixer", "INTERNAL_BT_SCO_RX", "INT_BT_SCO_RX"},
+	{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX Port Mixer"},
+
 
 	{"HDMI_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
 	{"HDMI", NULL, "HDMI_RX Port Mixer"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index b7c7631..5f5c12a 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -37,7 +37,8 @@
 #define LPASS_BE_STUB_TX "(Backend) STUB_TX"
 #define LPASS_BE_SLIMBUS_1_RX "(Backend) SLIMBUS_1_RX"
 #define LPASS_BE_SLIMBUS_1_TX "(Backend) SLIMBUS_1_TX"
-
+#define LPASS_BE_STUB_1_TX "(Backend) STUB_1_TX"
+#define LPASS_BE_SLIMBUS_3_RX "(Backend) SLIMBUS_3_RX"
 #define LPASS_BE_SLIMBUS_4_RX "(Backend) SLIMBUS_4_RX"
 #define LPASS_BE_SLIMBUS_4_TX "(Backend) SLIMBUS_4_TX"
 
@@ -88,7 +89,10 @@
 	MSM_BACKEND_DAI_SLIMBUS_1_TX,
 	MSM_BACKEND_DAI_SLIMBUS_4_RX,
 	MSM_BACKEND_DAI_SLIMBUS_4_TX,
+	MSM_BACKEND_DAI_SLIMBUS_3_RX,
 	MSM_BACKEND_DAI_EXTPROC_RX,
+	MSM_BACKEND_DAI_EXTPROC_TX,
+	MSM_BACKEND_DAI_EXTPROC_EC_TX,
 	MSM_BACKEND_DAI_MAX,
 };
 
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index dc120b08..9f058b9 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -147,6 +147,7 @@
 	case HDMI_RX:
 	case SLIMBUS_0_RX:
 	case SLIMBUS_1_RX:
+	case SLIMBUS_3_RX:
 	case INT_BT_SCO_RX:
 	case INT_BT_A2DP_RX:
 	case INT_FM_RX:
@@ -206,6 +207,7 @@
 	case SLIMBUS_1_RX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_3_RX:
 	case INT_BT_SCO_RX:
 	case INT_BT_SCO_TX:
 	case INT_BT_A2DP_RX:
@@ -271,6 +273,7 @@
 	case SLIMBUS_1_RX: return IDX_SLIMBUS_1_RX;
 	case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
 	case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
+	case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
 	case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
 	case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -305,6 +308,7 @@
 	case SLIMBUS_1_RX:
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_3_RX:
 	case SLIMBUS_4_RX:
 	case SLIMBUS_4_TX:
 		ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);
@@ -676,7 +680,7 @@
 	return ret;
 }
 
-int afe_loopback(u16 enable, u16 rx_port, u16 tx_port)
+int afe_loopback(u16 enable, u16 dst_port, u16 src_port)
 {
 	struct afe_loopback_command lb_cmd;
 	int ret = 0;
@@ -685,6 +689,11 @@
 	if (ret != 0)
 		return ret;
 
+	if ((afe_get_port_type(dst_port) == MSM_AFE_PORT_TYPE_RX) &&
+		(afe_get_port_type(src_port) == MSM_AFE_PORT_TYPE_RX))
+		return afe_loopback_cfg(enable, dst_port, src_port,
+					LB_MODE_EC_REF_VOICE_AUDIO);
+
 	lb_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(20), APR_PKT_VER);
 	lb_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
@@ -693,8 +702,8 @@
 	lb_cmd.hdr.dest_port = 0;
 	lb_cmd.hdr.token = 0;
 	lb_cmd.hdr.opcode = AFE_PORT_CMD_LOOPBACK;
-	lb_cmd.tx_port_id = tx_port;
-	lb_cmd.rx_port_id = rx_port;
+	lb_cmd.tx_port_id = src_port;
+	lb_cmd.rx_port_id = dst_port;
 	lb_cmd.mode = 0xFFFF;
 	lb_cmd.enable = (enable ? 1 : 0);
 	atomic_set(&this_afe.state, 1);
@@ -716,6 +725,63 @@
 	return ret;
 }
 
+int afe_loopback_cfg(u16 enable, u16 dst_port, u16 src_port, u16 mode)
+{
+	struct afe_port_cmd_set_param lp_cfg;
+	int ret = 0;
+
+	ret = afe_q6_interface_prepare();
+	if (ret != 0)
+		return ret;
+
+	pr_debug("%s: src_port %d, dst_port %d\n",
+		  __func__, src_port, dst_port);
+
+	lp_cfg.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+				APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+	lp_cfg.hdr.pkt_size = sizeof(lp_cfg);
+	lp_cfg.hdr.src_port = 0;
+	lp_cfg.hdr.dest_port = 0;
+	lp_cfg.hdr.token = 0;
+	lp_cfg.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
+
+	lp_cfg.port_id = src_port;
+	lp_cfg.payload_size	= sizeof(struct afe_param_payload);
+	lp_cfg.payload_address	= 0;
+
+	lp_cfg.payload.module_id = AFE_MODULE_LOOPBACK;
+	lp_cfg.payload.param_id	= AFE_PARAM_ID_LOOPBACK_CONFIG;
+	lp_cfg.payload.param_size = sizeof(struct afe_param_loopback_cfg);
+	lp_cfg.payload.reserved	= 0;
+
+	lp_cfg.payload.param.loopback_cfg.loopback_cfg_minor_version =
+			AFE_API_VERSION_LOOPBACK_CONFIG;
+	lp_cfg.payload.param.loopback_cfg.dst_port_id = dst_port;
+	lp_cfg.payload.param.loopback_cfg.routing_mode = mode;
+	lp_cfg.payload.param.loopback_cfg.enable = enable;
+	lp_cfg.payload.param.loopback_cfg.reserved = 0;
+
+	atomic_set(&this_afe.state, 1);
+	ret = apr_send_pkt(this_afe.apr, (uint32_t *) &lp_cfg);
+	if (ret < 0) {
+		pr_err("%s: AFE loopback config failed for src_port %d, dst_port %d\n",
+			   __func__, src_port, dst_port);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+
+	ret = wait_event_timeout(this_afe.wait,
+		(atomic_read(&this_afe.state) == 0),
+			msecs_to_jiffies(TIMEOUT_MS));
+	if (ret < 0) {
+		pr_err("%s: wait_event timeout\n", __func__);
+		ret = -EINVAL;
+		goto fail_cmd;
+	}
+	return 0;
+fail_cmd:
+	return ret;
+}
 
 int afe_loopback_gain(u16 port_id, u16 volume)
 {