Merge "defconfig: msm8960: Enable PRIO qdisc and class FW for MSM8960" into msm-3.0
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 3763bc1..50b4b08 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -23,7 +23,7 @@
 CONFIG_ASHMEM=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
+CONFIG_OPROFILE=y
 CONFIG_KPROBES=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -37,6 +37,8 @@
 CONFIG_MACH_MSM8X60_SURF=y
 CONFIG_MACH_MSM8X60_FFA=y
 CONFIG_MACH_MSM8X60_FLUID=y
+CONFIG_MACH_MSM8X60_FUSION=y
+CONFIG_MACH_MSM8X60_FUSN_FFA=y
 CONFIG_MACH_MSM8X60_DRAGON=y
 CONFIG_MSM7X00A_USE_DG_TIMER=y
 CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE=y
@@ -44,15 +46,20 @@
 # CONFIG_MSM_FIQ_SUPPORT is not set
 # CONFIG_MSM_PROC_COMM is not set
 CONFIG_MSM_SMD=y
+CONFIG_MSM_SDIO_DMUX=y
 # CONFIG_MSM_RESET_MODEM is not set
 # CONFIG_MSM_SMD_NMEA is not set
+CONFIG_MSM_SDIO_TTY=y
 # CONFIG_MSM_SMD_QMI is not set
+CONFIG_MSM_SDIO_CMUX=y
 CONFIG_MSM_DSPS=y
+CONFIG_MSM_SDIO_CTL=y
 CONFIG_MSM_ONCRPCROUTER=y
 # CONFIG_MSM_RPCSERVER_TIME_REMOTE is not set
 # CONFIG_MSM_RPCSERVER_WATCHDOG is not set
 # CONFIG_MSM_RPCSERVER_HANDSET is not set
 CONFIG_MSM_RMT_STORAGE_CLIENT=y
+CONFIG_MSM_SDIO_SMEM=y
 # CONFIG_MSM_HW3D is not set
 CONFIG_MSM_PIL_MODEM=y
 CONFIG_MSM_PIL_QDSP6V3=y
@@ -74,7 +81,8 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_VMALLOC_RESERVE=0x10000000
+CONFIG_VMALLOC_RESERVE=0x19000000
+CONFIG_CP_ACCESS=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
@@ -256,6 +264,7 @@
 CONFIG_SLIP=y
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_MSM_RMNET_SDIO=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_INPUT_KEYRESET=y
@@ -275,6 +284,7 @@
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
 CONFIG_DCC_TTY=y
@@ -300,6 +310,7 @@
 CONFIG_BATTERY_BQ27541=y
 CONFIG_SENSORS_MSM_ADC=y
 CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
 CONFIG_THERMAL_TSENS=y
 CONFIG_THERMAL_PM8XXX=y
 CONFIG_PMIC8058=y
@@ -317,6 +328,8 @@
 CONFIG_MT9E013=y
 CONFIG_MSM_GEMINI=y
 CONFIG_RADIO_TAVARUA=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
@@ -335,7 +348,6 @@
 CONFIG_SND=y
 CONFIG_SND_USB_AUDIO=y
 CONFIG_SND_SOC=y
-CONFIG_MSM_8x60_VOIP=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
@@ -344,8 +356,9 @@
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
 # CONFIG_USB_EHCI_TT_NEWSCHED is not set
-CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_72K=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -362,7 +375,9 @@
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MSM_72K=y
-CONFIG_USB_MSM_ACA=y
+CONFIG_USB_G_ANDROID=y
+CONFIG_RMNET_SMD_CTL_CHANNEL="DATA40_CNTL"
+CONFIG_RMNET_SMD_DATA_CHANNEL="DATA40"
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_UNSAFE_RESUME=y
@@ -427,7 +442,6 @@
 CONFIG_TIMER_STATS=y
 CONFIG_SLUB_DEBUG_ON=y
 # CONFIG_DEBUG_PREEMPT is not set
-CONFIG_PROVE_LOCKING=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index e52884f..ab28645 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -1215,7 +1215,7 @@
 	return NOTIFY_DONE;
 }
 
-static void bam_init(void)
+static int bam_init(void)
 {
 	u32 h;
 	dma_addr_t dma_addr;
@@ -1351,7 +1351,7 @@
 	toggle_apps_ack();
 	bam_connection_is_active = 1;
 	complete_all(&bam_connection_completion);
-	return;
+	return 0;
 
 rx_event_reg_failed:
 	sps_disconnect(bam_rx_pipe);
@@ -1371,8 +1371,45 @@
 	sps_deregister_bam_device(h);
 register_bam_failed:
 	/*destroy_workqueue(bam_mux_workqueue);*/
-	/*return ret;*/
-	return;
+	return ret;
+}
+
+static int bam_init_fallback(void)
+{
+	u32 h;
+	int ret;
+	void *a2_virt_addr;
+
+	unvote_dfab();
+	/* init BAM */
+	a2_virt_addr = ioremap_nocache(A2_PHYS_BASE, A2_PHYS_SIZE);
+	if (!a2_virt_addr) {
+		pr_err("%s: ioremap failed\n", __func__);
+		ret = -ENOMEM;
+		goto ioremap_failed;
+	}
+	a2_props.phys_addr = A2_PHYS_BASE;
+	a2_props.virt_addr = a2_virt_addr;
+	a2_props.virt_size = A2_PHYS_SIZE;
+	a2_props.irq = A2_BAM_IRQ;
+	a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
+	a2_props.num_pipes = A2_NUM_PIPES;
+	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
+	if (cpu_is_msm9615())
+		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
+	ret = sps_register_bam_device(&a2_props, &h);
+	if (ret < 0) {
+		pr_err("%s: register bam error %d\n", __func__, ret);
+		goto register_bam_failed;
+	}
+	a2_device_handle = h;
+
+	return 0;
+
+register_bam_failed:
+	iounmap(a2_virt_addr);
+ioremap_failed:
+	return ret;
 }
 
 static void toggle_apps_ack(void)
@@ -1387,6 +1424,7 @@
 
 static void bam_dmux_smsm_cb(void *priv, uint32_t old_state, uint32_t new_state)
 {
+	int ret = 0;
 	pr_info("%s: smsm activity 0x%08x -> 0x%08x\n", __func__, old_state,
 							new_state);
 	if (bam_mux_initialized && new_state & SMSM_A2_POWER_CONTROL) {
@@ -1401,7 +1439,13 @@
 	} else if (new_state & SMSM_A2_POWER_CONTROL) {
 		pr_info("%s: init\n", __func__);
 		wake_lock(&bam_wakelock);
-		bam_init();
+		ret = bam_init();
+		if (ret) {
+			ret = bam_init_fallback();
+			if (ret)
+				pr_err("%s: bam init fallback failed: %d",
+						__func__, ret);
+		}
 	} else {
 		pr_err("%s: unsupported state change\n", __func__);
 	}
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 50673b4..3075e07 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -56,6 +56,12 @@
 };
 #endif
 
+static struct gpiomux_setting cdc_mclk = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
 static struct gpiomux_setting audio_auxpcm[] = {
 	/* Suspended state */
 	{
@@ -71,6 +77,12 @@
 	},
 };
 
+static struct gpiomux_setting slimbus = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_KEEPER,
+};
+
 static struct msm_gpiomux_config apq8064_gsbi_configs[] __initdata = {
 #if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	{
@@ -100,6 +112,30 @@
 #endif
 };
 
+static struct msm_gpiomux_config apq8064_slimbus_config[] __initdata = {
+	{
+		.gpio   = 40,           /* slimbus clk */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &slimbus,
+		},
+	},
+	{
+		.gpio   = 41,           /* slimbus data */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &slimbus,
+		},
+	},
+};
+
+static struct msm_gpiomux_config apq8064_audio_codec_configs[] __initdata = {
+	{
+		.gpio = 39,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &cdc_mclk,
+		},
+	},
+};
+
 static struct msm_gpiomux_config apq8064_audio_auxpcm_configs[] __initdata = {
 	{
 		.gpio = 43,
@@ -149,6 +185,12 @@
 	msm_gpiomux_install(apq8064_gsbi_configs,
 			ARRAY_SIZE(apq8064_gsbi_configs));
 
+	msm_gpiomux_install(apq8064_slimbus_config,
+			ARRAY_SIZE(apq8064_slimbus_config));
+
+	msm_gpiomux_install(apq8064_audio_codec_configs,
+			ARRAY_SIZE(apq8064_audio_codec_configs));
+
 	msm_gpiomux_install(apq8064_audio_auxpcm_configs,
 			ARRAY_SIZE(apq8064_audio_auxpcm_configs));
 }
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d6532d5..f14381d 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -234,7 +234,7 @@
 		.name = "tabla-slave",
 		.e_addr = {0, 0, 0x10, 0, 0x17, 2},
 	},
-	.irq = MSM_GPIO_TO_INT(62),
+	.irq = MSM_GPIO_TO_INT(42),
 	.irq_base = TABLA_INTERRUPT_BASE,
 	.num_irqs = NR_TABLA_IRQS,
 	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
@@ -258,6 +258,35 @@
 	},
 };
 
+static struct tabla_pdata apq8064_tabla20_platform_data = {
+	.slimbus_slave_device = {
+		.name = "tabla-slave",
+		.e_addr = {0, 0, 0x60, 0, 0x17, 2},
+	},
+	.irq = MSM_GPIO_TO_INT(42),
+	.irq_base = TABLA_INTERRUPT_BASE,
+	.num_irqs = NR_TABLA_IRQS,
+	.reset_gpio = PM8921_GPIO_PM_TO_SYS(34),
+	.micbias = {
+		.ldoh_v = TABLA_LDOH_2P85_V,
+		.cfilt1_mv = 1800,
+		.cfilt2_mv = 1800,
+		.cfilt3_mv = 1800,
+		.bias1_cfilt_sel = TABLA_CFILT1_SEL,
+		.bias2_cfilt_sel = TABLA_CFILT2_SEL,
+		.bias3_cfilt_sel = TABLA_CFILT3_SEL,
+		.bias4_cfilt_sel = TABLA_CFILT3_SEL,
+	}
+};
+
+static struct slim_device apq8064_slim_tabla20 = {
+	.name = "tabla2x-slim",
+	.e_addr = {0, 1, 0x60, 0, 0x17, 2},
+	.dev = {
+		.platform_data = &apq8064_tabla20_platform_data,
+	},
+};
+
 #if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
 		defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
 		defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -510,8 +539,12 @@
 
 static struct slim_boardinfo apq8064_slim_devices[] = {
 	{
-	.bus_num = 1,
-	.slim_slave = &apq8064_slim_tabla,
+		.bus_num = 1,
+		.slim_slave = &apq8064_slim_tabla,
+	},
+	{
+		.bus_num = 1,
+		.slim_slave = &apq8064_slim_tabla20,
 	},
 	/* add more slimbus slaves as needed */
 };
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index c1b880c..afd79f4 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -22,6 +22,9 @@
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
 #include <mach/socinfo.h>
+#include <linux/ion.h>
+#include <mach/ion.h>
+
 #include "devices.h"
 
 /* TODO: Remove this once PM8038 physically becomes
@@ -435,19 +438,23 @@
 	.mdp_bus_scale_table = &mdp_bus_scale_pdata,
 #endif
 	.mdp_rev = MDP_REV_42,
-	.mdp_writeback_memtype = MEMTYPE_EBI1,
-	.mdp_writeback_phys = NULL,
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.mem_hid = ION_CP_MM_HEAP_ID,
+#else
+	.mem_hid = MEMTYPE_EBI1,
+#endif
 };
 
 void __init msm8930_mdp_writeback(struct memtype_reserve* reserve_table)
 {
-	mdp_pdata.mdp_writeback_size_ov0 = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
-	mdp_pdata.mdp_writeback_size_ov1 = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
-
-	reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
-		mdp_pdata.mdp_writeback_size_ov0;
-	reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
-		mdp_pdata.mdp_writeback_size_ov1;
+	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
+	mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
+#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov0_wb_size;
+	reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov1_wb_size;
+#endif
 }
 
 #define LPM_CHANNEL0 0
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index d39f64e..c2592ae 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -127,12 +127,13 @@
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0xB0C000
-#define MSM_ION_EBI_SIZE	(MSM_PMEM_SIZE + 0x600000)
-#define MSM_ION_ADSP_SIZE	MSM_PMEM_ADSP_SIZE
-#define MSM_ION_HEAP_NUM	4
+#define MSM_ION_SF_SIZE		0x1800000 /* 24MB */
+#define MSM_ION_MM_SIZE		0x4000000 /* (64MB) */
+#define MSM_ION_MFC_SIZE	SZ_8K
+#define MSM_ION_HEAP_NUM	5
 #else
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
-#define MSM_ION_HEAP_NUM	2
+#define MSM_ION_HEAP_NUM	1
 #endif
 
 #ifdef CONFIG_KERNEL_PMEM_EBI_REGION
@@ -284,30 +285,37 @@
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
 		{
-			.id	= ION_HEAP_SYSTEM_ID,
+			.id	= ION_SYSTEM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_SYSTEM,
-			.name	= ION_KMALLOC_HEAP_NAME,
-		},
-		{
-			.id	= ION_HEAP_SYSTEM_CONTIG_ID,
-			.type	= ION_HEAP_TYPE_SYSTEM_CONTIG,
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_HEAP_EBI_ID,
+			.id	= ION_SF_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_EBI1_HEAP_NAME,
-			.size	= MSM_ION_EBI_SIZE,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
 			.memory_type = ION_EBI_TYPE,
 		},
 		{
-			.id	= ION_HEAP_ADSP_ID,
+			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_ADSP_HEAP_NAME,
-			.size	= MSM_ION_ADSP_SIZE,
+			.name	= ION_MM_HEAP_NAME,
+			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_EBI_TYPE,
 		},
+		{
+			.id	= ION_CP_MFC_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_MFC_HEAP_NAME,
+			.size	= MSM_ION_MFC_SIZE,
+			.memory_type = ION_EBI_TYPE,
+		},
+		{
+			.id	= ION_IOMMU_HEAP_ID,
+			.type	= ION_HEAP_TYPE_IOMMU,
+			.name	= ION_IOMMU_HEAP_NAME,
+		},
 #endif
 	}
 };
@@ -322,8 +330,9 @@
 static void reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_EBI_SIZE;
-	msm8930_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
+	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_MFC_SIZE;
 #endif
 }
 
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index 3bc9f0f..69519f0 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -21,6 +21,9 @@
 #include <mach/board.h>
 #include <mach/gpio.h>
 #include <mach/gpiomux.h>
+#include <linux/ion.h>
+#include <mach/ion.h>
+
 #include "devices.h"
 #include "board-8960.h"
 
@@ -550,19 +553,23 @@
 	.mdp_bus_scale_table = &mdp_bus_scale_pdata,
 #endif
 	.mdp_rev = MDP_REV_42,
-	.mdp_writeback_memtype = MEMTYPE_EBI1,
-	.mdp_writeback_phys = NULL,
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.mem_hid = ION_CP_MM_HEAP_ID,
+#else
+	.mem_hid = MEMTYPE_EBI1,
+#endif
 };
 
 void __init msm8960_mdp_writeback(struct memtype_reserve* reserve_table)
 {
-	mdp_pdata.mdp_writeback_size_ov0 = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
-	mdp_pdata.mdp_writeback_size_ov1 = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
-
-	reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
-		mdp_pdata.mdp_writeback_size_ov0;
-	reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
-		mdp_pdata.mdp_writeback_size_ov1;
+	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
+	mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
+#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov0_wb_size;
+	reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov1_wb_size;
+#endif
 }
 
 static struct platform_device mipi_dsi_renesas_panel_device = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index a9424d6..109ab9c 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -141,14 +141,15 @@
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0xB0C000
-#define MSM_ION_EBI_SIZE	(MSM_PMEM_SIZE + 0x600000)
-#define MSM_ION_ADSP_SIZE	MSM_PMEM_ADSP_SIZE
+#define MSM_ION_SF_SIZE		0x1800000 /* 24MB */
+#define MSM_ION_MM_SIZE		0x4000000 /* (64MB) */
+#define MSM_ION_MFC_SIZE	SZ_8K
 #define MSM_ION_HEAP_NUM	5
-#define MSM_LIQUID_ION_EBI_SIZE (MSM_LIQUID_PMEM_SIZE + 0x600000)
-static unsigned msm_ion_ebi_size = MSM_ION_EBI_SIZE;
+#define MSM_LIQUID_ION_MM_SIZE (MSM_ION_MM_SIZE + 0x600000)
+static unsigned int msm_ion_cp_mm_size = MSM_ION_MM_SIZE;
 #else
 #define MSM_PMEM_KERNEL_EBI1_SIZE  0x110C000
-#define MSM_ION_HEAP_NUM	2
+#define MSM_ION_HEAP_NUM	1
 #endif
 
 #ifdef CONFIG_KERNEL_PMEM_EBI_REGION
@@ -312,32 +313,34 @@
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
 		{
-			.id	= ION_HEAP_SYSTEM_ID,
+			.id	= ION_SYSTEM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_SYSTEM,
-			.name	= ION_KMALLOC_HEAP_NAME,
-		},
-		{
-			.id	= ION_HEAP_SYSTEM_CONTIG_ID,
-			.type	= ION_HEAP_TYPE_SYSTEM_CONTIG,
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_HEAP_EBI_ID,
+			.id	= ION_SF_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_EBI1_HEAP_NAME,
-			.size	= MSM_ION_EBI_SIZE,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
 			.memory_type = ION_EBI_TYPE,
 		},
 		{
-			.id	= ION_HEAP_ADSP_ID,
+			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_ADSP_HEAP_NAME,
-			.size	= MSM_ION_ADSP_SIZE,
+			.name	= ION_MM_HEAP_NAME,
+			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_EBI_TYPE,
 		},
 		{
-			.id	= ION_HEAP_IOMMU_ID,
+			.id	= ION_CP_MFC_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_MFC_HEAP_NAME,
+			.size	= MSM_ION_MFC_SIZE,
+			.memory_type = ION_EBI_TYPE,
+		},
+		{
+			.id	= ION_IOMMU_HEAP_ID,
 			.type	= ION_HEAP_TYPE_IOMMU,
 			.name	= ION_IOMMU_HEAP_NAME,
 		},
@@ -364,18 +367,19 @@
 	unsigned int i;
 
 	if (!pmem_param_set && machine_is_msm8960_liquid()) {
-		msm_ion_ebi_size = MSM_LIQUID_ION_EBI_SIZE;
+		msm_ion_cp_mm_size = MSM_LIQUID_ION_MM_SIZE;
 		for (i = 0; i < ion_pdata.nr; i++) {
-			if (ion_pdata.heaps[i].id == ION_HEAP_EBI_ID) {
-				ion_pdata.heaps[i].size = msm_ion_ebi_size;
-				pr_debug("msm_ion_ebi_size 0x%x\n",
-					msm_ion_ebi_size);
+			if (ion_pdata.heaps[i].id == ION_CP_MM_HEAP_ID) {
+				ion_pdata.heaps[i].size = msm_ion_cp_mm_size;
+				pr_debug("msm_ion_cp_mm_size 0x%x\n",
+					msm_ion_cp_mm_size);
 				break;
 			}
 		}
 	}
-	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_ion_ebi_size;
-	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
+	msm8960_reserve_table[MEMTYPE_EBI1].size += msm_ion_cp_mm_size;
+	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
+	msm8960_reserve_table[MEMTYPE_EBI1].size += MSM_ION_MFC_SIZE;
 #endif
 }
 
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index ec2a71d..7259603 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -334,6 +334,7 @@
 	.phy_type		= SNPS_28NM_INTEGRATED_PHY,
 	.pclk_src_name	= "dfab_usb_hs_clk",
 	.vbus_power		= msm_hsusb_vbus_power,
+	.disable_reset_on_disconnect	= true,
 };
 
 static int usb_diag_update_pid_and_serial_num(uint32_t pid, const char *snum)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index ba7e658..d0fe8f9 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -2671,14 +2671,16 @@
 #define USER_SMI_SIZE         (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
 #define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
 
-#define MSM_ION_EBI_SIZE        MSM_PMEM_SF_SIZE
-#define MSM_ION_ADSP_SIZE       MSM_PMEM_ADSP_SIZE
-#define MSM_ION_SMI_SIZE	MSM_PMEM_SMIPOOL_SIZE
+#define MSM_ION_SF_SIZE		0x1800000 /* 24MB */
+#define MSM_ION_CAMERA_SIZE     MSM_PMEM_ADSP_SIZE
+#define MSM_ION_MM_SIZE		0x3800000 /* 56MB */
+#define MSM_ION_MFC_SIZE	SZ_8K
+#define MSM_ION_WB_SIZE		0x600000 /* 6MB */
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-#define MSM_ION_HEAP_NUM	5
+#define MSM_ION_HEAP_NUM	6
 #else
-#define MSM_ION_HEAP_NUM	2
+#define MSM_ION_HEAP_NUM	1
 #endif
 
 static unsigned fb_size;
@@ -5242,40 +5244,52 @@
 	.nr = MSM_ION_HEAP_NUM,
 	.heaps = {
 		{
-			.id	= ION_HEAP_SYSTEM_ID,
+			.id	= ION_SYSTEM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_SYSTEM,
 			.name	= ION_VMALLOC_HEAP_NAME,
 		},
-		{
-			.id	= ION_HEAP_SYSTEM_CONTIG_ID,
-			.type	= ION_HEAP_TYPE_SYSTEM_CONTIG,
-			.name	= ION_KMALLOC_HEAP_NAME,
-		},
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		{
-			.id	= ION_HEAP_EBI_ID,
+			.id	= ION_SF_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_EBI1_HEAP_NAME,
-			.size	= MSM_ION_EBI_SIZE,
+			.name	= ION_SF_HEAP_NAME,
+			.size	= MSM_ION_SF_SIZE,
 			.memory_type = ION_EBI_TYPE,
 		},
 		{
-			.id	= ION_HEAP_ADSP_ID,
+			.id	= ION_CP_MM_HEAP_ID,
 			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_ADSP_HEAP_NAME,
-			.size	= MSM_ION_ADSP_SIZE,
-			.memory_type = ION_EBI_TYPE,
-		},
-		{
-			.id	= ION_HEAP_SMI_ID,
-			.type	= ION_HEAP_TYPE_CARVEOUT,
-			.name	= ION_SMI_HEAP_NAME,
-			.size	= MSM_ION_SMI_SIZE,
+			.name	= ION_MM_HEAP_NAME,
+			.size	= MSM_ION_MM_SIZE,
 			.memory_type = ION_SMI_TYPE,
 			.request_region = request_smi_region,
 			.release_region = release_smi_region,
 			.setup_region = setup_smi_region,
 		},
+		{
+			.id	= ION_CAMERA_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_CAMERA_HEAP_NAME,
+			.size	= MSM_ION_CAMERA_SIZE,
+			.memory_type = ION_EBI_TYPE,
+		},
+		{
+			.id	= ION_CP_MFC_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_MFC_HEAP_NAME,
+			.size	= MSM_ION_MFC_SIZE,
+			.memory_type = ION_SMI_TYPE,
+			.request_region = request_smi_region,
+			.release_region = release_smi_region,
+			.setup_region = setup_smi_region,
+		},
+		{
+			.id	= ION_CP_WB_HEAP_ID,
+			.type	= ION_HEAP_TYPE_CARVEOUT,
+			.name	= ION_WB_HEAP_NAME,
+			.size	= MSM_ION_WB_SIZE,
+			.memory_type = ION_EBI_TYPE,
+		},
 #endif
 	}
 };
@@ -5318,9 +5332,11 @@
 static void reserve_ion_memory(void)
 {
 #if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
-	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_EBI_SIZE;
-	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_ADSP_SIZE;
-	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_SMI_SIZE;
+	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
+	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_SIZE;
+	msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MFC_SIZE;
+	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE;
+	msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_WB_SIZE;
 #endif
 }
 
@@ -9429,19 +9445,23 @@
 	.mdp_bus_scale_table = &mdp_bus_scale_pdata,
 #endif
 	.mdp_rev = MDP_REV_41,
-	.mdp_writeback_memtype = MEMTYPE_EBI1,
-	.mdp_writeback_phys = NULL,
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	.mem_hid = ION_CP_WB_HEAP_ID,
+#else
+	.mem_hid = MEMTYPE_EBI1,
+#endif
 };
 
 static void __init reserve_mdp_memory(void)
 {
-	mdp_pdata.mdp_writeback_size_ov0 = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
-	mdp_pdata.mdp_writeback_size_ov1 = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
-
-	msm8x60_reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
-		mdp_pdata.mdp_writeback_size_ov0;
-	msm8x60_reserve_table[mdp_pdata.mdp_writeback_memtype].size +=
-		mdp_pdata.mdp_writeback_size_ov1;
+	mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
+	mdp_pdata.ov1_wb_size = MSM_FB_OVERLAY1_WRITEBACK_SIZE;
+#if defined(CONFIG_ANDROID_PMEM) && !defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
+	msm8x60_reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov0_wb_size;
+	msm8x60_reserve_table[mdp_pdata.mem_hid].size +=
+		mdp_pdata.ov1_wb_size;
+#endif
 }
 
 #ifdef CONFIG_FB_MSM_TVOUT
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 26bb7ae..a4466ca 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -564,7 +564,7 @@
 	.vidc_bus_client_pdata = &vidc_bus_client_data,
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	.memtype = ION_HEAP_EBI_ID,
+	.memtype = ION_CP_MM_HEAP_ID,
 	.enable_ion = 1,
 #else
 	.memtype = MEMTYPE_EBI1,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 5b500a3..0d3abb6 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -737,7 +737,6 @@
 	[20] = MSM_GPIO_TO_INT(28),
 	[23] = MSM_GPIO_TO_INT(19),
 	[24] = MSM_GPIO_TO_INT(23),
-	[25] = USB1_HS_IRQ,
 	[26] = MSM_GPIO_TO_INT(3),
 	[27] = MSM_GPIO_TO_INT(68),
 	[29] = MSM_GPIO_TO_INT(78),
@@ -747,6 +746,7 @@
 	[34] = MSM_GPIO_TO_INT(17),
 	[37] = MSM_GPIO_TO_INT(20),
 	[39] = MSM_GPIO_TO_INT(84),
+	[40] = USB1_HS_IRQ,
 	[42] = MSM_GPIO_TO_INT(24),
 	[43] = MSM_GPIO_TO_INT(79),
 	[44] = MSM_GPIO_TO_INT(80),
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 8f1709b..4023332 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -2151,7 +2151,7 @@
 	.vidc_bus_client_pdata = &vidc_bus_client_data,
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	.memtype = ION_HEAP_SMI_ID,
+	.memtype = ION_CP_MM_HEAP_ID,
 	.enable_ion = 1,
 #else
 	.memtype = MEMTYPE_SMI_KERNEL,
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index ae68036..e598367 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -1,7 +1,7 @@
 /* arch/arm/mach-msm/include/mach/board.h
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -316,10 +316,9 @@
 	struct msm_bus_scale_pdata *mdp_bus_scale_table;
 #endif
 	int mdp_rev;
-	int mdp_writeback_memtype;
-	void *mdp_writeback_phys;    /* writeback physical addr */
-	int mdp_writeback_size_ov0;  /* overlay0 writeback size */
-	int mdp_writeback_size_ov1;  /* overlay1 writeback size */
+	u32 ov0_wb_size;  /* overlay0 writeback size */
+	u32 ov1_wb_size;  /* overlay1 writeback size */
+	u32 mem_hid;
 };
 
 
diff --git a/arch/arm/mach-msm/include/mach/diag_bridge.h b/arch/arm/mach-msm/include/mach/diag_bridge.h
index 281a1a6..a39ed25 100644
--- a/arch/arm/mach-msm/include/mach/diag_bridge.h
+++ b/arch/arm/mach-msm/include/mach/diag_bridge.h
@@ -16,27 +16,27 @@
 struct diag_bridge_ops {
 	void *ctxt;
 	void (*read_complete_cb)(void *ctxt, char *buf,
-			size_t buf_size, size_t actual);
+			int buf_size, int actual);
 	void (*write_complete_cb)(void *ctxt, char *buf,
-			size_t buf_size, size_t actual);
+			int buf_size, int actual);
 };
 
 #if defined(CONFIG_USB_QCOM_DIAG_BRIDGE) \
 	|| defined(CONFIG_USB_QCOM_DIAG_BRIDGE_MODULE)
 
-extern int diag_bridge_read(char *data, size_t size);
-extern int diag_bridge_write(char *data, size_t size);
+extern int diag_bridge_read(char *data, int size);
+extern int diag_bridge_write(char *data, int size);
 extern int diag_bridge_open(struct diag_bridge_ops *ops);
 extern void diag_bridge_close(void);
 
 #else
 
-static int __maybe_unused diag_bridge_read(char *data, size_t size)
+static int __maybe_unused diag_bridge_read(char *data, int size)
 {
 	return -ENODEV;
 }
 
-static int __maybe_unused diag_bridge_write(char *data, size_t size)
+static int __maybe_unused diag_bridge_write(char *data, int size)
 {
 	return -ENODEV;
 }
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index ef2956a..a8d787a 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -30,6 +30,7 @@
 #include <asm/hardware/gic.h>
 #include <mach/msm_iomap.h>
 #include <mach/rpm.h>
+#include <mach/socinfo.h>
 
 /******************************************************************************
  * Data type and structure definitions
@@ -64,7 +65,6 @@
 static LIST_HEAD(msm_rpm_notifications);
 static struct msm_rpm_notif_config msm_rpm_notif_cfgs[MSM_RPM_CTX_SET_COUNT];
 static bool msm_rpm_init_notif_done;
-
 /******************************************************************************
  * Internal functions
  *****************************************************************************/
@@ -380,6 +380,7 @@
  *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
  *   -ENOSPC: request rejected
+ *   -ENODEV: RPM driver not initialized
  */
 static int msm_rpm_set_common(
 	int ctx, struct msm_rpm_iv_pair *req, int count, bool noirq)
@@ -387,6 +388,13 @@
 	uint32_t sel_masks[MSM_RPM_SEL_MASK_SIZE] = {};
 	int rc;
 
+	if (!msm_rpm_platform) {
+		if (cpu_is_apq8064())
+			return 0;
+		else
+			return -ENODEV;
+	}
+
 	if (ctx >= MSM_RPM_CTX_SET_COUNT) {
 		rc = -EINVAL;
 		goto set_common_exit;
@@ -420,6 +428,7 @@
  *   0: success
  *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
+ *   -ENODEV: RPM driver not initialized.
  */
 static int msm_rpm_clear_common(
 	int ctx, struct msm_rpm_iv_pair *req, int count, bool noirq)
@@ -429,6 +438,13 @@
 	int rc;
 	int i;
 
+	if (!msm_rpm_platform) {
+		if (cpu_is_apq8064())
+			return 0;
+		else
+			return -ENODEV;
+	}
+
 	if (ctx >= MSM_RPM_CTX_SET_COUNT) {
 		rc = -EINVAL;
 		goto clear_common_exit;
@@ -556,6 +572,7 @@
  *   -EBUSY: RPM is updating the status page; values across different registers
  *           may not be consistent
  *   -EINVAL: invalid id in <status> array
+ *   -ENODEV: RPM driver not initialized
  */
 int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count)
 {
@@ -564,6 +581,13 @@
 	int rc;
 	int i;
 
+	if (!msm_rpm_platform) {
+		if (cpu_is_apq8064())
+			return 0;
+		else
+			return -ENODEV;
+	}
+
 	seq_begin = msm_rpm_read(MSM_RPM_PAGE_STATUS,
 				MSM_RPM_STATUS_ID_SEQUENCE);
 
@@ -609,6 +633,7 @@
  *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
  *   -ENOSPC: request rejected
+ *   -ENODEV: RPM driver not initialized
  */
 int msm_rpm_set(int ctx, struct msm_rpm_iv_pair *req, int count)
 {
@@ -693,6 +718,7 @@
  *   0: success
  *   -EINTR: interrupted
  *   -EINVAL: invalid id in <req> array
+ *   -ENODEV: RPM driver not initialized
  */
 int msm_rpm_register_notification(struct msm_rpm_notification *n,
 	struct msm_rpm_iv_pair *req, int count)
@@ -703,6 +729,13 @@
 	int rc;
 	int i;
 
+	if (!msm_rpm_platform) {
+		if (cpu_is_apq8064())
+			return 0;
+		else
+			return -ENODEV;
+	}
+
 	INIT_LIST_HEAD(&n->list);
 	rc = msm_rpm_fill_sel_masks(n->sel_masks, req, count);
 	if (rc)
@@ -745,6 +778,7 @@
  * Return value:
  *   0: success
  *   -EINTR: interrupted
+ *   -ENODEV: RPM driver not initialized
  */
 int msm_rpm_unregister_notification(struct msm_rpm_notification *n)
 {
@@ -754,6 +788,13 @@
 	int rc;
 	int i;
 
+	if (!msm_rpm_platform) {
+		if (cpu_is_apq8064())
+			return 0;
+		else
+			return -ENODEV;
+	}
+
 	rc = mutex_lock_interruptible(&msm_rpm_mutex);
 	if (rc)
 		goto unregister_notification_exit;
@@ -848,6 +889,9 @@
 	unsigned int irq;
 	int rc;
 
+	if (cpu_is_apq8064())
+		return 0;
+
 	msm_rpm_platform = data;
 
 	fw_major = msm_rpm_read(MSM_RPM_PAGE_STATUS,
diff --git a/arch/arm/mach-msm/smd_debug.c b/arch/arm/mach-msm/smd_debug.c
index 6171c92..b95a35c 100644
--- a/arch/arm/mach-msm/smd_debug.c
+++ b/arch/arm/mach-msm/smd_debug.c
@@ -650,7 +650,12 @@
 			  size_t count, loff_t *ppos)
 {
 	int (*fill)(char *buf, int max) = file->private_data;
-	int bsize = fill(debug_buffer, DEBUG_BUFMAX);
+	int bsize;
+
+	if (*ppos != 0)
+		return 0;
+
+	bsize = fill(debug_buffer, DEBUG_BUFMAX);
 	return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
 }
 
diff --git a/drivers/char/diag/Kconfig b/drivers/char/diag/Kconfig
index eb0b21e..53df29b 100644
--- a/drivers/char/diag/Kconfig
+++ b/drivers/char/diag/Kconfig
@@ -29,3 +29,13 @@
 	help
 	 SDIO Transport Layer for DIAG Router
 endmenu
+
+menu "HSIC support for DIAG"
+
+config DIAG_HSIC_PIPE
+	depends on USB_QCOM_DIAG_BRIDGE
+	default y
+	bool "Enable 9K DIAG traffic over HSIC"
+	help
+	 HSIC Transport Layer for DIAG Router
+endmenu
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index 52ab2b9..c62b7fd 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_DIAG_CHAR) := diagchar.o
 obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
+obj-$(CONFIG_DIAG_HSIC_PIPE) += diagfwd_hsic.o
 diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 10133f9..f493f79 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -39,6 +39,7 @@
 #define APPS_DATA  		3
 #define SDIO_DATA		4
 #define WCNSS_DATA		5
+#define HSIC_DATA		6
 #define MODEM_PROC		0
 #define APPS_PROC		1
 #define QDSP_PROC		2
@@ -218,6 +219,26 @@
 	struct diag_request *usb_read_mdm_ptr;
 	struct diag_request *write_ptr_mdm;
 #endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+	unsigned char *buf_in_hsic;
+	unsigned char *usb_buf_mdm_out;
+	int hsic_initialized;
+	int hsic_ch;
+	int hsic_device_enabled;
+	int hsic_device_opened;
+	int read_len_mdm;
+	int in_busy_hsic_read_on_mdm;
+	int in_busy_hsic_write_on_mdm;
+	int in_busy_hsic_write;
+	int in_busy_hsic_read;
+	int usb_mdm_connected;
+	struct usb_diag_ch *mdm_ch;
+	struct workqueue_struct *diag_hsic_wq;
+	struct work_struct diag_read_mdm_work;
+	struct work_struct diag_read_hsic_work;
+	struct diag_request *usb_read_mdm_ptr;
+	struct diag_request *write_ptr_mdm;
+#endif
 };
 
 extern struct diagchar_dev *driver;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 1fb8c9f..799be72 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -31,6 +31,9 @@
 #ifdef CONFIG_DIAG_SDIO_PIPE
 #include "diagfwd_sdio.h"
 #endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+#include "diagfwd_hsic.h"
+#endif
 #include <linux/timer.h>
 
 MODULE_DESCRIPTION("Diag Char Driver");
@@ -982,6 +985,18 @@
 inline void diag_sdio_fn(int type) {}
 #endif
 
+#ifdef CONFIG_DIAG_HSIC_PIPE
+void diag_hsic_fn(int type)
+{
+	if (type == INIT)
+		diagfwd_hsic_init();
+	else if (type == EXIT)
+		diagfwd_hsic_exit();
+}
+#else
+inline void diag_hsic_fn(int type) {}
+#endif
+
 static int __init diagchar_init(void)
 {
 	dev_t dev;
@@ -1020,6 +1035,7 @@
 		diagfwd_init();
 		diagfwd_cntl_init();
 		diag_sdio_fn(INIT);
+		diag_hsic_fn(INIT);
 		pr_debug("diagchar initializing ..\n");
 		driver->num = 1;
 		driver->name = ((void *)driver) + sizeof(struct diagchar_dev);
@@ -1052,6 +1068,7 @@
 	diagfwd_exit();
 	diagfwd_cntl_exit();
 	diag_sdio_fn(EXIT);
+	diag_hsic_fn(EXIT);
 	return -1;
 }
 
@@ -1064,6 +1081,7 @@
 	diagfwd_exit();
 	diagfwd_cntl_exit();
 	diag_sdio_fn(EXIT);
+	diag_hsic_fn(EXIT);
 	diagchar_cleanup();
 	printk(KERN_INFO "done diagchar exit\n");
 }
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index d7191c8..6853654 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -248,7 +248,18 @@
 				write_ptr->buf = buf;
 				err = usb_diag_write(driver->mdm_ch, write_ptr);
 			} else
-				pr_err("diag: Incorrect data while USB write");
+				pr_err("diag: Incorrect sdio data "
+						"while USB write\n");
+		}
+#endif
+#ifdef CONFIG_DIAG_HSIC_PIPE
+		else if (proc_num == HSIC_DATA) {
+			if (driver->hsic_device_enabled) {
+				write_ptr->buf = buf;
+				err = usb_diag_write(driver->mdm_ch, write_ptr);
+			} else
+				pr_err("diag: Incorrect hsic data "
+						"while USB write\n");
 		}
 #endif
 		APPEND_DEBUG('d');
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
new file mode 100644
index 0000000..ac5722f
--- /dev/null
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -0,0 +1,530 @@
+/* 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.
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/diagchar.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <asm/current.h>
+#ifdef CONFIG_DIAG_OVER_USB
+#include <mach/usbdiag.h>
+#endif
+#include "diagchar_hdlc.h"
+#include "diagmem.h"
+#include "diagchar.h"
+#include "diagfwd.h"
+#include "diagfwd_hsic.h"
+
+static void diag_read_hsic_work_fn(struct work_struct *work)
+{
+	if (!driver->hsic_ch) {
+		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+		return;
+	}
+
+	/*
+	 * If there is no hsic data being read from the hsic and there
+	 * is no hsic data being written to the usb mdm channel
+	 */
+	if (!driver->in_busy_hsic_read && !driver->in_busy_hsic_write_on_mdm) {
+		/*
+		 * Initiate the read from the hsic.  The hsic read is
+		 * asynchronous.  Once the read is complete the read
+		 * callback function will be called.
+		 */
+		int err;
+		driver->in_busy_hsic_read = 1;
+		APPEND_DEBUG('i');
+		err = diag_bridge_read((char *)driver->buf_in_hsic,
+					IN_BUF_SIZE);
+		if (err) {
+			pr_err("DIAG: Error initiating HSIC read, err: %d\n",
+				err);
+			/*
+			 * If the error is recoverable, then clear
+			 * the read flag, so we will resubmit a
+			 * read on the next frame.  Otherwise, don't
+			 * resubmit a read on the next frame.
+			 */
+			if ((-ESHUTDOWN) != err)
+				driver->in_busy_hsic_read = 0;
+		}
+	}
+
+	/*
+	 * If for some reason there was no hsic data, set up
+	 * the next read
+	 */
+	if (!driver->in_busy_hsic_read)
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+}
+
+static void diag_hsic_read_complete_callback(void *ctxt, char *buf,
+					int buf_size, int actual_size)
+{
+	/* The read of the data from the HSIC bridge is complete */
+	driver->in_busy_hsic_read = 0;
+
+	if (!driver->hsic_ch) {
+		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+		return;
+	}
+
+	APPEND_DEBUG('j');
+	if (actual_size > 0) {
+		if (!buf) {
+			pr_err("Out of diagmem for HSIC\n");
+		} else {
+			driver->write_ptr_mdm->length = actual_size;
+			/*
+			 * Set flag to denote hsic data is currently
+			 * being written to the usb mdm channel.
+			 * driver->buf_in_hsic was given to
+			 * diag_bridge_read(), so buf here should be
+			 * driver->buf_in_hsic
+			 */
+			driver->in_busy_hsic_write_on_mdm = 1;
+			diag_device_write((void *)buf, HSIC_DATA,
+						driver->write_ptr_mdm);
+		}
+	} else {
+		pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
+	}
+
+	/*
+	 * If for some reason there was no hsic data to write to the
+	 * mdm channel, set up another read
+	 */
+	if (!driver->in_busy_hsic_write_on_mdm)
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+}
+
+static void diag_hsic_write_complete_callback(void *ctxt, char *buf,
+					int buf_size, int actual_size)
+{
+	/* The write of the data to the HSIC bridge is complete */
+	driver->in_busy_hsic_write = 0;
+
+	if (!driver->hsic_ch) {
+		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+		return;
+	}
+
+	if (actual_size < 0)
+		pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
+
+	queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+}
+
+static struct diag_bridge_ops hsic_diag_bridge_ops = {
+	.ctxt = NULL,
+	.read_complete_cb = diag_hsic_read_complete_callback,
+	.write_complete_cb = diag_hsic_write_complete_callback,
+};
+
+static int diag_hsic_close(void)
+{
+	if (driver->hsic_device_enabled) {
+		driver->hsic_ch = 0;
+		if (driver->hsic_device_opened) {
+			driver->hsic_device_opened = 0;
+			diag_bridge_close();
+		}
+		pr_debug("DIAG in %s: closed successfully\n", __func__);
+	} else {
+		pr_debug("DIAG in %s: already closed\n", __func__);
+	}
+
+	return 0;
+}
+
+/* diagfwd_connect_hsic is called when the USB mdm channel is connected */
+static int diagfwd_connect_hsic(void)
+{
+	int err;
+
+	pr_debug("DIAG in %s\n", __func__);
+
+	err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE, N_MDM_READ);
+	if (err)
+		pr_err("DIAG: unable to alloc USB req on mdm ch err:%d\n", err);
+
+	driver->usb_mdm_connected = 1;
+	driver->in_busy_hsic_write_on_mdm = 0;
+	driver->in_busy_hsic_read_on_mdm = 0;
+	driver->in_busy_hsic_write = 0;
+	driver->in_busy_hsic_read = 0;
+
+	/* If the hsic (diag_bridge) platform device is not open */
+	if (driver->hsic_device_enabled) {
+		if (!driver->hsic_device_opened) {
+			err = diag_bridge_open(&hsic_diag_bridge_ops);
+			if (err) {
+				pr_err("DIAG: HSIC channel open error: %d\n",
+					err);
+			} else {
+				pr_info("DIAG: opened HSIC channel\n");
+				driver->hsic_device_opened = 1;
+			}
+		} else {
+			pr_info("DIAG: HSIC channel already open\n");
+		}
+
+		/*
+		 * Turn on communication over usb mdm and hsic, if the hsic
+		 * device driver is enabled and opened
+		 */
+		if (driver->hsic_device_opened)
+			driver->hsic_ch = 1;
+
+		/* Poll USB mdm channel to check for data */
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+
+		/* Poll HSIC channel to check for data */
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+	} else {
+		/* The hsic device driver has not yet been enabled */
+		pr_info("DIAG: HSIC channel not yet enabled\n");
+	}
+
+	return 0;
+}
+
+/*
+ * diagfwd_disconnect_hsic is called when the USB mdm channel
+ * is disconnected
+ */
+static int diagfwd_disconnect_hsic(void)
+{
+	pr_debug("DIAG in %s\n", __func__);
+
+	driver->usb_mdm_connected = 0;
+	usb_diag_free_req(driver->mdm_ch);
+	driver->in_busy_hsic_write_on_mdm = 1;
+	driver->in_busy_hsic_read_on_mdm = 1;
+	driver->in_busy_hsic_write = 1;
+	driver->in_busy_hsic_read = 1;
+
+	/* Turn off communication over usb mdm and hsic */
+	driver->hsic_ch = 0;
+
+	return 0;
+}
+
+/*
+ * diagfwd_write_complete_hsic is called after the asynchronous
+ * usb_diag_write() on mdm channel is complete
+ */
+static int diagfwd_write_complete_hsic(void)
+{
+	/*
+	 * Clear flag to denote that the write of the hsic data on the
+	 * usb mdm channel is complete
+	 */
+	driver->in_busy_hsic_write_on_mdm = 0;
+
+	if (!driver->hsic_ch) {
+		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+		return 0;
+	}
+
+	APPEND_DEBUG('q');
+
+	/* Read data from the hsic */
+	queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+
+	return 0;
+}
+
+/* Called after the asychronous usb_diag_read() on mdm channel is complete */
+static int diagfwd_read_complete_hsic(struct diag_request *diag_read_ptr)
+{
+	/* The read of the usb driver on the mdm (not hsic) has completed */
+	driver->in_busy_hsic_read_on_mdm = 0;
+	driver->read_len_mdm = diag_read_ptr->actual;
+
+	if (!driver->hsic_ch) {
+		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+		return 0;
+	}
+
+	/*
+	 * The read of the usb driver on the mdm channel has completed.
+	 * If there is no write on the hsic in progress, check if the
+	 * read has data to pass on to the hsic. If so, pass the usb
+	 * mdm data on to the hsic.
+	 */
+	if (!driver->in_busy_hsic_write && driver->usb_buf_mdm_out &&
+		(driver->read_len_mdm > 0)) {
+
+		/*
+		 * Initiate the hsic write. The hsic write is
+		 * asynchronous. When complete the write
+		 * complete callback function will be called
+		 */
+		int err;
+		driver->in_busy_hsic_write = 1;
+		err = diag_bridge_write(driver->usb_buf_mdm_out,
+					driver->read_len_mdm);
+		if (err) {
+			pr_err("DIAG: mdm data on hsic write err: %d\n", err);
+			/*
+			 * If the error is recoverable, then clear
+			 * the write flag, so we will resubmit a
+			 * write on the next frame.  Otherwise, don't
+			 * resubmit a write on the next frame.
+			 */
+			if ((-ESHUTDOWN) != err)
+				driver->in_busy_hsic_write = 0;
+		}
+	}
+
+	/*
+	 * If there is no write of the usb mdm data on the
+	 * hsic channel
+	 */
+	if (!driver->in_busy_hsic_write)
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+
+	return 0;
+}
+
+static void diagfwd_hsic_notifier(void *priv, unsigned event,
+					struct diag_request *d_req)
+{
+	switch (event) {
+	case USB_DIAG_CONNECT:
+		diagfwd_connect_hsic();
+		break;
+	case USB_DIAG_DISCONNECT:
+		diagfwd_disconnect_hsic();
+		break;
+	case USB_DIAG_READ_DONE:
+		diagfwd_read_complete_hsic(d_req);
+		break;
+	case USB_DIAG_WRITE_DONE:
+		diagfwd_write_complete_hsic();
+		break;
+	default:
+		pr_err("DIAG in %s: Unknown event from USB diag:%u\n",
+			__func__, event);
+		break;
+	}
+}
+
+static void diag_read_mdm_work_fn(struct work_struct *work)
+{
+	if (!driver->hsic_ch) {
+		pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+		return;
+	}
+
+	/*
+	 * If there is no data being read from the usb mdm channel
+	 * and there is no mdm channel data currently being written
+	 * to the hsic
+	 */
+	if (!driver->in_busy_hsic_read_on_mdm && !driver->in_busy_hsic_write) {
+		APPEND_DEBUG('x');
+
+		/* Setup the next read from usb mdm channel */
+		driver->in_busy_hsic_read_on_mdm = 1;
+		driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
+		driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
+		usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
+		APPEND_DEBUG('y');
+	}
+
+	/*
+	 * If for some reason there was no mdm channel read initiated,
+	 * queue up the reading of data from the mdm channel
+	 */
+	if (!driver->in_busy_hsic_read_on_mdm)
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+}
+
+int diag_hsic_enable(void)
+{
+	pr_debug("DIAG in %s\n", __func__);
+
+	driver->read_len_mdm = 0;
+	if (driver->buf_in_hsic == NULL)
+		driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+	if (driver->buf_in_hsic == NULL)
+		goto err;
+	if (driver->usb_buf_mdm_out  == NULL)
+		driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF, GFP_KERNEL);
+	if (driver->usb_buf_mdm_out == NULL)
+		goto err;
+	if (driver->write_ptr_mdm == NULL)
+		driver->write_ptr_mdm = kzalloc(
+		sizeof(struct diag_request), GFP_KERNEL);
+	if (driver->write_ptr_mdm == NULL)
+		goto err;
+	if (driver->usb_read_mdm_ptr == NULL)
+		driver->usb_read_mdm_ptr = kzalloc(
+		sizeof(struct diag_request), GFP_KERNEL);
+	if (driver->usb_read_mdm_ptr == NULL)
+		goto err;
+	driver->diag_hsic_wq = create_singlethread_workqueue("diag_hsic_wq");
+#ifdef CONFIG_DIAG_OVER_USB
+	INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
+#endif
+	INIT_WORK(&(driver->diag_read_hsic_work), diag_read_hsic_work_fn);
+
+	driver->hsic_device_enabled = 1;
+
+	return 0;
+err:
+	pr_err("DIAG could not initialize buf for HSIC\n");
+	kfree(driver->buf_in_hsic);
+	kfree(driver->usb_buf_mdm_out);
+	kfree(driver->write_ptr_mdm);
+	kfree(driver->usb_read_mdm_ptr);
+	if (driver->diag_hsic_wq)
+		destroy_workqueue(driver->diag_hsic_wq);
+
+	return -ENOMEM;
+}
+
+static int diag_hsic_probe(struct platform_device *pdev)
+{
+	int err;
+
+	if (!driver->hsic_device_enabled) {
+		err = diag_hsic_enable();
+		if (err) {
+			pr_err("DIAG could not enable HSIC, err: %d\n", err);
+			return err;
+		}
+	}
+
+	/* The hsic (diag_bridge) platform device driver is enabled */
+	err = diag_bridge_open(&hsic_diag_bridge_ops);
+	if (err) {
+		pr_err("DIAG could not open HSIC channel, err: %d\n", err);
+		driver->hsic_device_opened = 0;
+		return err;
+	}
+
+	pr_info("DIAG opened HSIC channel\n");
+	driver->hsic_device_opened = 1;
+
+	/*
+	 * The probe function was called after the usb was connected
+	 * on the legacy channel. Communication over usb mdm and hsic
+	 * needs to be turned on.
+	 */
+	if (driver->usb_connected) {
+		driver->hsic_ch = 1;
+		driver->in_busy_hsic_write_on_mdm = 0;
+		driver->in_busy_hsic_read_on_mdm = 0;
+		driver->in_busy_hsic_write = 0;
+		driver->in_busy_hsic_read = 0;
+
+		/* Poll USB mdm channel to check for data */
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+
+		/* Poll HSIC channel to check for data */
+		queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+	}
+
+	return err;
+}
+
+static int diag_hsic_remove(struct platform_device *pdev)
+{
+	pr_info("DIAG: %s called\n", __func__);
+	diag_hsic_close();
+	return 0;
+}
+
+static int diagfwd_hsic_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: suspending...\n");
+	return 0;
+}
+
+static int diagfwd_hsic_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: resuming...\n");
+	return 0;
+}
+
+static const struct dev_pm_ops diagfwd_hsic_dev_pm_ops = {
+	.runtime_suspend = diagfwd_hsic_runtime_suspend,
+	.runtime_resume = diagfwd_hsic_runtime_resume,
+};
+
+static struct platform_driver msm_hsic_ch_driver = {
+	.probe = diag_hsic_probe,
+	.remove = diag_hsic_remove,
+	.driver = {
+		   .name = "diag_bridge",
+		   .owner = THIS_MODULE,
+		   .pm   = &diagfwd_hsic_dev_pm_ops,
+		   },
+};
+
+
+void __init diagfwd_hsic_init(void)
+{
+	int ret;
+
+	pr_debug("DIAG in %s\n", __func__);
+
+#ifdef CONFIG_DIAG_OVER_USB
+	driver->mdm_ch = usb_diag_open(DIAG_MDM, driver, diagfwd_hsic_notifier);
+	if (IS_ERR(driver->mdm_ch)) {
+		pr_err("DIAG Unable to open USB diag MDM channel\n");
+		goto err;
+	}
+#endif
+	ret = platform_driver_register(&msm_hsic_ch_driver);
+	if (ret)
+		pr_err("DIAG could not register HSIC device, ret: %d\n", ret);
+	else
+		driver->hsic_initialized = 1;
+
+	return;
+err:
+	pr_err("DIAG could not initialize for HSIC execution\n");
+}
+
+void __exit diagfwd_hsic_exit(void)
+{
+	pr_debug("DIAG in %s\n", __func__);
+
+	if (driver->hsic_initialized)
+		diag_hsic_close();
+
+#ifdef CONFIG_DIAG_OVER_USB
+	if (driver->usb_mdm_connected)
+		usb_diag_free_req(driver->mdm_ch);
+#endif
+	platform_driver_unregister(&msm_hsic_ch_driver);
+#ifdef CONFIG_DIAG_OVER_USB
+	usb_diag_close(driver->mdm_ch);
+#endif
+	kfree(driver->buf_in_hsic);
+	kfree(driver->usb_buf_mdm_out);
+	kfree(driver->write_ptr_mdm);
+	kfree(driver->usb_read_mdm_ptr);
+	destroy_workqueue(driver->diag_hsic_wq);
+
+	driver->hsic_device_enabled = 0;
+}
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
new file mode 100644
index 0000000..6769052
--- /dev/null
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -0,0 +1,23 @@
+/* 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 DIAGFWD_HSIC_H
+#define DIAGFWD_HSIC_H
+
+#include <mach/diag_bridge.h>
+#define N_MDM_WRITE	1 /* Upgrade to 2 with ping pong buffer */
+#define N_MDM_READ	1
+
+void __init diagfwd_hsic_init(void);
+void __exit diagfwd_hsic_exit(void);
+
+#endif
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 99c6c52..a3d2c00 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -88,6 +88,12 @@
 
 extern struct adreno_gpudev adreno_a2xx_gpudev;
 
+/* A2XX register sets defined in adreno_a2xx.c */
+extern const unsigned int a200_registers[];
+extern const unsigned int a220_registers[];
+extern const unsigned int a200_registers_count;
+extern const unsigned int a220_registers_count;
+
 int adreno_idle(struct kgsl_device *device, unsigned int timeout);
 void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
 				unsigned int *value);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index d083586..16402c3 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -18,6 +18,74 @@
 #include "adreno_a2xx_trace.h"
 
 /*
+ * These are the registers that are dumped with GPU snapshot
+ * and postmortem.  The lists are dword offset pairs in the
+ * form of {start offset, end offset} inclusive.
+ */
+
+/* A200, A205 */
+const unsigned int a200_registers[] = {
+	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
+	0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
+	0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
+	0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
+	0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
+	0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
+	0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
+	0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
+	0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A43, 0x0A45, 0x0A45,
+	0x0A4E, 0x0A4F, 0x0C2C, 0x0C2C, 0x0C30, 0x0C30, 0x0C38, 0x0C3C,
+	0x0C40, 0x0C40, 0x0C44, 0x0C44, 0x0C80, 0x0C86, 0x0C88, 0x0C94,
+	0x0C99, 0x0C9A, 0x0CA4, 0x0CA5, 0x0D00, 0x0D03, 0x0D06, 0x0D06,
+	0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1, 0x0DC8, 0x0DD4,
+	0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04, 0x0E17, 0x0E1E,
+	0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0, 0x0ED4, 0x0ED7,
+	0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x0F0C, 0x0F0C, 0x0F0E, 0x0F12,
+	0x0F26, 0x0F2A, 0x0F2C, 0x0F2C, 0x2000, 0x2002, 0x2006, 0x200F,
+	0x2080, 0x2082, 0x2100, 0x2109, 0x210C, 0x2114, 0x2180, 0x2184,
+	0x21F5, 0x21F7, 0x2200, 0x2208, 0x2280, 0x2283, 0x2293, 0x2294,
+	0x2300, 0x2308, 0x2312, 0x2312, 0x2316, 0x231D, 0x2324, 0x2326,
+	0x2380, 0x2383, 0x2400, 0x2402, 0x2406, 0x240F, 0x2480, 0x2482,
+	0x2500, 0x2509, 0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7,
+	0x2600, 0x2608, 0x2680, 0x2683, 0x2693, 0x2694, 0x2700, 0x2708,
+	0x2712, 0x2712, 0x2716, 0x271D, 0x2724, 0x2726, 0x2780, 0x2783,
+	0x4000, 0x4003, 0x4800, 0x4805, 0x4900, 0x4900, 0x4908, 0x4908,
+};
+
+/* A220, A225 */
+const unsigned int a220_registers[] = {
+	0x0000, 0x0002, 0x0004, 0x000B, 0x003B, 0x003D, 0x0040, 0x0044,
+	0x0046, 0x0047, 0x01C0, 0x01C1, 0x01C3, 0x01C8, 0x01D5, 0x01D9,
+	0x01DC, 0x01DD, 0x01EA, 0x01EA, 0x01EE, 0x01F3, 0x01F6, 0x01F7,
+	0x01FC, 0x01FF, 0x0391, 0x0392, 0x039B, 0x039E, 0x03B2, 0x03B5,
+	0x03B7, 0x03B7, 0x03F8, 0x03FB, 0x0440, 0x0440, 0x0443, 0x0444,
+	0x044B, 0x044B, 0x044D, 0x044F, 0x0452, 0x0452, 0x0454, 0x045B,
+	0x047F, 0x047F, 0x0578, 0x0587, 0x05C9, 0x05C9, 0x05D0, 0x05D0,
+	0x0601, 0x0604, 0x0606, 0x0609, 0x060B, 0x060E, 0x0613, 0x0614,
+	0x0A29, 0x0A2B, 0x0A2F, 0x0A31, 0x0A40, 0x0A40, 0x0A42, 0x0A43,
+	0x0A45, 0x0A45, 0x0A4E, 0x0A4F, 0x0C30, 0x0C30, 0x0C38, 0x0C39,
+	0x0C3C, 0x0C3C, 0x0C80, 0x0C81, 0x0C88, 0x0C93, 0x0D00, 0x0D03,
+	0x0D05, 0x0D06, 0x0D08, 0x0D0B, 0x0D34, 0x0D35, 0x0DAE, 0x0DC1,
+	0x0DC8, 0x0DD4, 0x0DD8, 0x0DD9, 0x0E00, 0x0E00, 0x0E02, 0x0E04,
+	0x0E17, 0x0E1E, 0x0EC0, 0x0EC9, 0x0ECB, 0x0ECC, 0x0ED0, 0x0ED0,
+	0x0ED4, 0x0ED7, 0x0EE0, 0x0EE2, 0x0F01, 0x0F02, 0x2000, 0x2002,
+	0x2006, 0x200F, 0x2080, 0x2082, 0x2100, 0x2102, 0x2104, 0x2109,
+	0x210C, 0x2114, 0x2180, 0x2184, 0x21F5, 0x21F7, 0x2200, 0x2202,
+	0x2204, 0x2204, 0x2208, 0x2208, 0x2280, 0x2282, 0x2294, 0x2294,
+	0x2300, 0x2308, 0x2309, 0x230A, 0x2312, 0x2312, 0x2316, 0x2316,
+	0x2318, 0x231D, 0x2324, 0x2326, 0x2380, 0x2383, 0x2400, 0x2402,
+	0x2406, 0x240F, 0x2480, 0x2482, 0x2500, 0x2502, 0x2504, 0x2509,
+	0x250C, 0x2514, 0x2580, 0x2584, 0x25F5, 0x25F7, 0x2600, 0x2602,
+	0x2604, 0x2606, 0x2608, 0x2608, 0x2680, 0x2682, 0x2694, 0x2694,
+	0x2700, 0x2708, 0x2712, 0x2712, 0x2716, 0x2716, 0x2718, 0x271D,
+	0x2724, 0x2726, 0x2780, 0x2783, 0x4000, 0x4003, 0x4800, 0x4805,
+	0x4900, 0x4900, 0x4908, 0x4908,
+};
+
+const unsigned int a200_registers_count = ARRAY_SIZE(a200_registers) / 2;
+const unsigned int a220_registers_count = ARRAY_SIZE(a220_registers) / 2;
+
+/*
  *
  *  Memory Map for Register, Constant & Instruction Shadow, and Command Buffers
  *  (34.5KB)
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index aafef21..40dfb30 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -69,95 +69,6 @@
 	{CP_WAIT_FOR_IDLE,		"WAIT4IDL"},
 };
 
-/* Offset address pairs: start, end of range to dump (inclusive) */
-
-/* GPU < Z470 */
-
-static const int a200_registers[] = {
-	0x0000, 0x0008, 0x0010, 0x002c, 0x00ec, 0x00f4,
-	0x0100, 0x0110, 0x0118, 0x011c,
-	0x0700, 0x0704, 0x070c, 0x0720, 0x0754, 0x0764,
-	0x0770, 0x0774, 0x07a8, 0x07a8, 0x07b8, 0x07cc,
-	0x07d8, 0x07dc, 0x07f0, 0x07fc, 0x0e44, 0x0e48,
-	0x0e6c, 0x0e78, 0x0ec8, 0x0ed4, 0x0edc, 0x0edc,
-	0x0fe0, 0x0fec, 0x1100, 0x1100,
-
-	0x110c, 0x1110, 0x112c, 0x112c, 0x1134, 0x113c,
-	0x1148, 0x1148, 0x1150, 0x116c, 0x11fc, 0x11fc,
-	0x15e0, 0x161c, 0x1724, 0x1724, 0x1740, 0x1740,
-	0x1804, 0x1810, 0x1818, 0x1824, 0x182c, 0x1838,
-	0x184c, 0x1850, 0x28a4, 0x28ac, 0x28bc, 0x28c4,
-	0x2900, 0x290c, 0x2914, 0x2914, 0x2938, 0x293c,
-	0x30b0, 0x30b0, 0x30c0, 0x30c0, 0x30e0, 0x30f0,
-	0x3100, 0x3100, 0x3110, 0x3110, 0x3200, 0x3218,
-	0x3220, 0x3250, 0x3264, 0x3268, 0x3290, 0x3294,
-	0x3400, 0x340c, 0x3418, 0x3418, 0x3420, 0x342c,
-	0x34d0, 0x34d4, 0x36b8, 0x3704, 0x3720, 0x3750,
-	0x3760, 0x3764, 0x3800, 0x3800, 0x3808, 0x3810,
-	0x385c, 0x3878, 0x3b00, 0x3b24, 0x3b2c, 0x3b30,
-	0x3b40, 0x3b40, 0x3b50, 0x3b5c, 0x3b80, 0x3b88,
-	0x3c04, 0x3c08, 0x3c30, 0x3c30, 0x3c38, 0x3c48,
-	0x3c98, 0x3ca8, 0x3cb0, 0x3cb0,
-
-	0x8000, 0x8008, 0x8018, 0x803c, 0x8200, 0x8208,
-	0x8400, 0x8424, 0x8430, 0x8450, 0x8600, 0x8610,
-	0x87d4, 0x87dc, 0x8800, 0x8820, 0x8a00, 0x8a0c,
-	0x8a4c, 0x8a50, 0x8c00, 0x8c20, 0x8c48, 0x8c48,
-	0x8c58, 0x8c74, 0x8c90, 0x8c98, 0x8e00, 0x8e0c,
-
-	0x9000, 0x9008, 0x9018, 0x903c, 0x9200, 0x9208,
-	0x9400, 0x9424, 0x9430, 0x9450, 0x9600, 0x9610,
-	0x97d4, 0x97dc, 0x9800, 0x9820, 0x9a00, 0x9a0c,
-	0x9a4c, 0x9a50, 0x9c00, 0x9c20, 0x9c48, 0x9c48,
-	0x9c58, 0x9c74, 0x9c90, 0x9c98, 0x9e00, 0x9e0c,
-
-	0x10000, 0x1000c, 0x12000, 0x12014,
-	0x12400, 0x12400, 0x12420, 0x12420
-};
-
-/* GPU = Z470 */
-
-static const int a220_registers[] = {
-	0x0000, 0x0008, 0x0010, 0x002c, 0x00ec, 0x00f4,
-	0x0100, 0x0110, 0x0118, 0x011c,
-	0x0700, 0x0704, 0x070c, 0x0720, 0x0754, 0x0764,
-	0x0770, 0x0774, 0x07a8, 0x07a8, 0x07b8, 0x07cc,
-	0x07d8, 0x07dc, 0x07f0, 0x07fc, 0x0e44, 0x0e48,
-	0x0e6c, 0x0e78, 0x0ec8, 0x0ed4, 0x0edc, 0x0edc,
-	0x0fe0, 0x0fec, 0x1100, 0x1100,
-
-	0x110c, 0x1110, 0x112c, 0x112c, 0x1134, 0x113c,
-	0x1148, 0x1148, 0x1150, 0x116c, 0x11fc, 0x11fc,
-	0x15e0, 0x161c, 0x1724, 0x1724, 0x1740, 0x1740,
-	0x1804, 0x1810, 0x1818, 0x1824, 0x182c, 0x1838,
-	0x184c, 0x1850, 0x28a4, 0x28ac, 0x28bc, 0x28c4,
-	0x2900, 0x2900, 0x2908, 0x290c, 0x2914, 0x2914,
-	0x2938, 0x293c, 0x30c0, 0x30c0, 0x30e0, 0x30e4,
-	0x30f0, 0x30f0, 0x3200, 0x3204, 0x3220, 0x324c,
-	0x3400, 0x340c, 0x3414, 0x3418, 0x3420, 0x342c,
-	0x34d0, 0x34d4, 0x36b8, 0x3704, 0x3720, 0x3750,
-	0x3760, 0x3764, 0x3800, 0x3800, 0x3808, 0x3810,
-	0x385c, 0x3878, 0x3b00, 0x3b24, 0x3b2c, 0x3b30,
-	0x3b40, 0x3b40, 0x3b50, 0x3b5c, 0x3b80, 0x3b88,
-	0x3c04, 0x3c08, 0x8000, 0x8008, 0x8018, 0x803c,
-	0x8200, 0x8208, 0x8400, 0x8408, 0x8410, 0x8424,
-	0x8430, 0x8450, 0x8600, 0x8610, 0x87d4, 0x87dc,
-	0x8800, 0x8808, 0x8810, 0x8810, 0x8820, 0x8820,
-	0x8a00, 0x8a08, 0x8a50, 0x8a50,
-	0x8c00, 0x8c20, 0x8c24, 0x8c28, 0x8c48, 0x8c48,
-	0x8c58, 0x8c58, 0x8c60, 0x8c74, 0x8c90, 0x8c98,
-	0x8e00, 0x8e0c, 0x9000, 0x9008, 0x9018, 0x903c,
-	0x9200, 0x9208, 0x9400, 0x9408, 0x9410, 0x9424,
-	0x9430, 0x9450, 0x9600, 0x9610, 0x97d4, 0x97dc,
-	0x9800, 0x9808, 0x9810, 0x9818, 0x9820, 0x9820,
-	0x9a00, 0x9a08, 0x9a50, 0x9a50, 0x9c00, 0x9c20,
-	0x9c48, 0x9c48, 0x9c58, 0x9c58, 0x9c60, 0x9c74,
-	0x9c90, 0x9c98, 0x9e00, 0x9e0c,
-
-	0x10000, 0x1000c, 0x12000, 0x12014,
-	0x12400, 0x12400, 0x12420, 0x12420
-};
-
 static uint32_t adreno_is_pm4_len(uint32_t word)
 {
 	if (word == INVALID_RB_CMD)
@@ -224,8 +135,8 @@
 
 	for (range = 0; range < size; range++) {
 		/* start and end are in dword offsets */
-		int start = registers[range * 2] / 4;
-		int end = registers[range * 2 + 1] / 4;
+		int start = registers[range * 2];
+		int end = registers[range * 2 + 1];
 
 		unsigned char linebuf[32 * 3 + 2 + 32 + 1];
 		int linelen, i;
@@ -240,7 +151,7 @@
 			hex_dump_to_buffer(regvals, linelen*4, 32, 4,
 				linebuf, sizeof(linebuf), 0);
 			KGSL_LOG_DUMP(device,
-				"REG: %5.5X: %s\n", offset<<2, linebuf);
+				"REG: %5.5X: %s\n", offset, linebuf);
 		}
 	}
 }
@@ -774,10 +685,10 @@
 
 	if (adreno_is_a20x(adreno_dev))
 		adreno_dump_regs(device, a200_registers,
-			ARRAY_SIZE(a200_registers) / 2);
+			a200_registers_count);
 	else if (adreno_is_a22x(adreno_dev))
 		adreno_dump_regs(device, a220_registers,
-			ARRAY_SIZE(a220_registers) / 2);
+			a220_registers_count);
 
 error_vfree:
 	vfree(rb_copy);
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index fa0cd82..ffdfce1 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -22,9 +22,6 @@
 #define RMNET_DATA_LEN			2000
 #define HEADROOM_FOR_QOS		8
 
-#define FIRST_RMNET_USB_INTERFACE	5
-#define NUM_EMBEDDED_RMNET_IFACE	4
-
 static int	data_msg_dbg_mask;
 
 enum {
@@ -419,9 +416,10 @@
 {
 	struct usbnet		*unet;
 	struct usb_device	*udev;
-	int			iface_num;
-	int			last_rmnet_iface_num;
-	int			status = -ENODEV;
+	struct driver_info	*info;
+	unsigned int		iface_num;
+	static int		first_rmnet_iface_num = -EINVAL;
+	int			status = 0;
 
 	udev = interface_to_usbdev(iface);
 	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
@@ -432,38 +430,37 @@
 		goto out;
 	}
 
-	last_rmnet_iface_num = (FIRST_RMNET_USB_INTERFACE +
-		 NUM_EMBEDDED_RMNET_IFACE - 1);
+	info = (struct driver_info *)prod->driver_info;
+	if (!test_bit(iface_num, &info->data))
+		return -ENODEV;
 
-	if (iface_num >= FIRST_RMNET_USB_INTERFACE &&
-		iface_num <= last_rmnet_iface_num) {
-		status = usbnet_probe(iface, prod);
-		if (status < 0) {
-			dev_err(&udev->dev, "usbnet_probe failed %d\n",
-				status);
-			goto out;
-		}
-		unet = usb_get_intfdata(iface);
-
-		/*set rmnet operation mode to eth by default*/
-		set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
-
-		/*update net device*/
-		rmnet_usb_setup(unet->net);
-
-		/*create /sys/class/net/rmnet_usbx/dbg_mask*/
-		status = device_create_file(&unet->net->dev,
-				&dev_attr_dbg_mask);
-		if (status)
-			goto out;
-
-		/*save control device intstance */
-		unet->data[1] = (unsigned long)ctrl_dev	\
-		[iface_num - FIRST_RMNET_USB_INTERFACE];
-
-		status = rmnet_usb_ctrl_probe(iface, unet->status,
-			(struct rmnet_ctrl_dev *)unet->data[1]);
+	status = usbnet_probe(iface, prod);
+	if (status < 0) {
+		dev_err(&udev->dev, "usbnet_probe failed %d\n", status);
+		goto out;
 	}
+	unet = usb_get_intfdata(iface);
+
+	/*set rmnet operation mode to eth by default*/
+	set_bit(RMNET_MODE_LLP_ETH, &unet->data[0]);
+
+	/*update net device*/
+	rmnet_usb_setup(unet->net);
+
+	/*create /sys/class/net/rmnet_usbx/dbg_mask*/
+	status = device_create_file(&unet->net->dev, &dev_attr_dbg_mask);
+	if (status)
+		goto out;
+
+	if (first_rmnet_iface_num == -EINVAL)
+		first_rmnet_iface_num = iface_num;
+
+	/*save control device intstance */
+	unet->data[1] = (unsigned long)ctrl_dev	\
+			[iface_num - first_rmnet_iface_num];
+
+	status = rmnet_usb_ctrl_probe(iface, unet->status,
+		(struct rmnet_ctrl_dev *)unet->data[1]);
 out:
 	return status;
 }
@@ -473,51 +470,58 @@
 	struct usbnet		*unet;
 	struct usb_device	*udev;
 	struct rmnet_ctrl_dev	*dev;
-	int			iface_num;
-	int			last_rmnet_iface_num;
 
 	udev = interface_to_usbdev(intf);
-	iface_num = intf->cur_altsetting->desc.bInterfaceNumber;
 
-	last_rmnet_iface_num = (FIRST_RMNET_USB_INTERFACE +
-			 NUM_EMBEDDED_RMNET_IFACE - 1);
-
-	if (iface_num >= FIRST_RMNET_USB_INTERFACE &&
-		iface_num <= last_rmnet_iface_num) {
-		unet = usb_get_intfdata(intf);
-		if (!unet) {
-			dev_err(&udev->dev, "%s:data device not found\n",
-					__func__);
-			return;
-		}
-		dev = (struct rmnet_ctrl_dev *)unet->data[1];
-		if (!dev) {
-			dev_err(&udev->dev, "%s:ctrl device not found\n",
-					__func__);
-			return;
-		}
-		unet->data[0] = 0;
-		unet->data[1] = 0;
-		rmnet_usb_ctrl_disconnect(dev);
-		device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
-		usbnet_disconnect(intf);
+	unet = usb_get_intfdata(intf);
+	if (!unet) {
+		dev_err(&udev->dev, "%s:data device not found\n", __func__);
+		return;
 	}
+
+	dev = (struct rmnet_ctrl_dev *)unet->data[1];
+	if (!dev) {
+		dev_err(&udev->dev, "%s:ctrl device not found\n", __func__);
+		return;
+	}
+	unet->data[0] = 0;
+	unet->data[1] = 0;
+	rmnet_usb_ctrl_disconnect(dev);
+	device_remove_file(&unet->net->dev, &dev_attr_dbg_mask);
+	usbnet_disconnect(intf);
 }
 
-static const struct driver_info rmnet_info = {
+/*bit position represents interface number*/
+#define PID9034_IFACE_MASK	0xF0
+#define PID9048_IFACE_MASK	0x1E0
+
+static const struct driver_info rmnet_info_pid9034 = {
 	.description   = "RmNET net device",
 	.bind          = rmnet_usb_bind,
 	.tx_fixup      = rmnet_usb_tx_fixup,
 	.rx_fixup      = rmnet_usb_rx_fixup,
-	.data          = 0,
+	.data          = PID9034_IFACE_MASK,
+};
+
+static const struct driver_info rmnet_info_pid9048 = {
+	.description   = "RmNET net device",
+	.bind          = rmnet_usb_bind,
+	.tx_fixup      = rmnet_usb_tx_fixup,
+	.rx_fixup      = rmnet_usb_rx_fixup,
+	.data          = PID9048_IFACE_MASK,
 };
 
 static const struct usb_device_id vidpids[] = {
 	{
-		USB_DEVICE(0x05c6, 0x9048),	/* MDM9x15*/
-		.driver_info = (unsigned long)&rmnet_info,
+		USB_DEVICE(0x05c6, 0x9034), /* MDM9x15*/
+		.driver_info = (unsigned long)&rmnet_info_pid9034,
 	},
-	{ },
+	{
+		USB_DEVICE(0x05c6, 0x9048), /* MDM9x15*/
+		.driver_info = (unsigned long)&rmnet_info_pid9048,
+	},
+
+	{ }, /* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(usb, vidpids);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 9605927..fb850b0 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -665,6 +665,27 @@
 	struct bam_ch_info *d = &port->data_ch;
 	u32 sps_params;
 	int ret;
+	unsigned long flags;
+
+	ret = usb_ep_enable(port->gr->in, port->gr->in_desc);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+				__func__, port->gr->in);
+		return;
+	}
+	port->gr->in->driver_data = port;
+
+	ret = usb_ep_enable(port->gr->out, port->gr->out_desc);
+	if (ret) {
+		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+				__func__, port->gr->out);
+		port->gr->in->driver_data = 0;
+		return;
+	}
+	port->gr->out->driver_data = port;
+	spin_lock_irqsave(&port->port_lock, flags);
+	port->port_usb = port->gr;
+	spin_unlock_irqrestore(&port->port_lock, flags);
 
 	ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
 						  &d->dst_pipe_idx);
@@ -1047,37 +1068,39 @@
 
 	d = &port->data_ch;
 
-	ret = usb_ep_enable(gr->in, gr->in_desc);
-	if (ret) {
-		pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
-				__func__, gr->in);
-		return ret;
-	}
-	gr->in->driver_data = port;
-
-	ret = usb_ep_enable(gr->out, gr->out_desc);
-	if (ret) {
-		pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
-				__func__, gr->out);
-		gr->in->driver_data = 0;
-		return ret;
-	}
-	gr->out->driver_data = port;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	port->port_usb = gr;
-
 	if (trans == USB_GADGET_XPORT_BAM) {
+		ret = usb_ep_enable(gr->in, gr->in_desc);
+		if (ret) {
+			pr_err("%s: usb_ep_enable failed eptype:IN ep:%p",
+					__func__, gr->in);
+			return ret;
+		}
+		gr->in->driver_data = port;
+
+		ret = usb_ep_enable(gr->out, gr->out_desc);
+		if (ret) {
+			pr_err("%s: usb_ep_enable failed eptype:OUT ep:%p",
+					__func__, gr->out);
+			gr->in->driver_data = 0;
+			return ret;
+		}
+		gr->out->driver_data = port;
+
+		spin_lock_irqsave(&port->port_lock, flags);
+		port->port_usb = gr;
+
 		d->to_host = 0;
 		d->to_modem = 0;
 		d->pending_with_bam = 0;
 		d->tohost_drp_cnt = 0;
 		d->tomodem_drp_cnt = 0;
+		spin_unlock_irqrestore(&port->port_lock, flags);
 	}
-	spin_unlock_irqrestore(&port->port_lock, flags);
 
-	if (trans == USB_GADGET_XPORT_BAM2BAM)
+	if (trans == USB_GADGET_XPORT_BAM2BAM) {
+		port->gr = gr;
 		d->connection_idx = connection_idx;
+	}
 
 	queue_work(gbam_wq, &port->connect_w);
 
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 017ee8a..66cdcb1 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-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
@@ -86,7 +86,7 @@
 			urb->status < 0 ? urb->status : urb->actual_length);
 }
 
-int diag_bridge_read(char *data, size_t size)
+int diag_bridge_read(char *data, int size)
 {
 	struct urb		*urb = NULL;
 	unsigned int		pipe;
@@ -153,7 +153,7 @@
 			urb->status < 0 ? urb->status : urb->actual_length);
 }
 
-int diag_bridge_write(char *data, size_t size)
+int diag_bridge_write(char *data, int size)
 {
 	struct urb		*urb = NULL;
 	unsigned int		pipe;
@@ -293,6 +293,10 @@
 
 #define VALID_INTERFACE_NUM	0
 static const struct usb_device_id diag_bridge_ids[] = {
+	{ USB_DEVICE(0x5c6, 0x9001),
+	.driver_info = VALID_INTERFACE_NUM, },
+	{ USB_DEVICE(0x5c6, 0x9034),
+	.driver_info = VALID_INTERFACE_NUM, },
 	{ USB_DEVICE(0x5c6, 0x9048),
 	.driver_info = VALID_INTERFACE_NUM, },
 
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 89b8e5a..90c32cb 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -753,9 +753,6 @@
 static void data_bridge_debugfs_exit(void) { }
 #endif
 
-#define DUN_IFACE_NUM			3
-#define TETHERED_RMNET_IFACE_NUM	4
-
 static int __devinit
 bridge_probe(struct usb_interface *iface, const struct usb_device_id *id)
 {
@@ -767,7 +764,7 @@
 	int				i;
 	int				status = 0;
 	int				numends;
-	int				iface_num;
+	unsigned int			iface_num;
 
 	iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
 
@@ -780,7 +777,7 @@
 	udev = interface_to_usbdev(iface);
 	usb_get_dev(udev);
 
-	if (iface_num != DUN_IFACE_NUM && iface_num != TETHERED_RMNET_IFACE_NUM)
+	if (!test_bit(iface_num, &id->driver_info))
 		return -ENODEV;
 
 	numends = iface->cur_altsetting->desc.bNumEndpoints;
@@ -818,6 +815,7 @@
 		dev_err(&udev->dev, "ctrl_bridge_probe failed %d\n", status);
 		goto free_data_bridge;
 	}
+
 	ch_id++;
 
 	return 0;
@@ -839,17 +837,12 @@
 	struct list_head	*head;
 	struct urb		*rx_urb;
 	unsigned long		flags;
-	int			iface_num;
 
 	if (!dev) {
 		err("%s: data device not found\n", __func__);
 		return;
 	}
 
-	iface_num = intf->cur_altsetting->desc.bInterfaceNumber;
-	if (iface_num != DUN_IFACE_NUM && iface_num != TETHERED_RMNET_IFACE_NUM)
-		return;
-
 	ch_id--;
 	ctrl_bridge_disconnect(ch_id);
 	platform_device_del(dev->pdev);
@@ -873,12 +866,24 @@
 	kfree(dev);
 }
 
+/*bit position represents interface number*/
+#define PID9001_IFACE_MASK	0xC
+#define PID9034_IFACE_MASK	0xC
+#define PID9048_IFACE_MASK	0x18
+
 static const struct usb_device_id bridge_ids[] = {
-	{ USB_DEVICE(0x5c6, 0x9048) },
+	{ USB_DEVICE(0x5c6, 0x9001),
+	.driver_info = PID9001_IFACE_MASK,
+	},
+	{ USB_DEVICE(0x5c6, 0x9034),
+	.driver_info = PID9034_IFACE_MASK,
+	},
+	{ USB_DEVICE(0x5c6, 0x9048),
+	.driver_info = PID9048_IFACE_MASK,
+	},
 
 	{ } /* Terminating entry */
 };
-
 MODULE_DEVICE_TABLE(usb, bridge_ids);
 
 static struct usb_driver bridge_driver = {
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index d756dd8..4932551 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -523,6 +523,18 @@
 	u32 val = 0;
 	u32 ulpi_val = 0;
 
+	/*
+	 * USB PHY and Link reset also reset the USB BAM.
+	 * Thus perform reset operation only once to avoid
+	 * USB BAM reset on other cases e.g. USB cable disconnections.
+	 */
+	if (pdata->disable_reset_on_disconnect) {
+		if (motg->reset_counter)
+			return 0;
+		else
+			motg->reset_counter++;
+	}
+
 	clk_enable(motg->clk);
 	ret = msm_otg_phy_reset(motg);
 	if (ret) {
@@ -2333,6 +2345,9 @@
 		goto free_motg;
 	}
 
+	/* initialize reset counter */
+	motg->reset_counter = 0;
+
 	/* Some targets don't support PHY clock. */
 	motg->phy_reset_clk = clk_get(&pdev->dev, "usb_phy_clk");
 	if (IS_ERR(motg->phy_reset_clk))
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index 3d23522..c795a94 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -136,10 +136,10 @@
 	 480, 10, 2, 33, TRUE, 25200, 60000, FALSE, TRUE}
 #define HDMI_SETTINGS_720x480p60_4_3					\
 	{HDMI_VFRMT_720x480p60_4_3,      720,  16,  62,  60,  TRUE,	\
-	 480, 9, 6, 30,  TRUE, 27030, 60000, FALSE, TRUE}
+	 480, 9, 6, 30,  TRUE, 27027, 60000, FALSE, TRUE}
 #define HDMI_SETTINGS_720x480p60_16_9					\
 	{HDMI_VFRMT_720x480p60_16_9,     720,  16,  62,  60,  TRUE,	\
-	 480, 9, 6, 30,  TRUE, 27030, 60000, FALSE, TRUE}
+	 480, 9, 6, 30,  TRUE, 27027, 60000, FALSE, TRUE}
 #define HDMI_SETTINGS_1280x720p60_16_9					\
 	{HDMI_VFRMT_1280x720p60_16_9,    1280, 110, 40,  220, FALSE,	\
 	 720, 5, 5, 20, FALSE, 74250, 60000, FALSE, TRUE}
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index a449fc7..aaad2df 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3072,10 +3072,10 @@
 	HDMI_MSM_AUDIO_ARCS(27000, {
 		{4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
 		{12288, 27000}, {25088, 30000}, {24576, 27000} }),
-	/*  27.030MHz */
-	HDMI_MSM_AUDIO_ARCS(27030, {
-		{4096, 27030}, {6272, 30030}, {6144, 27030}, {12544, 30030},
-		{12288, 27030}, {25088, 30030}, {24576, 27030} }),
+	/*  27.027MHz */
+	HDMI_MSM_AUDIO_ARCS(27027, {
+		{4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
+		{12288, 27027}, {25088, 30030}, {24576, 27027} }),
 	/*  74.250MHz */
 	HDMI_MSM_AUDIO_ARCS(74250, {
 		{4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 9380257..0317857 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -2,7 +2,7 @@
  *
  * MSM MDP Interface (used by framebuffer core)
  *
- * Copyright (c) 2007-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2007-2012, Code Aurora Forum. All rights reserved.
  * Copyright (C) 2007 Google Incorporated
  *
  * This software is licensed under the terms of the GNU General Public
@@ -31,7 +31,6 @@
 #include <linux/mutex.h>
 #include <linux/pm_runtime.h>
 #include <linux/regulator/consumer.h>
-#include <linux/memory_alloc.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
 #include <linux/semaphore.h>
@@ -119,10 +118,8 @@
 extern int mdp_lcd_rd_cnt_offset_fast;
 extern int mdp_usec_diff_threshold;
 
-#ifdef CONFIG_FB_MSM_LCDC
 extern int first_pixel_start_x;
 extern int first_pixel_start_y;
-#endif
 
 #ifdef MSM_FB_ENABLE_DBGFS
 struct dentry *mdp_dir;
@@ -1356,30 +1353,7 @@
 #ifdef CONFIG_FB_MSM_OVERLAY
 		mdp_hw_cursor_init();
 #endif
-
 		mdp_resource_initialized = 1;
-
-		if (!mdp_pdata)
-			return 0;
-
-		size = mdp_pdata->mdp_writeback_size_ov0 +
-			mdp_pdata->mdp_writeback_size_ov1;
-		if (size) {
-			mdp_pdata->mdp_writeback_phys =
-				(void *)allocate_contiguous_memory_nomap
-				(size,
-				 mdp_pdata->mdp_writeback_memtype,
-				 4); /* align to word size */
-			if (mdp_pdata->mdp_writeback_phys) {
-				pr_info("allocating %d bytes at %p for mdp writeback\n",
-					size, mdp_pdata->mdp_writeback_phys);
-			} else {
-				pr_err("%s cannot allocate memory for mdp writeback!\n",
-				       __func__);
-			}
-		} else {
-			mdp_pdata->mdp_writeback_phys = 0;
-		}
 		return 0;
 	}
 
@@ -1405,6 +1379,21 @@
 	mfd->pdev = msm_fb_dev;
 	mfd->mdp_rev = mdp_rev;
 
+	mfd->ov0_wb_buf = MDP_ALLOC(sizeof(struct mdp_buf_type));
+	mfd->ov1_wb_buf = MDP_ALLOC(sizeof(struct mdp_buf_type));
+	memset((void *)mfd->ov0_wb_buf, 0, sizeof(struct mdp_buf_type));
+	memset((void *)mfd->ov1_wb_buf, 0, sizeof(struct mdp_buf_type));
+
+	if (mdp_pdata) {
+		mfd->ov0_wb_buf->size = mdp_pdata->ov0_wb_size;
+		mfd->ov1_wb_buf->size = mdp_pdata->ov1_wb_size;
+		mfd->mem_hid = mdp_pdata->mem_hid;
+	} else {
+		mfd->ov0_wb_buf->size = 0;
+		mfd->ov1_wb_buf->size = 0;
+		mfd->mem_hid = 0;
+	}
+
 	mfd->ov0_blt_state  = 0;
 	mfd->use_ov0_blt = 0 ;
 
@@ -1665,19 +1654,6 @@
 	}
 #endif
 
-	if (mdp_pdata && mdp_pdata->mdp_writeback_phys) {
-		mfd->writeback_overlay0_phys =
-			(mdp_pdata->mdp_writeback_size_ov0) ?
-			mdp_pdata->mdp_writeback_phys : 0;
-		mfd->writeback_overlay1_phys =
-			(mdp_pdata->mdp_writeback_size_ov1) ?
-			(mdp_pdata->mdp_writeback_phys +
-			 mdp_pdata->mdp_writeback_size_ov0) : 0;
-	} else {
-		mfd->writeback_overlay0_phys = 0;
-		mfd->writeback_overlay1_phys = 0;
-	}
-
 	/* set driver data */
 	platform_set_drvdata(msm_fb_dev, mfd);
 
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index ceb133b..7b67905 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -22,8 +22,9 @@
 #include <linux/fb.h>
 #include <linux/hrtimer.h>
 #include <linux/msm_mdp.h>
-
+#include <linux/memory_alloc.h>
 #include <mach/hardware.h>
+#include <linux/ion.h>
 
 #ifdef CONFIG_MSM_BUS_SCALING
 #include <mach/msm_bus.h>
@@ -66,6 +67,13 @@
 #define MDPOP_SHARPENING	BIT(11) /* enable sharpening */
 #define MDPOP_BLUR		BIT(12) /* enable blur */
 #define MDPOP_FG_PM_ALPHA       BIT(13)
+#define MDP_ALLOC(x)  kmalloc(x, GFP_KERNEL)
+
+struct mdp_buf_type {
+	struct ion_handle *ihdl;
+	u32 phys_addr;
+	u32 size;
+};
 
 struct mdp_table_entry {
 	uint32_t reg;
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index c45cebd..d7dd1ed 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -235,6 +235,7 @@
 #define MDP4_PIPE_PER_MIXER	2
 
 #define MDP4_MAX_PLANE		4
+#define VSYNC_PERIOD		16
 
 struct mdp4_hsic_regs {
 	int32_t params[NUM_HSIC_PARAM];
@@ -403,14 +404,26 @@
 uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
 uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
 void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
-void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
-			struct mdp4_overlay_pipe *pipe);
 #ifdef CONFIG_FB_MSM_DTV
 void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
 			struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
+			struct mdp4_overlay_pipe *pipe);
+void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
+	struct mdp4_overlay_pipe *pipe);
 #else
 static inline void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
-				struct mdp4_overlay_pipe *pipe)
+	struct mdp4_overlay_pipe *pipe)
+{
+	/* empty */
+}
+static inline void  mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
+			struct mdp4_overlay_pipe *pipe)
+{
+	/* empty */
+}
+static inline void  mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
+	struct mdp4_overlay_pipe *pipe)
 {
 	/* empty */
 }
@@ -428,7 +441,9 @@
 static inline int mdp4_overlay_borderfill_supported(void)
 {
 	unsigned int mdp_hw_version;
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 	mdp_hw_version = inpdw(MDP_BASE + 0x0); /* MDP_HW_VERSION */
+	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	return (mdp_hw_version >= 0x0402030b);
 }
 
@@ -465,8 +480,6 @@
 int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
 int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
 int mdp4_overlay_unset(struct fb_info *info, int ndx);
-void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
-	struct mdp4_overlay_pipe *pipe);
 int mdp4_overlay_play_wait(struct fb_info *info,
 	struct msmfb_overlay_data *req);
 int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
@@ -678,4 +691,9 @@
 
 void mdp4_hsic_set(struct mdp4_overlay_pipe *pipe, struct dpp_ctrl *ctrl);
 void mdp4_hsic_update(struct mdp4_overlay_pipe *pipe);
+
+u32  mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
+void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
+void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num);
+
 #endif /* MDP_H */
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 3cbf1f4..29f1f7c 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -1349,7 +1349,7 @@
 	struct mdp4_overlay_pipe *bg_pipe;
 	unsigned char *overlay_base, *rgb_base;
 	uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
-	uint32 fg_color3_out;
+	uint32 fg_color3_out, fg_alpha = 0, bg_alpha = 0;
 	int off;
 
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE)
@@ -1373,17 +1373,48 @@
 		return;
 	}
 
+	if (bg_pipe->pipe_type == OVERLAY_TYPE_BF &&
+	    pipe->mixer_stage > MDP4_MIXER_STAGE0) {
+		bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
+						  MDP4_MIXER_STAGE0);
+	}
+
+	if (pipe->alpha_enable) {
+		/* alpha channel is lost on VG pipe when downscaling */
+		if (pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
+		    (pipe->dst_w < pipe->src_w || pipe->dst_h < pipe->src_h))
+			fg_alpha = 0;
+		else
+			fg_alpha = 1;
+	}
+
+	if (!fg_alpha && bg_pipe && bg_pipe->alpha_enable) {
+		struct mdp4_overlay_pipe *tmp;
+		int stage;
+
+		bg_alpha = 1;
+		/* check all bg layers are opaque to propagate bg alpha */
+		stage = bg_pipe->mixer_stage + 1;
+		for (; stage < pipe->mixer_stage; stage++) {
+			tmp = mdp4_overlay_stage_pipe(pipe->mixer_num, stage);
+			if (!tmp || tmp->alpha_enable || tmp->is_fg) {
+				bg_alpha = 0;
+				break;
+			}
+		}
+	}
+
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
 
 	blend_op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
 		    MDP4_BLEND_BG_ALPHA_BG_CONST);
 	outpdw(overlay_base + off + 0x108, pipe->alpha);
 	outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
-	fg_color3_out = 0; /* keep bg alpha by default */
+	fg_color3_out = 1; /* keep fg alpha by default */
 
 	if (pipe->is_fg) {
 		if (pipe->alpha == 0xff &&
-		    bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
+		    bg_pipe && bg_pipe->pipe_num <= OVERLAY_PIPE_RGB2) {
 			rgb_base = MDP_BASE + MDP4_RGB_BASE;
 			rgb_base += MDP4_RGB_OFF * bg_pipe->pipe_num;
 			rgb_src_format = inpdw(rgb_base + 0x50);
@@ -1391,14 +1422,11 @@
 			outpdw(rgb_base + 0x50, rgb_src_format);
 			outpdw(rgb_base + 0x1008, constant_color);
 		}
-	} else if (pipe->alpha_enable) {
-		/* pick fg alpha */
+	} else if (fg_alpha) {
 		blend_op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
-			    MDP4_BLEND_FG_ALPHA_FG_PIXEL |
 			    MDP4_BLEND_BG_INV_ALPHA);
 		fg_color3_out = 1; /* keep fg alpha */
-	} else if (bg_pipe->alpha_enable) {
-		/* pick bg alpha */
+	} else if (bg_alpha) {
 		blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
 			    MDP4_BLEND_FG_ALPHA_BG_PIXEL |
 			    MDP4_BLEND_FG_INV_ALPHA);
@@ -1419,7 +1447,7 @@
 			outpdw(overlay_base + off + 0x118,
 					(c1 << 16 | c0));
 			outpdw(overlay_base + off + 0x11c, c2);
-		} else {
+		} else if (bg_pipe) {
 			transp_color_key(bg_pipe->src_format,
 				pipe->transp, &c0, &c1, &c2);
 			/* bg blocked */
@@ -1859,10 +1887,10 @@
 	}
 
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	*srcp_ihdl = ion_import_fd(mfd->client, img->memory_id);
+	*srcp_ihdl = ion_import_fd(mfd->iclient, img->memory_id);
 	if (IS_ERR_OR_NULL(*srcp_ihdl))
 		return PTR_ERR(*srcp_ihdl);
-	if (!ion_phys(mfd->client, *srcp_ihdl, start, (size_t *) len))
+	if (!ion_phys(mfd->iclient, *srcp_ihdl, start, (size_t *) len))
 		return 0;
 	else
 		return -EINVAL;
@@ -2125,6 +2153,7 @@
 	mixer = mfd->panel_info.pdest;	/* DISPLAY_1 or DISPLAY_2 */
 
 	ret = mdp4_overlay_req2pipe(req, mixer, &pipe, mfd);
+
 	if (ret < 0) {
 		mutex_unlock(&mfd->dma->ov_mutex);
 		pr_err("%s: mdp4_overlay_req2pipe, ret=%d\n", __func__, ret);
@@ -2137,6 +2166,13 @@
 		mfd->use_ov0_blt |= (use_blt << (pipe->pipe_ndx-1));
 	}
 
+	if (!IS_ERR_OR_NULL(mfd->iclient)) {
+		if (pipe->flags & MDP_SECURE_OVERLAY_SESSION)
+			mfd->mem_hid |= ION_SECURE;
+		else
+			mfd->mem_hid &= ~ION_SECURE;
+	}
+
 	/* return id back to user */
 	req->id = pipe->pipe_ndx;	/* pipe_ndx start from 1 */
 	pipe->req_data = *req;		/* keep original req */
@@ -2189,7 +2225,7 @@
 			}
 		} else {
 			if (ctrl->panel_mode & MDP4_PANEL_DTV)
-				mdp4_overlay_dtv_vsync_push(mfd, pipe);
+				mdp4_overlay_dtv_ov_done_push(mfd, pipe);
 		}
 	}
 	mutex_unlock(&mfd->dma->ov_mutex);
@@ -2284,6 +2320,8 @@
 
 		mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
 		mdp4_overlay_update_blt_mode(mfd);
+		if (!mfd->use_ov0_blt)
+			mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
 	}
 	else {	/* mixer1, DTV, ATV */
 		if (ctrl->panel_mode & MDP4_PANEL_DTV)
@@ -2601,11 +2639,11 @@
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	if (!IS_ERR_OR_NULL(srcp0_ihdl))
-		ion_free(mfd->client, srcp0_ihdl);
+		ion_free(mfd->iclient, srcp0_ihdl);
 	if (!IS_ERR_OR_NULL(srcp1_ihdl))
-		ion_free(mfd->client, srcp1_ihdl);
+		ion_free(mfd->iclient, srcp1_ihdl);
 	if (!IS_ERR_OR_NULL(srcp2_ihdl))
-		ion_free(mfd->client, srcp2_ihdl);
+		ion_free(mfd->iclient, srcp2_ihdl);
 #endif
 	return ret;
 }
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 484ed7d..db07cb5 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -156,7 +156,7 @@
 
 		dsi_pipe = pipe; /* keep it */
 
-		pipe->blt_base = (ulong) mfd->writeback_overlay0_phys;
+		mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
 		pipe->blt_addr = 0;
 
 	} else {
@@ -301,7 +301,9 @@
 	pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
 	__func__, dsi_pipe->blt_end, (int)dsi_pipe->blt_addr, current->pid);
 
-	if (dsi_pipe->blt_base == 0) {
+	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+	if (mfd->ov0_wb_buf->phys_addr == 0) {
 		pr_info("%s: no blt_base assigned\n", __func__);
 		return -EBUSY;
 	}
@@ -313,7 +315,7 @@
 		dsi_pipe->blt_cnt = 0;
 		dsi_pipe->ov_cnt = 0;
 		dsi_pipe->dmap_cnt = 0;
-		dsi_pipe->blt_addr = dsi_pipe->blt_base;
+		dsi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
 		mdp4_stat.blt_dsi_cmd++;
 		spin_unlock_irqrestore(&mdp_spin_lock, flag);
 		return 0;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index d68396a..c5d1b0c 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -139,7 +139,7 @@
 		dsi_pipe = pipe; /* keep it */
 		init_completion(&dsi_video_comp);
 
-		pipe->blt_base = (ulong) mfd->writeback_overlay0_phys;
+		mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
 		pipe->blt_addr = 0;
 
 	} else {
@@ -572,14 +572,16 @@
 	int data;
 	int change = 0;
 
-	if (dsi_pipe->blt_base == 0) {
+	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+	if (mfd->ov0_wb_buf->phys_addr == 0) {
 		pr_info("%s: no blt_base assigned\n", __func__);
 		return;
 	}
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	if (enable && dsi_pipe->blt_addr == 0) {
-		dsi_pipe->blt_addr = dsi_pipe->blt_base;
+		dsi_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
 		dsi_pipe->blt_cnt = 0;
 		dsi_pipe->ov_cnt = 0;
 		dsi_pipe->dmap_cnt = 0;
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index c8135d4..592febe 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-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
@@ -214,12 +214,6 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 	mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 
-	/*
-	 * wait for vsync == 16.6 ms to make sure
-	 * the last frame finishes
-	*/
-	msleep(20);
-
 	return 0;
 }
 
@@ -266,8 +260,6 @@
 
 	ret = panel_next_off(pdev);
 
-	msleep(20);
-
 	dev_info(&pdev->dev, "mdp4_overlay_dtv: off");
 	return ret;
 }
@@ -333,8 +325,6 @@
 		MDP_OUTP(MDP_BASE + MDP4_OVERLAYPROC1_BASE + 0x5008,
 			(0x0 & 0xFFF));		/* 12-bit R */
 		mdp_pipe_ctrl(MDP_OVERLAY1_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
-		pipe->src_format = MDP_ARGB_8888;
 	} else {
 		switch (mfd->ibuf.bpp) {
 		case 2:
@@ -399,7 +389,7 @@
 
 	flags = pipe->flags;
 	pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
-	mdp4_overlay_dtv_vsync_push(mfd, pipe);
+	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
 	pipe->flags = flags;
 
 	if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE &&
@@ -415,6 +405,9 @@
 	unsigned long flag;
 
 	/* enable irq */
+	if (mfd->ov_start)
+		return;
+
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	mdp_enable_irq(MDP_OVERLAY1_TERM);
 	INIT_COMPLETION(dtv_pipe->comp);
@@ -431,11 +424,14 @@
 {
 	u32 data = inpdw(MDP_BASE + DTV_BASE);
 
-	mfd->ov_start = false;
-
+	if (mfd->ov_start)
+		mfd->ov_start = false;
+	else
+		return;
 	if (!(data & 0x1) || (pipe == NULL))
 		return;
-	wait_for_completion_killable(&dtv_pipe->comp);
+	wait_for_completion_timeout(&dtv_pipe->comp,
+		msecs_to_jiffies(VSYNC_PERIOD));
 	mdp_disable_irq(MDP_OVERLAY1_TERM);
 }
 
@@ -457,17 +453,13 @@
 void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
 	struct mdp4_overlay_pipe *pipe)
 {
-	if (mfd->ov_end) {
-		mfd->ov_end = false;
-		return;
-	}
 	mdp4_overlay_dtv_wait4_ov_done(mfd, pipe);
 	mdp4_set_perf_level();
 }
 
 void mdp4_external_vsync_dtv()
 {
-	complete(&dtv_pipe->comp);
+	complete_all(&dtv_pipe->comp);
 }
 
 /*
@@ -475,7 +467,7 @@
  */
 void mdp4_overlay1_done_dtv()
 {
-	complete(&dtv_pipe->comp);
+	complete_all(&dtv_pipe->comp);
 }
 
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -529,10 +521,6 @@
 		pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
 		mdp4_overlay_rgb_setup(pipe);
 	}
-	if (mfd->ov_start) {
-		mdp4_overlay_dtv_wait4_ov_done(mfd, pipe);
-		mfd->ov_end = true;
-	}
 	mdp4_overlay_dtv_ov_done_push(mfd, pipe);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 1dbbf94..bef988c 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -126,7 +126,7 @@
 		lcdc_pipe = pipe; /* keep it */
 		init_completion(&lcdc_comp);
 
-		pipe->blt_base = (ulong) mfd->writeback_overlay0_phys;
+		mdp4_init_writeback_buf(mfd, MDP4_MIXER0);
 		pipe->blt_addr = 0;
 
 	} else {
@@ -466,14 +466,16 @@
 	unsigned long flag;
 	int change = 0;
 
-	if (lcdc_pipe->blt_base == 0) {
+	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+	if (!mfd->ov0_wb_buf->phys_addr) {
 		pr_debug("%s: no blt_base assigned\n", __func__);
 		return;
 	}
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	if (enable && lcdc_pipe->blt_addr == 0) {
-		lcdc_pipe->blt_addr = lcdc_pipe->blt_base;
+		lcdc_pipe->blt_addr = mfd->ov0_wb_buf->phys_addr;
 		change++;
 		lcdc_pipe->blt_cnt = 0;
 		lcdc_pipe->ov_cnt = 0;
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index f9edf07..e30f76a 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -2226,3 +2226,88 @@
 	return out;
 }
 
+void mdp4_init_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
+{
+	struct mdp_buf_type *buf;
+
+	if (mix_num == MDP4_MIXER0)
+		buf = mfd->ov0_wb_buf;
+	else
+		buf = mfd->ov1_wb_buf;
+
+	buf->ihdl = NULL;
+	buf->phys_addr = 0;
+}
+
+u32 mdp4_allocate_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
+{
+	struct mdp_buf_type *buf;
+	ion_phys_addr_t	addr;
+	u32 len;
+
+	if (mix_num == MDP4_MIXER0)
+		buf = mfd->ov0_wb_buf;
+	else
+		buf = mfd->ov1_wb_buf;
+
+	if (buf->phys_addr || !IS_ERR_OR_NULL(buf->ihdl))
+		return 0;
+
+	if (!buf->size) {
+		pr_err("%s:%d In valid size", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (!IS_ERR_OR_NULL(mfd->iclient)) {
+		pr_info("%s:%d ion based allocation", __func__, __LINE__);
+		buf->ihdl = ion_alloc(mfd->iclient, buf->size, 4,
+			(1 << mfd->mem_hid));
+		if (!IS_ERR_OR_NULL(buf->ihdl)) {
+			if (ion_phys(mfd->iclient, buf->ihdl,
+				&addr, &len)) {
+				pr_err("%s:%d: ion_phys map failed",
+					__func__, __LINE__);
+				return -ENOMEM;
+			}
+		} else {
+			pr_err("%s:%d: ion_alloc failed", __func__,
+				__LINE__);
+			return -ENOMEM;
+		}
+	} else {
+		addr = allocate_contiguous_memory_nomap(buf->size,
+			mfd->mem_hid, 4);
+	}
+	if (addr) {
+		pr_info("allocating %d bytes at %x for mdp writeback\n",
+			buf->size, (u32) addr);
+		buf->phys_addr = addr;
+		return 0;
+	} else {
+		pr_err("%s cannot allocate memory for mdp writeback!\n",
+			 __func__);
+		return -ENOMEM;
+	}
+}
+
+void mdp4_free_writeback_buf(struct msm_fb_data_type *mfd, u32 mix_num)
+{
+	struct mdp_buf_type *buf;
+
+	if (mix_num == MDP4_MIXER0)
+		buf = mfd->ov0_wb_buf;
+	else
+		buf = mfd->ov1_wb_buf;
+
+	if (!IS_ERR_OR_NULL(mfd->iclient)) {
+		if (!IS_ERR_OR_NULL(buf->ihdl))
+			ion_free(mfd->iclient, buf->ihdl);
+		buf->ihdl = NULL;
+		pr_info("%s:%d free writeback imem", __func__, __LINE__);
+	} else {
+		if (buf->phys_addr)
+			free_contiguous_memory_by_paddr(buf->phys_addr);
+		pr_info("%s:%d free writeback pmem", __func__, __LINE__);
+	}
+	buf->phys_addr = 0;
+}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index ab91e41..defb484 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -3,7 +3,7 @@
  * Core MSM framebuffer driver.
  *
  * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-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
@@ -3311,7 +3311,9 @@
 	mfd->index = fbi_list_index;
 	mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	mfd->client = msm_ion_client_create(-1, pdev->name);
+	mfd->iclient = msm_ion_client_create(-1, pdev->name);
+#else
+	mfd->iclient = NULL;
 #endif
 	/* link to the latest pdev */
 	mfd->pdev = this_dev;
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index 9ee8972..8c48a73 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -37,7 +37,6 @@
 #include <linux/fb.h>
 #include <linux/list.h>
 #include <linux/types.h>
-#include <linux/ion.h>
 
 #include <linux/msm_mdp.h>
 #ifdef CONFIG_HAS_EARLYSUSPEND
@@ -165,16 +164,17 @@
 	struct timer_list msmfb_no_update_notify_timer;
 	struct completion msmfb_update_notify;
 	struct completion msmfb_no_update_notify;
-	u32 ov_start, ov_end;
-	void *writeback_overlay0_phys;
-	void *writeback_overlay1_phys;
 	struct mutex writeback_mutex;
 	struct mutex unregister_mutex;
 	struct list_head writeback_busy_queue;
 	struct list_head writeback_free_queue;
 	struct list_head writeback_register_queue;
-	wait_queue_head_t		wait_q;
-	struct ion_client *client;
+	wait_queue_head_t wait_q;
+	struct ion_client *iclient;
+	struct mdp_buf_type *ov0_wb_buf;
+	struct mdp_buf_type *ov1_wb_buf;
+	u32 ov_start;
+	u32 mem_hid;
 	u32 mdp_rev;
 	u32 use_ov0_blt, ov0_blt_state;
 };
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index f883fd7..1e02a2c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -88,6 +88,7 @@
 			ddl_context->dram_base_a.align_virtual_addr;
 	}
 	if (!status) {
+		ddl_context->metadata_shared_input.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&ddl_context->metadata_shared_input,
 			DDL_METADATA_TOTAL_INPUTBUFSIZE,
 			DDL_LINEAR_BUFFER_ALIGN_BYTES);
@@ -163,14 +164,16 @@
 		DDL_MSG_ERROR("ddl_open:Client_trasac_failed");
 		return status;
 	}
+	ddl->shared_mem[0].mem_type = DDL_CMD_MEM;
 	ptr = ddl_pmem_alloc(&ddl->shared_mem[0],
-			DDL_FW_AUX_HOST_CMD_SPACE_SIZE, sizeof(u32));
+			DDL_FW_AUX_HOST_CMD_SPACE_SIZE, 0);
 	if (!ptr)
 		status = VCD_ERR_ALLOC_FAIL;
 	if (!status && ddl_context->frame_channel_depth
 		== VCD_DUAL_FRAME_COMMAND_CHANNEL) {
+		ddl->shared_mem[1].mem_type = DDL_CMD_MEM;
 		ptr = ddl_pmem_alloc(&ddl->shared_mem[1],
-				DDL_FW_AUX_HOST_CMD_SPACE_SIZE, sizeof(u32));
+				DDL_FW_AUX_HOST_CMD_SPACE_SIZE, 0);
 		if (!ptr) {
 			ddl_pmem_free(&ddl->shared_mem[0]);
 			status = VCD_ERR_ALLOC_FAIL;
@@ -278,7 +281,7 @@
 #ifdef DDL_BUF_LOG
 	ddl_list_buffers(ddl);
 #endif
-
+	encoder->seq_header.mem_type = DDL_MM_MEM;
 	ptr = ddl_pmem_alloc(&encoder->seq_header,
 		DDL_ENC_SEQHEADER_SIZE, DDL_LINEAR_BUFFER_ALIGN_BYTES);
 	if (!ptr) {
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 051d32d..e613f29 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -84,6 +84,12 @@
 
 #define DDL_MAX_NUM_IN_INPUTFRAME_POOL          (DDL_MAX_NUM_OF_B_FRAME + 1)
 
+enum ddl_mem_area {
+	DDL_FW_MEM	= 0x0,
+	DDL_MM_MEM	= 0x1,
+	DDL_CMD_MEM	= 0x2
+};
+
 struct ddl_buf_addr{
 	u8  *virtual_base_addr;
 	u8  *physical_base_addr;
@@ -93,6 +99,7 @@
 	struct msm_mapped_buffer *mapped_buffer;
 	struct ion_handle *alloc_handle;
 	u32 buffer_size;
+	enum ddl_mem_area mem_type;
 };
 enum ddl_cmd_state{
 	DDL_CMD_INVALID         = 0x0,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index f8cbccd..e9c5193 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -60,7 +60,7 @@
 #define DDL_ENC_MIN_DPB_BUFFERS           2
 #define DDL_ENC_MAX_DPB_BUFFERS           4
 
-#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE         (DDL_KILO_BYTE(10))
+#define DDL_FW_AUX_HOST_CMD_SPACE_SIZE         (DDL_KILO_BYTE(8))
 #define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE  (DDL_KILO_BYTE(800))
 #define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE      (DDL_KILO_BYTE(800))
 #define DDL_FW_OTHER_CONTEXT_SPACE_SIZE        (DDL_KILO_BYTE(10))
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 6078821..b3790a5 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -633,72 +633,84 @@
 	ddl_calc_dec_hw_buffers_size(ddl->codec_data.decoder.
 		codec.codec, width, height, dpb, &buf_size);
 	if (buf_size.sz_context > 0) {
+		dec_bufs->context.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->context, buf_size.sz_context,
 			DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_nb_ip > 0) {
+		dec_bufs->h264_nb_ip.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->h264_nb_ip, buf_size.sz_nb_ip,
 			DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_vert_nb_mv > 0) {
+		dec_bufs->h264_vert_nb_mv.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->h264_vert_nb_mv,
 			buf_size.sz_vert_nb_mv, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_nb_dcac > 0) {
+		dec_bufs->nb_dcac.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->nb_dcac, buf_size.sz_nb_dcac,
 			DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_upnb_mv > 0) {
+		dec_bufs->upnb_mv.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->upnb_mv, buf_size.sz_upnb_mv,
 			DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_sub_anchor_mv > 0) {
+		dec_bufs->sub_anchor_mv.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->sub_anchor_mv,
 			buf_size.sz_sub_anchor_mv, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_overlap_xform > 0) {
+		dec_bufs->overlay_xform.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->overlay_xform,
 			buf_size.sz_overlap_xform, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_bit_plane3 > 0) {
+		dec_bufs->bit_plane3.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->bit_plane3,
 			buf_size.sz_bit_plane3, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_bit_plane2 > 0) {
+		dec_bufs->bit_plane2.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->bit_plane2,
 			buf_size.sz_bit_plane2, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_bit_plane1 > 0) {
+		dec_bufs->bit_plane1.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->bit_plane1,
 			buf_size.sz_bit_plane1, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_stx_parser > 0) {
+		dec_bufs->stx_parser.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->stx_parser,
 			buf_size.sz_stx_parser, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 	}
 	if (buf_size.sz_desc > 0) {
+		dec_bufs->desc.mem_type = DDL_MM_MEM;
 		ptr = ddl_pmem_alloc(&dec_bufs->desc, buf_size.sz_desc,
 			DDL_KILO_BYTE(2));
 		if (!ptr)
@@ -830,48 +842,56 @@
 		enc_bufs->sz_dpb_y = buf_size.sz_dpb_y;
 		enc_bufs->sz_dpb_c = buf_size.sz_dpb_c;
 		if (buf_size.sz_mv > 0) {
+			enc_bufs->mv.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->mv, buf_size.sz_mv,
 				DDL_KILO_BYTE(2));
 			if (!ptr)
 				status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_col_zero > 0) {
+			enc_bufs->col_zero.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->col_zero,
 				buf_size.sz_col_zero, DDL_KILO_BYTE(2));
 		if (!ptr)
 			status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_md > 0) {
+			enc_bufs->md.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->md, buf_size.sz_md,
 				DDL_KILO_BYTE(2));
 			if (!ptr)
 				status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_pred > 0) {
+			enc_bufs->pred.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->pred,
 				buf_size.sz_pred, DDL_KILO_BYTE(2));
 			if (!ptr)
 				status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_nbor_info > 0) {
+			enc_bufs->nbor_info.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->nbor_info,
 				buf_size.sz_nbor_info, DDL_KILO_BYTE(2));
 			if (!ptr)
 				status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_acdc_coef > 0) {
+			enc_bufs->acdc_coef.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->acdc_coef,
 				buf_size.sz_acdc_coef, DDL_KILO_BYTE(2));
 			if (!ptr)
 				status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_mb_info > 0) {
+			enc_bufs->mb_info.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->mb_info,
 				buf_size.sz_mb_info, DDL_KILO_BYTE(2));
 			if (!ptr)
 				status = VCD_ERR_ALLOC_FAIL;
 		}
 		if (buf_size.sz_context > 0) {
+			enc_bufs->context.mem_type = DDL_MM_MEM;
 			ptr = ddl_pmem_alloc(&enc_bufs->context,
 				buf_size.sz_context, DDL_KILO_BYTE(2));
 			if (!ptr)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 43aba2e..f69a471 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -52,6 +52,7 @@
 		goto bail_out;
 	}
 	ddl_context = ddl_get_context();
+	res_trk_set_mem_type(addr->mem_type);
 	alloc_size = (sz + alignment);
 	if (res_trk_get_enable_ion()) {
 		if (!ddl_context->video_ion_client)
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index 79f56bd..3a86afc 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -224,8 +224,7 @@
 
 static struct ion_client *res_trk_create_ion_client(void){
 	struct ion_client *video_client;
-	video_client = msm_ion_client_create((1<<ION_HEAP_TYPE_CARVEOUT),
-						"video_client");
+	video_client = msm_ion_client_create(-1, "video_client");
 	return video_client;
 }
 
@@ -423,6 +422,10 @@
 		if (resource_context.vidc_platform_data) {
 			resource_context.memtype =
 			resource_context.vidc_platform_data->memtype;
+			resource_context.fw_mem_type =
+			resource_context.vidc_platform_data->memtype;
+			resource_context.cmd_mem_type =
+			resource_context.vidc_platform_data->memtype;
 			if (resource_context.vidc_platform_data->enable_ion) {
 				resource_context.res_ion_client =
 					res_trk_create_ion_client();
@@ -431,6 +434,10 @@
 							__func__);
 					return;
 				}
+				resource_context.fw_mem_type =
+				resource_context.vidc_platform_data->memtype;
+				resource_context.cmd_mem_type =
+				ION_CP_MFC_HEAP_ID;
 			}
 			resource_context.disable_dmx =
 			resource_context.vidc_platform_data->disable_dmx;
@@ -444,6 +451,7 @@
 			resource_context.disable_dmx = 0;
 		}
 		resource_context.core_type = VCD_CORE_1080P;
+		resource_context.firmware_addr.mem_type = DDL_FW_MEM;
 		if (!ddl_pmem_alloc(&resource_context.firmware_addr,
 			VIDC_FW_SIZE, DDL_KILO_BYTE(128))) {
 			pr_err("%s() Firmware buffer allocation failed",
@@ -469,8 +477,18 @@
 	return status;
 }
 
-u32 res_trk_get_mem_type(void){
-	return resource_context.memtype;
+u32 res_trk_get_mem_type(void)
+{
+	switch (resource_context.res_mem_type) {
+	case DDL_FW_MEM:
+		return resource_context.fw_mem_type;
+	case DDL_MM_MEM:
+		return resource_context.memtype;
+	case DDL_CMD_MEM:
+		return resource_context.cmd_mem_type;
+	default:
+		return 0;
+	}
 }
 
 u32 res_trk_get_enable_ion(void)
@@ -489,3 +507,9 @@
 u32 res_trk_get_disable_dmx(void){
 	return resource_context.disable_dmx;
 }
+
+void res_trk_set_mem_type(enum ddl_mem_area mem_type)
+{
+	resource_context.res_mem_type = mem_type;
+	return;
+}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
index a90ccec..7283991 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.h
@@ -40,6 +40,8 @@
 	struct regulator *footswitch;
 	struct msm_vidc_platform_data *vidc_platform_data;
 	int memtype;
+	int fw_mem_type;
+	int cmd_mem_type;
 #ifdef CONFIG_MSM_BUS_SCALING
 	struct msm_bus_scale_pdata *vidc_bus_client_pdata;
 	uint32_t     pcl;
@@ -48,6 +50,7 @@
 	struct ddl_buf_addr firmware_addr;
 	struct ion_client *res_ion_client;
 	u32 disable_dmx;
+	enum ddl_mem_area res_mem_type;
 };
 
 #if DEBUG
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
index 04f28c6..47fa363 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker_api.h
@@ -33,4 +33,5 @@
 u32 res_trk_get_enable_ion(void);
 struct ion_client *res_trk_get_ion_client(void);
 u32 res_trk_get_disable_dmx(void);
+void res_trk_set_mem_type(enum ddl_mem_area mem_type);
 #endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index e5a5a84..e1407c8 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -67,6 +67,10 @@
 
 #define DDL_DEC_REQ_OUTPUT_FLUSH                0x1
 
+enum ddl_mem_area {
+	DDL_MM_MEM	= 0x0
+};
+
 struct ddl_buf_addr {
 	u32 *physical_base_addr;
 	u32 *virtual_base_addr;
@@ -74,6 +78,7 @@
 	u32 *align_virtual_addr;
 	struct msm_mapped_buffer *mapped_buffer;
 	u32 buffer_size;
+	enum ddl_mem_area mem_type;
 };
 
 enum ddl_cmd_state {
@@ -282,4 +287,6 @@
 void ddl_client_fatal_cb(struct ddl_context *ddl_context);
 void ddl_hw_fatal_cb(struct ddl_context *ddl_context);
 u32 ddl_hal_engine_reset(struct ddl_context *ddl_context);
+void ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment);
+void ddl_pmem_free(struct ddl_buf_addr *addr);
 #endif
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
index 4d39ef0..539f753 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.h
@@ -40,10 +40,6 @@
 		printk(KERN_DEBUG x); \
 } while (0)
 
-void ddl_pmem_alloc(struct ddl_buf_addr *, u32, u32);
-
-void ddl_pmem_free(struct ddl_buf_addr *);
-
 void ddl_set_core_start_time(const char *func_name, u32 index);
 
 void ddl_calc_core_proc_time(const char *func_name, u32 index);
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
index fe8e185..0172427 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker.c
@@ -718,3 +718,8 @@
 {
 	return NULL;
 }
+
+void res_trk_set_mem_type(enum ddl_mem_area mem_type)
+{
+	return;
+}
diff --git a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
index 7f9a2be..fbc91e2 100644
--- a/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
+++ b/drivers/video/msm/vidc/720p/resource_tracker/vcd_res_tracker_api.h
@@ -14,6 +14,7 @@
 #define _VIDEO_720P_RESOURCE_TRACKER_API_H_
 
 #include "vcd_core.h"
+#include "vcd_ddl.h"
 
 void res_trk_init(struct device *device, u32 irq);
 u32 res_trk_power_up(void);
@@ -29,4 +30,5 @@
 u32 res_trk_get_mem_type(void);
 u32 res_trk_get_enable_ion(void);
 struct ion_client *res_trk_get_ion_client(void);
+void res_trk_set_mem_type(enum ddl_mem_area mem_type);
 #endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 217030f..77affcd 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -57,6 +57,7 @@
 		pr_err("%s() map table is full", __func__);
 		goto bailout;
 	}
+	res_trk_set_mem_type(DDL_MM_MEM);
 	memtype = res_trk_get_mem_type();
 	if (!cctxt->vcd_enable_ion) {
 		map_buffer->phy_addr = (phys_addr_t)
diff --git a/include/linux/ion.h b/include/linux/ion.h
index 2cced6d..4f8756a 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -27,8 +27,8 @@
  * @ION_HEAP_TYPE_SYSTEM:	 memory allocated via vmalloc
  * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
  * @ION_HEAP_TYPE_CARVEOUT:	 memory allocated from a prereserved
- *				 carveout heap, allocations are physically
- *				 contiguous
+ * 				 carveout heap, allocations are physically
+ * 				 contiguous
  * @ION_HEAP_END:		 helper for iterating over heaps
  */
 enum ion_heap_type {
@@ -51,24 +51,42 @@
  * The ids listed are the order in which allocation will be attempted
  * if specified. Don't swap the order of heap ids unless you know what
  * you are doing!
+ * Id's are spaced by purpose to allow new Id's to be inserted in-between (for
+ * possible fallbacks)
  */
 
 enum ion_heap_ids {
-	ION_HEAP_SYSTEM_ID,
-	ION_HEAP_SYSTEM_CONTIG_ID,
-	ION_HEAP_EBI_ID,
-	ION_HEAP_SMI_ID,
-	ION_HEAP_ADSP_ID,
-	ION_HEAP_AUDIO_ID,
-	ION_HEAP_IOMMU_ID,
+	ION_IOMMU_HEAP_ID = 4,
+	ION_CP_MM_HEAP_ID = 8,
+	ION_CP_MFC_HEAP_ID = 12,
+	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
+	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
+	ION_SF_HEAP_ID = 24,
+	ION_AUDIO_HEAP_ID = 28,
+
+	ION_SYSTEM_HEAP_ID = 30,
+
+	ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_SECURE flag */
 };
 
-#define ION_KMALLOC_HEAP_NAME	"kmalloc"
+/**
+ * Flag to use when allocating to indicate that a heap is secure.
+ */
+#define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
+
+/**
+ * Macro should be used with ion_heap_ids defined above.
+ */
+#define ION_HEAP(bit) (1 << (bit))
+
 #define ION_VMALLOC_HEAP_NAME	"vmalloc"
-#define ION_EBI1_HEAP_NAME	"EBI1"
-#define ION_ADSP_HEAP_NAME	"adsp"
-#define ION_SMI_HEAP_NAME	"smi"
+#define ION_AUDIO_HEAP_NAME	"audio"
+#define ION_SF_HEAP_NAME	"sf"
+#define ION_MM_HEAP_NAME	"mm"
+#define ION_CAMERA_HEAP_NAME	"camera_preview"
 #define ION_IOMMU_HEAP_NAME	"iommu"
+#define ION_MFC_HEAP_NAME	"mfc"
+#define ION_WB_HEAP_NAME	"wb"
 
 #define CACHED          1
 #define UNCACHED        0
@@ -98,7 +116,7 @@
  * struct ion_platform_heap - defines a heap in the given platform
  * @type:	type of the heap from ion_heap_type enum
  * @id:		unique identifier for heap.  When allocating (lower numbers
- *		will be allocated from first)
+ * 		will be allocated from first)
  * @name:	used for debug purposes
  * @base:	base address of heap in physical memory if applicable
  * @size:	size of the heap in bytes if applicable
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 0c09799..d8c2edb 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -139,9 +139,10 @@
 #define MDP_DEINTERLACE_ODD		0x00400000
 #define MDP_OV_PLAY_NOWAIT		0x00200000
 #define MDP_SOURCE_ROTATED_90		0x00100000
-#define MDP_BORDERFILL_SUPPORTED	0x00010000
-#define MDP_MEMORY_ID_TYPE_FB		0x00001000
 #define MDP_DPP_HSIC			0x00080000
+#define MDP_BORDERFILL_SUPPORTED	0x00010000
+#define MDP_SECURE_OVERLAY_SESSION      0x00008000
+#define MDP_MEMORY_ID_TYPE_FB		0x00001000
 
 #define MDP_TRANSP_NOP 0xffffffff
 #define MDP_ALPHA_NOP 0xff
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index eb2c543..409e697 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -159,6 +159,8 @@
  *              dfab_usb_hs_clk in case of 8660 and 8960.
  * @pmic_id_irq: IRQ number assigned for PMIC USB ID line.
  * @mhl_enable: indicates MHL connector or not.
+ * @disable_reset_on_disconnect: perform USB PHY and LINK reset
+ *              on USB cable disconnection.
  * @swfi_latency: miminum latency to allow swfi.
  */
 struct msm_otg_platform_data {
@@ -173,6 +175,7 @@
 	const char *pclk_src_name;
 	int pmic_id_irq;
 	bool mhl_enable;
+	bool disable_reset_on_disconnect;
 	u32 swfi_latency;
 };
 
@@ -263,6 +266,7 @@
 #define PHY_RETENTIONED			BIT(1)
 #define PHY_OTG_COMP_DISABLED		BIT(2)
 	struct pm_qos_request_list pm_qos_req_dma;
+	int reset_counter;
 };
 
 struct msm_hsic_host_platform_data {
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 4be4265..33afdc9 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* 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
@@ -968,6 +968,7 @@
 {
 	struct snd_soc_codec *codec = w->codec;
 	u16 adc_reg;
+	u8 init_bit_shift;
 
 	pr_debug("%s %d\n", __func__, event);
 
@@ -982,16 +983,28 @@
 		return -EINVAL;
 	}
 
+	if (w->shift == 3)
+		init_bit_shift = 6;
+	else if  (w->shift == 7)
+		init_bit_shift = 7;
+	else {
+		pr_err("%s: Error, invalid init bit postion adc register\n",
+				__func__);
+		return -EINVAL;
+	}
+
+
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		tabla_codec_enable_adc_block(codec, 1);
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
+				1 << init_bit_shift);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
-		snd_soc_update_bits(codec, adc_reg, 1 << w->shift,
-			1 << w->shift);
-		usleep_range(1000, 1000);
-		snd_soc_update_bits(codec, adc_reg, 1 << w->shift, 0x00);
-		usleep_range(1000, 1000);
+
+		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+
 		break;
 	case SND_SOC_DAPM_POST_PMD:
 		tabla_codec_enable_adc_block(codec, 0);
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 453bce4..e7c2694 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1348,7 +1348,7 @@
 
 	mutex_lock(&routing_lock);
 
-	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_MAX_ID) {
+	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION)
 			adm_close(bedai->port_id);
 	}
@@ -1402,7 +1402,7 @@
 	 */
 	bedai->active = 1;
 
-	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_MAX_ID) {
+	for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
 		if (fe_dai_map[i][session_type] != INVALID_SESSION) {
 			adm_open(bedai->port_id, path_type,
 				params_rate(bedai->hw_params),