Merge "msm: camera: Fixed memory leak and added NULL check" into msm-3.0
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index c6e314e..64cba23 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -97,6 +97,9 @@
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
@@ -104,9 +107,8 @@
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP=y
 CONFIG_MSM_QPNP_INT=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_QUP=y
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_SUPPLY=y
@@ -146,8 +148,6 @@
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_BAMDMA=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
-CONFIG_SLIMBUS=y
-CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 6a5497d..5b55f99 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CFG80211=m
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="$(KERNEL_LOCAL_VERSION)-perf"
 # CONFIG_SWAP is not set
@@ -170,6 +169,7 @@
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_BT_MSM_SLEEP=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=m
 # CONFIG_CFG80211_WEXT is not set
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 11c4224..7f9c54d 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CFG80211=m
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOCALVERSION="$(KERNEL_LOCAL_VERSION)"
 # CONFIG_SWAP is not set
@@ -170,6 +169,7 @@
 CONFIG_BT_HCIUART_IBS=y
 CONFIG_BT_MSM_SLEEP=y
 CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=m
 # CONFIG_CFG80211_WEXT is not set
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 2bc922a..1bd3c56 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -9,7 +9,6 @@
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
@@ -87,9 +86,9 @@
 CONFIG_MSM_DLOAD_MODE=y
 CONFIG_MSM_QDSS=y
 CONFIG_MSM_SLEEP_STATS=y
-CONFIG_MSM_DCVS=y
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_DCVS=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -291,7 +290,6 @@
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
-CONFIG_SPI_MASTER=y
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -303,7 +301,6 @@
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
 CONFIG_SENSORS_PM8XXX_ADC=y
-CONFIG_HWMON=y
 CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
@@ -332,9 +329,9 @@
 CONFIG_OV2720=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX091=y
 CONFIG_MSM_GEMINI=y
 CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 706bc88..69806d0 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -8,7 +8,6 @@
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
 CONFIG_NAMESPACES=y
 # CONFIG_UTS_NS is not set
@@ -87,13 +86,13 @@
 CONFIG_MSM_QDSS=y
 CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
 CONFIG_MSM_SLEEP_STATS=y
-CONFIG_MSM_DCVS=y
 CONFIG_MSM_RTB=y
 CONFIG_MSM_RTB_SEPARATE_CPUS=y
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L1_ERR_PANIC=y
 CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_DCVS=y
 CONFIG_MSM_CACHE_DUMP=y
 CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
 CONFIG_STRICT_MEMORY_RWX=y
@@ -297,7 +296,6 @@
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
-CONFIG_SPI_MASTER=y
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -309,7 +307,6 @@
 CONFIG_PM8921_CHARGER=y
 CONFIG_PM8921_BMS=y
 CONFIG_SENSORS_PM8XXX_ADC=y
-CONFIG_HWMON=y
 CONFIG_SENSORS_EPM_ADC=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS8960=y
@@ -338,9 +335,9 @@
 CONFIG_OV2720=y
 CONFIG_MSM_CAMERA_SENSOR=y
 CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX091=y
 CONFIG_MSM_GEMINI=y
 CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=m
 CONFIG_ION=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index ebb78d4..70cba0f 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -43,7 +43,6 @@
 # CONFIG_MSM_RESET_MODEM is not set
 CONFIG_MSM_IPC_ROUTER=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
-CONFIG_MSM_PIL_QDSP6V4=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 # CONFIG_MSM_SYSMON_COMM is not set
 CONFIG_MSM_MODEM_8960=y
@@ -192,7 +191,6 @@
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=m
-CONFIG_SLIMBUS=y
 CONFIG_SLIMBUS_MSM_CTRL=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index faa7748..e55c484 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -13,6 +13,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/unwind.h>
 
 #ifdef __ARMEB__
 #define xh r0
@@ -44,6 +45,7 @@
  */
 
 ENTRY(__do_div64)
+UNWIND(.fnstart)
 
 	@ Test for easy paths first.
 	subs	ip, r4, #1
@@ -189,7 +191,12 @@
 	moveq	yh, xh
 	moveq	xh, #0
 	moveq	pc, lr
+UNWIND(.fnend)
 
+UNWIND(.fnstart)
+UNWIND(.pad #4)
+UNWIND(.save {lr})
+Ldiv0_64:
 	@ Division by 0:
 	str	lr, [sp, #-8]!
 	bl	__div0
@@ -200,4 +207,5 @@
 	mov	xh, #0
 	ldr	pc, [sp], #8
 
+UNWIND(.fnend)
 ENDPROC(__do_div64)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d142713..2609aca 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -222,7 +222,6 @@
 obj-$(CONFIG_ARCH_MSM7X27A) += clock-pcom-lookup.o devices-msm7x27a.o
 board-7627a-all-objs += board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
 board-7627a-all-objs += board-msm7627a-display.o board-msm7627a-wlan.o board-msm7627a-io.o
-board-7627a-all-objs += board-msm7627a-audio.o
 obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-7627a-all.o
 obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-7627a-all.o
 obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-7627a-all.o
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 0ff931a..7b84a68 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -181,12 +181,12 @@
 			.io_fraction = 0,
 		},
 		{
-			.gpu_freq = 320000000,
+			.gpu_freq = 325000000,
 			.bus_freq = 2,
 			.io_fraction = 33,
 		},
 		{
-			.gpu_freq = 192000000,
+			.gpu_freq = 200000000,
 			.bus_freq = 1,
 			.io_fraction = 100,
 		},
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d06b5bd..3f4266f 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -588,6 +588,12 @@
 	.name = "usb",
 };
 
+static int phy_init_seq[] = {
+	0x38, 0x81, /* update DC voltage level */
+	0x24, 0x82, /* set pre-emphasis and rise/fall time */
+	-1
+};
+
 static struct msm_otg_platform_data msm_otg_pdata = {
 	.mode			= USB_OTG,
 	.otg_control		= OTG_PMIC_CONTROL,
@@ -595,6 +601,7 @@
 	.pmic_id_irq		= PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
 	.power_budget		= 750,
 	.bus_scale_table	= &usb_bus_scale_pdata,
+	.phy_init_seq		= phy_init_seq,
 };
 
 static struct msm_usb_host_platform_data msm_ehci_host_pdata3 = {
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 5b632bd..bfb8be3 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -55,7 +55,7 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
-static struct gpiomux_setting gsbi5 = {
+static struct gpiomux_setting gsbi_uart = {
 	.func = GPIOMUX_FUNC_1,
 	.drv = GPIOMUX_DRV_8MA,
 	.pull = GPIOMUX_PULL_NONE,
@@ -327,30 +327,6 @@
 		},
 	},
 	{
-		.gpio      = 22,	/* GSBI5 UART2 */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gsbi5,
-		},
-	},
-	{
-		.gpio      = 23,	/* GSBI5 UART2 */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gsbi5,
-		},
-	},
-	{
-		.gpio      = 24,	/* GSBI5 UART2 */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gsbi5,
-		},
-	},
-	{
-		.gpio      = 25,	/* GSBI5 UART2 */
-		.settings = {
-			[GPIOMUX_SUSPENDED] = &gsbi5,
-		},
-	},
-	{
 		.gpio      = 44,	/* GSBI12 I2C QUP SDA */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gsbi12,
@@ -376,6 +352,60 @@
 	},
 };
 
+static struct msm_gpiomux_config msm8960_gsbi5_uart_configs[] __initdata = {
+	{
+		.gpio      = 22,        /* GSBI5 UART2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+	{
+		.gpio      = 23,        /* GSBI5 UART2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+	{
+		.gpio      = 24,        /* GSBI5 UART2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+	{
+		.gpio      = 25,        /* GSBI5 UART2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+};
+
+static struct msm_gpiomux_config msm8960_gsbi8_uart_configs[] __initdata = {
+	{
+		.gpio      = 34,        /* GSBI8 UART3 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+	{
+		.gpio      = 35,        /* GSBI8 UART3 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+	{
+		.gpio      = 36,        /* GSBI8 UART3 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+	{
+		.gpio      = 37,        /* GSBI8 UART3 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi_uart,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm8960_slimbus_config[] __initdata = {
 	{
 		.gpio	= 60,		/* slimbus data */
@@ -686,5 +716,12 @@
 	msm_gpiomux_install(msm8960_mdp_vsync_configs,
 			ARRAY_SIZE(msm8960_mdp_vsync_configs));
 
+	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+		msm_gpiomux_install(msm8960_gsbi8_uart_configs,
+			ARRAY_SIZE(msm8960_gsbi8_uart_configs));
+	else
+		msm_gpiomux_install(msm8960_gsbi5_uart_configs,
+			ARRAY_SIZE(msm8960_gsbi5_uart_configs));
+
 	return 0;
 }
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 257b27f..f462c7a 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2192,7 +2192,6 @@
 static struct platform_device *common_devices[] __initdata = {
 	&msm8960_device_dmov,
 	&msm_device_smd,
-	&msm8960_device_uart_gsbi5,
 	&msm_device_uart_dm6,
 	&msm_device_saw_core0,
 	&msm_device_saw_core1,
@@ -2275,6 +2274,7 @@
 };
 
 static struct platform_device *sim_devices[] __initdata = {
+	&msm8960_device_uart_gsbi5,
 	&msm8960_device_otg,
 	&msm8960_device_gadget_peripheral,
 	&msm_device_hsusb_host,
@@ -2320,6 +2320,7 @@
 };
 
 static struct platform_device *rumi3_devices[] __initdata = {
+	&msm8960_device_uart_gsbi5,
 	&msm_kgsl_3d0,
 	&msm_kgsl_2d0,
 	&msm_kgsl_2d1,
@@ -2900,6 +2901,12 @@
 		platform_device_register(&msm8960_device_ext_3p3v_vreg);
 	if (machine_is_msm8960_cdp())
 		platform_device_register(&msm8960_device_ext_l2_vreg);
+
+	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+		platform_device_register(&msm8960_device_uart_gsbi8);
+	else
+		platform_device_register(&msm8960_device_uart_gsbi5);
+
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 52f3de6..674df09 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -61,7 +61,7 @@
 	}
 }
 
-static const char *msm_dt_match[] __initdata = {
+static const char *msm_dt_match[] __initconst = {
 	"qcom,msmcopper",
 	NULL
 };
diff --git a/arch/arm/mach-msm/board-msm7627a-audio.c b/arch/arm/mach-msm/board-msm7627a-audio.c
deleted file mode 100644
index c393226..0000000
--- a/arch/arm/mach-msm/board-msm7627a-audio.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/* 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 <asm/mach-types.h>
-#include <linux/platform_device.h>
-#include <linux/android_pmem.h>
-#include <linux/gfp.h>
-#include <mach/msm_memtypes.h>
-#include <mach/board.h>
-#include <mach/msm_rpcrouter.h>
-#include <mach/socinfo.h>
-
-#include "devices.h"
-#include "board-msm7627a.h"
-#include "devices-msm7x2xa.h"
-
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
-	.name = "pmem_adsp",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-	.request_region = request_fmem_c_region,
-	.release_region = release_fmem_c_region,
-	.reusable = 1,
-};
-
-static struct platform_device android_pmem_adsp_device = {
-	.name = "android_pmem",
-	.id = 1,
-	.dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-#define SND(desc, num) { .name = #desc, .id = num }
-static struct snd_endpoint snd_endpoints_list[] = {
-	SND(HANDSET, 0),
-	SND(MONO_HEADSET, 2),
-	SND(HEADSET, 3),
-	SND(SPEAKER, 6),
-	SND(TTY_HEADSET, 8),
-	SND(TTY_VCO, 9),
-	SND(TTY_HCO, 10),
-	SND(BT, 12),
-	SND(IN_S_SADC_OUT_HANDSET, 16),
-	SND(IN_S_SADC_OUT_SPEAKER_PHONE, 25),
-	SND(FM_DIGITAL_STEREO_HEADSET, 26),
-	SND(FM_DIGITAL_SPEAKER_PHONE, 27),
-	SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
-	SND(STEREO_HEADSET_AND_SPEAKER, 31),
-	SND(CURRENT, 0x7FFFFFFE),
-	SND(FM_ANALOG_STEREO_HEADSET, 35),
-	SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
-};
-#undef SND
-
-static struct msm_snd_endpoints msm_device_snd_endpoints = {
-	.endpoints = snd_endpoints_list,
-	.num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
-};
-
-static struct platform_device msm_device_snd = {
-	.name = "msm_snd",
-	.id = -1,
-	.dev    = {
-		.platform_data = &msm_device_snd_endpoints
-	},
-};
-
-#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
-	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
-	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
-	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
-	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
-	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC1_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
-	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
-	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
-	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
-	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
-	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC2_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
-	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
-	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
-	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
-	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
-	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC3_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
-	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
-	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
-	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
-	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
-	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC4_FORMAT (1<<MSM_ADSP_CODEC_MIDI)
-
-static unsigned int dec_concurrency_table[] = {
-	/* Audio LP */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DMA)), 0,
-	0, 0, 0,
-
-	/* Concurrency 1 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC4_FORMAT),
-
-	 /* Concurrency 2 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC4_FORMAT),
-
-	/* Concurrency 3 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC4_FORMAT),
-
-	/* Concurrency 4 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC4_FORMAT),
-
-	/* Concurrency 5 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC4_FORMAT),
-
-	/* Concurrency 6 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	0, 0, 0,
-
-	/* Concurrency 7 */
-	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
-	(DEC4_FORMAT),
-};
-
-#define DEC_INFO(name, queueid, decid, nr_codec) { .module_name = name, \
-	.module_queueid = queueid, .module_decid = decid, \
-	.nr_codec_support = nr_codec}
-
-static struct msm_adspdec_info dec_info_list[] = {
-	DEC_INFO("AUDPLAY0TASK", 13, 0, 11), /* AudPlay0BitStreamCtrlQueue */
-	DEC_INFO("AUDPLAY1TASK", 14, 1, 11),  /* AudPlay1BitStreamCtrlQueue */
-	DEC_INFO("AUDPLAY2TASK", 15, 2, 11),  /* AudPlay2BitStreamCtrlQueue */
-	DEC_INFO("AUDPLAY3TASK", 16, 3, 11),  /* AudPlay3BitStreamCtrlQueue */
-	DEC_INFO("AUDPLAY4TASK", 17, 4, 1),  /* AudPlay4BitStreamCtrlQueue */
-};
-
-static struct msm_adspdec_database msm_device_adspdec_database = {
-	.num_dec = ARRAY_SIZE(dec_info_list),
-	.num_concurrency_support = (ARRAY_SIZE(dec_concurrency_table) / \
-					ARRAY_SIZE(dec_info_list)),
-	.dec_concurrency_table = dec_concurrency_table,
-	.dec_info_list = dec_info_list,
-};
-
-static struct platform_device msm_device_adspdec = {
-	.name = "msm_adspdec",
-	.id = -1,
-	.dev    = {
-		.platform_data = &msm_device_adspdec_database
-	},
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
-	.name = "pmem_audio",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 0,
-	.memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
-	.name = "android_pmem",
-	.id = 2,
-	.dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
-static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
-{
-	pmem_kernel_ebi1_size = memparse(p, NULL);
-	return 0;
-}
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
-
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
-static int __init pmem_audio_size_setup(char *p)
-{
-	pmem_audio_size = memparse(p, NULL);
-	return 0;
-}
-early_param("pmem_audio_size", pmem_audio_size_setup);
-
-static struct memtype_reserve msm7627a_reserve_table[] __initdata = {
-	[MEMTYPE_SMI] = {
-	},
-	[MEMTYPE_EBI0] = {
-		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
-	},
-	[MEMTYPE_EBI1] = {
-		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
-	},
-};
-
-static struct android_pmem_platform_data android_pmem_pdata = {
-	.name = "pmem",
-	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
-	.cached = 1,
-	.memory_type = MEMTYPE_EBI1,
-};
-static struct platform_device android_pmem_device = {
-	.name = "android_pmem",
-	.id = 0,
-	.dev = { .platform_data = &android_pmem_pdata },
-};
-
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
-		&android_pmem_adsp_pdata,
-		&android_pmem_audio_pdata,
-		&android_pmem_pdata,
-};
-
-static unsigned pmem_mdp_size;
-static unsigned pmem_adsp_size;
-
-static int __init pmem_mdp_size_setup(char *p)
-{
-	pmem_mdp_size = memparse(p, NULL);
-	return 0;
-}
-early_param("pmem_mdp_size", pmem_mdp_size_setup);
-
-static int __init pmem_adsp_size_setup(char *p)
-{
-	pmem_adsp_size = memparse(p, NULL);
-	return 0;
-}
-early_param("pmem_adsp_size", pmem_adsp_size_setup);
-
-static void __init msm7627a_size_pmem_devices(void)
-{
-	unsigned int i;
-	unsigned int reusable_count = 0;
-
-	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
-		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
-		pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
-	} else {
-		pmem_mdp_size = MSM_PMEM_MDP_SIZE;
-		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
-	}
-
-	android_pmem_adsp_pdata.size = pmem_adsp_size;
-	android_pmem_pdata.size = pmem_mdp_size;
-	android_pmem_audio_pdata.size = pmem_audio_size;
-
-	fmem_pdata.size = 0;
-
-	/* Find pmem devices that should use FMEM (reusable) memory.
-	 */
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
-		if (!reusable_count && pdata->reusable)
-			fmem_pdata.size += pdata->size;
-
-		reusable_count += (pdata->reusable) ? 1 : 0;
-
-		if (pdata->reusable && reusable_count > 1) {
-			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
-				__func__, pdata->name);
-			pdata->reusable = 0;
-		}
-	}
-}
-
-static void __init qrd7627a_size_pmem_devices(void)
-{
-	unsigned int i;
-	unsigned int reusable_count = 0;
-
-	pmem_mdp_size = QRD_PMEM_MDP_SIZE;
-	pmem_adsp_size = QRD_PMEM_ADSP_SIZE;
-
-	android_pmem_adsp_pdata.size = pmem_adsp_size;
-	android_pmem_pdata.size = pmem_mdp_size;
-	android_pmem_audio_pdata.size = pmem_audio_size;
-
-	fmem_pdata.size = 0;
-
-	/* Find pmem devices that should use FMEM (reusable) memory.
-	 */
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
-		if (!reusable_count && pdata->reusable)
-			fmem_pdata.size += pdata->size;
-
-		reusable_count += (pdata->reusable) ? 1 : 0;
-
-		if (pdata->reusable && reusable_count > 1) {
-			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
-				__func__, pdata->name);
-			pdata->reusable = 0;
-		}
-	}
-}
-
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
-	msm7627a_reserve_table[p->memory_type].size += p->size;
-}
-
-static void __init msm7627a_reserve_pmem_memory(void)
-{
-	unsigned int i;
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		if (!pmem_pdata_array[i]->reusable)
-			reserve_memory_for(pmem_pdata_array[i]);
-	}
-
-	msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-}
-
-static void __init qrd7627a_reserve_pmem_memory(void)
-{
-	reserve_memory_for(&android_pmem_adsp_pdata);
-	reserve_memory_for(&android_pmem_pdata);
-	reserve_memory_for(&android_pmem_audio_pdata);
-	msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-}
-
-static void __init msm7627a_calculate_reserve_sizes(void)
-{
-	msm7627a_size_pmem_devices();
-	msm7627a_reserve_pmem_memory();
-}
-
-static void __init qrd7627a_calculate_reserve_sizes(void)
-{
-	qrd7627a_size_pmem_devices();
-	qrd7627a_reserve_pmem_memory();
-}
-
-static int msm7627a_paddr_to_memtype(unsigned int paddr)
-{
-	return MEMTYPE_EBI1;
-}
-
-static struct reserve_info msm7627a_reserve_info __initdata = {
-	.memtype_reserve_table = msm7627a_reserve_table,
-	.calculate_reserve_sizes = msm7627a_calculate_reserve_sizes,
-	.paddr_to_memtype = msm7627a_paddr_to_memtype,
-};
-
-static struct reserve_info qrd7627a_reserve_info __initdata = {
-	.memtype_reserve_table = msm7627a_reserve_table,
-	.calculate_reserve_sizes = qrd7627a_calculate_reserve_sizes,
-	.paddr_to_memtype = msm7627a_paddr_to_memtype,
-};
-
-void __init msm7627a_reserve(void)
-{
-	reserve_info = &msm7627a_reserve_info;
-	msm_reserve();
-	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
-}
-
-void __init qrd7627a_reserve(void)
-{
-	reserve_info = &qrd7627a_reserve_info;
-	msm_reserve();
-	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
-}
-
-static struct platform_device *audio_devices[] __initdata = {
-	&android_pmem_device,
-	&android_pmem_adsp_device,
-	&android_pmem_audio_device,
-	&msm_device_adspdec,
-	&msm_device_snd,
-};
-
-void __init msm_adsp_add_pdev(void)
-{
-	int rc = 0;
-	struct rpc_board_dev *rpc_adsp_pdev;
-
-	rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
-	if (rpc_adsp_pdev == NULL) {
-		pr_err("%s: Memory Allocation failure\n", __func__);
-		return;
-	}
-	rpc_adsp_pdev->prog = ADSP_RPC_PROG;
-
-	if (cpu_is_msm8625())
-		rpc_adsp_pdev->pdev = msm8625_device_adsp;
-	else
-		rpc_adsp_pdev->pdev = msm_adsp_device;
-	rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
-	if (rc < 0) {
-		pr_err("%s: return val: %d\n",	__func__, rc);
-		kfree(rpc_adsp_pdev);
-	}
-
-	platform_add_devices(audio_devices,
-				ARRAY_SIZE(audio_devices));
-
-}
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 2269073..94b8710 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -206,9 +206,9 @@
 };
 
 static struct msm_camera_sensor_flash_src msm_flash_src_ov5647 = {
-	.flash_sr_type = MSM_CAMERA_FLASH_SRC_LED,
-	._fsrc.led_src.led_name = "flashlight",
-	._fsrc.led_src.led_name_len = 10,
+	.flash_sr_type = MSM_CAMERA_FLASH_SRC_LED1,
+	._fsrc.ext_driver_src.led_en = 13,
+	._fsrc.ext_driver_src.led_flash_en = 32,
 };
 
 static struct msm_camera_sensor_flash_data flash_ov5647 = {
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 33a46cc..e96284a 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -573,6 +573,93 @@
 };
 #endif
 
+static int evb_backlight_control(int level)
+{
+
+	int i = 0;
+	int remainder;
+	/* device address byte = 0x72 */
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+	gpio_set_value_cansleep(96, 0);
+	udelay(33);
+	gpio_set_value_cansleep(96, 1);
+	udelay(67);
+	gpio_set_value_cansleep(96, 0);
+	udelay(33);
+	gpio_set_value_cansleep(96, 1);
+	udelay(67);
+	gpio_set_value_cansleep(96, 0);
+	udelay(33);
+	gpio_set_value_cansleep(96, 1);
+	udelay(67);
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+	gpio_set_value_cansleep(96, 0);
+	udelay(33);
+	gpio_set_value_cansleep(96, 1);
+	udelay(67);
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+
+	/* t-EOS and t-start */
+	gpio_set_value_cansleep(96, 0);
+	ndelay(4200);
+	gpio_set_value_cansleep(96, 1);
+	ndelay(9000);
+
+	/* data byte */
+	/* RFA = 0 */
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+
+	/* Address bits */
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+	gpio_set_value_cansleep(96, 0);
+	udelay(67);
+	gpio_set_value_cansleep(96, 1);
+	udelay(33);
+
+	/* Data bits */
+	for (i = 0; i < 5; i++) {
+		remainder = (level) & (16);
+		if (remainder) {
+			gpio_set_value_cansleep(96, 0);
+			udelay(33);
+			gpio_set_value_cansleep(96, 1);
+			udelay(67);
+		} else {
+			gpio_set_value_cansleep(96, 0);
+			udelay(67);
+			gpio_set_value_cansleep(96, 1);
+			udelay(33);
+		}
+		level = level << 1;
+	}
+
+	/* t-EOS */
+	gpio_set_value_cansleep(96, 0);
+	ndelay(12000);
+	gpio_set_value_cansleep(96, 1);
+	return 0;
+}
+
+
 static struct msm_panel_common_pdata mipi_truly_pdata = {
 	.pmic_backlight = mipi_truly_set_bl,
 };
@@ -586,7 +673,7 @@
 };
 
 static struct msm_panel_common_pdata mipi_NT35510_pdata = {
-	.pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
+	.pmic_backlight = evb_backlight_control,
 };
 
 static struct platform_device mipi_dsi_NT35510_panel_device = {
@@ -1028,7 +1115,7 @@
 			return rc;
 
 		rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
-			GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+			GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
 			GPIO_CFG_ENABLE);
 		if (rc < 0) {
 			pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
@@ -1084,7 +1171,17 @@
 			qrd3_dsi_gpio_initialized = 1;
 	}
 
-	gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+	if (on) {
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+		udelay(190);
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 0);
+		udelay(286);
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+		/* 1 wire mode starts from this low to high transition */
+		udelay(50);
+	} else
+		gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+
 	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
 	gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
 
@@ -1167,10 +1264,11 @@
 	if (machine_is_msm7627a_qrd1())
 		platform_add_devices(qrd_fb_devices,
 				ARRAY_SIZE(qrd_fb_devices));
-	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
+	else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
+		mipi_NT35510_pdata.bl_lock = 1;
 		platform_add_devices(evb_fb_devices,
 				ARRAY_SIZE(evb_fb_devices));
-	else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
+	} else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
 		sku3_lcdc_lcd_camera_power_init();
 		platform_add_devices(qrd3_fb_devices,
 						ARRAY_SIZE(qrd3_fb_devices));
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index e3c9469..68e333f 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -14,25 +14,11 @@
 #define __ARCH_ARM_MACH_MSM_BOARD_7627A__
 
 #include "pm.h"
-#include <linux/fmem.h>
-
 void __init msm7627a_init_mmc(void);
 
 void __init msm_msm7627a_allocate_memory_regions(void);
 void __init msm_fb_add_devices(void);
 
-#define PMEM_KERNEL_EBI1_SIZE	0x3A000
-#define MSM_PMEM_AUDIO_SIZE	0x1F4000
-
-#define MSM_PMEM_MDP_SIZE		0x2300000
-#define MSM_PMEM_ADSP_SIZE		0x1100000
-
-#define MSM7x25A_MSM_PMEM_MDP_SIZE	0x1500000
-#define MSM7x25A_MSM_PMEM_ADSP_SIZE	0xB91000
-
-#define QRD_PMEM_MDP_SIZE		0x1DD1000
-#define QRD_PMEM_ADSP_SIZE		0x1100000
-
 enum {
 	GPIO_EXPANDER_IRQ_BASE  = NR_MSM_IRQS + NR_GPIO_IRQS,
 	GPIO_EXPANDER_GPIO_BASE = NR_MSM_GPIOS,
@@ -116,14 +102,9 @@
 void __init msm7627a_bt_power_init(void);
 #endif
 
-extern struct fmem_platform_data fmem_pdata;
-
 void __init msm7627a_camera_init(void);
 u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode);
 
 void __init msm7627a_add_io_devices(void);
 void __init qrd7627a_add_io_devices(void);
-void __init msm_adsp_add_pdev(void);
-void __init msm7627a_reserve(void);
-void __init qrd7627a_reserve(void);
 #endif
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index b203c29..09f44a7 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -59,6 +59,9 @@
 #include "pm-boot.h"
 #include "board-msm7627a.h"
 
+#define PMEM_KERNEL_EBI1_SIZE	0x3A000
+#define MSM_PMEM_AUDIO_SIZE	0x5B000
+
 #if defined(CONFIG_GPIO_SX150X)
 enum {
 	SX150X_CORE,
@@ -152,6 +155,15 @@
 	.msm_i2c_config_gpio	= gsbi_qup_i2c_gpio_config,
 };
 
+#ifdef CONFIG_ARCH_MSM7X27A
+#define MSM_PMEM_MDP_SIZE       0x2300000
+#define MSM7x25A_MSM_PMEM_MDP_SIZE       0x1500000
+
+#define MSM_PMEM_ADSP_SIZE      0x1100000
+#define MSM7x25A_MSM_PMEM_ADSP_SIZE      0xB91000
+
+#endif
+
 static struct android_usb_platform_data android_usb_pdata = {
 	.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
 };
@@ -438,6 +450,207 @@
 	.v_addr = MSM_CFG_CTL_BASE,
 };
 
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+	.name = "pmem_adsp",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 1,
+	.memory_type = MEMTYPE_EBI1,
+	.request_region = request_fmem_c_region,
+	.release_region = release_fmem_c_region,
+	.reusable = 1,
+};
+
+static struct platform_device android_pmem_adsp_device = {
+	.name = "android_pmem",
+	.id = 1,
+	.dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+
+static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+static int __init pmem_mdp_size_setup(char *p)
+{
+	pmem_mdp_size = memparse(p, NULL);
+	return 0;
+}
+
+early_param("pmem_mdp_size", pmem_mdp_size_setup);
+
+static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+static int __init pmem_adsp_size_setup(char *p)
+{
+	pmem_adsp_size = memparse(p, NULL);
+	return 0;
+}
+
+early_param("pmem_adsp_size", pmem_adsp_size_setup);
+
+#define SND(desc, num) { .name = #desc, .id = num }
+static struct snd_endpoint snd_endpoints_list[] = {
+	SND(HANDSET, 0),
+	SND(MONO_HEADSET, 2),
+	SND(HEADSET, 3),
+	SND(SPEAKER, 6),
+	SND(TTY_HEADSET, 8),
+	SND(TTY_VCO, 9),
+	SND(TTY_HCO, 10),
+	SND(BT, 12),
+	SND(IN_S_SADC_OUT_HANDSET, 16),
+	SND(IN_S_SADC_OUT_SPEAKER_PHONE, 25),
+	SND(FM_DIGITAL_STEREO_HEADSET, 26),
+	SND(FM_DIGITAL_SPEAKER_PHONE, 27),
+	SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
+	SND(STEREO_HEADSET_AND_SPEAKER, 31),
+	SND(CURRENT, 0x7FFFFFFE),
+	SND(FM_ANALOG_STEREO_HEADSET, 35),
+	SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
+};
+#undef SND
+
+static struct msm_snd_endpoints msm_device_snd_endpoints = {
+	.endpoints = snd_endpoints_list,
+	.num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
+};
+
+static struct platform_device msm_device_snd = {
+	.name = "msm_snd",
+	.id = -1,
+	.dev    = {
+		.platform_data = &msm_device_snd_endpoints
+	},
+};
+
+#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC1_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC2_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC3_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC4_FORMAT (1<<MSM_ADSP_CODEC_MIDI)
+
+static unsigned int dec_concurrency_table[] = {
+	/* Audio LP */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DMA)), 0,
+	0, 0, 0,
+
+	/* Concurrency 1 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	 /* Concurrency 2 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 3 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 4 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 5 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 6 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	0, 0, 0,
+
+	/* Concurrency 7 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+};
+
+#define DEC_INFO(name, queueid, decid, nr_codec) { .module_name = name, \
+	.module_queueid = queueid, .module_decid = decid, \
+	.nr_codec_support = nr_codec}
+
+static struct msm_adspdec_info dec_info_list[] = {
+	DEC_INFO("AUDPLAY0TASK", 13, 0, 11), /* AudPlay0BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY1TASK", 14, 1, 11),  /* AudPlay1BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY2TASK", 15, 2, 11),  /* AudPlay2BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY3TASK", 16, 3, 11),  /* AudPlay3BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY4TASK", 17, 4, 1),  /* AudPlay4BitStreamCtrlQueue */
+};
+
+static struct msm_adspdec_database msm_device_adspdec_database = {
+	.num_dec = ARRAY_SIZE(dec_info_list),
+	.num_concurrency_support = (ARRAY_SIZE(dec_concurrency_table) / \
+					ARRAY_SIZE(dec_info_list)),
+	.dec_concurrency_table = dec_concurrency_table,
+	.dec_info_list = dec_info_list,
+};
+
+static struct platform_device msm_device_adspdec = {
+	.name = "msm_adspdec",
+	.id = -1,
+	.dev    = {
+		.platform_data = &msm_device_adspdec_database
+	},
+};
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+	.name = "pmem_audio",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 0,
+	.memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+	.name = "android_pmem",
+	.id = 2,
+	.dev = { .platform_data = &android_pmem_audio_pdata },
+};
+
+static struct android_pmem_platform_data android_pmem_pdata = {
+	.name = "pmem",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 1,
+	.memory_type = MEMTYPE_EBI1,
+};
+static struct platform_device android_pmem_device = {
+	.name = "android_pmem",
+	.id = 0,
+	.dev = { .platform_data = &android_pmem_pdata },
+};
+
 static u32 msm_calculate_batt_capacity(u32 current_voltage);
 
 static struct msm_psy_batt_pdata msm_psy_batt_data = {
@@ -590,8 +803,13 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
+	&android_pmem_device,
+	&android_pmem_adsp_device,
+	&android_pmem_audio_device,
 	&fmem_device,
 	&msm_device_nand,
+	&msm_device_snd,
+	&msm_device_adspdec,
 	&asoc_msm_pcm,
 	&asoc_msm_dai0,
 	&asoc_msm_dai1,
@@ -611,9 +829,126 @@
 	&msm8625_kgsl_3d0,
 };
 
+static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
+static int __init pmem_kernel_ebi1_size_setup(char *p)
+{
+	pmem_kernel_ebi1_size = memparse(p, NULL);
+	return 0;
+}
+early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+
+static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
+static int __init pmem_audio_size_setup(char *p)
+{
+	pmem_audio_size = memparse(p, NULL);
+	return 0;
+}
+early_param("pmem_audio_size", pmem_audio_size_setup);
+
+static struct memtype_reserve msm7x27a_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+		&android_pmem_adsp_pdata,
+		&android_pmem_audio_pdata,
+		&android_pmem_pdata,
+};
+#endif
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	unsigned int i;
+	unsigned int reusable_count = 0;
+
+	if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
+		pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
+		pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
+	} else {
+		pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+		pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+	}
+
+	android_pmem_adsp_pdata.size = pmem_adsp_size;
+	android_pmem_pdata.size = pmem_mdp_size;
+	android_pmem_audio_pdata.size = pmem_audio_size;
+
+	fmem_pdata.size = 0;
+
+	/* Find pmem devices that should use FMEM (reusable) memory.
+	 */
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+		if (!reusable_count && pdata->reusable)
+			fmem_pdata.size += pdata->size;
+
+		reusable_count += (pdata->reusable) ? 1 : 0;
+
+		if (pdata->reusable && reusable_count > 1) {
+			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+				__func__, pdata->name);
+			pdata->reusable = 0;
+		}
+	}
+#endif
+
+}
+
+static void __init reserve_memory_for(struct android_pmem_platform_data *p)
+{
+	msm7x27a_reserve_table[p->memory_type].size += p->size;
+}
+
+static void __init reserve_pmem_memory(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	unsigned int i;
+	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+		if (!pmem_pdata_array[i]->reusable)
+			reserve_memory_for(pmem_pdata_array[i]);
+	}
+
+	msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+#endif
+}
+
+static void __init msm7x27a_calculate_reserve_sizes(void)
+{
+	size_pmem_devices();
+	reserve_pmem_memory();
+}
+
+static int msm7x27a_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msm7x27a_reserve_info __initdata = {
+	.memtype_reserve_table = msm7x27a_reserve_table,
+	.calculate_reserve_sizes = msm7x27a_calculate_reserve_sizes,
+	.paddr_to_memtype = msm7x27a_paddr_to_memtype,
+};
+
+static void __init msm7x27a_reserve(void)
+{
+	reserve_info = &msm7x27a_reserve_info;
+	msm_reserve();
+	fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
+}
+
 static void __init msm8625_reserve(void)
 {
-	msm7627a_reserve();
+	msm7x27a_reserve();
 	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
 	memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
 }
@@ -674,6 +1009,29 @@
 	}
 };
 
+static void msm_adsp_add_pdev(void)
+{
+	int rc = 0;
+	struct rpc_board_dev *rpc_adsp_pdev;
+
+	rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+	if (rpc_adsp_pdev == NULL) {
+		pr_err("%s: Memory Allocation failure\n", __func__);
+		return;
+	}
+	rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+	if (cpu_is_msm8625())
+		rpc_adsp_pdev->pdev = msm8625_device_adsp;
+	else
+		rpc_adsp_pdev->pdev = msm_adsp_device;
+	rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+	if (rc < 0) {
+		pr_err("%s: return val: %d\n",	__func__, rc);
+		kfree(rpc_adsp_pdev);
+	}
+}
+
 static void __init msm7627a_rumi3_init(void)
 {
 	msm7x27a_init_ebi2();
@@ -821,7 +1179,7 @@
 MACHINE_START(MSM7X27A_RUMI3, "QCT MSM7x27a RUMI3")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
-	.reserve	= msm7627a_reserve,
+	.reserve	= msm7x27a_reserve,
 	.init_irq	= msm_init_irq,
 	.init_machine	= msm7627a_rumi3_init,
 	.timer		= &msm_timer,
@@ -831,7 +1189,7 @@
 MACHINE_START(MSM7X27A_SURF, "QCT MSM7x27a SURF")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
-	.reserve	= msm7627a_reserve,
+	.reserve	= msm7x27a_reserve,
 	.init_irq	= msm_init_irq,
 	.init_machine	= msm7x2x_init,
 	.timer		= &msm_timer,
@@ -841,7 +1199,7 @@
 MACHINE_START(MSM7X27A_FFA, "QCT MSM7x27a FFA")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
-	.reserve	= msm7627a_reserve,
+	.reserve	= msm7x27a_reserve,
 	.init_irq	= msm_init_irq,
 	.init_machine	= msm7x2x_init,
 	.timer		= &msm_timer,
@@ -851,7 +1209,7 @@
 MACHINE_START(MSM7625A_SURF, "QCT MSM7625a SURF")
 	.boot_params    = PHYS_OFFSET + 0x100,
 	.map_io         = msm_common_io_init,
-	.reserve        = msm7627a_reserve,
+	.reserve        = msm7x27a_reserve,
 	.init_irq       = msm_init_irq,
 	.init_machine   = msm7x2x_init,
 	.timer          = &msm_timer,
@@ -861,7 +1219,7 @@
 MACHINE_START(MSM7625A_FFA, "QCT MSM7625a FFA")
 	.boot_params    = PHYS_OFFSET + 0x100,
 	.map_io         = msm_common_io_init,
-	.reserve        = msm7627a_reserve,
+	.reserve        = msm7x27a_reserve,
 	.init_irq       = msm_init_irq,
 	.init_machine   = msm7x2x_init,
 	.timer          = &msm_timer,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 947c639..88b442c 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2666,7 +2666,7 @@
 				MSM_FB_DSUB_PMEM_ADDER, 4096)
 
 #define MSM_PMEM_SF_SIZE 0x4000000 /* 64 Mbytes */
-#define MSM_HDMI_PRIM_PMEM_SF_SIZE 0x4000000 /* 64 Mbytes */
+#define MSM_HDMI_PRIM_PMEM_SF_SIZE 0x8000000 /* 128 Mbytes */
 
 #ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
 unsigned char hdmi_is_primary = 1;
@@ -2882,7 +2882,7 @@
 	.id = 2,
 	.dev = { .platform_data = &android_pmem_adsp_pdata },
 };
-#endif
+
 static struct android_pmem_platform_data android_pmem_audio_pdata = {
 	.name = "pmem_audio",
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
@@ -2895,7 +2895,7 @@
 	.id = 4,
 	.dev = { .platform_data = &android_pmem_audio_pdata },
 };
-
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 #define PMEM_BUS_WIDTH(_bw) \
 	{ \
 		.vectors = &(struct msm_bus_vectors){ \
@@ -2954,8 +2954,8 @@
 	.id = 7,
 	.dev = { .platform_data = &android_pmem_smipool_pdata },
 };
-#endif
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 
 #define GPIO_DONGLE_PWR_EN 258
 static void setup_display_power(void);
@@ -4264,9 +4264,9 @@
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_smipool_device,
-#endif
 	&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 #ifdef CONFIG_MSM_ROTATOR
 	&msm_rotator_device,
 #endif
@@ -5195,9 +5195,9 @@
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_smipool_device,
-#endif
 	&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 #ifdef CONFIG_MSM_ROTATOR
 	&msm_rotator_device,
 #endif
@@ -5491,15 +5491,19 @@
 	if (hdmi_is_primary)
 		pmem_sf_size = MSM_HDMI_PRIM_PMEM_SF_SIZE;
 	android_pmem_pdata.size = pmem_sf_size;
-#endif
 	android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 }
 
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
 static void __init reserve_memory_for(struct android_pmem_platform_data *p)
 {
 	msm8x60_reserve_table[p->memory_type].size += p->size;
 }
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
 
 static void __init reserve_pmem_memory(void)
 {
@@ -5508,10 +5512,10 @@
 	reserve_memory_for(&android_pmem_adsp_pdata);
 	reserve_memory_for(&android_pmem_smipool_pdata);
 	reserve_memory_for(&android_pmem_pdata);
-#endif
 	reserve_memory_for(&android_pmem_audio_pdata);
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
 	msm8x60_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
+#endif /*CONFIG_ANDROID_PMEM*/
 }
 
 static void __init reserve_mdp_memory(void);
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index f3b2178..60457cc 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -24,6 +24,9 @@
 #include <linux/bootmem.h>
 #include <linux/mfd/marimba.h>
 #include <linux/power_supply.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/input/rmi_i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/regulator/consumer.h>
 #include <linux/memblock.h>
 #include <linux/input/ft5x06_ts.h>
@@ -55,6 +58,20 @@
 #include "board-msm7x27a-regulator.h"
 #include "board-msm7627a.h"
 
+#define PMEM_KERNEL_EBI1_SIZE	0x3A000
+#define MSM_PMEM_AUDIO_SIZE	0x5B000
+#define BAHAMA_SLAVE_ID_FM_REG 0x02
+#define FM_GPIO	83
+#define BT_PCM_BCLK_MODE  0x88
+#define BT_PCM_DIN_MODE   0x89
+#define BT_PCM_DOUT_MODE  0x8A
+#define BT_PCM_SYNC_MODE  0x8B
+#define FM_I2S_SD_MODE    0x8E
+#define FM_I2S_WS_MODE    0x8F
+#define FM_I2S_SCK_MODE   0x90
+#define I2C_PIN_CTL       0x15
+#define I2C_NORMAL        0x40
+
 static struct platform_device msm_wlan_ar6000_pm_device = {
 	.name           = "wlan_ar6000_pm_dev",
 	.id             = -1,
@@ -108,6 +125,11 @@
 	.msm_i2c_config_gpio	= gsbi_qup_i2c_gpio_config,
 };
 
+#ifdef CONFIG_ARCH_MSM7X27A
+#define MSM_PMEM_MDP_SIZE       0x1DD1000
+#define MSM_PMEM_ADSP_SIZE      0x1100000
+#endif
+
 static struct android_usb_platform_data android_usb_pdata = {
 	.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
 };
@@ -354,6 +376,203 @@
 	.v_addr = MSM_CFG_CTL_BASE,
 };
 
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+	.name = "pmem_adsp",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 1,
+	.memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_adsp_device = {
+	.name = "android_pmem",
+	.id = 1,
+	.dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+
+static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+static int __init pmem_mdp_size_setup(char *p)
+{
+	pmem_mdp_size = memparse(p, NULL);
+	return 0;
+}
+
+early_param("pmem_mdp_size", pmem_mdp_size_setup);
+
+static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+static int __init pmem_adsp_size_setup(char *p)
+{
+	pmem_adsp_size = memparse(p, NULL);
+	return 0;
+}
+
+early_param("pmem_adsp_size", pmem_adsp_size_setup);
+
+#define SND(desc, num) { .name = #desc, .id = num }
+static struct snd_endpoint snd_endpoints_list[] = {
+	SND(HANDSET, 0),
+	SND(MONO_HEADSET, 2),
+	SND(HEADSET, 3),
+	SND(SPEAKER, 6),
+	SND(TTY_HEADSET, 8),
+	SND(TTY_VCO, 9),
+	SND(TTY_HCO, 10),
+	SND(BT, 12),
+	SND(IN_S_SADC_OUT_HANDSET, 16),
+	SND(IN_S_SADC_OUT_SPEAKER_PHONE, 25),
+	SND(FM_DIGITAL_STEREO_HEADSET, 26),
+	SND(FM_DIGITAL_SPEAKER_PHONE, 27),
+	SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
+	SND(STEREO_HEADSET_AND_SPEAKER, 31),
+	SND(CURRENT, 0x7FFFFFFE),
+	SND(FM_ANALOG_STEREO_HEADSET, 35),
+	SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
+};
+#undef SND
+
+static struct msm_snd_endpoints msm_device_snd_endpoints = {
+	.endpoints = snd_endpoints_list,
+	.num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
+};
+
+static struct platform_device msm_device_snd = {
+	.name = "msm_snd",
+	.id = -1,
+	.dev    = {
+		.platform_data = &msm_device_snd_endpoints
+	},
+};
+
+#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC1_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC2_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC3_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+	(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+	(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+	(1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+	(1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+	(1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC4_FORMAT (1<<MSM_ADSP_CODEC_MIDI)
+
+static unsigned int dec_concurrency_table[] = {
+	/* Audio LP */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DMA)), 0,
+	0, 0, 0,
+
+	/* Concurrency 1 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	 /* Concurrency 2 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 3 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 4 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 5 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+
+	/* Concurrency 6 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	0, 0, 0, 0,
+
+	/* Concurrency 7 */
+	(DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+	(DEC4_FORMAT),
+};
+
+#define DEC_INFO(name, queueid, decid, nr_codec) { .module_name = name, \
+	.module_queueid = queueid, .module_decid = decid, \
+	.nr_codec_support = nr_codec}
+
+static struct msm_adspdec_info dec_info_list[] = {
+	DEC_INFO("AUDPLAY0TASK", 13, 0, 11), /* AudPlay0BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY1TASK", 14, 1, 11),  /* AudPlay1BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY2TASK", 15, 2, 11),  /* AudPlay2BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY3TASK", 16, 3, 11),  /* AudPlay3BitStreamCtrlQueue */
+	DEC_INFO("AUDPLAY4TASK", 17, 4, 1),  /* AudPlay4BitStreamCtrlQueue */
+};
+
+static struct msm_adspdec_database msm_device_adspdec_database = {
+	.num_dec = ARRAY_SIZE(dec_info_list),
+	.num_concurrency_support = (ARRAY_SIZE(dec_concurrency_table) / \
+					ARRAY_SIZE(dec_info_list)),
+	.dec_concurrency_table = dec_concurrency_table,
+	.dec_info_list = dec_info_list,
+};
+
+static struct platform_device msm_device_adspdec = {
+	.name = "msm_adspdec",
+	.id = -1,
+	.dev    = {
+		.platform_data = &msm_device_adspdec_database
+	},
+};
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+	.name = "pmem_audio",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 0,
+	.memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+	.name = "android_pmem",
+	.id = 2,
+	.dev = { .platform_data = &android_pmem_audio_pdata },
+};
+
+static struct android_pmem_platform_data android_pmem_pdata = {
+	.name = "pmem",
+	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+	.cached = 1,
+	.memory_type = MEMTYPE_EBI1,
+};
+static struct platform_device android_pmem_device = {
+	.name = "android_pmem",
+	.id = 0,
+	.dev = { .platform_data = &android_pmem_pdata },
+};
+
 static u32 msm_calculate_batt_capacity(u32 current_voltage);
 
 static struct msm_psy_batt_pdata msm_psy_batt_data = {
@@ -381,7 +600,12 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&android_usb_device,
+	&android_pmem_device,
+	&android_pmem_adsp_device,
+	&android_pmem_audio_device,
 	&msm_batt_device,
+	&msm_device_adspdec,
+	&msm_device_snd,
 	&asoc_msm_pcm,
 	&asoc_msm_dai0,
 	&asoc_msm_dai1,
@@ -415,6 +639,110 @@
 	&msm8625_kgsl_3d0,
 };
 
+static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
+static int __init pmem_kernel_ebi1_size_setup(char *p)
+{
+	pmem_kernel_ebi1_size = memparse(p, NULL);
+	return 0;
+}
+early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+
+static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
+static int __init pmem_audio_size_setup(char *p)
+{
+	pmem_audio_size = memparse(p, NULL);
+	return 0;
+}
+early_param("pmem_audio_size", pmem_audio_size_setup);
+
+static struct memtype_reserve msm7627a_reserve_table[] __initdata = {
+	[MEMTYPE_SMI] = {
+	},
+	[MEMTYPE_EBI0] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+	[MEMTYPE_EBI1] = {
+		.flags	=	MEMTYPE_FLAGS_1M_ALIGN,
+	},
+};
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	android_pmem_adsp_pdata.size = pmem_adsp_size;
+	android_pmem_pdata.size = pmem_mdp_size;
+	android_pmem_audio_pdata.size = pmem_audio_size;
+#endif
+}
+
+static void __init reserve_memory_for(struct android_pmem_platform_data *p)
+{
+	msm7627a_reserve_table[p->memory_type].size += p->size;
+}
+
+static void __init reserve_pmem_memory(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+	reserve_memory_for(&android_pmem_adsp_pdata);
+	reserve_memory_for(&android_pmem_pdata);
+	reserve_memory_for(&android_pmem_audio_pdata);
+	msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+#endif
+}
+
+static void __init msm7627a_calculate_reserve_sizes(void)
+{
+	size_pmem_devices();
+	reserve_pmem_memory();
+}
+
+static int msm7627a_paddr_to_memtype(unsigned int paddr)
+{
+	return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msm7627a_reserve_info __initdata = {
+	.memtype_reserve_table = msm7627a_reserve_table,
+	.calculate_reserve_sizes = msm7627a_calculate_reserve_sizes,
+	.paddr_to_memtype = msm7627a_paddr_to_memtype,
+};
+
+static void __init msm7627a_reserve(void)
+{
+	reserve_info = &msm7627a_reserve_info;
+	msm_reserve();
+	memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
+}
+
+static void __init msm8625_reserve(void)
+{
+	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+	msm7627a_reserve();
+}
+
+static void msmqrd_adsp_add_pdev(void)
+{
+	int rc = 0;
+	struct rpc_board_dev *rpc_adsp_pdev;
+
+	rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+	if (rpc_adsp_pdev == NULL) {
+		pr_err("%s: Memory Allocation failure\n", __func__);
+		return;
+	}
+	rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+	if (cpu_is_msm8625())
+		rpc_adsp_pdev->pdev = msm8625_device_adsp;
+	else
+		rpc_adsp_pdev->pdev = msm_adsp_device;
+	rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+	if (rc < 0) {
+		pr_err("%s: return val: %d\n",	__func__, rc);
+		kfree(rpc_adsp_pdev);
+	}
+}
+
 static void __init msm7627a_device_i2c_init(void)
 {
 	msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
@@ -520,19 +848,11 @@
 	}
 }
 
-static void __init qrd8625_reserve(void)
-{
-	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
-	qrd7627a_reserve();
-	memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
-	msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
-}
-
 static void __init msm_qrd_init(void)
 {
 	msm7x2x_misc_init();
 	msm7627a_init_regulators();
-	msm_adsp_add_pdev();
+	msmqrd_adsp_add_pdev();
 
 	if (cpu_is_msm8625())
 		msm8625_device_i2c_init();
@@ -577,7 +897,7 @@
 MACHINE_START(MSM7627A_QRD1, "QRD MSM7627a QRD1")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
-	.reserve	= qrd7627a_reserve,
+	.reserve	= msm7627a_reserve,
 	.init_irq	= msm_init_irq,
 	.init_machine	= msm_qrd_init,
 	.timer		= &msm_timer,
@@ -587,7 +907,7 @@
 MACHINE_START(MSM7627A_QRD3, "QRD MSM7627a QRD3")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
-	.reserve	= qrd7627a_reserve,
+	.reserve	= msm7627a_reserve,
 	.init_irq	= msm_init_irq,
 	.init_machine	= msm_qrd_init,
 	.timer		= &msm_timer,
@@ -597,7 +917,7 @@
 MACHINE_START(MSM7627A_EVB, "QRD MSM7627a EVB")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm_common_io_init,
-	.reserve	= qrd7627a_reserve,
+	.reserve	= msm7627a_reserve,
 	.init_irq	= msm_init_irq,
 	.init_machine	= msm_qrd_init,
 	.timer		= &msm_timer,
@@ -607,7 +927,7 @@
 MACHINE_START(MSM8625_EVB, "QRD MSM8625 EVB")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm8625_map_io,
-	.reserve	= qrd8625_reserve,
+	.reserve	= msm8625_reserve,
 	.init_irq	= msm8625_init_irq,
 	.init_machine	= msm_qrd_init,
 	.timer		= &msm_timer,
@@ -617,7 +937,7 @@
 MACHINE_START(MSM8625_QRD7, "QRD MSM8625 QRD7")
 	.boot_params	= PHYS_OFFSET + 0x100,
 	.map_io		= msm8625_map_io,
-	.reserve	= qrd8625_reserve,
+	.reserve	= msm8625_reserve,
 	.init_irq	= msm8625_init_irq,
 	.init_machine	= msm_qrd_init,
 	.timer		= &msm_timer,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7828d64..794c342 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4493,6 +4493,8 @@
 static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_tzcom_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c);
 
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
 static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c);
@@ -4927,10 +4929,10 @@
 	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
+	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		""),
-	CLK_LOOKUP("dfab_clk",		dfab_clk.c,		""),
-	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,		""),
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		""),
 	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,		"clock-8960"),
 	CLK_LOOKUP("cfpb_a_clk",	cfpb_a_clk.c,		"clock-8960"),
@@ -5211,10 +5213,10 @@
 	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
+	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		NULL),
-	CLK_LOOKUP("dfab_clk",		dfab_clk.c,		NULL),
-	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,		NULL),
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		NULL),
 	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,		"clock-8960"),
 	CLK_LOOKUP("cfpb_a_clk",	cfpb_a_clk.c,		"clock-8960"),
@@ -5229,7 +5231,7 @@
 	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c, "msm_serial_hsl.0"),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c, "msm_serial_hs.0"),
 	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	""),
-	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c,	""),
+	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c, "msm_serial_hsl.1"),
 	CLK_LOOKUP("core_clk",		gsbi9_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi10_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi11_uart_clk.c,	""),
@@ -5282,7 +5284,7 @@
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,	"msm_serial_hsl.0"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,  "msm_serial_hs.0"),
 	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		""),
-	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,		""),
+	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,	"msm_serial_hsl.1"),
 	CLK_LOOKUP("iface_clk",		gsbi9_p_clk.c,		""),
 	CLK_LOOKUP("iface_clk",		gsbi10_p_clk.c,		"qup_i2c.10"),
 	CLK_LOOKUP("iface_clk",		gsbi11_p_clk.c,		""),
@@ -5502,10 +5504,10 @@
 	CLK_LOOKUP("bus_a_clk",		mmfab_a_clk.c,		"msm_mm_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
+	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		NULL),
-	CLK_LOOKUP("dfab_clk",		dfab_clk.c,		NULL),
-	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,		NULL),
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		NULL),
 	CLK_LOOKUP("mmfpb_a_clk",	mmfpb_a_clk.c,		"clock-8960"),
 	CLK_LOOKUP("cfpb_a_clk",	cfpb_a_clk.c,		"clock-8960"),
@@ -5897,18 +5899,6 @@
 	writel_relaxed(0, SW_RESET_CORE_REG);
 	writel_relaxed(0, SW_RESET_CORE2_REG);
 
-	/* Reset 3D core once more, with its clock enabled. This can
-	 * eventually be done as part of the GDFS footswitch driver. */
-	clk_set_rate(&gfx3d_clk.c, 27000000);
-	clk_prepare_enable(&gfx3d_clk.c);
-	writel_relaxed(BIT(12), SW_RESET_CORE_REG);
-	mb();
-	udelay(5);
-	writel_relaxed(0, SW_RESET_CORE_REG);
-	/* Make sure reset is de-asserted before clock is disabled. */
-	mb();
-	clk_disable_unprepare(&gfx3d_clk.c);
-
 	/* Enable TSSC and PDM PXO sources. */
 	writel_relaxed(BIT(11), TSSC_CLK_CTL_REG);
 	writel_relaxed(BIT(15), PDM_CLK_NS_REG);
@@ -6052,6 +6042,14 @@
 	/* Keep PXO on whenever APPS cpu is active */
 	clk_prepare_enable(&pxo_a_clk.c);
 
+	/* Reset 3D core while clocked to ensure it resets completely. */
+	clk_set_rate(&gfx3d_clk.c, 27000000);
+	clk_prepare_enable(&gfx3d_clk.c);
+	clk_reset(&gfx3d_clk.c, CLK_RESET_ASSERT);
+	udelay(5);
+	clk_reset(&gfx3d_clk.c, CLK_RESET_DEASSERT);
+	clk_disable_unprepare(&gfx3d_clk.c);
+
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 27000000);
 	clk_set_rate(&prng_clk.c, 64000000);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index ad8c936..c724414 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3813,18 +3813,6 @@
 	/* Deassert all MM core resets. */
 	writel_relaxed(0, SW_RESET_CORE_REG);
 
-	/* Reset 3D core once more, with its clock enabled. This can
-	 * eventually be done as part of the GDFS footswitch driver. */
-	clk_set_rate(&gfx3d_clk.c, 27000000);
-	clk_prepare_enable(&gfx3d_clk.c);
-	writel_relaxed(BIT(12), SW_RESET_CORE_REG);
-	mb();
-	udelay(5);
-	writel_relaxed(0, SW_RESET_CORE_REG);
-	/* Make sure reset is de-asserted before clock is disabled. */
-	mb();
-	clk_disable_unprepare(&gfx3d_clk.c);
-
 	/* Enable TSSC and PDM PXO sources. */
 	writel_relaxed(BIT(11), TSSC_CLK_CTL_REG);
 	writel_relaxed(BIT(15), PDM_CLK_NS_REG);
@@ -3838,6 +3826,14 @@
 	/* Keep PXO on whenever APPS cpu is active */
 	clk_prepare_enable(&pxo_a_clk.c);
 
+	/* Reset 3D core while clocked to ensure it resets completely. */
+	clk_set_rate(&gfx3d_clk.c, 27000000);
+	clk_prepare_enable(&gfx3d_clk.c);
+	clk_reset(&gfx3d_clk.c, CLK_RESET_ASSERT);
+	udelay(5);
+	clk_reset(&gfx3d_clk.c, CLK_RESET_DEASSERT);
+	clk_disable_unprepare(&gfx3d_clk.c);
+
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 27000000);
 	clk_set_rate(&prng_clk.c, 64000000);
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index a2ebe50..89e3036 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1356,6 +1356,8 @@
 static DEFINE_CLK_VOTER(dfab_sdc2_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c);
 static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c);
 static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
 static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c);
 
@@ -1611,14 +1613,14 @@
 	CLK_LOOKUP("bus_a_clk",		sfab_a_clk.c,		"msm_sys_fab"),
 	CLK_LOOKUP("mem_clk",		ebi1_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("mem_a_clk",		ebi1_a_clk.c,		"msm_bus"),
+	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
+	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 
 	CLK_LOOKUP("bus_clk",		sfpb_clk.c,	NULL),
 	CLK_LOOKUP("bus_a_clk",		sfpb_a_clk.c,	NULL),
 	CLK_LOOKUP("bus_clk",		cfpb_clk.c,	NULL),
 	CLK_LOOKUP("bus_a_clk",		cfpb_a_clk.c,	NULL),
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,	NULL),
-	CLK_LOOKUP("dfab_clk",		dfab_clk.c,	NULL),
-	CLK_LOOKUP("dfab_a_clk",	dfab_a_clk.c,	NULL),
 
 	CLK_LOOKUP("core_clk",		gp0_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gp1_clk.c,	""),
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 9ad653d..8ff4878 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -29,7 +29,7 @@
 	list_for_each_entry(clk, &parent->children, siblings) {
 		struct clk_voter *v = to_clk_voter(clk);
 		if (v->enabled)
-			rate = max(v->rate, rate);
+			rate = max(clk->rate, rate);
 	}
 	return rate;
 }
@@ -54,10 +54,10 @@
 		list_for_each_entry(clkp, &parent->children, siblings) {
 			clkh = to_clk_voter(clkp);
 			if (clkh->enabled && clkh != v)
-				other_rate = max(clkh->rate, other_rate);
+				other_rate = max(clkp->rate, other_rate);
 		}
 
-		cur_rate = max(other_rate, v->rate);
+		cur_rate = max(other_rate, clk->rate);
 		new_rate = max(other_rate, rate);
 
 		if (new_rate != cur_rate) {
@@ -66,7 +66,7 @@
 				goto unlock;
 		}
 	}
-	v->rate = rate;
+	clk->rate = rate;
 unlock:
 	spin_unlock_irqrestore(&voter_clk_lock, flags);
 
@@ -89,8 +89,8 @@
 	 * than the current rate.
 	 */
 	cur_rate = voter_clk_aggregate_rate(parent);
-	if (v->rate > cur_rate) {
-		ret = clk_set_rate(parent, v->rate);
+	if (clk->rate > cur_rate) {
+		ret = clk_set_rate(parent, clk->rate);
 		if (ret)
 			goto out;
 	}
@@ -116,7 +116,7 @@
 	 */
 	v->enabled = false;
 	new_rate = voter_clk_aggregate_rate(parent);
-	cur_rate = max(new_rate, v->rate);
+	cur_rate = max(new_rate, clk->rate);
 
 	if (new_rate < cur_rate)
 		clk_set_rate(parent, new_rate);
@@ -124,18 +124,6 @@
 	spin_unlock_irqrestore(&voter_clk_lock, flags);
 }
 
-static unsigned long voter_clk_get_rate(struct clk *clk)
-{
-	unsigned long rate, flags;
-	struct clk_voter *v = to_clk_voter(clk);
-
-	spin_lock_irqsave(&voter_clk_lock, flags);
-	rate = v->rate;
-	spin_unlock_irqrestore(&voter_clk_lock, flags);
-
-	return rate;
-}
-
 static int voter_clk_is_enabled(struct clk *clk)
 {
 	struct clk_voter *v = to_clk_voter(clk);
@@ -163,7 +151,6 @@
 	.enable = voter_clk_enable,
 	.disable = voter_clk_disable,
 	.set_rate = voter_clk_set_rate,
-	.get_rate = voter_clk_get_rate,
 	.is_enabled = voter_clk_is_enabled,
 	.round_rate = voter_clk_round_rate,
 	.get_parent = voter_clk_get_parent,
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 10353d4..de17894 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -19,7 +19,6 @@
 
 struct clk_voter {
 	bool enabled;
-	unsigned long rate;
 	struct clk *parent;
 	struct clk c;
 };
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 029fc6f3..3255248 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -36,6 +36,7 @@
 #include <sound/apr_audio.h>
 #include <mach/msm_tsif.h>
 #include <mach/qdss.h>
+#include <mach/msm_serial_hs_lite.h>
 #include "clock.h"
 #include "devices.h"
 #include "devices-msm8x60.h"
@@ -72,6 +73,7 @@
 #define MSM_UART2DM_PHYS	(MSM_GSBI2_PHYS + 0x40000)
 #define MSM_UART5DM_PHYS	(MSM_GSBI5_PHYS + 0x40000)
 #define MSM_UART6DM_PHYS	(MSM_GSBI6_PHYS + 0x40000)
+#define MSM_UART8DM_PHYS	(MSM_GSBI8_PHYS + 0x40000)
 
 /* GSBI QUP devices */
 #define MSM_GSBI1_QUP_PHYS	(MSM_GSBI1_PHYS + 0x80000)
@@ -308,6 +310,39 @@
 	.num_resources	= ARRAY_SIZE(resources_uart_gsbi5),
 	.resource	= resources_uart_gsbi5,
 };
+
+static struct msm_serial_hslite_platform_data uart_gsbi8_pdata = {
+	.line		= 0,
+};
+
+static struct resource resources_uart_gsbi8[] = {
+	{
+		.start	= GSBI8_UARTDM_IRQ,
+		.end	= GSBI8_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART8DM_PHYS,
+		.end	= MSM_UART8DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uartdm_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI8_PHYS,
+		.end	= MSM_GSBI8_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_uart_gsbi8 = {
+	.name	= "msm_serial_hsl",
+	.id	= 1,
+	.num_resources	   = ARRAY_SIZE(resources_uart_gsbi8),
+	.resource	   = resources_uart_gsbi8,
+	.dev.platform_data = &uart_gsbi8_pdata,
+};
+
 /* MSM Video core device */
 #ifdef CONFIG_MSM_BUS_SCALING
 static struct msm_bus_vectors vidc_init_vectors[] = {
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 77314e7..5ec339e 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -855,6 +855,7 @@
 	.num_levels = 1,
 	.set_grp_async = NULL,
 	.idle_timeout = HZ,
+	.strtstp_sleepwake = true,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
 
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 4575166..70f1c2c 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -809,6 +809,7 @@
 	.num_levels = 3,
 	.set_grp_async = set_grp_xbar_async,
 	.idle_timeout = HZ,
+	.strtstp_sleepwake = true,
 	.nap_allowed = false,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
@@ -836,8 +837,10 @@
 
 void __init msm8x25_kgsl_3d0_init(void)
 {
-	if (cpu_is_msm8625())
+	if (cpu_is_msm8625()) {
 		kgsl_3d0_pdata.idle_timeout = HZ/5;
+		kgsl_3d0_pdata.strtstp_sleepwake = false;
+	}
 }
 
 static void __init msm_register_device(struct platform_device *pdev, void *data)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5758dc4..078e931 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -55,6 +55,7 @@
 
 extern struct platform_device msm8960_device_uart_gsbi2;
 extern struct platform_device msm8960_device_uart_gsbi5;
+extern struct platform_device msm8960_device_uart_gsbi8;
 extern struct platform_device msm8960_device_ssbi_pmic;
 extern struct platform_device msm8960_device_qup_i2c_gsbi3;
 extern struct platform_device msm8960_device_qup_i2c_gsbi4;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 5b3f297..f01b0f7 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -99,6 +99,7 @@
 #define MSM_CAMERA_FLASH_SRC_CURRENT_DRIVER	(0x00000001<<2)
 #define MSM_CAMERA_FLASH_SRC_EXT     (0x00000001<<3)
 #define MSM_CAMERA_FLASH_SRC_LED (0x00000001<<3)
+#define MSM_CAMERA_FLASH_SRC_LED1 (0x00000001<<4)
 
 struct msm_camera_sensor_flash_pmic {
 	uint8_t num_of_src;
@@ -357,6 +358,7 @@
 struct msm_panel_common_pdata {
 	uintptr_t hw_revision_addr;
 	int gpio;
+	bool bl_lock;
 	int (*backlight_level)(int level, int max, int min);
 	int (*pmic_backlight)(int level);
 	int (*panel_num)(void);
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index 5eea63f..74ddfbd 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -15,7 +15,7 @@
 
 /*
  * These numbers are used from the kernel command line and sysfs
- * to control filtering. Remove items from here with extreme caution
+ * to control filtering. Remove items from here with extreme caution.
  */
 enum logk_event_type {
 	LOGK_NONE = 0,
@@ -24,9 +24,11 @@
 	LOGK_LOGBUF = 3,
 	LOGK_HOTPLUG = 4,
 	LOGK_CTXID = 5,
-	LOGK_OTHER = 31,
+	LOGK_TIMESTAMP = 6,
 };
 
+#define LOGTYPE_NOPC 0x80
+
 struct msm_rtb_platform_data {
 	unsigned int size;
 };
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 99bf212..aee562e 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -44,6 +44,8 @@
 #define machine_is_copper_sim()	0
 #endif
 
+#define PLATFORM_SUBTYPE_SGLTE	6
+
 enum msm_cpu {
 	MSM_CPU_UNKNOWN = 0,
 	MSM_CPU_7X01,
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 9b72f7c..7eaf526 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -1205,4 +1205,17 @@
 int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
 		  u32 addr, u32 size, int use_offset);
 
+/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ *
+ * @h - client context for SPS connection end point
+ *
+ * @desc_num - number of unused descriptors
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_get_unused_desc_num(struct sps_pipe *h, u32 *desc_num);
+
 #endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
index d05eaea..5a3d722 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
@@ -360,6 +360,8 @@
 		.tier = tier2,
 		.num_tiers = ARRAY_SIZE(tier2),
 		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "dfab_clk",
+		.slaveclk[ACTIVE_CTX] = "dfab_a_clk",
 	},
 	{
 		.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
index 36fe156..0f37c6d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
@@ -316,6 +316,8 @@
 		.tier = tier2,
 		.num_tiers = ARRAY_SIZE(tier2),
 		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "dfab_clk",
+		.slaveclk[ACTIVE_CTX] = "dfab_a_clk",
 	},
 	{
 		.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 0d265c7..7ede23d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -356,6 +356,8 @@
 		.tier = tier2,
 		.num_tiers = ARRAY_SIZE(tier2),
 		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "dfab_clk",
+		.slaveclk[ACTIVE_CTX] = "dfab_a_clk",
 	},
 	{
 		.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
index 5b52cb9..34cb2db 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
@@ -184,6 +184,8 @@
 		.tier = tier2,
 		.num_tiers = ARRAY_SIZE(tier2),
 		.buswidth = 8,
+		.slaveclk[DUAL_CTX] = "dfab_clk",
+		.slaveclk[ACTIVE_CTX] = "dfab_a_clk",
 	},
 	{
 		.id = MSM_BUS_SLAVE_EBI_CH0,
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 3f56d1a..403c13d 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -20,6 +20,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#include <linux/atomic.h>
 #include <asm/io.h>
 #include <asm-generic/sizes.h>
 #include <mach/memory.h>
@@ -76,7 +77,7 @@
 int msm_rtb_event_should_log(enum logk_event_type log_type)
 {
 	return msm_rtb.initialized && msm_rtb.enabled &&
-		((1 << log_type) & msm_rtb.filter);
+		((1 << (log_type & ~LOGTYPE_NOPC)) & msm_rtb.filter);
 }
 EXPORT_SYMBOL(msm_rtb_event_should_log);
 
@@ -109,10 +110,39 @@
 	start->data = data;
 }
 
+static void uncached_logk_pc_idx(enum logk_event_type log_type, void *caller,
+				 void *data, int idx)
+{
+	struct msm_rtb_layout *start;
+
+	start = &msm_rtb.rtb[idx & (msm_rtb.nentries - 1)];
+
+	msm_rtb_emit_sentinel(start);
+	msm_rtb_write_type(log_type, start);
+	msm_rtb_write_caller(caller, start);
+	msm_rtb_write_idx(idx, start);
+	msm_rtb_write_data(data, start);
+	mb();
+
+	return;
+}
+
+static void uncached_logk_timestamp(int idx)
+{
+	unsigned long long timestamp;
+	void *timestamp_upper, *timestamp_lower;
+	timestamp = sched_clock();
+	timestamp_lower = (void *)lower_32_bits(timestamp);
+	timestamp_upper = (void *)upper_32_bits(timestamp);
+
+	uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC, timestamp_lower,
+			     timestamp_upper, idx);
+}
+
 #if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
 static int msm_rtb_get_idx(void)
 {
-	int cpu, i;
+	int cpu, i, offset;
 	atomic_t *index;
 
 	/*
@@ -126,16 +156,34 @@
 	i = atomic_add_return(msm_rtb.step_size, index);
 	i -= msm_rtb.step_size;
 
+	/* Check if index has wrapped around */
+	offset = (i & (msm_rtb.nentries - 1)) -
+		 ((i - msm_rtb.step_size) & (msm_rtb.nentries - 1));
+	if (offset < 0) {
+		uncached_logk_timestamp(i);
+		i = atomic_add_return(msm_rtb.step_size, index);
+		i -= msm_rtb.step_size;
+	}
+
 	return i;
 }
 #else
 static int msm_rtb_get_idx(void)
 {
-	int i;
+	int i, offset;
 
 	i = atomic_inc_return(&msm_rtb_idx);
 	i--;
 
+	/* Check if index has wrapped around */
+	offset = (i & (msm_rtb.nentries - 1)) -
+		 ((i - 1) & (msm_rtb.nentries - 1));
+	if (offset < 0) {
+		uncached_logk_timestamp(i);
+		i = atomic_inc_return(&msm_rtb_idx);
+		i--;
+	}
+
 	return i;
 }
 #endif
@@ -144,21 +192,13 @@
 				void *data)
 {
 	int i;
-	struct msm_rtb_layout *start;
 
 	if (!msm_rtb_event_should_log(log_type))
 		return 0;
 
 	i = msm_rtb_get_idx();
 
-	start = &msm_rtb.rtb[i & (msm_rtb.nentries - 1)];
-
-	msm_rtb_emit_sentinel(start);
-	msm_rtb_write_type(log_type, start);
-	msm_rtb_write_caller(caller, start);
-	msm_rtb_write_idx(i, start);
-	msm_rtb_write_data(data, start);
-	mb();
+	uncached_logk_pc_idx(log_type, caller, data, i);
 
 	return 1;
 }
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index b5f071f..2403c02 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -371,14 +371,11 @@
 	mutex_lock(&q6.lock);
 	if (q6.state == APR_Q6_NOIMG) {
 		q6.pil = pil_get("q6");
-		if (!q6.pil) {
-			pr_err("APR: Unable to load q6 image\n");
+		if (IS_ERR(q6.pil)) {
+			rc = PTR_ERR(q6.pil);
+			pr_err("APR: Unable to load q6 image, error:%d\n", rc);
 			mutex_unlock(&q6.lock);
-			/* Return failure if not intended for simulator */
-			if (!machine_is_apq8064_sim()) {
-				pr_debug("APR: Not apq8064 sim\n");
-				return svc;
-			}
+			return svc;
 		}
 		q6.state = APR_Q6_LOADED;
 	}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index 75af881..ee32b80 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -69,7 +69,7 @@
 			/* Configure PCM output block */
 			rc = q6asm_enc_cfg_blk_pcm(audio->ac,
 				0, /*native sampling rate*/
-				(audio->pcm_cfg.channel_count <= 2) ? 0 : 2);
+				0 /*native channel count*/);
 			if (rc < 0) {
 				pr_err("pcm output block config failed\n");
 				break;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 3cf0550..d00dd1a 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -39,6 +39,7 @@
 #include <mach/system.h>
 #include <mach/subsystem_notif.h>
 #include <mach/socinfo.h>
+#include <asm/cacheflush.h>
 
 #include "smd_private.h"
 #include "proc_comm.h"
@@ -2473,10 +2474,12 @@
 			modem_queue_start_reset_notify();
 
 		} else if (modm & SMSM_RESET) {
-			if (!disable_smsm_reset_handshake)
-				apps |= SMSM_RESET;
-
 			pr_err("\nSMSM: Modem SMSM state changed to SMSM_RESET.");
+			if (!disable_smsm_reset_handshake) {
+				apps |= SMSM_RESET;
+				flush_cache_all();
+				outer_flush_all();
+			}
 			modem_queue_start_reset_notify();
 
 		} else if (modm & SMSM_INIT) {
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 9ef4028..5f835a2 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -88,24 +88,65 @@
 static int msm_smd_pkt_debug_mask;
 module_param_named(debug_mask, msm_smd_pkt_debug_mask,
 		int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+enum {
+	SMD_PKT_STATUS = 1U << 0,
+	SMD_PKT_READ = 1U << 1,
+	SMD_PKT_WRITE = 1U << 2,
+	SMD_PKT_READ_DUMP_BUFFER = 1U << 3,
+	SMD_PKT_WRITE_DUMP_BUFFER = 1U << 4,
+	SMD_PKT_POLL = 1U << 5,
+};
+
 #define DEBUG
 
 #ifdef DEBUG
-#define D_DUMP_BUFFER(prestr, cnt, buf) \
+#define D_STATUS(x...) \
 do { \
-	if (msm_smd_pkt_debug_mask) \
-		print_hex_dump(KERN_DEBUG, prestr, \
-				DUMP_PREFIX_NONE, 16, 1, \
-				buf, cnt, 1); \
+	if (msm_smd_pkt_debug_mask & SMD_PKT_STATUS) \
+		pr_info("Status: "x); \
+} while (0)
+
+#define D_READ(x...) \
+do { \
+	if (msm_smd_pkt_debug_mask & SMD_PKT_READ) \
+		pr_info("Read: "x); \
+} while (0)
+
+#define D_WRITE(x...) \
+do { \
+	if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE) \
+		pr_info("Write: "x); \
+} while (0)
+
+#define D_READ_DUMP_BUFFER(prestr, cnt, buf) \
+do { \
+	if (msm_smd_pkt_debug_mask & SMD_PKT_READ_DUMP_BUFFER) \
+		print_hex_dump(KERN_INFO, prestr, \
+			       DUMP_PREFIX_NONE, 16, 1, \
+			       buf, cnt, 1); \
+} while (0)
+
+#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) \
+do { \
+	if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE_DUMP_BUFFER) \
+		print_hex_dump(KERN_INFO, prestr, \
+			       DUMP_PREFIX_NONE, 16, 1, \
+			       buf, cnt, 1); \
+} while (0)
+
+#define D_POLL(x...) \
+do { \
+	if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
+		pr_info("Poll: "x); \
 } while (0)
 #else
-#define D_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
-#endif
-
-#ifdef DEBUG
-#define D(x...) if (msm_smd_pkt_debug_mask) printk(x)
-#else
-#define D(x...) do {} while (0)
+#define D_STATUS(x...) do {} while (0)
+#define D_READ(x...) do {} while (0)
+#define D_WRITE(x...) do {} while (0)
+#define D_READ_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
+#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
+#define D_POLL(x...) do {} while (0)
 #endif
 
 static ssize_t open_timeout_store(struct device *d,
@@ -171,6 +212,7 @@
 	wake_up(&smd_pkt_devp->ch_read_wait_queue);
 	wake_up(&smd_pkt_devp->ch_write_wait_queue);
 	wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
+	D_STATUS("%s smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
 }
 
 static void loopback_probe_worker(struct work_struct *work)
@@ -195,9 +237,12 @@
 	smd_pkt_devp = container_of(work, struct smd_pkt_dev,
 				    packet_arrival_work);
 	mutex_lock(&smd_pkt_devp->ch_lock);
-	if (smd_pkt_devp->ch)
+	if (smd_pkt_devp->ch) {
+		D_READ("%s locking smd_pkt_dev id:%d wakelock\n",
+			__func__, smd_pkt_devp->i);
 		wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
 				  WAKELOCK_TIMEOUT);
+	}
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 }
 
@@ -213,15 +258,20 @@
 
 	switch (cmd) {
 	case TIOCMGET:
+		D_STATUS("%s TIOCMGET command on smd_pkt_dev id:%d\n",
+			 __func__, smd_pkt_devp->i);
 		ret = smd_tiocmget(smd_pkt_devp->ch);
 		break;
 	case TIOCMSET:
+		D_STATUS("%s TIOCSET command on smd_pkt_dev id:%d\n",
+			 __func__, smd_pkt_devp->i);
 		ret = smd_tiocmset(smd_pkt_devp->ch, arg, ~arg);
 		break;
 	case SMD_PKT_IOCTL_BLOCKING_WRITE:
 		ret = get_user(smd_pkt_devp->blocking_write, (int *)arg);
 		break;
 	default:
+		pr_err("%s: Unrecognized ioctl command %d\n", __func__, cmd);
 		ret = -1;
 	}
 
@@ -240,18 +290,27 @@
 	struct smd_channel *chl;
 	unsigned long flags;
 
-	D(KERN_ERR "%s: read %i bytes\n",
-	  __func__, count);
-
 	smd_pkt_devp = file->private_data;
 
-	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+	if (!smd_pkt_devp) {
+		pr_err("%s on NULL smd_pkt_dev\n", __func__);
 		return -EINVAL;
+	}
+
+	if (!smd_pkt_devp->ch) {
+		pr_err("%s on a closed smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
+		return -EINVAL;
+	}
 
 	if (smd_pkt_devp->do_reset_notification) {
 		/* notify client that a reset occurred */
+		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
 		return notify_reset(smd_pkt_devp);
 	}
+	D_READ("Begin %s on smd_pkt_dev id:%d buffer_size %d\n",
+		__func__, smd_pkt_devp->i, count);
 
 	chl = smd_pkt_devp->ch;
 wait_for_packet:
@@ -260,20 +319,19 @@
 				      smd_read_avail(chl)) ||
 				     smd_pkt_devp->has_reset);
 
-	if (smd_pkt_devp->has_reset)
+	if (smd_pkt_devp->has_reset) {
+		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
 		return notify_reset(smd_pkt_devp);
+	}
 
 	if (r < 0) {
 		/* qualify error message */
 		if (r != -ERESTARTSYS) {
 			/* we get this anytime a signal comes in */
-			printk(KERN_ERR "ERROR:%s:%i:%s: "
-			       "wait_event_interruptible ret %i\n",
-			       __FILE__,
-			       __LINE__,
-			       __func__,
-			       r
-				);
+			pr_err("%s: wait_event_interruptible on smd_pkt_dev"
+			       " id:%d ret %i\n",
+				__func__, smd_pkt_devp->i, r);
 		}
 		return r;
 	}
@@ -284,13 +342,16 @@
 	pkt_size = smd_cur_packet_size(smd_pkt_devp->ch);
 
 	if (!pkt_size) {
-		D(KERN_ERR "%s: Nothing to read\n", __func__);
+		pr_err("%s: No data on smd_pkt_dev id:%d, False wakeup\n",
+			__func__, smd_pkt_devp->i);
 		mutex_unlock(&smd_pkt_devp->rx_lock);
 		goto wait_for_packet;
 	}
 
 	if (pkt_size > count) {
-		pr_err("packet size %i > buffer size %i,", pkt_size, count);
+		pr_err("%s: failure on smd_pkt_dev id: %d - packet size %d"
+		       " > buffer size %d,", __func__, smd_pkt_devp->i,
+			pkt_size, count);
 		mutex_unlock(&smd_pkt_devp->rx_lock);
 		return -ETOOSMALL;
 	}
@@ -302,8 +363,12 @@
 					 (pkt_size - bytes_read));
 		if (r < 0) {
 			mutex_unlock(&smd_pkt_devp->rx_lock);
-			if (smd_pkt_devp->has_reset)
+			if (smd_pkt_devp->has_reset) {
+				pr_err("%s notifying reset for smd_pkt_dev"
+				       " id:%d\n", __func__, smd_pkt_devp->i);
 				return notify_reset(smd_pkt_devp);
+			}
+			pr_err("%s Error while reading %d\n", __func__, r);
 			return r;
 		}
 		bytes_read += r;
@@ -313,10 +378,12 @@
 				   smd_pkt_devp->has_reset);
 		if (smd_pkt_devp->has_reset) {
 			mutex_unlock(&smd_pkt_devp->rx_lock);
+			pr_err("%s notifying reset for smd_pkt_dev  id:%d\n",
+				__func__, smd_pkt_devp->i);
 			return notify_reset(smd_pkt_devp);
 		}
 	} while (pkt_size != bytes_read);
-	D_DUMP_BUFFER("read: ", bytes_read, buf);
+	D_READ_DUMP_BUFFER("Read: ", (bytes_read > 16 ? 16 : bytes_read), buf);
 	mutex_unlock(&smd_pkt_devp->rx_lock);
 
 	mutex_lock(&smd_pkt_devp->ch_lock);
@@ -325,12 +392,14 @@
 	    !smd_cur_packet_size(smd_pkt_devp->ch)) {
 		wake_unlock(&smd_pkt_devp->pa_wake_lock);
 		smd_pkt_devp->poll_mode = 0;
+		D_READ("%s unlocked smd_pkt_dev id:%d wakelock\n",
+			__func__, smd_pkt_devp->i);
 	}
 	spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
 	mutex_unlock(&smd_pkt_devp->ch_lock);
 
-	D(KERN_ERR "%s: just read %i bytes\n",
-	  __func__, bytes_read);
+	D_READ("Finished %s on smd_pkt_dev id:%d  %d bytes\n",
+		__func__, smd_pkt_devp->i, bytes_read);
 
 	/* check and wakeup read threads waiting on this device */
 	check_and_wakeup_reader(smd_pkt_devp);
@@ -347,24 +416,33 @@
 	struct smd_pkt_dev *smd_pkt_devp;
 	DEFINE_WAIT(write_wait);
 
-	D(KERN_ERR "%s: writting %i bytes\n",
-	  __func__, count);
-
 	smd_pkt_devp = file->private_data;
 
-	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+	if (!smd_pkt_devp) {
+		pr_err("%s on NULL smd_pkt_dev\n", __func__);
 		return -EINVAL;
+	}
+
+	if (!smd_pkt_devp->ch) {
+		pr_err("%s on a closed smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
+		return -EINVAL;
+	}
 
 	if (smd_pkt_devp->do_reset_notification) {
+		pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
 		/* notify client that a reset occurred */
 		return notify_reset(smd_pkt_devp);
 	}
+	D_WRITE("Begin %s on smd_pkt_dev id:%d data_size %d\n",
+		__func__, smd_pkt_devp->i, count);
 
 	mutex_lock(&smd_pkt_devp->tx_lock);
 	if (!smd_pkt_devp->blocking_write) {
 		if (smd_write_avail(smd_pkt_devp->ch) < count) {
-			D(KERN_ERR "%s: Not enough space to write\n",
-				   __func__);
+			pr_err("%s: Not enough space in smd_pkt_dev id:%d\n",
+				   __func__, smd_pkt_devp->i);
 			mutex_unlock(&smd_pkt_devp->tx_lock);
 			return -ENOMEM;
 		}
@@ -373,7 +451,8 @@
 	r = smd_write_start(smd_pkt_devp->ch, count);
 	if (r < 0) {
 		mutex_unlock(&smd_pkt_devp->tx_lock);
-		pr_err("%s: Error %d @ smd_write_start\n", __func__, r);
+		pr_err("%s: Error:%d in smd_pkt_dev id:%d @ smd_write_start\n",
+			__func__, r, smd_pkt_devp->i);
 		return r;
 	}
 
@@ -391,6 +470,8 @@
 
 		if (smd_pkt_devp->has_reset) {
 			mutex_unlock(&smd_pkt_devp->tx_lock);
+			pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+				__func__, smd_pkt_devp->i);
 			return notify_reset(smd_pkt_devp);
 		} else {
 			r = smd_write_segment(smd_pkt_devp->ch,
@@ -398,17 +479,22 @@
 					      (count - bytes_written), 1);
 			if (r < 0) {
 				mutex_unlock(&smd_pkt_devp->tx_lock);
-				if (smd_pkt_devp->has_reset)
+				if (smd_pkt_devp->has_reset) {
+					pr_err("%s notifying reset for"
+					       " smd_pkt_dev id:%d\n",
+						__func__, smd_pkt_devp->i);
 					return notify_reset(smd_pkt_devp);
+				}
 			}
 			bytes_written += r;
 		}
 	} while (bytes_written != count);
 	smd_write_end(smd_pkt_devp->ch);
 	mutex_unlock(&smd_pkt_devp->tx_lock);
-
-	D(KERN_ERR "%s: just wrote %i bytes\n",
-	       __func__, count);
+	D_WRITE_DUMP_BUFFER("Write: ",
+			    (bytes_written > 16 ? 16 : bytes_written), buf);
+	D_WRITE("Finished %s on smd_pkt_dev id:%d %d bytes\n",
+		__func__, smd_pkt_devp->i, count);
 
 	return count;
 }
@@ -419,13 +505,18 @@
 	unsigned int mask = 0;
 
 	smd_pkt_devp = file->private_data;
-	if (!smd_pkt_devp)
+	if (!smd_pkt_devp) {
+		pr_err("%s on a NULL device\n", __func__);
 		return POLLERR;
+	}
 
 	smd_pkt_devp->poll_mode = 1;
 	poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
-	if (smd_read_avail(smd_pkt_devp->ch))
+	if (smd_read_avail(smd_pkt_devp->ch)) {
 		mask |= POLLIN | POLLRDNORM;
+		D_POLL("%s sets POLLIN for smd_pkt_dev id: %d\n",
+			__func__, smd_pkt_devp->i);
+	}
 
 	return mask;
 }
@@ -435,18 +526,27 @@
 	int sz;
 	unsigned long flags;
 
-	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+	if (!smd_pkt_devp) {
+		pr_err("%s on a NULL device\n", __func__);
 		return;
+	}
+
+	if (!smd_pkt_devp->ch) {
+		pr_err("%s on a closed smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
+		return;
+	}
 
 	sz = smd_cur_packet_size(smd_pkt_devp->ch);
 	if (sz == 0) {
-		D(KERN_ERR "%s: packet size is 0\n", __func__);
+		D_READ("%s: No packet in smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
 		return;
 	}
 	if (!smd_read_avail(smd_pkt_devp->ch)) {
-		D(KERN_ERR "%s: packet size is %i - "
-		  "but the data isn't here\n",
-		  __func__, sz);
+		D_READ("%s: packet size is %d in smd_pkt_dev id:%d -"
+			" but the data isn't here\n",
+			__func__, sz, smd_pkt_devp->i);
 		return;
 	}
 
@@ -456,20 +556,28 @@
 	wake_lock(&smd_pkt_devp->pa_wake_lock);
 	spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
 	schedule_work(&smd_pkt_devp->packet_arrival_work);
-	D(KERN_ERR "%s: after wake_up\n", __func__);
+	D_READ("%s: wake_up smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
 }
 
 static void check_and_wakeup_writer(struct smd_pkt_dev *smd_pkt_devp)
 {
 	int sz;
 
-	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+	if (!smd_pkt_devp) {
+		pr_err("%s on a NULL device\n", __func__);
 		return;
+	}
+
+	if (!smd_pkt_devp->ch) {
+		pr_err("%s on a closed smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
+		return;
+	}
 
 	sz = smd_write_avail(smd_pkt_devp->ch);
 	if (sz) {
-		D(KERN_ERR "%s: %d bytes Write Space available\n",
-			    __func__, sz);
+		D_WRITE("%s: %d bytes write space in smd_pkt_dev id:%d\n",
+			__func__, sz, smd_pkt_devp->i);
 		smd_disable_read_intr(smd_pkt_devp->ch);
 		wake_up(&smd_pkt_devp->ch_write_wait_queue);
 	}
@@ -479,31 +587,32 @@
 {
 	struct smd_pkt_dev *smd_pkt_devp = priv;
 
-	if (smd_pkt_devp->ch == 0)
+	if (smd_pkt_devp->ch == 0) {
+		pr_err("%s on a closed smd_pkt_dev id:%d\n",
+			__func__, smd_pkt_devp->i);
 		return;
+	}
 
 	switch (event) {
 	case SMD_EVENT_DATA: {
-		D(KERN_ERR "%s: data\n", __func__);
+		D_STATUS("%s: DATA event in smd_pkt_dev id:%d\n",
+			 __func__, smd_pkt_devp->i);
 		check_and_wakeup_reader(smd_pkt_devp);
 		if (smd_pkt_devp->blocking_write)
 			check_and_wakeup_writer(smd_pkt_devp);
-		D(KERN_ERR "%s: data after check_and_wakeup\n", __func__);
 		break;
 	}
 	case SMD_EVENT_OPEN:
-		D(KERN_ERR "%s: smd opened\n",
-		  __func__);
-
+		D_STATUS("%s: OPEN event in smd_pkt_dev id:%d\n",
+			  __func__, smd_pkt_devp->i);
 		smd_pkt_devp->has_reset = 0;
 		smd_pkt_devp->is_open = 1;
 		wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
 		break;
 	case SMD_EVENT_CLOSE:
+		D_STATUS("%s: CLOSE event in smd_pkt_dev id:%d\n",
+			  __func__, smd_pkt_devp->i);
 		smd_pkt_devp->is_open = 0;
-		printk(KERN_ERR "%s: smd closed\n",
-		       __func__);
-
 		/* put port into reset state */
 		clean_and_signal(smd_pkt_devp);
 		if (smd_pkt_devp->i == LOOPBACK_INX)
@@ -591,6 +700,8 @@
 	for (i = 0; i < NUM_SMD_PKT_PORTS; i++) {
 		if (!strncmp(pdev->name, smd_ch_name[i], SMD_MAX_CH_NAME_LEN)) {
 			complete_all(&smd_pkt_devp[i]->ch_allocated);
+			D_STATUS("%s allocated SMD ch for smd_pkt_dev id:%d\n",
+				 __func__, i);
 			break;
 		}
 	}
@@ -614,8 +725,11 @@
 
 	smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev);
 
-	if (!smd_pkt_devp)
+	if (!smd_pkt_devp) {
+		pr_err("%s on a NULL device\n", __func__);
 		return -EINVAL;
+	}
+	D_STATUS("Begin %s on smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
 
 	wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
 			smd_pkt_dev_name[smd_pkt_devp->i]);
@@ -643,6 +757,9 @@
 			smd_pkt_devp->pil = pil_get(peripheral);
 			if (IS_ERR(smd_pkt_devp->pil)) {
 				r = PTR_ERR(smd_pkt_devp->pil);
+				pr_err("%s failed on smd_pkt_dev id:%d -"
+				       " pil_get failed for %s\n", __func__,
+					smd_pkt_devp->i, peripheral);
 				goto release_pd;
 			}
 
@@ -672,8 +789,9 @@
 				if (r == 0)
 					r = -ETIMEDOUT;
 				if (r < 0) {
-					pr_err("%s: wait failed for smd port:"
-					       " %d\n", __func__, r);
+					pr_err("%s: wait on smd_pkt_dev id:%d"
+					       " allocation failed rc:%d\n",
+						__func__, smd_pkt_devp->i, r);
 					goto release_pil;
 				}
 			}
@@ -697,16 +815,19 @@
 			r = -ETIMEDOUT;
 
 		if (r < 0) {
-			pr_err("%s: wait failed for smd open: %d\n",
-			       __func__, r);
+			pr_err("%s: wait on smd_pkt_dev id:%d OPEN event failed"
+			       " rc:%d\n", __func__, smd_pkt_devp->i, r);
 		} else if (!smd_pkt_devp->is_open) {
-			pr_err("%s: Invalid open notification\n", __func__);
+			pr_err("%s: Invalid OPEN event on smd_pkt_dev id:%d\n",
+				__func__, smd_pkt_devp->i);
 			r = -ENODEV;
 		} else {
 			smd_disable_read_intr(smd_pkt_devp->ch);
 			smd_pkt_devp->ch_size =
 				smd_write_avail(smd_pkt_devp->ch);
 			r = 0;
+			D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
+				 __func__, smd_pkt_devp->i);
 		}
 	}
 release_pil:
@@ -730,8 +851,12 @@
 	int r = 0;
 	struct smd_pkt_dev *smd_pkt_devp = file->private_data;
 
-	if (!smd_pkt_devp)
+	if (!smd_pkt_devp) {
+		pr_err("%s on a NULL device\n", __func__);
 		return -EINVAL;
+	}
+	D_STATUS("Begin %s on smd_pkt_dev id:%d\n",
+		 __func__, smd_pkt_devp->i);
 
 	clean_and_signal(smd_pkt_devp);
 
@@ -750,6 +875,8 @@
 	smd_pkt_devp->has_reset = 0;
 	smd_pkt_devp->do_reset_notification = 0;
 	wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+	D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
+		 __func__, smd_pkt_devp->i);
 
 	return r;
 }
@@ -774,22 +901,14 @@
 			       NUM_SMD_PKT_PORTS,
 			       DEVICE_NAME);
 	if (IS_ERR_VALUE(r)) {
-		printk(KERN_ERR "ERROR:%s:%i:%s: "
-		       "alloc_chrdev_region() ret %i.\n",
-		       __FILE__,
-		       __LINE__,
-		       __func__,
-		       r);
+		pr_err("%s: alloc_chrdev_region() failed ret:%i\n",
+		       __func__, r);
 		goto error0;
 	}
 
 	smd_pkt_classp = class_create(THIS_MODULE, DEVICE_NAME);
 	if (IS_ERR(smd_pkt_classp)) {
-		printk(KERN_ERR "ERROR:%s:%i:%s: "
-		       "class_create() ENOMEM\n",
-		       __FILE__,
-		       __LINE__,
-		       __func__);
+		pr_err("%s: class_create() failed ENOMEM\n", __func__);
 		r = -ENOMEM;
 		goto error1;
 	}
@@ -798,10 +917,8 @@
 		smd_pkt_devp[i] = kzalloc(sizeof(struct smd_pkt_dev),
 					 GFP_KERNEL);
 		if (IS_ERR(smd_pkt_devp[i])) {
-			printk(KERN_ERR "ERROR:%s:%i:%s kmalloc() ENOMEM\n",
-			       __FILE__,
-			       __LINE__,
-			       __func__);
+			pr_err("%s: kzalloc() failed for smd_pkt_dev id:%d\n",
+				__func__, i);
 			r = -ENOMEM;
 			goto error2;
 		}
@@ -827,11 +944,8 @@
 			     1);
 
 		if (IS_ERR_VALUE(r)) {
-			printk(KERN_ERR "%s:%i:%s: cdev_add() ret %i\n",
-			       __FILE__,
-			       __LINE__,
-			       __func__,
-			       r);
+			pr_err("%s: cdev_add() failed for smd_pkt_dev id:%d"
+			       " ret:%i\n", __func__, i, r);
 			kfree(smd_pkt_devp[i]);
 			goto error2;
 		}
@@ -844,11 +958,8 @@
 				      smd_pkt_dev_name[i]);
 
 		if (IS_ERR(smd_pkt_devp[i]->devicep)) {
-			printk(KERN_ERR "%s:%i:%s: "
-			       "device_create() ENOMEM\n",
-			       __FILE__,
-			       __LINE__,
-			       __func__);
+			pr_err("%s: device_create() failed for smd_pkt_dev"
+			       " id:%d\n", __func__, i);
 			r = -ENOMEM;
 			cdev_del(&smd_pkt_devp[i]->cdev);
 			kfree(smd_pkt_devp[i]);
@@ -856,13 +967,13 @@
 		}
 		if (device_create_file(smd_pkt_devp[i]->devicep,
 					&dev_attr_open_timeout))
-			pr_err("%s: unable to create device attr on #%d\n",
-				__func__, i);
+			pr_err("%s: unable to create device attr for"
+			       " smd_pkt_dev id:%d\n", __func__, i);
 	}
 
 	INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
 
-	D(KERN_INFO "SMD Packet Port Driver Initialized.\n");
+	D_STATUS("SMD Packet Port Driver Initialized.\n");
 	return 0;
 
  error2:
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 59643c5..8b2566a 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -566,7 +566,7 @@
 
 	of_property_read_u32_array(np, "arm,filter-ranges",
 				   filter, ARRAY_SIZE(filter));
-	if (filter[0] && filter[1]) {
+	if (filter[1]) {
 		writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
 			       l2x0_base + L2X0_ADDR_FILTER_END);
 		writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a77d825..65ddfec 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -510,6 +510,18 @@
 
 }
 
+void diag_toggle_event_mask(int toggle)
+{
+	uint8_t *ptr = driver->event_masks;
+
+	mutex_lock(&driver->diagchar_mutex);
+	if (toggle)
+		memset(ptr, 0xFF, EVENT_MASK_SIZE);
+	else
+		memset(ptr, 0, EVENT_MASK_SIZE);
+	mutex_unlock(&driver->diagchar_mutex);
+}
+
 static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
 {
 	uint8_t *ptr = driver->event_masks;
@@ -813,9 +825,8 @@
 			*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
 			*(uint16_t *)(driver->apps_rsp_buf + 4) =
 							EVENT_LAST_ID + 1;
-			for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
-				*(unsigned char *)(driver->apps_rsp_buf + 6 + i)
-									 = 0x0;
+			memcpy(driver->apps_rsp_buf+6, driver->event_masks,
+							 EVENT_LAST_ID/8+1);
 			/* cannot do this on work queue, as each event update
 			needs a num_bytes variable. Each queue_work call will
 			overwrite the previous input, as its the same struct */
@@ -832,6 +843,8 @@
 #endif
 	} else if (*buf == 0x60) {
 		diag_event_config = *(buf+1);
+		diag_toggle_event_mask(*(buf+1));
+		diag_update_userspace_clients(EVENT_MASKS_TYPE);
 #if defined(CONFIG_DIAG_OVER_USB)
 		if (chk_apps_only()) {
 			driver->apps_rsp_buf[0] = 0x60;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d7a104c..fb672e4 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -113,6 +113,7 @@
 	.pfp_fw = NULL,
 	.pm4_fw = NULL,
 	.wait_timeout = 10000, /* in milliseconds */
+	.ib_check_level = 0,
 };
 
 
@@ -975,7 +976,7 @@
 	return status;
 }
 
-const struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
+struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
 						unsigned int pt_base,
 						unsigned int gpuaddr,
 						unsigned int size)
@@ -1034,7 +1035,7 @@
 uint8_t *adreno_convertaddr(struct kgsl_device *device, unsigned int pt_base,
 			    unsigned int gpuaddr, unsigned int size)
 {
-	const struct kgsl_memdesc *memdesc;
+	struct kgsl_memdesc *memdesc;
 
 	memdesc = adreno_find_region(device, pt_base, gpuaddr, size);
 
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 07ccb85..4885312 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -77,6 +77,7 @@
 	unsigned int istore_size;
 	unsigned int pix_shader_start;
 	unsigned int instruction_size;
+	unsigned int ib_check_level;
 };
 
 struct adreno_gpudev {
@@ -119,7 +120,7 @@
 void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
 				unsigned int value);
 
-const struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
+struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
 						unsigned int pt_base,
 						unsigned int gpuaddr,
 						unsigned int size);
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 3461316..9e022b9 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -113,6 +113,8 @@
 			    &kgsl_cff_dump_enable_fops);
 	debugfs_create_u32("wait_timeout", 0644, device->d_debugfs,
 		&adreno_dev->wait_timeout);
+	debugfs_create_u32("ib_check", 0644, device->d_debugfs,
+			   &adreno_dev->ib_check_level);
 
 	/* Create post mortem control files */
 
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index 6e85ec6..fb44b25 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -29,11 +29,6 @@
 /* skip N 32-bit words to get to the next packet */
 #define CP_NOP			0x10
 
-/* indirect buffer dispatch.  prefetch parser uses this packet type to determine
-*  whether to pre-fetch the IB
-*/
-#define CP_INDIRECT_BUFFER	0x3f
-
 /* indirect buffer dispatch.  same as IB, but init is pipelined */
 #define CP_INDIRECT_BUFFER_PFD	0x37
 
@@ -120,6 +115,9 @@
 /* load constants from a location in memory */
 #define CP_LOAD_CONSTANT_CONTEXT 0x2e
 
+/* (A2x) sets binning configuration registers */
+#define CP_SET_BIN_DATA             0x2f
+
 /* selective invalidation of state pointers */
 #define CP_INVALIDATE_STATE	0x3b
 
@@ -213,7 +211,7 @@
 /* packet headers */
 #define CP_HDR_ME_INIT	cp_type3_packet(CP_ME_INIT, 18)
 #define CP_HDR_INDIRECT_BUFFER_PFD cp_type3_packet(CP_INDIRECT_BUFFER_PFD, 2)
-#define CP_HDR_INDIRECT_BUFFER	cp_type3_packet(CP_INDIRECT_BUFFER, 2)
+#define CP_HDR_INDIRECT_BUFFER_PFE cp_type3_packet(CP_INDIRECT_BUFFER_PFE, 2)
 
 /* dword base address of the GFX decode space */
 #define SUBBLOCK_OFFSET(reg) ((unsigned int)((reg) - (0x2000)))
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 5b197b4..d97659c 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -54,7 +54,7 @@
 	{CP_IM_LOAD,			"IN__LOAD"},
 	{CP_IM_LOAD_IMMEDIATE,		"IM_LOADI"},
 	{CP_IM_STORE,			"IM_STORE"},
-	{CP_INDIRECT_BUFFER,		"IND_BUF_"},
+	{CP_INDIRECT_BUFFER_PFE,	"IND_BUF_"},
 	{CP_INDIRECT_BUFFER_PFD,	"IND_BUFP"},
 	{CP_INTERRUPT,			"PM4_INTR"},
 	{CP_INVALIDATE_STATE,		"INV_STAT"},
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 9542dfc..b9c0a28 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -22,6 +22,7 @@
 #include "adreno.h"
 #include "adreno_pm4types.h"
 #include "adreno_ringbuffer.h"
+#include "adreno_debugfs.h"
 
 #include "a2xx_reg.h"
 #include "a3xx_reg.h"
@@ -545,6 +546,198 @@
 	adreno_ringbuffer_addcmds(rb, flags, cmds, sizedwords);
 }
 
+static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
+			   int sizedwords);
+
+static bool
+_handle_type3(struct kgsl_device_private *dev_priv, uint *hostaddr)
+{
+	unsigned int opcode = cp_type3_opcode(*hostaddr);
+	switch (opcode) {
+	case CP_INDIRECT_BUFFER_PFD:
+	case CP_INDIRECT_BUFFER_PFE:
+	case CP_COND_INDIRECT_BUFFER_PFE:
+	case CP_COND_INDIRECT_BUFFER_PFD:
+		return _parse_ibs(dev_priv, hostaddr[1], hostaddr[2]);
+	case CP_NOP:
+	case CP_WAIT_FOR_IDLE:
+	case CP_WAIT_REG_MEM:
+	case CP_WAIT_REG_EQ:
+	case CP_WAT_REG_GTE:
+	case CP_WAIT_UNTIL_READ:
+	case CP_WAIT_IB_PFD_COMPLETE:
+	case CP_REG_RMW:
+	case CP_REG_TO_MEM:
+	case CP_MEM_WRITE:
+	case CP_MEM_WRITE_CNTR:
+	case CP_COND_EXEC:
+	case CP_COND_WRITE:
+	case CP_EVENT_WRITE:
+	case CP_EVENT_WRITE_SHD:
+	case CP_EVENT_WRITE_CFL:
+	case CP_EVENT_WRITE_ZPD:
+	case CP_DRAW_INDX:
+	case CP_DRAW_INDX_2:
+	case CP_DRAW_INDX_BIN:
+	case CP_DRAW_INDX_2_BIN:
+	case CP_VIZ_QUERY:
+	case CP_SET_STATE:
+	case CP_SET_CONSTANT:
+	case CP_IM_LOAD:
+	case CP_IM_LOAD_IMMEDIATE:
+	case CP_LOAD_CONSTANT_CONTEXT:
+	case CP_INVALIDATE_STATE:
+	case CP_SET_SHADER_BASES:
+	case CP_SET_BIN_MASK:
+	case CP_SET_BIN_SELECT:
+	case CP_SET_BIN_BASE_OFFSET:
+	case CP_SET_BIN_DATA:
+	case CP_CONTEXT_UPDATE:
+	case CP_INTERRUPT:
+	case CP_IM_STORE:
+	case CP_LOAD_STATE:
+		break;
+	/* these shouldn't come from userspace */
+	case CP_ME_INIT:
+	case CP_SET_PROTECTED_MODE:
+	default:
+		KGSL_CMD_ERR(dev_priv->device, "bad CP opcode %0x\n", opcode);
+		return false;
+		break;
+	}
+
+	return true;
+}
+
+static bool
+_handle_type0(struct kgsl_device_private *dev_priv, uint *hostaddr)
+{
+	unsigned int reg = type0_pkt_offset(*hostaddr);
+	unsigned int cnt = type0_pkt_size(*hostaddr);
+	if (reg < 0x0192 || (reg + cnt) >= 0x8000) {
+		KGSL_CMD_ERR(dev_priv->device, "bad type0 reg: 0x%0x cnt: %d\n",
+			     reg, cnt);
+		return false;
+	}
+	return true;
+}
+
+/*
+ * Traverse IBs and dump them to test vector. Detect swap by inspecting
+ * register writes, keeping note of the current state, and dump
+ * framebuffer config to test vector
+ */
+static bool _parse_ibs(struct kgsl_device_private *dev_priv,
+			   uint gpuaddr, int sizedwords)
+{
+	static uint level; /* recursion level */
+	bool ret = false;
+	uint *hostaddr, *hoststart;
+	int dwords_left = sizedwords; /* dwords left in the current command
+					 buffer */
+	struct kgsl_mem_entry *entry;
+
+	spin_lock(&dev_priv->process_priv->mem_lock);
+	entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
+					   gpuaddr, sizedwords * sizeof(uint));
+	spin_unlock(&dev_priv->process_priv->mem_lock);
+	if (entry == NULL) {
+		KGSL_CMD_ERR(dev_priv->device,
+			     "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
+		return false;
+	}
+
+	hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(&entry->memdesc, gpuaddr);
+	if (hostaddr == NULL) {
+		KGSL_CMD_ERR(dev_priv->device,
+			     "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
+		return false;
+	}
+
+	hoststart = hostaddr;
+
+	level++;
+
+	KGSL_CMD_INFO(dev_priv->device, "ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
+		gpuaddr, sizedwords, hostaddr);
+
+	mb();
+	while (dwords_left > 0) {
+		bool cur_ret = true;
+		int count = 0; /* dword count including packet header */
+
+		switch (*hostaddr >> 30) {
+		case 0x0: /* type-0 */
+			count = (*hostaddr >> 16)+2;
+			cur_ret = _handle_type0(dev_priv, hostaddr);
+			break;
+		case 0x1: /* type-1 */
+			count = 2;
+			break;
+		case 0x3: /* type-3 */
+			count = ((*hostaddr >> 16) & 0x3fff) + 2;
+			cur_ret = _handle_type3(dev_priv, hostaddr);
+			break;
+		default:
+			KGSL_CMD_ERR(dev_priv->device, "unexpected type: "
+				"type:%d, word:0x%08x @ 0x%p, gpu:0x%08x\n",
+				*hostaddr >> 30, *hostaddr, hostaddr,
+				gpuaddr+4*(sizedwords-dwords_left));
+			cur_ret = false;
+			count = dwords_left;
+			break;
+		}
+
+		if (!cur_ret) {
+			KGSL_CMD_ERR(dev_priv->device,
+				"bad sub-type: #:%d/%d, v:0x%08x"
+				" @ 0x%p[gb:0x%08x], level:%d\n",
+				sizedwords-dwords_left, sizedwords, *hostaddr,
+				hostaddr, gpuaddr+4*(sizedwords-dwords_left),
+				level);
+
+			if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
+				>= 2)
+				print_hex_dump(KERN_ERR,
+					level == 1 ? "IB1:" : "IB2:",
+					DUMP_PREFIX_OFFSET, 32, 4, hoststart,
+					sizedwords*4, 0);
+			goto done;
+		}
+
+		/* jump to next packet */
+		dwords_left -= count;
+		hostaddr += count;
+		if (dwords_left < 0) {
+			KGSL_CMD_ERR(dev_priv->device,
+				"bad count: c:%d, #:%d/%d, "
+				"v:0x%08x @ 0x%p[gb:0x%08x], level:%d\n",
+				count, sizedwords-(dwords_left+count),
+				sizedwords, *(hostaddr-count), hostaddr-count,
+				gpuaddr+4*(sizedwords-(dwords_left+count)),
+				level);
+			if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
+				>= 2)
+				print_hex_dump(KERN_ERR,
+					level == 1 ? "IB1:" : "IB2:",
+					DUMP_PREFIX_OFFSET, 32, 4, hoststart,
+					sizedwords*4, 0);
+			goto done;
+		}
+	}
+
+	ret = true;
+done:
+	if (!ret)
+		KGSL_DRV_ERR(dev_priv->device,
+			"parsing failed: gpuaddr:0x%08x, "
+			"host:0x%p, wc:%d\n", gpuaddr, hoststart, sizedwords);
+
+	level--;
+
+	return ret;
+}
+
 int
 adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
 				struct kgsl_context *context,
@@ -603,9 +796,12 @@
 		*cmds++ = ibdesc[0].sizedwords;
 	}
 	for (i = start_index; i < numibs; i++) {
-		(void)kgsl_cffdump_parse_ibs(dev_priv, NULL,
-			ibdesc[i].gpuaddr, ibdesc[i].sizedwords, false);
-
+		if (unlikely(adreno_dev->ib_check_level >= 1 &&
+		    !_parse_ibs(dev_priv, ibdesc[i].gpuaddr,
+				ibdesc[i].sizedwords))) {
+			kfree(link);
+			return -EINVAL;
+		}
 		*cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
 		*cmds++ = ibdesc[i].gpuaddr;
 		*cmds++ = ibdesc[i].sizedwords;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 0361387..d0110b9 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -13,10 +13,6 @@
 #ifndef __ADRENO_RINGBUFFER_H
 #define __ADRENO_RINGBUFFER_H
 
-#define GSL_RB_USE_MEM_RPTR
-#define GSL_RB_USE_MEM_TIMESTAMP
-#define GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
-
 /*
  * Adreno ringbuffer sizes in bytes - these are converted to
  * the appropriate log2 values in the code
@@ -71,37 +67,16 @@
 		gpuaddr += sizeof(uint); \
 	} while (0)
 
-/* timestamp */
-#ifdef GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
-#define GSL_RB_USE_MEM_TIMESTAMP
-#endif /* GSL_DEVICE_SHADOW_MEMSTORE_TO_USER */
-
-#ifdef GSL_RB_USE_MEM_TIMESTAMP
 /* enable timestamp (...scratch0) memory shadowing */
 #define GSL_RB_MEMPTRS_SCRATCH_MASK 0x1
 #define GSL_RB_INIT_TIMESTAMP(rb)
 
-#else
-#define GSL_RB_MEMPTRS_SCRATCH_MASK 0x0
-#define GSL_RB_INIT_TIMESTAMP(rb) \
-		adreno_regwrite((rb)->device->id, REG_CP_TIMESTAMP, 0)
-
-#endif /* GSL_RB_USE_MEMTIMESTAMP */
-
 /* mem rptr */
-#ifdef GSL_RB_USE_MEM_RPTR
 #define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
 #define GSL_RB_GET_READPTR(rb, data) \
 	do { \
 		*(data) = rb->memptrs->rptr; \
 	} while (0)
-#else
-#define GSL_RB_CNTL_NO_UPDATE 0x1 /* disable */
-#define GSL_RB_GET_READPTR(rb, data) \
-	do { \
-		adreno_regread((rb)->device->id, REG_CP_RB_RPTR, (data)); \
-	} while (0)
-#endif /* GSL_RB_USE_MEMRPTR */
 
 #define GSL_RB_CNTL_POLL_EN 0x0 /* disable */
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6c1199e..45bcf69 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -938,40 +938,6 @@
 
 	return result;
 }
-static bool check_ibdesc(struct kgsl_device_private *dev_priv,
-			 struct kgsl_ibdesc *ibdesc, unsigned int numibs,
-			 bool parse)
-{
-	bool result = true;
-	unsigned int i;
-	for (i = 0; i < numibs; i++) {
-		struct kgsl_mem_entry *entry;
-		spin_lock(&dev_priv->process_priv->mem_lock);
-		entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
-			ibdesc[i].gpuaddr, ibdesc[i].sizedwords * sizeof(uint));
-		spin_unlock(&dev_priv->process_priv->mem_lock);
-		if (entry == NULL) {
-			KGSL_DRV_ERR(dev_priv->device,
-				"invalid cmd buffer gpuaddr %08x " \
-				"sizedwords %d\n", ibdesc[i].gpuaddr,
-				ibdesc[i].sizedwords);
-			result = false;
-			break;
-		}
-
-		if (parse && !kgsl_cffdump_parse_ibs(dev_priv, &entry->memdesc,
-			ibdesc[i].gpuaddr, ibdesc[i].sizedwords, true)) {
-			KGSL_DRV_ERR(dev_priv->device,
-				"invalid cmd buffer gpuaddr %08x " \
-				"sizedwords %d numibs %d/%d\n",
-				ibdesc[i].gpuaddr,
-				ibdesc[i].sizedwords, i+1, numibs);
-			result = false;
-			break;
-		}
-	}
-	return result;
-}
 
 static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
 				      unsigned int cmd, void *data)
@@ -1037,12 +1003,6 @@
 		param->numibs = 1;
 	}
 
-	if (!check_ibdesc(dev_priv, ibdesc, param->numibs, true)) {
-		KGSL_DRV_ERR(dev_priv->device, "bad ibdesc");
-		result = -EINVAL;
-		goto free_ibdesc;
-	}
-
 	result = dev_priv->device->ftbl->issueibcmds(dev_priv,
 					     context,
 					     ibdesc,
@@ -1052,18 +1012,6 @@
 
 	trace_kgsl_issueibcmds(dev_priv->device, param, result);
 
-	if (result != 0)
-		goto free_ibdesc;
-
-	/* this is a check to try to detect if a command buffer was freed
-	 * during issueibcmds().
-	 */
-	if (!check_ibdesc(dev_priv, ibdesc, param->numibs, false)) {
-		KGSL_DRV_ERR(dev_priv->device, "bad ibdesc AFTER issue");
-		result = -EINVAL;
-		goto free_ibdesc;
-	}
-
 free_ibdesc:
 	kfree(ibdesc);
 done:
@@ -1286,9 +1234,9 @@
 
 	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
-	result = remap_vmalloc_range(vma, (void *) entry->memdesc.hostptr, 0);
+	result = kgsl_sharedmem_map_vma(vma, &entry->memdesc);
 	if (result) {
-		KGSL_CORE_ERR("remap_vmalloc_range failed: %d\n", result);
+		KGSL_CORE_ERR("kgsl_sharedmem_map_vma failed: %d\n", result);
 		goto error_free_vmalloc;
 	}
 
@@ -1428,7 +1376,8 @@
 	int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
 	unsigned long paddr = (unsigned long) addr;
 
-	memdesc->sg = vmalloc(sglen * sizeof(struct scatterlist));
+	memdesc->sg = kgsl_sg_alloc(sglen);
+
 	if (memdesc->sg == NULL)
 		return -ENOMEM;
 
@@ -1468,7 +1417,7 @@
 
 err:
 	spin_unlock(&current->mm->page_table_lock);
-	vfree(memdesc->sg);
+	kgsl_sg_free(memdesc->sg,  sglen);
 	memdesc->sg = NULL;
 
 	return -EINVAL;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3dafbb9..87bba25 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -21,6 +21,7 @@
 #include <linux/mutex.h>
 #include <linux/cdev.h>
 #include <linux/regulator/consumer.h>
+#include <linux/mm.h>
 
 #define KGSL_NAME "kgsl"
 
@@ -98,7 +99,15 @@
 extern struct kgsl_driver kgsl_driver;
 
 struct kgsl_pagetable;
-struct kgsl_memdesc_ops;
+struct kgsl_memdesc;
+
+struct kgsl_memdesc_ops {
+	int (*vmflags)(struct kgsl_memdesc *);
+	int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
+		       struct vm_fault *);
+	void (*free)(struct kgsl_memdesc *memdesc);
+	int (*map_kernel_mem)(struct kgsl_memdesc *);
+};
 
 /* shared memory allocation */
 struct kgsl_memdesc {
@@ -185,13 +194,15 @@
 	}
 	return 0;
 }
-static inline uint8_t *kgsl_gpuaddr_to_vaddr(const struct kgsl_memdesc *memdesc,
+static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
 					     unsigned int gpuaddr)
 {
-	if (memdesc->hostptr == NULL || memdesc->gpuaddr == 0 ||
-		(gpuaddr < memdesc->gpuaddr ||
-		gpuaddr >= memdesc->gpuaddr + memdesc->size))
-		return NULL;
+	if (memdesc->gpuaddr == 0 ||
+		gpuaddr < memdesc->gpuaddr ||
+		gpuaddr >= (memdesc->gpuaddr + memdesc->size) ||
+		(NULL == memdesc->hostptr && memdesc->ops->map_kernel_mem &&
+			memdesc->ops->map_kernel_mem(memdesc)))
+			return NULL;
 
 	return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
 }
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index a972f69..4e354d0 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -497,190 +497,6 @@
 }
 EXPORT_SYMBOL(kgsl_cffdump_waitirq);
 
-#define ADDRESS_STACK_SIZE 256
-#define GET_PM4_TYPE3_OPCODE(x) ((*(x) >> 8) & 0xFF)
-static unsigned int kgsl_cffdump_addr_count;
-
-static bool kgsl_cffdump_handle_type3(struct kgsl_device_private *dev_priv,
-	uint *hostaddr, bool check_only)
-{
-	static uint addr_stack[ADDRESS_STACK_SIZE];
-	static uint size_stack[ADDRESS_STACK_SIZE];
-
-	switch (GET_PM4_TYPE3_OPCODE(hostaddr)) {
-	case CP_INDIRECT_BUFFER_PFD:
-	case CP_INDIRECT_BUFFER:
-	{
-		/* traverse indirect buffers */
-		int i;
-		uint ibaddr = hostaddr[1];
-		uint ibsize = hostaddr[2];
-
-		/* is this address already in encountered? */
-		for (i = 0;
-			i < kgsl_cffdump_addr_count && addr_stack[i] != ibaddr;
-			++i)
-			;
-
-		if (kgsl_cffdump_addr_count == i) {
-			addr_stack[kgsl_cffdump_addr_count] = ibaddr;
-			size_stack[kgsl_cffdump_addr_count++] = ibsize;
-
-			if (kgsl_cffdump_addr_count >= ADDRESS_STACK_SIZE) {
-				KGSL_CORE_ERR("stack overflow\n");
-				return false;
-			}
-
-			return kgsl_cffdump_parse_ibs(dev_priv, NULL,
-				ibaddr, ibsize, check_only);
-		} else if (size_stack[i] != ibsize) {
-			KGSL_CORE_ERR("gpuaddr: 0x%08x, "
-				"wc: %u, with size wc: %u already on the "
-				"stack\n", ibaddr, ibsize, size_stack[i]);
-			return false;
-		}
-	}
-	break;
-	}
-
-	return true;
-}
-
-/*
- * Traverse IBs and dump them to test vector. Detect swap by inspecting
- * register writes, keeping note of the current state, and dump
- * framebuffer config to test vector
- */
-bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv,
-	const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords,
-	bool check_only)
-{
-	static uint level; /* recursion level */
-	bool ret = true;
-	uint *hostaddr, *hoststart;
-	int dwords_left = sizedwords; /* dwords left in the current command
-					 buffer */
-
-	if (level == 0)
-		kgsl_cffdump_addr_count = 0;
-
-	if (memdesc == NULL) {
-		struct kgsl_mem_entry *entry;
-		spin_lock(&dev_priv->process_priv->mem_lock);
-		entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
-			gpuaddr, sizedwords * sizeof(uint));
-		spin_unlock(&dev_priv->process_priv->mem_lock);
-		if (entry == NULL) {
-			KGSL_CORE_ERR("did not find mapping "
-				"for gpuaddr: 0x%08x\n", gpuaddr);
-			return true;
-		}
-		memdesc = &entry->memdesc;
-	}
-	hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
-	if (hostaddr == NULL) {
-		KGSL_CORE_ERR("no kernel mapping for "
-			"gpuaddr: 0x%08x\n", gpuaddr);
-		return true;
-	}
-
-	hoststart = hostaddr;
-
-	level++;
-
-	mb();
-	kgsl_cache_range_op((struct kgsl_memdesc *)memdesc,
-				KGSL_CACHE_OP_INV);
-#ifdef DEBUG
-	pr_info("kgsl: cffdump: ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
-		gpuaddr, sizedwords, hostaddr);
-#endif
-
-	while (dwords_left > 0) {
-		int count = 0; /* dword count including packet header */
-		bool cur_ret = true;
-
-		switch (*hostaddr >> 30) {
-		case 0x0: /* type-0 */
-			count = (*hostaddr >> 16)+2;
-			break;
-		case 0x1: /* type-1 */
-			count = 2;
-			break;
-		case 0x3: /* type-3 */
-			count = ((*hostaddr >> 16) & 0x3fff) + 2;
-			cur_ret = kgsl_cffdump_handle_type3(dev_priv,
-				hostaddr, check_only);
-			break;
-		default:
-			pr_warn("kgsl: cffdump: parse-ib: unexpected type: "
-				"type:%d, word:0x%08x @ 0x%p, gpu:0x%08x\n",
-				*hostaddr >> 30, *hostaddr, hostaddr,
-				gpuaddr+4*(sizedwords-dwords_left));
-			cur_ret = false;
-			count = dwords_left;
-			break;
-		}
-
-#ifdef DEBUG
-		if (!cur_ret) {
-			pr_info("kgsl: cffdump: bad sub-type: #:%d/%d, v:0x%08x"
-				" @ 0x%p[gb:0x%08x], level:%d\n",
-				sizedwords-dwords_left, sizedwords, *hostaddr,
-				hostaddr, gpuaddr+4*(sizedwords-dwords_left),
-				level);
-
-			print_hex_dump(KERN_ERR, level == 1 ? "IB1:" : "IB2:",
-				DUMP_PREFIX_OFFSET, 32, 4, hoststart,
-				sizedwords*4, 0);
-		}
-#endif
-		ret = ret && cur_ret;
-
-		/* jump to next packet */
-		dwords_left -= count;
-		hostaddr += count;
-		cur_ret = dwords_left >= 0;
-
-#ifdef DEBUG
-		if (!cur_ret) {
-			pr_info("kgsl: cffdump: bad count: c:%d, #:%d/%d, "
-				"v:0x%08x @ 0x%p[gb:0x%08x], level:%d\n",
-				count, sizedwords-(dwords_left+count),
-				sizedwords, *(hostaddr-count), hostaddr-count,
-				gpuaddr+4*(sizedwords-(dwords_left+count)),
-				level);
-
-			print_hex_dump(KERN_ERR, level == 1 ? "IB1:" : "IB2:",
-				DUMP_PREFIX_OFFSET, 32, 4, hoststart,
-				sizedwords*4, 0);
-		}
-#endif
-
-		ret = ret && cur_ret;
-	}
-
-	if (!ret)
-		pr_info("kgsl: cffdump: parsing failed: gpuaddr:0x%08x, "
-			"host:0x%p, wc:%d\n", gpuaddr, hoststart, sizedwords);
-
-	if (!check_only) {
-#ifdef DEBUG
-		uint offset = gpuaddr - memdesc->gpuaddr;
-		pr_info("kgsl: cffdump: ib-dump: hostptr:%p, gpuaddr:%08x, "
-			"physaddr:%08x, offset:%d, size:%d", hoststart,
-			gpuaddr, memdesc->physaddr + offset, offset,
-			sizedwords*4);
-#endif
-		kgsl_cffdump_syncmem(dev_priv, memdesc, gpuaddr, sizedwords*4,
-			false);
-	}
-
-	level--;
-
-	return ret;
-}
-
 static int subbuf_start_handler(struct rchan_buf *buf,
 	void *subbuf, void *prev_subbuf, uint prev_padding)
 {
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 03f8c42..d43b29b 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -903,17 +903,18 @@
 	struct drm_gem_object *obj = vma->vm_private_data;
 	struct drm_device *dev = obj->dev;
 	struct drm_kgsl_gem_object *priv;
-	unsigned long offset, pg;
+	unsigned long offset;
 	struct page *page;
+	int i;
 
 	mutex_lock(&dev->struct_mutex);
 
 	priv = obj->driver_private;
 
 	offset = (unsigned long) vmf->virtual_address - vma->vm_start;
-	pg = (unsigned long) priv->memdesc.hostptr + offset;
+	i = offset >> PAGE_SHIFT;
+	page = sg_page(&(priv->memdesc.sg[i]));
 
-	page = vmalloc_to_page((void *) pg);
 	if (!page) {
 		mutex_unlock(&dev->struct_mutex);
 		return VM_FAULT_SIGBUS;
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 942aa12..bbb5d46 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -357,8 +357,8 @@
 int kgsl_gpummu_pt_equal(struct kgsl_pagetable *pt,
 					unsigned int pt_base)
 {
-	struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
-	return pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
+	struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL;
+	return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
 }
 
 void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 194067b..ea11068 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -46,8 +46,8 @@
 static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
 					unsigned int pt_base)
 {
-	struct iommu_domain *domain = pt->priv;
-	return pt && pt_base && ((unsigned int)domain == pt_base);
+	struct iommu_domain *domain = pt ? pt->priv : NULL;
+	return domain && pt_base && ((unsigned int)domain == pt_base);
 }
 
 static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt)
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6f575ec..d960eaf 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -509,6 +509,7 @@
 	pwr->nap_allowed = pdata->nap_allowed;
 	pwr->idle_needed = pdata->idle_needed;
 	pwr->interval_timeout = pdata->idle_timeout;
+	pwr->strtstp_sleepwake = pdata->strtstp_sleepwake;
 	pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
 	if (IS_ERR(pwr->ebi1_clk))
 		pwr->ebi1_clk = NULL;
@@ -629,7 +630,8 @@
 
 	KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id);
 	if (device->requested_state != KGSL_STATE_SUSPEND) {
-		if (device->pwrctrl.restore_slumber)
+		if (device->pwrctrl.restore_slumber ||
+					device->pwrctrl.strtstp_sleepwake)
 			kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
 		else
 			kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
@@ -770,7 +772,9 @@
 	case KGSL_STATE_NAP:
 	case KGSL_STATE_SLEEP:
 		del_timer_sync(&device->idle_timer);
-		kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+		if (!device->pwrctrl.strtstp_sleepwake)
+			kgsl_pwrctrl_pwrlevel_change(device,
+					KGSL_PWRLEVEL_NOMINAL);
 		device->pwrctrl.restore_slumber = true;
 		device->ftbl->suspend_context(device);
 		device->ftbl->stop(device);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 2222cdf..7dd429f 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -48,6 +48,7 @@
 	int thermal_pwrlevel;
 	unsigned int num_pwrlevels;
 	unsigned int interval_timeout;
+	bool strtstp_sleepwake;
 	struct regulator *gpu_reg;
 	uint32_t pcl;
 	unsigned int nap_allowed;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
index 2976b0b..71af893 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
@@ -153,6 +153,14 @@
 		MSM_IDLE_STATS_EVENT_IDLE_TIMER_EXPIRED);
 }
 
+static void idlestats_wake(struct kgsl_device *device,
+			struct kgsl_pwrscale *pwrscale)
+{
+	/* Use highest perf level on wake-up from
+	   sleep for better performance */
+	kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
+}
+
 static int idlestats_init(struct kgsl_device *device,
 		     struct kgsl_pwrscale *pwrscale)
 {
@@ -218,5 +226,6 @@
 	.idle = idlestats_idle,
 	.busy = idlestats_busy,
 	.sleep = idlestats_sleep,
+	.wake = idlestats_wake,
 	.close = idlestats_close
 };
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 5634a19..1f142f8 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -299,13 +299,14 @@
 				struct vm_area_struct *vma,
 				struct vm_fault *vmf)
 {
-	unsigned long offset, pg;
+	unsigned long offset;
 	struct page *page;
+	int i;
 
 	offset = (unsigned long) vmf->virtual_address - vma->vm_start;
-	pg = (unsigned long) memdesc->hostptr + offset;
 
-	page = vmalloc_to_page((void *) pg);
+	i = offset >> PAGE_SHIFT;
+	page = sg_page(&memdesc->sg[i]);
 	if (page == NULL)
 		return VM_FAULT_SIGBUS;
 
@@ -322,8 +323,14 @@
 
 static void kgsl_vmalloc_free(struct kgsl_memdesc *memdesc)
 {
+	int i = 0;
+	struct scatterlist *sg;
 	kgsl_driver.stats.vmalloc -= memdesc->size;
-	vfree(memdesc->hostptr);
+	if (memdesc->hostptr)
+		vunmap(memdesc->hostptr);
+	if (memdesc->sg)
+		for_each_sg(memdesc->sg, sg, memdesc->sglen, i)
+			__free_page(sg_page(sg));
 }
 
 static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc)
@@ -331,6 +338,39 @@
 	return VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
 }
 
+/*
+ * kgsl_vmalloc_map_kernel - Map the memory in memdesc to kernel address space
+ *
+ * @memdesc - The memory descriptor which contains information about the memory
+ *
+ * Return: 0 on success else error code
+ */
+static int kgsl_vmalloc_map_kernel(struct kgsl_memdesc *memdesc)
+{
+	if (!memdesc->hostptr) {
+		pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
+		struct page **pages = NULL;
+		struct scatterlist *sg;
+		int i;
+		/* create a list of pages to call vmap */
+		pages = vmalloc(memdesc->sglen * sizeof(struct page *));
+		if (!pages) {
+			KGSL_CORE_ERR("vmalloc(%d) failed\n",
+				memdesc->sglen * sizeof(struct page *));
+			return -ENOMEM;
+		}
+		for_each_sg(memdesc->sg, sg, memdesc->sglen, i)
+			pages[i] = sg_page(sg);
+		memdesc->hostptr = vmap(pages, memdesc->sglen,
+					VM_IOREMAP, page_prot);
+		vfree(pages);
+	}
+	if (!memdesc->hostptr)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc,
 				struct vm_area_struct *vma,
 				struct vm_fault *vmf)
@@ -374,6 +414,7 @@
 	.free = kgsl_vmalloc_free,
 	.vmflags = kgsl_vmalloc_vmflags,
 	.vmfault = kgsl_vmalloc_vmfault,
+	.map_kernel_mem = kgsl_vmalloc_map_kernel,
 };
 EXPORT_SYMBOL(kgsl_vmalloc_ops);
 
@@ -411,7 +452,7 @@
 static int
 _kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
 			struct kgsl_pagetable *pagetable,
-			void *ptr, size_t size, unsigned int protflags)
+			size_t size, unsigned int protflags)
 {
 	int order, ret = 0;
 	int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
@@ -421,9 +462,9 @@
 	memdesc->pagetable = pagetable;
 	memdesc->priv = KGSL_MEMFLAGS_CACHED;
 	memdesc->ops = &kgsl_vmalloc_ops;
-	memdesc->hostptr = (void *) ptr;
 
-	memdesc->sg = vmalloc(sglen * sizeof(struct scatterlist));
+	memdesc->sg = kgsl_sg_alloc(sglen);
+
 	if (memdesc->sg == NULL) {
 		ret = -ENOMEM;
 		goto done;
@@ -434,17 +475,18 @@
 	memdesc->sglen = sglen;
 	sg_init_table(memdesc->sg, sglen);
 
-	for (i = 0; i < memdesc->sglen; i++, ptr += PAGE_SIZE) {
-		struct page *page = vmalloc_to_page(ptr);
+	for (i = 0; i < memdesc->sglen; i++) {
+		struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO |
+						__GFP_HIGHMEM);
 		if (!page) {
-			ret = -EINVAL;
+			ret = -ENOMEM;
+			memdesc->sglen = i;
 			goto done;
 		}
+		flush_dcache_page(page);
 		sg_set_page(&memdesc->sg[i], page, PAGE_SIZE, 0);
 	}
 
-	kgsl_cache_range_op(memdesc, KGSL_CACHE_OP_FLUSH);
-
 	ret = kgsl_mmu_map(pagetable, memdesc, protflags);
 
 	if (ret)
@@ -469,20 +511,18 @@
 kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
 		       struct kgsl_pagetable *pagetable, size_t size)
 {
-	void *ptr;
-
+	int ret = 0;
 	BUG_ON(size == 0);
 
 	size = ALIGN(size, PAGE_SIZE * 2);
-	ptr = vmalloc(size);
 
-	if (ptr  == NULL) {
-		KGSL_CORE_ERR("vmalloc(%d) failed\n", size);
-		return -ENOMEM;
-	}
-
-	return _kgsl_sharedmem_vmalloc(memdesc, pagetable, ptr, size,
+	ret =  _kgsl_sharedmem_vmalloc(memdesc, pagetable, size,
 		GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	if (!ret)
+		ret = kgsl_vmalloc_map_kernel(memdesc);
+	if (ret)
+		kgsl_sharedmem_free(memdesc);
+	return ret;
 }
 EXPORT_SYMBOL(kgsl_sharedmem_vmalloc);
 
@@ -491,25 +531,15 @@
 			    struct kgsl_pagetable *pagetable,
 			    size_t size, int flags)
 {
-	void *ptr;
 	unsigned int protflags;
 
 	BUG_ON(size == 0);
-	ptr = vmalloc_user(size);
-
-	if (ptr == NULL) {
-		KGSL_CORE_ERR("vmalloc_user(%d) failed: allocated=%d\n",
-			      size, kgsl_driver.stats.vmalloc);
-		return -ENOMEM;
-	}
-
-	kmemleak_not_leak(ptr);
 
 	protflags = GSL_PT_PAGE_RV;
 	if (!(flags & KGSL_MEMFLAGS_GPUREADONLY))
 		protflags |= GSL_PT_PAGE_WV;
 
-	return _kgsl_sharedmem_vmalloc(memdesc, pagetable, ptr, size,
+	return _kgsl_sharedmem_vmalloc(memdesc, pagetable, size,
 		protflags);
 }
 EXPORT_SYMBOL(kgsl_sharedmem_vmalloc_user);
@@ -560,7 +590,7 @@
 	if (memdesc->ops && memdesc->ops->free)
 		memdesc->ops->free(memdesc);
 
-	vfree(memdesc->sg);
+	kgsl_sg_free(memdesc->sg, memdesc->sglen);
 
 	memset(memdesc, 0, sizeof(*memdesc));
 }
@@ -692,3 +722,33 @@
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_sharedmem_set);
+
+/*
+ * kgsl_sharedmem_map_vma - Map a user vma to physical memory
+ *
+ * @vma - The user vma to map
+ * @memdesc - The memory descriptor which contains information about the
+ * physical memory
+ *
+ * Return: 0 on success else error code
+ */
+int
+kgsl_sharedmem_map_vma(struct vm_area_struct *vma,
+			const struct kgsl_memdesc *memdesc)
+{
+	unsigned long addr = vma->vm_start;
+	unsigned long size = vma->vm_end - vma->vm_start;
+	int ret, i = 0;
+
+	if (!memdesc->sg || (size != memdesc->size) ||
+		(memdesc->sglen != (size / PAGE_SIZE)))
+		return -EINVAL;
+
+	for (; addr < vma->vm_end; addr += PAGE_SIZE, i++) {
+		ret = vm_insert_page(vma, addr, sg_page(&memdesc->sg[i]));
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_sharedmem_map_vma);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index a1e4c91..def29b3 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -32,13 +32,6 @@
 /** Set if the memdesc is mapped into all pagetables */
 #define KGSL_MEMFLAGS_GLOBAL    0x00000002
 
-struct kgsl_memdesc_ops {
-	int (*vmflags)(struct kgsl_memdesc *);
-	int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
-		       struct vm_fault *);
-	void (*free)(struct kgsl_memdesc *memdesc);
-};
-
 extern struct kgsl_memdesc_ops kgsl_vmalloc_ops;
 
 int kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
@@ -92,13 +85,38 @@
 	return pa;
 }
 
+int
+kgsl_sharedmem_map_vma(struct vm_area_struct *vma,
+			const struct kgsl_memdesc *memdesc);
+
+/*
+ * For relatively small sglists, it is preferable to use kzalloc
+ * rather than going down the vmalloc rat hole.  If the size of
+ * the sglist is < PAGE_SIZE use kzalloc otherwise fallback to
+ * vmalloc
+ */
+
+static inline void *kgsl_sg_alloc(unsigned int sglen)
+{
+	if ((sglen * sizeof(struct scatterlist)) <  PAGE_SIZE)
+		return kzalloc(sglen * sizeof(struct scatterlist), GFP_KERNEL);
+	else
+		return vmalloc(sglen * sizeof(struct scatterlist));
+}
+
+static inline void kgsl_sg_free(void *ptr, unsigned int sglen)
+{
+	if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE)
+		kfree(ptr);
+	else
+		vfree(ptr);
+}
+
 static inline int
 memdesc_sg_phys(struct kgsl_memdesc *memdesc,
 		unsigned int physaddr, unsigned int size)
 {
-	memdesc->sg = vmalloc(sizeof(struct scatterlist) * 1);
-	if (memdesc->sg == NULL)
-		return -ENOMEM;
+	memdesc->sg = kgsl_sg_alloc(1);
 
 	kmemleak_not_leak(memdesc->sg);
 
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 6c43a75..41f4435 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -409,7 +409,7 @@
 	unsigned int index	= 0;
 	unsigned int nextindex;
 	unsigned int nextcnt    = Z180_STREAM_END_CMD | 5;
-	struct kgsl_memdesc tmp = {0};
+	struct kgsl_mem_entry *entry = NULL;
 	unsigned int cmd;
 	struct kgsl_device *device = dev_priv->device;
 	struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable;
@@ -427,8 +427,30 @@
 	}
 	cmd = ibdesc[0].gpuaddr;
 	sizedwords = ibdesc[0].sizedwords;
-
-	tmp.hostptr = (void *)*timestamp;
+	/*
+	 * Get a kernel mapping to the IB for monkey patching.
+	 * See the end of this function.
+	 */
+	entry = kgsl_sharedmem_find_region(dev_priv->process_priv, cmd,
+		sizedwords);
+	if (entry == NULL) {
+		KGSL_DRV_ERR(device, "Bad ibdesc: gpuaddr 0x%x size %d\n",
+			     cmd, sizedwords);
+		result = -EINVAL;
+		goto error;
+	}
+	/*
+	 * This will only map memory if it exists, otherwise it will reuse the
+	 * mapping. And the 2d userspace reuses IBs so we likely won't create
+	 * too many mappings.
+	 */
+	if (kgsl_gpuaddr_to_vaddr(&entry->memdesc, cmd) == NULL) {
+		KGSL_DRV_ERR(device,
+			     "Cannot make kernel mapping for gpuaddr 0x%x\n",
+			     cmd);
+		result = -EINVAL;
+		goto error;
+	}
 
 	KGSL_CMD_INFO(device, "ctxt %d ibaddr 0x%08x sizedwords %d\n",
 		context->id, cmd, sizedwords);
@@ -470,12 +492,13 @@
 	nextaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr
 		+ rb_offset(nextindex);
 
-	tmp.hostptr = (void *)(tmp.hostptr +
-			(sizedwords * sizeof(unsigned int)));
-	tmp.size = 12;
-
-	kgsl_sharedmem_writel(&tmp, 4, nextaddr);
-	kgsl_sharedmem_writel(&tmp, 8, nextcnt);
+	/* monkey patch the IB so that it jumps back to the ringbuffer */
+	kgsl_sharedmem_writel(&entry->memdesc,
+			      ((sizedwords + 1) * sizeof(unsigned int)),
+			      nextaddr);
+	kgsl_sharedmem_writel(&entry->memdesc,
+			      ((sizedwords + 2) * sizeof(unsigned int)),
+			      nextcnt);
 
 	/* sync memory before activating the hardware for the new command*/
 	mb();
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ab732b2..a276e84 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -99,6 +99,7 @@
 	struct hci_fm_ssbi_peek   ssbi_peek_reg;
 	struct hci_fm_sig_threshold_rsp sig_th;
 	struct hci_fm_ch_det_threshold ch_det_threshold;
+	struct hci_fm_data_rd_rsp default_data;
 };
 
 static struct video_device *priv_videodev;
@@ -1769,23 +1770,15 @@
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 	__u8 status = *((__u8 *) skb->data);
 	__u8 len;
-	char *data;
 
 	if (status)
 		return;
 	len = skb->data[1];
-	data = kmalloc(len+2, GFP_ATOMIC);
-	if (!data) {
-		FMDERR("Memory allocation failed");
-		return;
-	}
 
-	data[0] = status;
-	data[1] = len;
-	memcpy(&data[2], &skb->data[DEFAULT_DATA_OFFSET], len);
-	iris_q_evt_data(radio, data, len+2, IRIS_BUF_RD_DEFAULT);
+	memset(&radio->default_data, 0 , sizeof(struct hci_fm_data_rd_rsp));
+	memcpy(&radio->default_data, &skb->data[0], len+2);
+	iris_q_evt_data(radio, &skb->data[0], len+2, IRIS_BUF_RD_DEFAULT);
 	radio_hci_req_complete(hdev, status);
-	kfree(data);
 }
 
 static void hci_cc_ssbi_peek_rsp(struct radio_hci_dev *hdev,
@@ -2773,6 +2766,8 @@
 	unsigned long arg = 0;
 	struct hci_fm_tx_ps tx_ps = {0};
 	struct hci_fm_tx_rt tx_rt = {0};
+	struct hci_fm_def_data_rd_req rd_txgain;
+	struct hci_fm_def_data_wr_req wr_txgain;
 
 	switch (ctrl->id) {
 	case V4L2_CID_PRIVATE_IRIS_TX_TONE:
@@ -3055,6 +3050,32 @@
 		radio->ps_repeatcount = ctrl->value;
 		break;
 	case V4L2_CID_TUNE_POWER_LEVEL:
+		if (ctrl->value > FM_TX_PWR_LVL_MAX)
+			ctrl->value = FM_TX_PWR_LVL_MAX;
+		if (ctrl->value < FM_TX_PWR_LVL_0)
+			ctrl->value = FM_TX_PWR_LVL_0;
+		rd_txgain.mode = FM_TX_PHY_CFG_MODE;
+		rd_txgain.length = FM_TX_PHY_CFG_LEN;
+		rd_txgain.param_len = 0x00;
+		rd_txgain.param = 0x00;
+
+		retval = hci_def_data_read(&rd_txgain, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Default data read failed for PHY_CFG %d\n",
+			retval);
+			break;
+		}
+		memset(&wr_txgain, 0, sizeof(wr_txgain));
+		wr_txgain.mode = FM_TX_PHY_CFG_MODE;
+		wr_txgain.length = FM_TX_PHY_CFG_LEN;
+		memcpy(&wr_txgain.data, &radio->default_data.data,
+					radio->default_data.ret_data_len);
+		wr_txgain.data[FM_TX_PWR_GAIN_OFFSET] =
+				(ctrl->value) * FM_TX_PWR_LVL_STEP_SIZE;
+		retval = hci_def_data_write(&wr_txgain, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("Default write failed for PHY_TXGAIN %d\n",
+			retval);
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
 		radio->mute_mode.soft_mute = ctrl->value;
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index a2ec006..212e5d5 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -3631,13 +3631,8 @@
 					struct v4l2_hw_freq_seek *seek)
 {
 	struct tavarua_device  *radio = video_get_drvdata(video_devdata(file));
-	int dir;
-	if (seek->seek_upward)
-		dir = SRCH_DIR_UP;
-	else
-		dir = SRCH_DIR_DOWN;
 	FMDBG("starting search\n");
-	return tavarua_search(radio, CTRL_ON, dir);
+	return tavarua_search(radio, CTRL_ON, seek->seek_upward);
 }
 
 /*
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index 6985f3c..a86e5c4 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -212,6 +212,66 @@
 #endif /* CONFIG_LEDS_PMIC8058 */
 	return rc;
 }
+
+int msm_camera_flash_led(
+		struct msm_camera_sensor_flash_external *external,
+		unsigned led_state)
+{
+	int rc = 0;
+
+	CDBG("msm_camera_flash_led: %d\n", led_state);
+	switch (led_state) {
+	case MSM_CAMERA_LED_INIT:
+		rc = gpio_request(external->led_en, "sgm3141");
+		CDBG("MSM_CAMERA_LED_INIT: gpio_req: %d %d\n",
+				external->led_en, rc);
+		if (!rc)
+			gpio_direction_output(external->led_en, 0);
+		else
+			return 0;
+
+		rc = gpio_request(external->led_flash_en, "sgm3141");
+		CDBG("MSM_CAMERA_LED_INIT: gpio_req: %d %d\n",
+				external->led_flash_en, rc);
+		if (!rc)
+			gpio_direction_output(external->led_flash_en, 0);
+
+			break;
+
+	case MSM_CAMERA_LED_RELEASE:
+		CDBG("MSM_CAMERA_LED_RELEASE\n");
+		gpio_set_value_cansleep(external->led_en, 0);
+		gpio_free(external->led_en);
+		gpio_set_value_cansleep(external->led_flash_en, 0);
+		gpio_free(external->led_flash_en);
+		break;
+
+	case MSM_CAMERA_LED_OFF:
+		CDBG("MSM_CAMERA_LED_OFF\n");
+		gpio_set_value_cansleep(external->led_en, 0);
+		gpio_set_value_cansleep(external->led_flash_en, 0);
+		break;
+
+	case MSM_CAMERA_LED_LOW:
+		CDBG("MSM_CAMERA_LED_LOW\n");
+		gpio_set_value_cansleep(external->led_en, 1);
+		gpio_set_value_cansleep(external->led_flash_en, 1);
+		break;
+
+	case MSM_CAMERA_LED_HIGH:
+		CDBG("MSM_CAMERA_LED_HIGH\n");
+		gpio_set_value_cansleep(external->led_en, 1);
+		gpio_set_value_cansleep(external->led_flash_en, 1);
+		break;
+
+	default:
+		rc = -EFAULT;
+		break;
+	}
+
+	return rc;
+}
+
 int msm_camera_flash_external(
 	struct msm_camera_sensor_flash_external *external,
 	unsigned led_state)
@@ -439,6 +499,12 @@
 			led_state);
 		break;
 
+	case MSM_CAMERA_FLASH_SRC_LED1:
+		rc = msm_camera_flash_led(
+				&fdata->flash_src->_fsrc.ext_driver_src,
+				led_state);
+		break;
+
 	default:
 		rc = -ENODEV;
 		break;
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index af27a56..e2236191 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -743,13 +743,13 @@
 	if (mode == OUTPUT_SEC) {
 		/* Thumbnail */
 		if (vfe2x_ctrl->zsl_mode) {
-			ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
-			ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
-			ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
-			ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
-			ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
-			ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
-			bptr = &ao->output2buffer4_y_phy;
+			ao->output1buffer1_y_phy = ad->ping.ch_paddr[0];
+			ao->output1buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+			ao->output1buffer2_y_phy = ad->pong.ch_paddr[0];
+			ao->output1buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+			ao->output1buffer3_y_phy = ad->free_buf.ch_paddr[0];
+			ao->output1buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+			bptr = &ao->output1buffer4_y_phy;
 			for (cnt = 0; cnt < 5; cnt++) {
 				*bptr = ad->pong.ch_paddr[0];
 				bptr++;
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index ac133d2..3052832 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -3,6 +3,7 @@
 EXTRA_CFLAGS += -Idrivers/media/video/msm/io
 EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
 obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
+obj-$(CONFIG_OV5647) += ov5647_v4l2.o
 obj-$(CONFIG_IMX074) += imx074_v4l2.o
 obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
 obj-$(CONFIG_IMX091) += imx091.o
@@ -12,4 +13,3 @@
 obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
 obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
 obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd_v4l2.o
-obj-$(CONFIG_OV5647) += ov5647_v4l2.o
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index 9a85836..ba0592e 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -273,16 +273,16 @@
 		.y_output = 0x7A0,   /*1952*/
 		.line_length_pclk = 0xA8C,
 		.frame_length_lines = 0x7B0,
-		.vt_pixel_clk = 159408000,
+		.vt_pixel_clk = 79704000,
 		.op_pixel_clk = 159408000,
 		.binning_factor = 0x0,
 	},
 	{ /* For PREVIEW */
-		.x_output = 0x500,  /*2608*/  /*for 5Mp*/
-		.y_output = 0x3C0,   /*1952*/
-		.line_length_pclk = 0x768 * 2,
+		.x_output = 0x500, /*1280*/
+		.y_output = 0x3C0, /*960*/
+		.line_length_pclk = 0x768,
 		.frame_length_lines = 0x3D8,
-		.vt_pixel_clk = 159408000,
+		.vt_pixel_clk = 55969920,
 		.op_pixel_clk = 159408000,
 		.binning_factor = 0x0,
 	},
diff --git a/drivers/media/video/msm/wfd/Makefile b/drivers/media/video/msm/wfd/Makefile
index 2b39e66..5decaca 100644
--- a/drivers/media/video/msm/wfd/Makefile
+++ b/drivers/media/video/msm/wfd/Makefile
@@ -2,3 +2,4 @@
 obj-y += enc-subdev.o
 obj-y += vsg-subdev.o
 obj-y += wfd-ioctl.o
+obj-y += wfd-util.o
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.c b/drivers/media/video/msm/wfd/vsg-subdev.c
index 6ceadad..ac8e4e7 100644
--- a/drivers/media/video/msm/wfd/vsg-subdev.c
+++ b/drivers/media/video/msm/wfd/vsg-subdev.c
@@ -244,7 +244,7 @@
 		goto threshold_err_bad_param;
 	} else if (!context) {
 		WFD_MSG_ERR("Context not proper in %s", __func__);
-		goto threshold_err_bad_param;
+		goto threshold_err_no_context;
 	}
 
 	INIT_WORK(&task->work, vsg_timer_helper_func);
@@ -255,6 +255,8 @@
 	hrtimer_forward_now(&context->threshold_timer, ns_to_ktime(
 				context->max_frame_interval));
 	return HRTIMER_RESTART;
+threshold_err_no_context:
+	return HRTIMER_NORESTART;
 }
 
 int vsg_init(struct v4l2_subdev *sd, u32 val)
@@ -399,13 +401,13 @@
 					&context->last_buffer->mdp_buf_info,
 					&temp->mdp_buf_info);
 
+			list_del(&temp->node);
+
 			if (!is_last_buffer &&
 				!(temp->flags & VSG_NEVER_RELEASE)) {
 				vsg_release_input_buffer(context, temp);
 				kfree(temp);
 			}
-
-			list_del(&temp->node);
 		}
 	}
 
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 7692f43..2c2c551 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -86,6 +86,7 @@
 	u32 input_buf_size;
 	u32 out_buf_size;
 	struct list_head input_mem_list;
+	struct wfd_stats stats;
 };
 
 struct wfd_vid_buffer {
@@ -313,6 +314,9 @@
 			WFD_MSG_ERR("Unable to queue the"
 					" buffer to mdp\n");
 			break;
+		} else {
+			wfd_stats_update(&inst->stats,
+					WFD_STAT_EVENT_MDP_QUEUE);
 		}
 	}
 	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
@@ -514,6 +518,9 @@
 			WFD_MSG_ERR("Either streamoff called or"
 						" MDP REPORTED ERROR\n");
 			break;
+		} else {
+			wfd_stats_update(&inst->stats,
+				WFD_STAT_EVENT_MDP_DEQUEUE);
 		}
 
 		mregion = obuf_mdp.cookie;
@@ -534,8 +541,11 @@
 			core, ioctl, VSG_Q_BUFFER, (void *)&ibuf_vsg);
 
 		if (rc) {
-			WFD_MSG_ERR("Failed to encode frame\n");
+			WFD_MSG_ERR("Failed to queue frame to vsg\n");
 			break;
+		} else {
+			wfd_stats_update(&inst->stats,
+				WFD_STAT_EVENT_VSG_QUEUE);
 		}
 	}
 	WFD_MSG_DBG("Exiting the thread\n");
@@ -833,9 +843,13 @@
 		WFD_MSG_ERR("Failed to register buffer\n");
 		return rc;
 	}
+
 	rc = vb2_qbuf(&inst->vid_bufq, b);
 	if (rc)
 		WFD_MSG_ERR("Failed to queue buffer\n");
+	else
+		wfd_stats_update(&inst->stats, WFD_STAT_EVENT_CLIENT_QUEUE);
+
 	return rc;
 }
 
@@ -894,8 +908,17 @@
 		struct v4l2_buffer *b)
 {
 	struct wfd_inst *inst = filp->private_data;
+	int rc;
+
 	WFD_MSG_INFO("Waiting to dequeue buffer\n");
-	return vb2_dqbuf(&inst->vid_bufq, b, 0);
+	rc = vb2_dqbuf(&inst->vid_bufq, b, 0);
+
+	if (rc)
+		WFD_MSG_ERR("Failed to dequeue buffer\n");
+	else
+		wfd_stats_update(&inst->stats, WFD_STAT_EVENT_CLIENT_DEQUEUE);
+
+	return rc;
 }
 static int wfdioc_g_ctrl(struct file *filp, void *fh,
 					struct v4l2_control *a)
@@ -1129,11 +1152,15 @@
 			ioctl, VSG_RETURN_IP_BUFFER, (void *)&buf);
 	if (rc)
 		WFD_MSG_ERR("Failed to return buffer to vsg\n");
+	else
+		wfd_stats_update(&inst->stats, WFD_STAT_EVENT_ENC_DEQUEUE);
+
 }
 
 static int vsg_release_input_frame(void *cookie, struct vsg_buf_info *buf)
 {
 	struct file *filp = cookie;
+	struct wfd_inst *inst = filp->private_data;
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
 	int rc = 0;
@@ -1142,6 +1169,10 @@
 			ioctl, MDP_Q_BUFFER, buf);
 	if (rc)
 		WFD_MSG_ERR("Failed to Q buffer to mdp\n");
+	else {
+		wfd_stats_update(&inst->stats, WFD_STAT_EVENT_MDP_QUEUE);
+		wfd_stats_update(&inst->stats, WFD_STAT_EVENT_VSG_DEQUEUE);
+	}
 
 	return rc;
 }
@@ -1149,9 +1180,11 @@
 static int vsg_encode_frame(void *cookie, struct vsg_buf_info *buf)
 {
 	struct file *filp = cookie;
+	struct wfd_inst *inst = filp->private_data;
 	struct wfd_device *wfd_dev =
 		(struct wfd_device *)video_drvdata(filp);
 	struct venc_buf_info venc_buf;
+	int rc = 0;
 
 	if (!buf)
 		return -EINVAL;
@@ -1162,8 +1195,16 @@
 	};
 
 	wfd_flush_ion_buffer(wfd_dev->ion_client, venc_buf.mregion);
-	return v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+
+	rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
 			ENCODE_FRAME, &venc_buf);
+
+	if (rc)
+		WFD_MSG_ERR("Encode failed\n");
+	else
+		wfd_stats_update(&inst->stats, WFD_STAT_EVENT_ENC_QUEUE);
+
+	return rc;
 }
 
 void *wfd_vb2_mem_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
@@ -1220,6 +1261,9 @@
 	spin_lock_init(&inst->inst_lock);
 	INIT_LIST_HEAD(&inst->input_mem_list);
 	INIT_LIST_HEAD(&inst->minfo_list);
+
+	wfd_stats_init(&inst->stats, MINOR(filp->f_dentry->d_inode->i_rdev));
+
 	rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl, MDP_OPEN,
 				(void *)&inst->mdp_inst);
 	if (rc) {
@@ -1298,6 +1342,8 @@
 
 		kfree(inst);
 	}
+
+	wfd_stats_deinit(&inst->stats);
 	WFD_MSG_DBG("wfd_close: X\n");
 	return 0;
 }
@@ -1371,6 +1417,7 @@
 		goto err_venc_init;
 	}
 
+	WFD_MSG_DBG("__wfd_probe: X\n");
 	return rc;
 
 err_venc_init:
@@ -1403,6 +1450,14 @@
 	pdev->dev.platform_data = (void *) wfd_dev;
 
 	ion_client = msm_ion_client_create(-1, "wfd");
+
+	rc = wfd_stats_setup();
+	if (rc) {
+		WFD_MSG_ERR("No debugfs support: %d\n", rc);
+		/* Don't treat this as a fatal err */
+		rc = 0;
+	}
+
 	if (!ion_client) {
 		WFD_MSG_ERR("Failed to create ion client\n");
 		rc = -ENODEV;
@@ -1461,6 +1516,7 @@
 		return -ENODEV;
 	}
 
+	wfd_stats_teardown();
 	for (c = 0; c < WFD_NUM_DEVICES; ++c) {
 		v4l2_device_unregister_subdev(&wfd_dev[c].vsg_sdev);
 		v4l2_device_unregister_subdev(&wfd_dev[c].enc_sdev);
diff --git a/drivers/media/video/msm/wfd/wfd-util.c b/drivers/media/video/msm/wfd/wfd-util.c
new file mode 100644
index 0000000..233668b0
--- /dev/null
+++ b/drivers/media/video/msm/wfd/wfd-util.c
@@ -0,0 +1,217 @@
+/* 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/debugfs.h>
+#include <linux/hrtimer.h>
+#include <linux/limits.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include "wfd-util.h"
+
+static struct dentry *wfd_debugfs_root;
+
+int wfd_stats_setup()
+{
+	wfd_debugfs_root = debugfs_create_dir("wfd", NULL);
+
+	if (wfd_debugfs_root == ERR_PTR(-ENODEV))
+		return -ENODEV;
+	else if (!wfd_debugfs_root)
+		return -ENOMEM;
+	else
+		return 0;
+}
+
+void wfd_stats_teardown()
+{
+	if (wfd_debugfs_root)
+		debugfs_remove_recursive(wfd_debugfs_root);
+}
+
+int wfd_stats_init(struct wfd_stats *stats, int device)
+{
+	char device_str[NAME_MAX] = "";
+	int rc = 0;
+
+	if (!stats) {
+		rc = -EINVAL;
+		goto wfd_stats_init_fail;
+	} else if (!wfd_debugfs_root) {
+		WFD_MSG_ERR("wfd debugfs root does not exist\n");
+		rc = -ENOENT;
+		goto wfd_stats_init_fail;
+	}
+
+	memset(stats, 0, sizeof(*stats));
+	INIT_LIST_HEAD(&stats->enc_queue);
+
+	snprintf(device_str, sizeof(device_str), "%d", device);
+	stats->d_parent = debugfs_create_dir(device_str, wfd_debugfs_root);
+	if (IS_ERR(stats->d_parent)) {
+		rc = PTR_ERR(stats->d_parent);
+		stats->d_parent = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_v4l2_buf_count = debugfs_create_u32("v4l2_buf_count", S_IRUGO,
+			stats->d_parent, &stats->v4l2_buf_count);
+	if (IS_ERR(stats->d_v4l2_buf_count)) {
+		rc = PTR_ERR(stats->d_v4l2_buf_count);
+		stats->d_v4l2_buf_count = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_mdp_buf_count = debugfs_create_u32("mdp_buf_count", S_IRUGO,
+			stats->d_parent, &stats->mdp_buf_count);
+	if (IS_ERR(stats->d_mdp_buf_count)) {
+		rc = PTR_ERR(stats->d_mdp_buf_count);
+		stats->d_mdp_buf_count = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_vsg_buf_count = debugfs_create_u32("vsg_buf_count", S_IRUGO,
+			stats->d_parent, &stats->vsg_buf_count);
+	if (IS_ERR(stats->d_vsg_buf_count)) {
+		rc = PTR_ERR(stats->d_vsg_buf_count);
+		stats->d_vsg_buf_count = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_enc_buf_count = debugfs_create_u32("enc_buf_count", S_IRUGO,
+			stats->d_parent, &stats->enc_buf_count);
+	if (IS_ERR(stats->d_enc_buf_count)) {
+		rc = PTR_ERR(stats->d_enc_buf_count);
+		stats->d_enc_buf_count = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_frames_encoded = debugfs_create_u32("frames_encoded", S_IRUGO,
+			stats->d_parent, &stats->frames_encoded);
+	if (IS_ERR(stats->d_frames_encoded)) {
+		rc = PTR_ERR(stats->d_frames_encoded);
+		stats->d_frames_encoded = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_mdp_updates = debugfs_create_u32("mdp_updates", S_IRUGO,
+			stats->d_parent, &stats->mdp_updates);
+	if (IS_ERR(stats->d_mdp_updates)) {
+		rc = PTR_ERR(stats->d_mdp_updates);
+		stats->d_mdp_updates = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	stats->d_enc_avg_latency = debugfs_create_u32("enc_avg_latency",
+			S_IRUGO, stats->d_parent, &stats->enc_avg_latency);
+	if (IS_ERR(stats->d_enc_avg_latency)) {
+		rc = PTR_ERR(stats->d_enc_avg_latency);
+		stats->d_enc_avg_latency = NULL;
+		goto wfd_stats_init_fail;
+	}
+
+	return rc;
+wfd_stats_init_fail:
+	return rc;
+}
+
+int wfd_stats_update(struct wfd_stats *stats, enum wfd_stats_event event)
+{
+	int rc = 0;
+	switch (event) {
+	case WFD_STAT_EVENT_CLIENT_QUEUE:
+		stats->v4l2_buf_count++;
+		break;
+	case WFD_STAT_EVENT_CLIENT_DEQUEUE: {
+		struct wfd_stats_encode_sample *sample = NULL;
+
+		stats->v4l2_buf_count--;
+
+		if (!list_empty(&stats->enc_queue))
+			sample = list_first_entry(&stats->enc_queue,
+					struct wfd_stats_encode_sample,
+					list);
+		if (sample) {
+			ktime_t kdiff = ktime_sub(ktime_get(),
+						sample->encode_start_ts);
+			uint32_t diff = ktime_to_ms(kdiff);
+
+			stats->enc_cumulative_latency += diff;
+			stats->enc_latency_samples++;
+			stats->enc_avg_latency = stats->enc_cumulative_latency /
+				stats->enc_latency_samples;
+
+			list_del(&sample->list);
+			kfree(sample);
+			sample = NULL;
+		}
+		break;
+	}
+	case WFD_STAT_EVENT_MDP_QUEUE:
+		stats->mdp_buf_count++;
+		stats->mdp_updates++;
+		break;
+	case WFD_STAT_EVENT_MDP_DEQUEUE:
+		stats->mdp_buf_count--;
+		break;
+	case WFD_STAT_EVENT_ENC_QUEUE: {
+		struct wfd_stats_encode_sample *sample = NULL;
+
+		stats->enc_buf_count++;
+		stats->frames_encoded++;
+
+		sample = kzalloc(sizeof(*sample), GFP_KERNEL);
+		if (sample) {
+			INIT_LIST_HEAD(&sample->list);
+			sample->encode_start_ts = ktime_get();
+			list_add_tail(&sample->list, &stats->enc_queue);
+		} else {
+			WFD_MSG_WARN("Unable to measure latency\n");
+		}
+		break;
+	}
+	case WFD_STAT_EVENT_ENC_DEQUEUE:
+		stats->enc_buf_count--;
+		break;
+	case WFD_STAT_EVENT_VSG_QUEUE:
+		stats->vsg_buf_count++;
+		break;
+	case WFD_STAT_EVENT_VSG_DEQUEUE:
+		stats->vsg_buf_count--;
+		break;
+	default:
+		rc = -ENOTSUPP;
+	}
+
+	return rc;
+}
+
+int wfd_stats_deinit(struct wfd_stats *stats)
+{
+	WFD_MSG_ERR("Latencies: avg enc. latency %d",
+			stats->enc_avg_latency);
+	/* Delete all debugfs files in one shot :) */
+	if (stats->d_parent)
+		debugfs_remove_recursive(stats->d_parent);
+
+	stats->d_parent =
+	stats->d_v4l2_buf_count =
+	stats->d_mdp_buf_count =
+	stats->d_vsg_buf_count =
+	stats->d_enc_buf_count =
+	stats->d_frames_encoded =
+	stats->d_mdp_updates =
+	stats->d_enc_avg_latency = NULL;
+
+	return 0;
+}
diff --git a/drivers/media/video/msm/wfd/wfd-util.h b/drivers/media/video/msm/wfd/wfd-util.h
index 06dbffa..b6bb245 100644
--- a/drivers/media/video/msm/wfd/wfd-util.h
+++ b/drivers/media/video/msm/wfd/wfd-util.h
@@ -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
@@ -11,6 +11,10 @@
  *
  */
 
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/ktime.h>
+
 #ifndef _WFD_UTIL_H_
 #define _WFD_UTIL_H_
 
@@ -27,4 +31,59 @@
 	#define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR WFD_TAG fmt)
 	#define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT WFD_TAG fmt)
 	#define WFD_MSG_DBG(fmt...) pr_debug(WFD_TAG fmt)
+
+
+struct wfd_stats_encode_sample {
+	ktime_t encode_start_ts;
+	struct list_head list;
+};
+
+struct wfd_stats {
+	/* Output Buffers */
+	uint32_t v4l2_buf_count;
+
+	/* Input Buffers */
+	uint32_t mdp_buf_count;
+	uint32_t vsg_buf_count;
+	uint32_t enc_buf_count;
+
+	/* Other */
+	uint32_t frames_encoded;
+	uint32_t mdp_updates;
+
+	uint32_t enc_avg_latency;
+	uint32_t enc_cumulative_latency;
+	uint32_t enc_latency_samples;
+	struct list_head enc_queue;
+
+	/* Debugfs entries */
+	struct dentry *d_parent;
+	struct dentry *d_v4l2_buf_count;
+	struct dentry *d_mdp_buf_count;
+	struct dentry *d_vsg_buf_count;
+	struct dentry *d_enc_buf_count;
+	struct dentry *d_frames_encoded;
+	struct dentry *d_mdp_updates;
+	struct dentry *d_enc_avg_latency;
+};
+
+enum wfd_stats_event {
+	WFD_STAT_EVENT_CLIENT_QUEUE,
+	WFD_STAT_EVENT_CLIENT_DEQUEUE,
+
+	WFD_STAT_EVENT_MDP_QUEUE,
+	WFD_STAT_EVENT_MDP_DEQUEUE,
+
+	WFD_STAT_EVENT_VSG_QUEUE,
+	WFD_STAT_EVENT_VSG_DEQUEUE,
+
+	WFD_STAT_EVENT_ENC_QUEUE,
+	WFD_STAT_EVENT_ENC_DEQUEUE,
+};
+
+int wfd_stats_setup(void);
+int wfd_stats_init(struct wfd_stats *, int device);
+int wfd_stats_update(struct wfd_stats *, enum wfd_stats_event);
+int wfd_stats_deinit(struct wfd_stats *);
+void wfd_stats_teardown(void);
 #endif
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 217f18d..0fe8f2a 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1352,6 +1352,32 @@
 EXPORT_SYMBOL(sps_free_mem);
 
 /**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ *
+ */
+int sps_get_unused_desc_num(struct sps_pipe *h, u32 *desc_num)
+{
+	struct sps_pipe *pipe = h;
+	struct sps_bam *bam;
+	int result;
+
+	SPS_DBG("sps:%s.", __func__);
+
+	bam = sps_bam_lock(pipe);
+	if (bam == NULL)
+		return SPS_ERROR;
+
+	result = sps_bam_pipe_get_unused_desc_num(bam, pipe->pipe_index,
+						desc_num);
+
+	sps_bam_unlock(bam);
+
+	return result;
+}
+EXPORT_SYMBOL(sps_get_unused_desc_num);
+
+/**
  * Register a BAM device
  *
  */
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index da1de86..6c8b1f9 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1960,3 +1960,29 @@
 	return result;
 }
 
+/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ */
+int sps_bam_pipe_get_unused_desc_num(struct sps_bam *dev, u32 pipe_index,
+					u32 *desc_num)
+{
+	u32 sw_offset, peer_offset, fifo_size;
+	u32 desc_size = sizeof(struct sps_iovec);
+	struct sps_pipe *pipe = dev->pipes[pipe_index];
+
+	if (pipe == NULL)
+		return SPS_ERROR;
+
+	fifo_size = pipe->desc_size;
+
+	sw_offset = bam_pipe_get_desc_read_offset(dev->base, pipe_index);
+	peer_offset = bam_pipe_get_desc_write_offset(dev->base, pipe_index);
+
+	if (sw_offset <= peer_offset)
+		*desc_num = (peer_offset - sw_offset) / desc_size;
+	else
+		*desc_num = (peer_offset + fifo_size - sw_offset) / desc_size;
+
+	return 0;
+}
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index 70e7898..6004b75 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -545,4 +545,20 @@
 int sps_bam_pipe_timer_ctrl(struct sps_bam *dev, u32 pipe_index,
 			    struct sps_timer_ctrl *timer_ctrl,
 			    struct sps_timer_result *timer_result);
+
+
+/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ *
+ * @dev - pointer to BAM device descriptor
+ *
+ * @pipe_index - pipe index
+ *
+ * @desc_num - number of unused descriptors
+ *
+ */
+int sps_bam_pipe_get_unused_desc_num(struct sps_bam *dev, u32 pipe_index,
+					u32 *desc_num);
+
 #endif	/* _SPSBAM_H_ */
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 80f50de..0e121d1 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -440,7 +440,6 @@
 	int ret;
 	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
 
-	wake_lock(&msm_uport->dma_wake_lock);
 	/* Set up the MREG/NREG/DREG/MNDREG */
 	ret = clk_set_rate(msm_uport->clk, uport->uartclk);
 	if (ret) {
@@ -456,6 +455,7 @@
 	if (msm_uport->pclk) {
 		ret = clk_enable(msm_uport->pclk);
 		if (ret) {
+			clk_disable(msm_uport->clk);
 			dev_err(uport->dev,
 				"Error could not turn on UART pclk\n");
 			return ret;
@@ -1578,10 +1578,14 @@
 	tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE,
 				      DMA_TO_DEVICE);
 
+	wake_lock(&msm_uport->dma_wake_lock);
 	/* turn on uart clk */
 	ret = msm_hs_init_clk(uport);
-	if (unlikely(ret))
+	if (unlikely(ret)) {
+		pr_err("Turning ON uartclk error\n");
+		wake_unlock(&msm_uport->dma_wake_lock);
 		return ret;
+	}
 
 	/* Set auto RFR Level */
 	data = msm_hs_read(uport, UARTDM_MR1_ADDR);
@@ -1646,20 +1650,26 @@
 
 	if (use_low_power_wakeup(msm_uport)) {
 		ret = irq_set_irq_wake(msm_uport->wakeup.irq, 1);
-		if (unlikely(ret))
-			return ret;
+		if (unlikely(ret)) {
+			pr_err("%s():Err setting wakeup irq\n", __func__);
+			goto deinit_uart_clk;
+		}
 	}
 
 	ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
 			  "msm_hs_uart", msm_uport);
-	if (unlikely(ret))
-		return ret;
+	if (unlikely(ret)) {
+		pr_err("%s():Error getting uart irq\n", __func__);
+		goto free_wake_irq;
+	}
 	if (use_low_power_wakeup(msm_uport)) {
 		ret = request_irq(msm_uport->wakeup.irq, msm_hs_wakeup_isr,
 				  IRQF_TRIGGER_FALLING,
 				  "msm_hs_wakeup", msm_uport);
-		if (unlikely(ret))
-			return ret;
+		if (unlikely(ret)) {
+			pr_err("%s():Err getting uart wakeup_irq\n", __func__);
+			goto free_uart_irq;
+		}
 		disable_irq(msm_uport->wakeup.irq);
 	}
 
@@ -1673,8 +1683,19 @@
 		dev_err(uport->dev, "set active error:%d\n", ret);
 	pm_runtime_enable(uport->dev);
 
-
 	return 0;
+
+free_uart_irq:
+	free_irq(uport->irq, msm_uport);
+free_wake_irq:
+	irq_set_irq_wake(msm_uport->wakeup.irq, 0);
+deinit_uart_clk:
+	clk_disable(msm_uport->clk);
+	if (msm_uport->pclk)
+		clk_disable(msm_uport->pclk);
+	wake_unlock(&msm_uport->dma_wake_lock);
+
+	return ret;
 }
 
 /* Initialize tx and rx data structures */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 3e5c6f1..3fb9c83 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -70,6 +70,8 @@
 #include "f_rndis.c"
 #include "rndis.c"
 #include "u_ether.c"
+#include "u_bam_data.c"
+#include "f_mbim.c"
 
 MODULE_AUTHOR("Mike Lockwood");
 MODULE_DESCRIPTION("Android Composite USB Driver");
@@ -386,6 +388,35 @@
 	.attributes	= rmnet_function_attributes,
 };
 
+
+/* MBIM - used with BAM */
+#define MAX_MBIM_INSTANCES 1
+
+static int mbim_function_init(struct android_usb_function *f,
+					 struct usb_composite_dev *cdev)
+{
+	return mbim_init(MAX_MBIM_INSTANCES);
+}
+
+static void mbim_function_cleanup(struct android_usb_function *f)
+{
+	fmbim_cleanup();
+}
+
+static int mbim_function_bind_config(struct android_usb_function *f,
+					  struct usb_configuration *c)
+{
+	return mbim_bind_config(c, 0);
+}
+
+static struct android_usb_function mbim_function = {
+	.name		= "usb_mbim",
+	.cleanup	= mbim_function_cleanup,
+	.bind_config	= mbim_function_bind_config,
+	.init		= mbim_function_init,
+};
+
+
 /* DIAG */
 static char diag_clients[32];	    /*enabled DIAG clients- "diag[,diag_mdm]" */
 static ssize_t clients_store(
@@ -1004,6 +1035,7 @@
 
 
 static struct android_usb_function *supported_functions[] = {
+	&mbim_function,
 	&rmnet_smd_function,
 	&rmnet_sdio_function,
 	&rmnet_smd_sdio_function,
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 9cbfad8..8e0bef0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2710,6 +2710,12 @@
 	return 0;
 }
 
+static int is_sps_req(struct ci13xxx_req *mReq)
+{
+	return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
+			mReq->req.udc_priv & MSM_SPS_MODE);
+}
+
 /**
  * ep_set_halt: sets the endpoint halt feature
  *
@@ -2731,7 +2737,9 @@
 #ifndef STALL_IN
 	/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
 	if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
-	    !list_empty(&mEp->qh.queue)) {
+		!list_empty(&mEp->qh.queue) &&
+		!is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
+							   queue))){
 		spin_unlock_irqrestore(mEp->lock, flags);
 		return -EAGAIN;
 	}
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
new file mode 100644
index 0000000..8288496
--- /dev/null
+++ b/drivers/usb/gadget/f_mbim.c
@@ -0,0 +1,1772 @@
+/* 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.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include <linux/usb/cdc.h>
+
+#include <linux/usb/composite.h>
+#include <linux/usb/android_composite.h>
+#include <linux/platform_device.h>
+
+#include <linux/spinlock.h>
+
+/*
+ * This function is a "Mobile Broadband Interface Model" (MBIM) link.
+ * MBIM is intended to be used with high-speed network attachments.
+ *
+ * Note that MBIM requires the use of "alternate settings" for its data
+ * interface.  This means that the set_alt() method has real work to do,
+ * and also means that a get_alt() method is required.
+ */
+
+#define MBIM_BULK_BUFFER_SIZE		4096
+
+#define MBIM_IOCTL_MAGIC		'o'
+#define MBIM_GET_NTB_SIZE		_IOR(MBIM_IOCTL_MAGIC, 2, u32)
+#define MBIM_GET_DATAGRAM_COUNT		_IOR(MBIM_IOCTL_MAGIC, 3, u16)
+
+#define NR_MBIM_PORTS			1
+
+struct ctrl_pkt {
+	void			*buf;
+	int			len;
+	struct list_head	list;
+};
+
+struct mbim_ep_descs {
+	struct usb_endpoint_descriptor	*in;
+	struct usb_endpoint_descriptor	*out;
+	struct usb_endpoint_descriptor	*notify;
+};
+
+struct mbim_notify_port {
+	struct usb_ep			*notify;
+	struct usb_request		*notify_req;
+	u8				notify_state;
+	atomic_t			notify_count;
+};
+
+enum mbim_notify_state {
+	NCM_NOTIFY_NONE,
+	NCM_NOTIFY_CONNECT,
+	NCM_NOTIFY_SPEED,
+};
+
+struct f_mbim {
+	struct usb_function function;
+	struct usb_composite_dev *cdev;
+
+	atomic_t	online;
+	bool		is_open;
+
+	atomic_t	open_excl;
+	atomic_t	ioctl_excl;
+	atomic_t	read_excl;
+	atomic_t	write_excl;
+
+	wait_queue_head_t read_wq;
+	wait_queue_head_t write_wq;
+
+	u8				port_num;
+	struct data_port		bam_port;
+	struct mbim_notify_port		not_port;
+
+	struct mbim_ep_descs		fs;
+	struct mbim_ep_descs		hs;
+
+	u8				ctrl_id, data_id;
+
+	struct ndp_parser_opts		*parser_opts;
+
+	spinlock_t			lock;
+
+	struct list_head	cpkt_req_q;
+	struct list_head	cpkt_resp_q;
+
+	u32			ntb_input_size;
+	u16			ntb_max_datagrams;
+
+	pid_t			user_pid;
+
+	atomic_t		error;
+};
+
+struct mbim_ntb_input_size {
+	u32	ntb_input_size;
+	u16	ntb_max_datagrams;
+	u16	reserved;
+};
+
+/* temporary variable used between mbim_open() and mbim_gadget_bind() */
+static struct f_mbim *_mbim_dev;
+
+static unsigned int nr_mbim_ports;
+
+static struct mbim_ports {
+	struct f_mbim	*port;
+	unsigned	port_num;
+} mbim_ports[NR_MBIM_PORTS];
+
+static inline struct f_mbim *func_to_mbim(struct usb_function *f)
+{
+	return container_of(f, struct f_mbim, function);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static inline unsigned mbim_bitrate(struct usb_gadget *g)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return 13 * 512 * 8 * 1000 * 8;
+	else
+		return 19 *  64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define NTB_DEFAULT_IN_SIZE	(0x4000)
+#define NTB_OUT_SIZE		(0x1000)
+#define NDP_IN_DIVISOR		(0x4)
+
+#define FORMATS_SUPPORTED	USB_CDC_NCM_NTB16_SUPPORTED
+
+static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
+	.wLength = sizeof ntb_parameters,
+	.bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
+	.dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
+	.wNdpInDivisor = cpu_to_le16(NDP_IN_DIVISOR),
+	.wNdpInPayloadRemainder = cpu_to_le16(0),
+	.wNdpInAlignment = cpu_to_le16(4),
+
+	.dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE),
+	.wNdpOutDivisor = cpu_to_le16(4),
+	.wNdpOutPayloadRemainder = cpu_to_le16(0),
+	.wNdpOutAlignment = cpu_to_le16(4),
+	.wNtbOutMaxDatagrams = cpu_to_le16(4),
+};
+
+/*
+ * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancellation; and a big transfer interval, to
+ * waste less bandwidth.
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC	5	/* 1 << 5 == 32 msec */
+#define NCM_STATUS_BYTECOUNT		16	/* 8 byte header + data */
+
+static struct usb_interface_assoc_descriptor mbim_iad_desc = {
+	.bLength =		sizeof mbim_iad_desc,
+	.bDescriptorType =	USB_DT_INTERFACE_ASSOCIATION,
+
+	/* .bFirstInterface =	DYNAMIC, */
+	.bInterfaceCount =	2,	/* control + data */
+	.bFunctionClass =	2,
+	.bFunctionSubClass =	0x0e,
+	.bFunctionProtocol =	0,
+	/* .iFunction =		DYNAMIC */
+};
+
+/* interface descriptor: */
+static struct usb_interface_descriptor mbim_control_intf = {
+	.bLength =		sizeof mbim_control_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	0x02,
+	.bInterfaceSubClass =	0x0e,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc mbim_header_desc = {
+	.bLength =		sizeof mbim_header_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+
+	.bcdCDC =		cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_union_desc mbim_union_desc = {
+	.bLength =		sizeof(mbim_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
+static struct usb_cdc_mbb_desc mbb_desc = {
+	.bLength =		sizeof mbb_desc,
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_MBB_TYPE,
+
+	.bcdMbbVersion =	cpu_to_le16(0x0100),
+
+	.wMaxControlMessage =	cpu_to_le16(0x1000),
+	.bNumberFilters =	0x10,
+	.bMaxFilterSize =	0x80,
+	.wMaxSegmentSize =	cpu_to_le16(0x1000),
+	.bmNetworkCapabilities = 0x20,
+};
+
+/* the default data interface has no endpoints ... */
+static struct usb_interface_descriptor mbim_data_nop_intf = {
+	.bLength =		sizeof mbim_data_nop_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	0,
+	.bInterfaceClass =	0x0a,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0x02,
+	/* .iInterface = DYNAMIC */
+};
+
+/* ... but the "real" data interface has two bulk endpoints */
+static struct usb_interface_descriptor mbim_data_intf = {
+	.bLength =		sizeof mbim_data_intf,
+	.bDescriptorType =	USB_DT_INTERFACE,
+
+	/* .bInterfaceNumber = DYNAMIC */
+	.bAlternateSetting =	1,
+	.bNumEndpoints =	2,
+	.bInterfaceClass =	0x0a,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0x02,
+	/* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_mbim_notify_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
+	.bInterval =		1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_mbim_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_mbim_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *mbim_fs_function[] = {
+	(struct usb_descriptor_header *) &mbim_iad_desc,
+	/* MBIM control descriptors */
+	(struct usb_descriptor_header *) &mbim_control_intf,
+	(struct usb_descriptor_header *) &mbim_header_desc,
+	(struct usb_descriptor_header *) &mbb_desc,
+	(struct usb_descriptor_header *) &fs_mbim_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &mbim_data_nop_intf,
+	(struct usb_descriptor_header *) &mbim_data_intf,
+	(struct usb_descriptor_header *) &fs_mbim_in_desc,
+	(struct usb_descriptor_header *) &fs_mbim_out_desc,
+	NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_mbim_notify_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
+	.bInterval =		LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_mbim_in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_mbim_out_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+
+	.bEndpointAddress =	USB_DIR_OUT,
+	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *mbim_hs_function[] = {
+	(struct usb_descriptor_header *) &mbim_iad_desc,
+	/* MBIM control descriptors */
+	(struct usb_descriptor_header *) &mbim_control_intf,
+	(struct usb_descriptor_header *) &mbim_header_desc,
+	(struct usb_descriptor_header *) &mbb_desc,
+	(struct usb_descriptor_header *) &hs_mbim_notify_desc,
+	/* data interface, altsettings 0 and 1 */
+	(struct usb_descriptor_header *) &mbim_data_nop_intf,
+	(struct usb_descriptor_header *) &mbim_data_intf,
+	(struct usb_descriptor_header *) &hs_mbim_in_desc,
+	(struct usb_descriptor_header *) &hs_mbim_out_desc,
+	NULL,
+};
+
+/* string descriptors: */
+
+#define STRING_CTRL_IDX	0
+#define STRING_DATA_IDX	1
+
+static struct usb_string mbim_string_defs[] = {
+	[STRING_CTRL_IDX].s = "MBIM Control",
+	[STRING_DATA_IDX].s = "MBIM Data",
+	{  } /* end of list */
+};
+
+static struct usb_gadget_strings mbim_string_table = {
+	.language =		0x0409,	/* en-us */
+	.strings =		mbim_string_defs,
+};
+
+static struct usb_gadget_strings *mbim_strings[] = {
+	&mbim_string_table,
+	NULL,
+};
+
+/*
+ * Here are options for the Datagram Pointer table (NDP) parser.
+ * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
+ * in NDP16 offsets and sizes fields are 1 16bit word wide,
+ * in NDP32 -- 2 16bit words wide. Also signatures are different.
+ * To make the parser code the same, put the differences in the structure,
+ * and switch pointers to the structures when the format is changed.
+ */
+
+struct ndp_parser_opts {
+	u32		nth_sign;
+	u32		ndp_sign;
+	unsigned	nth_size;
+	unsigned	ndp_size;
+	unsigned	ndplen_align;
+	/* sizes in u16 units */
+	unsigned	dgram_item_len; /* index or length */
+	unsigned	block_length;
+	unsigned	fp_index;
+	unsigned	reserved1;
+	unsigned	reserved2;
+	unsigned	next_fp_index;
+};
+
+#define INIT_NDP16_OPTS {				\
+	.nth_sign = USB_CDC_NCM_NTH16_SIGN,		\
+	.ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN,	\
+	.nth_size = sizeof(struct usb_cdc_ncm_nth16),	\
+	.ndp_size = sizeof(struct usb_cdc_ncm_ndp16),	\
+	.ndplen_align = 4,				\
+	.dgram_item_len = 1,				\
+	.block_length = 1,				\
+	.fp_index = 1,					\
+	.reserved1 = 0,					\
+	.reserved2 = 0,					\
+	.next_fp_index = 1,				\
+}
+
+#define INIT_NDP32_OPTS {				\
+	.nth_sign = USB_CDC_NCM_NTH32_SIGN,		\
+	.ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN,	\
+	.nth_size = sizeof(struct usb_cdc_ncm_nth32),	\
+	.ndp_size = sizeof(struct usb_cdc_ncm_ndp32),	\
+	.ndplen_align = 8,				\
+	.dgram_item_len = 2,				\
+	.block_length = 2,				\
+	.fp_index = 2,					\
+	.reserved1 = 1,					\
+	.reserved2 = 2,					\
+	.next_fp_index = 2,				\
+}
+
+static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
+static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
+
+static inline int mbim_lock(atomic_t *excl)
+{
+	if (atomic_inc_return(excl) == 1) {
+		return 0;
+	} else {
+		atomic_dec(excl);
+		return -EBUSY;
+	}
+}
+
+static inline void mbim_unlock(atomic_t *excl)
+{
+	atomic_dec(excl);
+}
+
+static struct ctrl_pkt *mbim_alloc_ctrl_pkt(unsigned len, gfp_t flags)
+{
+	struct ctrl_pkt *pkt;
+
+	pkt = kzalloc(sizeof(struct ctrl_pkt), flags);
+	if (!pkt)
+		return ERR_PTR(-ENOMEM);
+
+	pkt->buf = kmalloc(len, flags);
+	if (!pkt->buf) {
+		kfree(pkt);
+		return ERR_PTR(-ENOMEM);
+	}
+	pkt->len = len;
+
+	return pkt;
+}
+
+static void mbim_free_ctrl_pkt(struct ctrl_pkt *pkt)
+{
+	if (pkt) {
+		kfree(pkt->buf);
+		kfree(pkt);
+	}
+}
+
+static struct usb_request *mbim_alloc_req(struct usb_ep *ep, int buffer_size)
+{
+	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
+	if (!req)
+		return NULL;
+
+	req->buf = kmalloc(buffer_size, GFP_KERNEL);
+	if (!req->buf) {
+		usb_ep_free_request(ep, req);
+		return NULL;
+	}
+	req->length = buffer_size;
+	return req;
+}
+
+void fmbim_free_req(struct usb_ep *ep, struct usb_request *req)
+{
+	if (req) {
+		kfree(req->buf);
+		usb_ep_free_request(ep, req);
+	}
+}
+
+static void fmbim_ctrl_response_available(struct f_mbim *dev)
+{
+	struct usb_request		*req = dev->not_port.notify_req;
+	struct usb_cdc_notification	*event = NULL;
+	unsigned long			flags;
+	int				ret;
+
+	int notif_c = 0;
+
+	pr_info("dev:%p portno#%d\n", dev, dev->port_num);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (!atomic_read(&dev->online)) {
+		pr_info("dev:%p is not online\n", dev);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return;
+	}
+
+	if (!req) {
+		pr_info("dev:%p req is NULL\n", dev);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return;
+	}
+
+	if (!req->buf) {
+		pr_info("dev:%p req->buf is NULL\n", dev);
+		spin_unlock_irqrestore(&dev->lock, flags);
+		return;
+	}
+
+	notif_c = atomic_inc_return(&dev->not_port.notify_count);
+	pr_info("atomic_inc_return[notif_c] = %d", notif_c);
+
+	event = req->buf;
+	event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+			| USB_RECIP_INTERFACE;
+	event->bNotificationType = USB_CDC_NOTIFY_RESPONSE_AVAILABLE;
+	event->wValue = cpu_to_le16(0);
+	event->wIndex = cpu_to_le16(dev->ctrl_id);
+	event->wLength = cpu_to_le16(0);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	pr_info("Call usb_ep_queue");
+
+	ret = usb_ep_queue(dev->not_port.notify,
+			   dev->not_port.notify_req, GFP_ATOMIC);
+	if (ret) {
+		atomic_dec(&dev->not_port.notify_count);
+		pr_err("ep enqueue error %d\n", ret);
+	}
+
+	pr_info("Succcessfull Exit");
+}
+
+static int
+fmbim_send_cpkt_response(struct f_mbim *gr, struct ctrl_pkt *cpkt)
+{
+	struct f_mbim	*dev = gr;
+	unsigned long	flags;
+
+	if (!gr || !cpkt) {
+		pr_err("Invalid cpkt, dev:%p cpkt:%p\n",
+				gr, cpkt);
+		return -ENODEV;
+	}
+
+	pr_info("dev:%p port_num#%d\n", dev, dev->port_num);
+
+	if (!atomic_read(&dev->online)) {
+		pr_info("dev:%p is not connected\n", dev);
+		mbim_free_ctrl_pkt(cpkt);
+		return 0;
+	}
+
+	spin_lock_irqsave(&dev->lock, flags);
+	list_add(&cpkt->list, &dev->cpkt_resp_q);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	fmbim_ctrl_response_available(dev);
+
+	return 0;
+}
+
+/* ---------------------------- BAM INTERFACE ----------------------------- */
+
+static int mbim_bam_setup(int no_ports)
+{
+	int ret;
+
+	pr_info("no_ports:%d\n", no_ports);
+
+	ret = bam_data_setup(no_ports);
+	if (ret) {
+		pr_err("bam_data_setup failed err: %d\n", ret);
+		return ret;
+	}
+
+	pr_info("Initialized %d ports\n", no_ports);
+	return 0;
+}
+
+static int mbim_bam_connect(struct f_mbim *dev)
+{
+	int ret;
+
+	pr_info("dev:%p portno:%d\n", dev, dev->port_num);
+
+	ret = bam_data_connect(&dev->bam_port, dev->port_num, dev->port_num);
+	if (ret) {
+		pr_err("bam_data_setup failed: err:%d\n",
+				ret);
+		return ret;
+	} else {
+		pr_info("mbim bam connected\n");
+	}
+
+	return 0;
+}
+
+static int mbim_bam_disconnect(struct f_mbim *dev)
+{
+	pr_info("dev:%p port:%d. Do nothing.\n",
+			dev, dev->port_num);
+
+	/* bam_data_disconnect(&dev->bam_port, dev->port_num); */
+
+	return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+static inline void mbim_reset_values(struct f_mbim *mbim)
+{
+	mbim->parser_opts = &ndp16_opts;
+
+	mbim->ntb_input_size = NTB_DEFAULT_IN_SIZE;
+
+	atomic_set(&mbim->not_port.notify_count, 0);
+	atomic_set(&mbim->online, 0);
+}
+
+/*
+ * Context: mbim->lock held
+ */
+static void mbim_do_notify(struct f_mbim *mbim)
+{
+	struct usb_request		*req = mbim->not_port.notify_req;
+	struct usb_cdc_notification	*event;
+	struct usb_composite_dev	*cdev = mbim->cdev;
+	__le32				*data;
+	int				status;
+
+	pr_info("notify_state: %d", mbim->not_port.notify_state);
+
+	if (!req)
+		return;
+
+	event = req->buf;
+
+	switch (mbim->not_port.notify_state) {
+
+	case NCM_NOTIFY_NONE:
+		return;
+
+	case NCM_NOTIFY_CONNECT:
+		event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+		if (mbim->is_open)
+			event->wValue = cpu_to_le16(1);
+		else
+			event->wValue = cpu_to_le16(0);
+		event->wLength = 0;
+		req->length = sizeof *event;
+
+		pr_info("notify connect %s\n",
+			mbim->is_open ? "true" : "false");
+		mbim->not_port.notify_state = NCM_NOTIFY_NONE;
+		break;
+
+	case NCM_NOTIFY_SPEED:
+		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
+		event->wValue = cpu_to_le16(0);
+		event->wLength = cpu_to_le16(8);
+		req->length = NCM_STATUS_BYTECOUNT;
+
+		/* SPEED_CHANGE data is up/down speeds in bits/sec */
+		data = req->buf + sizeof *event;
+		data[0] = cpu_to_le32(mbim_bitrate(cdev->gadget));
+		data[1] = data[0];
+
+		pr_info("notify speed %d\n",
+			mbim_bitrate(cdev->gadget));
+		mbim->not_port.notify_state = NCM_NOTIFY_CONNECT;
+		break;
+	}
+	event->bmRequestType = 0xA1;
+	event->wIndex = cpu_to_le16(mbim->ctrl_id);
+
+	mbim->not_port.notify_req = NULL;
+	/*
+	 * In double buffering if there is a space in FIFO,
+	 * completion callback can be called right after the call,
+	 * so unlocking
+	 */
+	spin_unlock(&mbim->lock);
+	status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
+	spin_lock(&mbim->lock);
+	if (status < 0) {
+		mbim->not_port.notify_req = req;
+		atomic_dec(&mbim->not_port.notify_count);
+		pr_err("usb_ep_queue failed, err: %d", status);
+	}
+}
+
+/*
+ * Context: mbim->lock held
+ */
+static void mbim_notify(struct f_mbim *mbim)
+{
+	/*
+	 * If mbim_notify() is called before the second (CONNECT)
+	 * notification is sent, then it will reset to send the SPEED
+	 * notificaion again (and again, and again), but it's not a problem
+	 */
+	pr_info("dev:%p\n", mbim);
+
+	mbim->not_port.notify_state = NCM_NOTIFY_SPEED;
+	mbim_do_notify(mbim);
+}
+
+static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_mbim			*mbim = req->context;
+	struct usb_cdc_notification	*event = req->buf;
+
+	int notif_c = 0;
+
+	pr_info("dev:%p\n", mbim);
+
+	spin_lock(&mbim->lock);
+	switch (req->status) {
+	case 0:
+		pr_info("Notification %02x sent\n",
+			event->bNotificationType);
+
+		notif_c = atomic_dec_return(&mbim->not_port.notify_count);
+
+		if (notif_c != 0) {
+			pr_info("Continue to mbim_do_notify()");
+			break;
+		} else {
+			pr_info("notify_count decreased to 0. Do not notify");
+			spin_unlock(&mbim->lock);
+			return;
+		}
+
+		break;
+
+	case -ECONNRESET:
+	case -ESHUTDOWN:
+		/* connection gone */
+		mbim->not_port.notify_state = NCM_NOTIFY_NONE;
+		atomic_set(&mbim->not_port.notify_count, 0);
+		pr_info("ESHUTDOWN/ECONNRESET, connection gone");
+		break;
+	default:
+		pr_err("Unknown event %02x --> %d\n",
+			event->bNotificationType, req->status);
+		break;
+	}
+
+	mbim->not_port.notify_req = req;
+	mbim_do_notify(mbim);
+
+	spin_unlock(&mbim->lock);
+
+	pr_info("dev:%p Exit\n", mbim);
+}
+
+static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	/* now for SET_NTB_INPUT_SIZE only */
+	unsigned		in_size = 0;
+	struct usb_function	*f = req->context;
+	struct f_mbim		*mbim = func_to_mbim(f);
+	struct mbim_ntb_input_size *ntb = NULL;
+
+	pr_info("dev:%p\n", mbim);
+
+	req->context = NULL;
+	if (req->status || req->actual != req->length) {
+		pr_err("Bad control-OUT transfer\n");
+		goto invalid;
+	}
+
+	if (req->length == 4) {
+		in_size = get_unaligned_le32(req->buf);
+		if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
+		    in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
+			pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
+			goto invalid;
+		}
+	} else if (req->length == 8) {
+		ntb = (struct mbim_ntb_input_size *)req->buf;
+		in_size = get_unaligned_le32(&(ntb->ntb_input_size));
+		if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
+		    in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
+			pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
+			goto invalid;
+		}
+		mbim->ntb_max_datagrams =
+			get_unaligned_le16(&(ntb->ntb_max_datagrams));
+	} else {
+		pr_err("Illegal NTB length %d\n", in_size);
+		goto invalid;
+	}
+
+	pr_info("Set NTB INPUT SIZE %d\n", in_size);
+
+	mbim->ntb_input_size = in_size;
+	return;
+
+invalid:
+	usb_ep_set_halt(ep);
+
+	pr_err("dev:%p Failed\n", mbim);
+
+	return;
+}
+
+static void
+fmbim_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_mbim		*dev = req->context;
+	struct ctrl_pkt		*cpkt = NULL;
+	int			len = req->actual;
+
+	if (!dev) {
+		pr_err("mbim dev is null\n");
+		return;
+	}
+
+	if (req->status < 0) {
+		pr_err("mbim command error %d\n", req->status);
+		return;
+	}
+
+	pr_info("dev:%p port#%d\n", dev, dev->port_num);
+
+	spin_lock(&dev->lock);
+	if (!dev->is_open) {
+		pr_err("mbim file handler %p is not open", dev);
+		spin_unlock(&dev->lock);
+		return;
+	}
+
+	cpkt = mbim_alloc_ctrl_pkt(len, GFP_ATOMIC);
+	if (!cpkt) {
+		pr_err("Unable to allocate ctrl pkt\n");
+		spin_unlock(&dev->lock);
+		return;
+	}
+
+	pr_info("Add to cpkt_req_q packet with len = %d\n", len);
+	memcpy(cpkt->buf, req->buf, len);
+	list_add_tail(&cpkt->list, &dev->cpkt_req_q);
+	spin_unlock(&dev->lock);
+
+	/* wakeup read thread */
+	pr_info("Wake up read queue");
+	wake_up(&dev->read_wq);
+
+	return;
+}
+
+static int
+mbim_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_mbim			*mbim = func_to_mbim(f);
+	struct usb_composite_dev	*cdev = mbim->cdev;
+	struct usb_request		*req = cdev->req;
+	struct ctrl_pkt		*cpkt = NULL;
+	int	value = -EOPNOTSUPP;
+	u16	w_index = le16_to_cpu(ctrl->wIndex);
+	u16	w_value = le16_to_cpu(ctrl->wValue);
+	u16	w_length = le16_to_cpu(ctrl->wLength);
+
+	/*
+	 * composite driver infrastructure handles everything except
+	 * CDC class messages; interface activation uses set_alt().
+	 */
+
+	if (!atomic_read(&mbim->online)) {
+		pr_info("usb cable is not connected\n");
+		return -ENOTCONN;
+	}
+
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_RESET_FUNCTION:
+
+		pr_info("USB_CDC_RESET_FUNCTION");
+		value = 0;
+		if (!_mbim_dev->user_pid) {
+			pr_err("QBI pid is not set");
+			break;
+		}
+
+		if (!_mbim_dev->is_open) {
+			pr_err("QBI is not up yet");
+			break;
+		}
+
+		send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
+			find_task_by_vpid(_mbim_dev->user_pid));
+
+		pr_info("Sent signal to QBI pid %d",
+			_mbim_dev->user_pid);
+		break;
+
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_SEND_ENCAPSULATED_COMMAND:
+
+		pr_info("USB_CDC_SEND_ENCAPSULATED_COMMAND");
+
+		if (w_length > req->length) {
+			pr_err("w_length > req->length: %d > %d",
+			w_length, req->length);
+		}
+		value = w_length;
+		req->complete = fmbim_cmd_complete;
+		req->context = mbim;
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_ENCAPSULATED_RESPONSE:
+
+		pr_info("USB_CDC_GET_ENCAPSULATED_RESPONSE");
+
+		if (w_value) {
+			pr_err("w_length > 0: %d", w_length);
+			break;
+		}
+
+		pr_info("req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+
+		spin_lock(&mbim->lock);
+		if (list_empty(&mbim->cpkt_resp_q)) {
+			pr_err("ctrl resp queue empty\n");
+			spin_unlock(&mbim->lock);
+			break;
+		}
+
+		cpkt = list_first_entry(&mbim->cpkt_resp_q,
+					struct ctrl_pkt, list);
+		list_del(&cpkt->list);
+		spin_unlock(&mbim->lock);
+
+		value = min_t(unsigned, w_length, cpkt->len);
+		memcpy(req->buf, cpkt->buf, value);
+		mbim_free_ctrl_pkt(cpkt);
+
+		pr_info("copied encapsulated_response %d bytes",
+			value);
+
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_NTB_PARAMETERS:
+
+		pr_info("USB_CDC_GET_NTB_PARAMETERS");
+
+		if (w_length == 0 || w_value != 0 || w_index != mbim->ctrl_id)
+			break;
+
+		value = w_length > sizeof ntb_parameters ?
+			sizeof ntb_parameters : w_length;
+		memcpy(req->buf, &ntb_parameters, value);
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_NTB_INPUT_SIZE:
+
+		pr_info("USB_CDC_GET_NTB_INPUT_SIZE");
+
+		if (w_length < 4 || w_value != 0 || w_index != mbim->ctrl_id)
+			break;
+
+		put_unaligned_le32(mbim->ntb_input_size, req->buf);
+		value = 4;
+		pr_info("Reply to host INPUT SIZE %d\n",
+		     mbim->ntb_input_size);
+		break;
+
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_SET_NTB_INPUT_SIZE:
+
+		pr_info("USB_CDC_SET_NTB_INPUT_SIZE");
+
+		if (w_length != 4 && w_length != 8) {
+			pr_err("wrong NTB length %d", w_length);
+			break;
+		}
+
+		if (w_value != 0 || w_index != mbim->ctrl_id)
+			break;
+
+		req->complete = mbim_ep0out_complete;
+		req->length = w_length;
+		req->context = f;
+
+		value = req->length;
+		break;
+
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_GET_NTB_FORMAT:
+	{
+		uint16_t format;
+
+		pr_info("USB_CDC_GET_NTB_FORMAT");
+
+		if (w_length < 2 || w_value != 0 || w_index != mbim->ctrl_id)
+			break;
+
+		format = (mbim->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
+		put_unaligned_le16(format, req->buf);
+		value = 2;
+		pr_info("NTB FORMAT: sending %d\n", format);
+		break;
+	}
+
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+		| USB_CDC_SET_NTB_FORMAT:
+	{
+		pr_info("USB_CDC_SET_NTB_FORMAT");
+
+		if (w_length != 0 || w_index != mbim->ctrl_id)
+			break;
+		switch (w_value) {
+		case 0x0000:
+			mbim->parser_opts = &ndp16_opts;
+			pr_info("NCM16 selected\n");
+			break;
+		case 0x0001:
+			mbim->parser_opts = &ndp32_opts;
+			pr_info("NCM32 selected\n");
+			break;
+		default:
+			break;
+		}
+		value = 0;
+		break;
+	}
+
+	/* optional in mbim descriptor: */
+	/* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */
+	/* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */
+
+	default:
+	pr_err("invalid control req: %02x.%02x v%04x i%04x l%d\n",
+		ctrl->bRequestType, ctrl->bRequest,
+		w_value, w_index, w_length);
+	}
+
+	 /* respond with data transfer or status phase? */
+	if (value >= 0) {
+		pr_info("control request: %02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0) {
+			pr_err("queueing req failed: %02x.%02x, err %d\n",
+				ctrl->bRequestType,
+			       ctrl->bRequest, value);
+		}
+	} else {
+		pr_err("ctrl req err %d: %02x.%02x v%04x i%04x l%d\n",
+			value, ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
+
+static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_mbim		*mbim = func_to_mbim(f);
+	struct usb_composite_dev *cdev = mbim->cdev;
+	int ret = 0;
+
+	/* Control interface has only altsetting 0 */
+	if (intf == mbim->ctrl_id) {
+
+		pr_info("CONTROL_INTERFACE");
+
+		if (alt != 0)
+			goto fail;
+
+		if (mbim->not_port.notify->driver_data) {
+			pr_info("reset mbim control %d\n", intf);
+			usb_ep_disable(mbim->not_port.notify);
+		}
+
+		ret = config_ep_by_speed(cdev->gadget, f,
+					mbim->not_port.notify);
+		if (ret) {
+			mbim->not_port.notify->desc = NULL;
+			pr_err("Failed configuring notify ep %s: err %d\n",
+				mbim->not_port.notify->name, ret);
+			return ret;
+		}
+
+		ret = usb_ep_enable(mbim->not_port.notify);
+		if (ret) {
+			pr_err("usb ep#%s enable failed, err#%d\n",
+				mbim->not_port.notify->name, ret);
+			return ret;
+		}
+		mbim->not_port.notify->driver_data = mbim;
+
+	/* Data interface has two altsettings, 0 and 1 */
+	} else if (intf == mbim->data_id) {
+
+		pr_info("DATA_INTERFACE");
+
+		if (alt > 1)
+			goto fail;
+
+		if (mbim->bam_port.in->driver_data) {
+			pr_info("reset mbim\n");
+			mbim_reset_values(mbim);
+			mbim_bam_disconnect(mbim);
+		}
+
+		/*
+		 * CDC Network only sends data in non-default altsettings.
+		 * Changing altsettings resets filters, statistics, etc.
+		 */
+		if (alt == 1) {
+			pr_info("Alt set 1, initialize ports");
+
+			if (!mbim->bam_port.in->desc) {
+
+				pr_info("Choose endpoints");
+
+				ret = config_ep_by_speed(cdev->gadget, f,
+							mbim->bam_port.in);
+				if (ret) {
+					mbim->bam_port.in->desc = NULL;
+					pr_err("IN ep %s failed: %d\n",
+					mbim->bam_port.in->name, ret);
+					return ret;
+				}
+
+				pr_info("Set mbim port in_desc = 0x%p",
+					mbim->bam_port.in->desc);
+
+				ret = config_ep_by_speed(cdev->gadget, f,
+							mbim->bam_port.out);
+				if (ret) {
+					mbim->bam_port.out->desc = NULL;
+					pr_err("OUT ep %s failed: %d\n",
+					mbim->bam_port.out->name, ret);
+					return ret;
+				}
+
+				pr_info("Set mbim port out_desc = 0x%p",
+					mbim->bam_port.out->desc);
+			} else {
+				pr_info("PORTS already SET");
+			}
+
+			pr_info("Activate mbim\n");
+			mbim_bam_connect(mbim);
+		}
+
+		spin_lock(&mbim->lock);
+		mbim_notify(mbim);
+		spin_unlock(&mbim->lock);
+	} else {
+		goto fail;
+	}
+
+	atomic_set(&mbim->online, 1);
+
+	pr_info("SET DEVICE ONLINE");
+
+	/* wakeup file threads */
+	wake_up(&mbim->read_wq);
+	wake_up(&mbim->write_wq);
+
+	return 0;
+
+fail:
+	pr_err("ERROR: Illegal Interface");
+	return -EINVAL;
+}
+
+/*
+ * Because the data interface supports multiple altsettings,
+ * this MBIM function *MUST* implement a get_alt() method.
+ */
+static int mbim_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_mbim	*mbim = func_to_mbim(f);
+
+	if (intf == mbim->ctrl_id)
+		return 0;
+	return mbim->bam_port.in->driver_data ? 1 : 0;
+}
+
+static void mbim_disable(struct usb_function *f)
+{
+	struct f_mbim	*mbim = func_to_mbim(f);
+
+	pr_info("SET DEVICE OFFLINE");
+	atomic_set(&mbim->online, 0);
+
+	if (_mbim_dev && _mbim_dev->user_pid && _mbim_dev->is_open) {
+		send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
+			find_task_by_vpid(_mbim_dev->user_pid));
+		pr_info("Sending reset signal to QBI pid %d",
+			_mbim_dev->user_pid);
+	}
+
+	mbim_bam_disconnect(mbim);
+
+	if (mbim->not_port.notify->driver_data) {
+		usb_ep_disable(mbim->not_port.notify);
+		mbim->not_port.notify->driver_data = NULL;
+	}
+
+	pr_info("mbim deactivated\n");
+}
+
+/*---------------------- function driver setup/binding ---------------------*/
+
+static int
+mbim_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_mbim		*mbim = func_to_mbim(f);
+	int			status;
+	struct usb_ep		*ep;
+
+	pr_info("Enter");
+
+	mbim->cdev = cdev;
+
+	/* allocate instance-specific interface IDs */
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	mbim->ctrl_id = status;
+	mbim_iad_desc.bFirstInterface = status;
+
+	mbim_control_intf.bInterfaceNumber = status;
+	mbim_union_desc.bMasterInterface0 = status;
+
+	status = usb_interface_id(c, f);
+	if (status < 0)
+		goto fail;
+	mbim->data_id = status;
+
+	mbim_data_nop_intf.bInterfaceNumber = status;
+	mbim_data_intf.bInterfaceNumber = status;
+	mbim_union_desc.bSlaveInterface0 = status;
+
+	status = -ENODEV;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_in_desc);
+	if (!ep) {
+		pr_err("usb epin autoconfig failed\n");
+		goto fail;
+	}
+	pr_info("usb epin autoconfig succeeded\n");
+	ep->driver_data = cdev;	/* claim */
+	mbim->bam_port.in = ep;
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_out_desc);
+	if (!ep) {
+		pr_err("usb epout autoconfig failed\n");
+		goto fail;
+	}
+	pr_info("usb epout autoconfig succeeded\n");
+	ep->driver_data = cdev;	/* claim */
+	mbim->bam_port.out = ep;
+
+	ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_notify_desc);
+	if (!ep) {
+		pr_err("usb notify ep autoconfig failed\n");
+		goto fail;
+	}
+	pr_info("usb notify ep autoconfig succeeded\n");
+	mbim->not_port.notify = ep;
+	ep->driver_data = cdev;	/* claim */
+
+	status = -ENOMEM;
+
+	/* allocate notification request and buffer */
+	mbim->not_port.notify_req = mbim_alloc_req(ep, NCM_STATUS_BYTECOUNT);
+	if (!mbim->not_port.notify_req) {
+		pr_info("failed to allocate notify request\n");
+		goto fail;
+	}
+	pr_info("allocated notify ep request & request buffer\n");
+
+	mbim->not_port.notify_req->context = mbim;
+	mbim->not_port.notify_req->complete = mbim_notify_complete;
+
+	/* copy descriptors, and track endpoint copies */
+	f->descriptors = usb_copy_descriptors(mbim_fs_function);
+	if (!f->descriptors)
+		goto fail;
+
+	/*
+	 * support all relevant hardware speeds... we expect that when
+	 * hardware is dual speed, all bulk-capable endpoints work at
+	 * both speeds
+	 */
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		hs_mbim_in_desc.bEndpointAddress =
+				fs_mbim_in_desc.bEndpointAddress;
+		hs_mbim_out_desc.bEndpointAddress =
+				fs_mbim_out_desc.bEndpointAddress;
+		hs_mbim_notify_desc.bEndpointAddress =
+				fs_mbim_notify_desc.bEndpointAddress;
+
+		/* copy descriptors, and track endpoint copies */
+		f->hs_descriptors = usb_copy_descriptors(mbim_hs_function);
+		if (!f->hs_descriptors)
+			goto fail;
+	}
+
+	pr_info("mbim(%d): %s speed IN/%s OUT/%s NOTIFY/%s\n",
+			mbim->port_num,
+			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+			mbim->bam_port.in->name, mbim->bam_port.out->name,
+			mbim->not_port.notify->name);
+
+	return 0;
+
+fail:
+	pr_err("%s failed to bind, err %d\n", f->name, status);
+
+	if (f->descriptors)
+		usb_free_descriptors(f->descriptors);
+
+	if (mbim->not_port.notify_req) {
+		kfree(mbim->not_port.notify_req->buf);
+		usb_ep_free_request(mbim->not_port.notify,
+				    mbim->not_port.notify_req);
+	}
+
+	/* we might as well release our claims on endpoints */
+	if (mbim->not_port.notify)
+		mbim->not_port.notify->driver_data = NULL;
+	if (mbim->bam_port.out)
+		mbim->bam_port.out->driver_data = NULL;
+	if (mbim->bam_port.in)
+		mbim->bam_port.in->driver_data = NULL;
+
+	return status;
+}
+
+static void mbim_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct f_mbim	*mbim = func_to_mbim(f);
+
+	if (gadget_is_dualspeed(c->cdev->gadget))
+		usb_free_descriptors(f->hs_descriptors);
+	usb_free_descriptors(f->descriptors);
+
+	kfree(mbim->not_port.notify_req->buf);
+	usb_ep_free_request(mbim->not_port.notify, mbim->not_port.notify_req);
+}
+
+/**
+ * mbim_bind_config - add MBIM link to a configuration
+ * @c: the configuration to support the network link
+ * Context: single threaded during gadget setup
+ * Returns zero on success, else negative errno.
+ */
+int mbim_bind_config(struct usb_configuration *c, unsigned portno)
+{
+	struct f_mbim	*mbim = NULL;
+	int status = 0;
+
+	pr_info("port number %u", portno);
+
+	if (portno >= nr_mbim_ports) {
+		pr_err("Can not add port %u. Max ports = %d",
+		       portno, nr_mbim_ports);
+		return -ENODEV;
+	}
+
+	status = mbim_bam_setup(nr_mbim_ports);
+	if (status) {
+		pr_err("bam setup failed");
+		return status;
+	}
+
+	/* maybe allocate device-global string IDs */
+	if (mbim_string_defs[0].id == 0) {
+
+		/* control interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		mbim_string_defs[STRING_CTRL_IDX].id = status;
+		mbim_control_intf.iInterface = status;
+
+		/* data interface label */
+		status = usb_string_id(c->cdev);
+		if (status < 0)
+			return status;
+		mbim_string_defs[STRING_DATA_IDX].id = status;
+		mbim_data_nop_intf.iInterface = status;
+		mbim_data_intf.iInterface = status;
+	}
+
+	/* allocate and initialize one new instance */
+	mbim = mbim_ports[0].port;
+	if (!mbim) {
+		pr_info("mbim struct not allocated");
+		return -ENOMEM;
+	}
+
+	mbim->cdev = c->cdev;
+
+	spin_lock_init(&mbim->lock);
+
+	mbim_reset_values(mbim);
+
+	mbim->function.name = "usb_mbim";
+	mbim->function.strings = mbim_strings;
+	mbim->function.bind = mbim_bind;
+	mbim->function.unbind = mbim_unbind;
+	mbim->function.set_alt = mbim_set_alt;
+	mbim->function.get_alt = mbim_get_alt;
+	mbim->function.setup = mbim_setup;
+	mbim->function.disable = mbim_disable;
+
+	INIT_LIST_HEAD(&mbim->cpkt_req_q);
+	INIT_LIST_HEAD(&mbim->cpkt_resp_q);
+
+	status = usb_add_function(c, &mbim->function);
+
+	pr_info("Exit status %d", status);
+
+	return status;
+}
+
+/* ------------ MBIM DRIVER File Operations API for USER SPACE ------------ */
+
+static ssize_t
+mbim_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
+{
+	struct f_mbim *dev = fp->private_data;
+	struct ctrl_pkt *cpkt = NULL;
+	int ret = 0;
+
+	pr_debug("Enter(%d)\n", count);
+
+	if (!dev) {
+		pr_err("Received NULL mbim pointer\n");
+		return -ENODEV;
+	}
+
+	if (count > MBIM_BULK_BUFFER_SIZE) {
+		pr_err("Buffer size is too big %d, should be at most %d\n",
+			count, MBIM_BULK_BUFFER_SIZE);
+		return -EINVAL;
+	}
+
+	if (mbim_lock(&dev->read_excl)) {
+		pr_err("Previous reading is not finished yet\n");
+		return -EBUSY;
+	}
+
+	/* block until mbim online */
+	while (!(atomic_read(&dev->online) || atomic_read(&dev->error))) {
+		pr_err("USB cable not connected. Wait.\n");
+		ret = wait_event_interruptible(dev->read_wq,
+			(atomic_read(&dev->online) ||
+			atomic_read(&dev->error)));
+		if (ret < 0) {
+			mbim_unlock(&dev->read_excl);
+			return 0;
+		}
+	}
+
+	if (atomic_read(&dev->error)) {
+		mbim_unlock(&dev->read_excl);
+		return -EIO;
+	}
+
+	while (list_empty(&dev->cpkt_req_q)) {
+		pr_err("Requests list is empty. Wait.\n");
+		ret = wait_event_interruptible(dev->read_wq,
+			!list_empty(&dev->cpkt_req_q));
+		if (ret < 0) {
+			pr_err("Waiting failed\n");
+			mbim_unlock(&dev->read_excl);
+			return 0;
+		}
+		pr_debug("Received request packet\n");
+	}
+
+	cpkt = list_first_entry(&dev->cpkt_req_q, struct ctrl_pkt,
+							list);
+	if (cpkt->len > count) {
+		mbim_unlock(&dev->read_excl);
+		pr_err("cpkt size too big:%d > buf size:%d\n",
+				cpkt->len, count);
+		return -ENOMEM;
+	}
+
+	pr_debug("cpkt size:%d\n", cpkt->len);
+
+	list_del(&cpkt->list);
+	mbim_unlock(&dev->read_excl);
+
+	ret = copy_to_user(buf, cpkt->buf, cpkt->len);
+	if (ret) {
+		pr_err("copy_to_user failed: err %d\n", ret);
+		ret = 0;
+	} else {
+		pr_debug("copied %d bytes to user\n", cpkt->len);
+		ret = cpkt->len;
+	}
+
+	mbim_free_ctrl_pkt(cpkt);
+
+	return ret;
+}
+
+static ssize_t
+mbim_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
+{
+	struct f_mbim *dev = fp->private_data;
+	struct ctrl_pkt *cpkt = NULL;
+	int ret = 0;
+
+	pr_debug("Enter(%d)", count);
+
+	if (!dev) {
+		pr_err("Received NULL mbim pointer\n");
+		return -ENODEV;
+	}
+
+	if (!count) {
+		pr_err("zero length ctrl pkt\n");
+		return -ENODEV;
+	}
+
+	if (count > MAX_CTRL_PKT_SIZE) {
+		pr_err("given pkt size too big:%d > max_pkt_size:%d\n",
+				count, MAX_CTRL_PKT_SIZE);
+		return -ENOMEM;
+	}
+
+	if (mbim_lock(&dev->write_excl)) {
+		pr_err("Previous writing not finished yet\n");
+		return -EBUSY;
+	}
+
+	if (!atomic_read(&dev->online)) {
+		pr_err("USB cable not connected\n");
+		mbim_unlock(&dev->write_excl);
+		return -EPIPE;
+	}
+
+	cpkt = mbim_alloc_ctrl_pkt(count, GFP_KERNEL);
+	if (!cpkt) {
+		pr_err("failed to allocate ctrl pkt\n");
+		mbim_unlock(&dev->write_excl);
+		return -ENOMEM;
+	}
+
+	ret = copy_from_user(cpkt->buf, buf, count);
+	if (ret) {
+		pr_err("copy_from_user failed err:%d\n", ret);
+		mbim_free_ctrl_pkt(cpkt);
+		mbim_unlock(&dev->write_excl);
+		return 0;
+	}
+
+	fmbim_send_cpkt_response(dev, cpkt);
+
+	mbim_unlock(&dev->write_excl);
+
+	pr_debug("Exit(%d)", count);
+
+	return count;
+}
+
+static int mbim_open(struct inode *ip, struct file *fp)
+{
+	pr_info("Open mbim driver\n");
+
+	while (!_mbim_dev) {
+		pr_err("mbim_dev not created yet\n");
+		return -ENODEV;
+	}
+
+	if (mbim_lock(&_mbim_dev->open_excl)) {
+		pr_err("Already opened\n");
+		return -EBUSY;
+	}
+
+	pr_info("Lock mbim_dev->open_excl for open\n");
+
+	if (!atomic_read(&_mbim_dev->online))
+		pr_err("USB cable not connected\n");
+
+	pr_info("Set QBI pid %d\n", pid_nr(task_pid(current)));
+	_mbim_dev->user_pid = pid_nr(task_pid(current));
+
+	fp->private_data = _mbim_dev;
+
+	atomic_set(&_mbim_dev->error, 0);
+
+	spin_lock(&_mbim_dev->lock);
+	_mbim_dev->is_open = true;
+	mbim_notify(_mbim_dev);
+	spin_unlock(&_mbim_dev->lock);
+
+	pr_info("Exit, mbim file opened\n");
+
+	return 0;
+}
+
+static int mbim_release(struct inode *ip, struct file *fp)
+{
+	struct f_mbim *mbim = fp->private_data;
+
+	pr_info("Close mbim file");
+
+	spin_lock(&mbim->lock);
+	mbim->is_open = false;
+	mbim_notify(mbim);
+	spin_unlock(&mbim->lock);
+
+	mbim->user_pid = 0;
+
+	mbim_unlock(&_mbim_dev->open_excl);
+
+	return 0;
+}
+
+static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
+{
+	struct f_mbim *mbim = fp->private_data;
+	int ret = 0;
+
+	pr_info("Received command %d", cmd);
+
+	if (mbim_lock(&mbim->ioctl_excl))
+		return -EBUSY;
+
+	switch (cmd) {
+	case MBIM_GET_NTB_SIZE:
+		ret = copy_to_user((void __user *)arg,
+			&mbim->ntb_input_size, sizeof(mbim->ntb_input_size));
+		if (ret) {
+			pr_err("copying to user space failed");
+			ret = -EFAULT;
+		}
+		pr_info("Sent NTB size %d", mbim->ntb_input_size);
+		break;
+	case MBIM_GET_DATAGRAM_COUNT:
+		ret = copy_to_user((void __user *)arg,
+			&mbim->ntb_max_datagrams,
+			sizeof(mbim->ntb_max_datagrams));
+		if (ret) {
+			pr_err("copying to user space failed");
+			ret = -EFAULT;
+		}
+		pr_info("Sent NTB datagrams count %d",
+			mbim->ntb_max_datagrams);
+		break;
+	default:
+		pr_err("wrong parameter");
+		ret = -EINVAL;
+	}
+
+	mbim_unlock(&mbim->ioctl_excl);
+
+	return ret;
+}
+
+/* file operations for MBIM device /dev/android_mbim */
+static const struct file_operations mbim_fops = {
+	.owner = THIS_MODULE,
+	.open = mbim_open,
+	.release = mbim_release,
+	.read = mbim_read,
+	.write = mbim_write,
+	.unlocked_ioctl	= mbim_ioctl,
+};
+
+static struct miscdevice mbim_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "android_mbim",
+	.fops = &mbim_fops,
+};
+
+static int mbim_init(int instances)
+{
+	int i;
+	struct f_mbim *dev = NULL;
+	int ret;
+
+	pr_info("initialize %d instances\n", instances);
+
+	if (instances > NR_MBIM_PORTS) {
+		pr_err("Max-%d instances supported\n", NR_MBIM_PORTS);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < instances; i++) {
+		dev = kzalloc(sizeof(struct f_mbim), GFP_KERNEL);
+		if (!dev) {
+			pr_err("Failed to allocate mbim dev\n");
+			ret = -ENOMEM;
+			goto fail_probe;
+		}
+
+		dev->port_num = i;
+		spin_lock_init(&dev->lock);
+		INIT_LIST_HEAD(&dev->cpkt_req_q);
+		INIT_LIST_HEAD(&dev->cpkt_resp_q);
+
+		mbim_ports[i].port = dev;
+		mbim_ports[i].port_num = i;
+
+		init_waitqueue_head(&dev->read_wq);
+		init_waitqueue_head(&dev->write_wq);
+
+		atomic_set(&dev->open_excl, 0);
+		atomic_set(&dev->ioctl_excl, 0);
+		atomic_set(&dev->read_excl, 0);
+		atomic_set(&dev->write_excl, 0);
+
+		nr_mbim_ports++;
+
+	}
+
+	_mbim_dev = dev;
+	ret = misc_register(&mbim_device);
+	if (ret) {
+		pr_err("mbim driver failed to register");
+		goto fail_probe;
+	}
+
+	pr_info("Initialized %d ports\n", nr_mbim_ports);
+
+	return ret;
+
+fail_probe:
+	pr_err("Failed");
+	for (i = 0; i < nr_mbim_ports; i++) {
+		kfree(mbim_ports[i].port);
+		mbim_ports[i].port = NULL;
+	}
+
+	return ret;
+}
+
+static void fmbim_cleanup(void)
+{
+	int i = 0;
+
+	pr_info("Enter");
+
+	for (i = 0; i < nr_mbim_ports; i++) {
+		kfree(mbim_ports[i].port);
+		mbim_ports[i].port = NULL;
+	}
+	nr_mbim_ports = 0;
+
+	misc_deregister(&mbim_device);
+
+	_mbim_dev = NULL;
+}
+
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index cc26c85..b086428 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -488,20 +488,16 @@
 	}
 	dev->notify->driver_data = dev;
 
-	if (dev->port.in->driver_data) {
-		pr_debug("%s: reset port:%d\n", __func__, dev->port_num);
-		gport_rmnet_disconnect(dev);
+	if (!dev->port.in->driver_data) {
+		if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
+			config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
+				dev->port.in->desc = NULL;
+				dev->port.out->desc = NULL;
+				return -EINVAL;
+		}
+		ret = gport_rmnet_connect(dev);
 	}
 
-	if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
-	    config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
-			dev->port.in->desc = NULL;
-			dev->port.out->desc = NULL;
-			return -EINVAL;
-	}
-
-	ret = gport_rmnet_connect(dev);
-
 	atomic_set(&dev->online, 1);
 
 	return ret;
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
new file mode 100644
index 0000000..73b4e75
--- /dev/null
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -0,0 +1,328 @@
+/* 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.
+ */
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/usb/gadget.h>
+
+#include <mach/bam_dmux.h>
+#include <mach/usb_gadget_xport.h>
+#include <mach/usb_bam.h>
+
+#define BAM2BAM_DATA_N_PORTS	1
+
+static struct workqueue_struct *bam_data_wq;
+static int n_bam2bam_data_ports;
+
+#define SPS_PARAMS_SPS_MODE		BIT(5)
+#define SPS_PARAMS_TBE		        BIT(6)
+#define MSM_VENDOR_ID			BIT(16)
+
+struct data_port {
+	struct usb_function		func;
+	struct usb_ep			*in;
+	struct usb_ep			*out;
+};
+
+struct bam_data_ch_info {
+	unsigned long		flags;
+	unsigned		id;
+
+	struct bam_data_port	*port;
+	struct work_struct	write_tobam_w;
+
+	struct usb_request	*rx_req;
+	struct usb_request	*tx_req;
+
+	u8			src_pipe_idx;
+	u8			dst_pipe_idx;
+	u8			connection_idx;
+};
+
+struct bam_data_port {
+	unsigned			port_num;
+	struct data_port		*port_usb;
+	struct bam_data_ch_info		data_ch;
+
+	struct work_struct		connect_w;
+	struct work_struct		disconnect_w;
+};
+
+struct bam_data_port *bam2bam_data_ports[BAM2BAM_DATA_N_PORTS];
+
+/*------------data_path----------------------------*/
+
+static void bam_data_endless_rx_complete(struct usb_ep *ep,
+					 struct usb_request *req)
+{
+	int status = req->status;
+
+	pr_info("status: %d\n", status);
+}
+
+static void bam_data_endless_tx_complete(struct usb_ep *ep,
+					 struct usb_request *req)
+{
+	int status = req->status;
+
+	pr_info("status: %d\n", status);
+}
+
+static void bam_data_start_endless_rx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
+	if (status)
+		pr_err("error enqueuing transfer, %d\n", status);
+}
+
+static void bam_data_start_endless_tx(struct bam_data_port *port)
+{
+	struct bam_data_ch_info *d = &port->data_ch;
+	int status;
+
+	status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
+	if (status)
+		pr_err("error enqueuing transfer, %d\n", status);
+}
+
+static void bam2bam_data_disconnect_work(struct work_struct *w)
+{
+	struct bam_data_port *port =
+			container_of(w, struct bam_data_port, disconnect_w);
+
+	pr_info("Enter");
+
+	/* disable endpoints */
+	if (!port->port_usb || !port->port_usb->out || !port->port_usb->in) {
+		pr_err("port_usb->out/in == NULL. Exit");
+		return;
+	}
+	usb_ep_disable(port->port_usb->out);
+	usb_ep_disable(port->port_usb->in);
+
+	port->port_usb->in->driver_data = NULL;
+	port->port_usb->out->driver_data = NULL;
+
+	port->port_usb = 0;
+
+	pr_info("Exit");
+}
+
+static void bam2bam_data_connect_work(struct work_struct *w)
+{
+	struct bam_data_port *port = container_of(w, struct bam_data_port,
+						  connect_w);
+	struct bam_data_ch_info *d = &port->data_ch;
+	u32 sps_params;
+	int ret;
+
+	pr_info("Enter");
+
+	ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
+						  &d->dst_pipe_idx);
+	d->src_pipe_idx = 11;
+	d->dst_pipe_idx = 10;
+
+	if (ret) {
+		pr_err("usb_bam_connect failed: err:%d\n", ret);
+		return;
+	}
+
+	if (!port->port_usb) {
+		pr_err("port_usb is NULL");
+		return;
+	}
+
+	if (!port->port_usb->out) {
+		pr_err("port_usb->out (bulk out ep) is NULL");
+		return;
+	}
+
+	d->rx_req = usb_ep_alloc_request(port->port_usb->out, GFP_KERNEL);
+	if (!d->rx_req)
+		return;
+
+	d->rx_req->context = port;
+	d->rx_req->complete = bam_data_endless_rx_complete;
+	d->rx_req->length = 0;
+	sps_params = (SPS_PARAMS_SPS_MODE | d->src_pipe_idx |
+				 MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
+	d->rx_req->udc_priv = sps_params;
+	d->tx_req = usb_ep_alloc_request(port->port_usb->in, GFP_KERNEL);
+	if (!d->tx_req)
+		return;
+
+	d->tx_req->context = port;
+	d->tx_req->complete = bam_data_endless_tx_complete;
+	d->tx_req->length = 0;
+	sps_params = (SPS_PARAMS_SPS_MODE | d->dst_pipe_idx |
+				 MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
+	d->tx_req->udc_priv = sps_params;
+
+	/* queue in & out requests */
+	bam_data_start_endless_rx(port);
+	bam_data_start_endless_tx(port);
+
+	pr_info("Done\n");
+}
+
+static void bam2bam_data_port_free(int portno)
+{
+	kfree(bam2bam_data_ports[portno]);
+	bam2bam_data_ports[portno] = NULL;
+}
+
+static int bam2bam_data_port_alloc(int portno)
+{
+	struct bam_data_port	*port = NULL;
+	struct bam_data_ch_info	*d = NULL;
+
+	port = kzalloc(sizeof(struct bam_data_port), GFP_KERNEL);
+	if (!port)
+		return -ENOMEM;
+
+	port->port_num = portno;
+
+	INIT_WORK(&port->connect_w, bam2bam_data_connect_work);
+	INIT_WORK(&port->disconnect_w, bam2bam_data_disconnect_work);
+
+	/* data ch */
+	d = &port->data_ch;
+	d->port = port;
+	bam2bam_data_ports[portno] = port;
+
+	pr_info("port:%p portno:%d\n", port, portno);
+
+	return 0;
+}
+
+void bam_data_disconnect(struct data_port *gr, u8 port_num)
+{
+	struct bam_data_port	*port;
+	struct bam_data_ch_info	*d;
+
+	pr_info("dev:%p port#%d\n", gr, port_num);
+
+	if (port_num >= n_bam2bam_data_ports) {
+		pr_err("invalid bam2bam portno#%d\n", port_num);
+		return;
+	}
+
+	if (!gr) {
+		pr_err("mbim data port is null\n");
+		return;
+	}
+
+	port = bam2bam_data_ports[port_num];
+
+	d = &port->data_ch;
+	port->port_usb = gr;
+
+	queue_work(bam_data_wq, &port->disconnect_w);
+}
+
+int bam_data_connect(struct data_port *gr, u8 port_num,
+				 u8 connection_idx)
+{
+	struct bam_data_port	*port;
+	struct bam_data_ch_info	*d;
+	int			ret;
+
+	pr_info("dev:%p port#%d\n", gr, port_num);
+
+	if (port_num >= n_bam2bam_data_ports) {
+		pr_err("invalid portno#%d\n", port_num);
+		return -ENODEV;
+	}
+
+	if (!gr) {
+		pr_err("mbim data port is null\n");
+		return -ENODEV;
+	}
+
+	port = bam2bam_data_ports[port_num];
+
+	d = &port->data_ch;
+
+	ret = usb_ep_enable(gr->in);
+	if (ret) {
+		pr_err("usb_ep_enable failed eptype:IN ep:%p", gr->in);
+		return ret;
+	}
+	gr->in->driver_data = port;
+
+	ret = usb_ep_enable(gr->out);
+	if (ret) {
+		pr_err("usb_ep_enable failed eptype:OUT ep:%p", gr->out);
+		gr->in->driver_data = 0;
+		return ret;
+	}
+	gr->out->driver_data = port;
+
+	port->port_usb = gr;
+
+	d->connection_idx = connection_idx;
+
+	queue_work(bam_data_wq, &port->connect_w);
+
+	return 0;
+}
+
+int bam_data_setup(unsigned int no_bam2bam_port)
+{
+	int	i;
+	int	ret;
+
+	pr_info("requested %d BAM2BAM ports", no_bam2bam_port);
+
+	if (!no_bam2bam_port || no_bam2bam_port > BAM2BAM_DATA_N_PORTS) {
+		pr_err("Invalid num of ports count:%d\n", no_bam2bam_port);
+		return -EINVAL;
+	}
+
+	bam_data_wq = alloc_workqueue("k_bam_data",
+				      WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+	if (!bam_data_wq) {
+		pr_err("Failed to create workqueue\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < no_bam2bam_port; i++) {
+		n_bam2bam_data_ports++;
+		ret = bam2bam_data_port_alloc(i);
+		if (ret) {
+			n_bam2bam_data_ports--;
+			pr_err("Failed to alloc port:%d\n", i);
+			goto free_bam_ports;
+		}
+	}
+
+	return 0;
+
+free_bam_ports:
+	for (i = 0; i < n_bam2bam_data_ports; i++)
+		bam2bam_data_port_free(i);
+	destroy_workqueue(bam_data_wq);
+
+	return ret;
+}
+
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
index 930b4e9..c6f531e 100644
--- a/drivers/video/msm/mipi_NT35510.c
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -18,6 +18,7 @@
 static struct msm_panel_common_pdata *mipi_nt35510_pdata;
 static struct dsi_buf nt35510_tx_buf;
 static struct dsi_buf nt35510_rx_buf;
+spinlock_t bl_spinlock;
 
 #define NT35510_SLEEP_OFF_DELAY 150
 #define NT35510_DISPLAY_ON_DELAY 150
@@ -506,6 +507,8 @@
 
 	if (pdev->id == 0) {
 		mipi_nt35510_pdata = pdev->dev.platform_data;
+		if (mipi_nt35510_pdata->bl_lock)
+			spin_lock_init(&bl_spinlock);
 		return 0;
 	}
 
@@ -523,8 +526,16 @@
 
 static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
 {
-	/* Add backlight changes later*/
-	return;
+	int bl_level;
+	unsigned long flags;
+	bl_level = mfd->bl_level;
+
+	if (mipi_nt35510_pdata->bl_lock) {
+		spin_lock_irqsave(&bl_spinlock, flags);
+		mipi_nt35510_pdata->pmic_backlight(bl_level);
+		spin_unlock_irqrestore(&bl_spinlock, flags);
+	} else
+		mipi_nt35510_pdata->pmic_backlight(bl_level);
 }
 
 static struct msm_fb_panel_data nt35510_panel_data = {
@@ -564,7 +575,6 @@
 		return -ENOMEM;
 
 	nt35510_panel_data.panel_info = *pinfo;
-
 	ret = platform_device_add_data(pdev, &nt35510_panel_data,
 				sizeof(nt35510_panel_data));
 	if (ret) {
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
index 2c4ee3e..f052e93 100644
--- a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -56,7 +56,7 @@
 	pinfo.lcdc.border_clr = 0;	/* blk */
 	pinfo.lcdc.underflow_clr = 0xff;	/* blue */
 	pinfo.lcdc.hsync_skew = 0;
-	pinfo.bl_max = 100;
+	pinfo.bl_max = 31;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
index 82e03b2..4e97d99 100644
--- a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -59,7 +59,7 @@
 	delayed from VSYNC active edge */
 	pinfo.lcdc.hsync_skew = 0;
 	pinfo.clk_rate = 499000000;
-	pinfo.bl_max = 100; /*16; CHECK THIS!!!*/
+	pinfo.bl_max = 31;
 	pinfo.bl_min = 1;
 	pinfo.fb_num = 2;
 
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 672468e..8739122 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -164,6 +164,7 @@
 	int num_levels;
 	int (*set_grp_async)(void);
 	unsigned int idle_timeout;
+	bool strtstp_sleepwake;
 	unsigned int nap_allowed;
 	unsigned int clk_map;
 	unsigned int idle_needed;
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index 81a9279..2b39f69 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -53,6 +53,7 @@
 #define USB_CDC_DMM_TYPE		0x14
 #define USB_CDC_OBEX_TYPE		0x15
 #define USB_CDC_NCM_TYPE		0x1a
+#define USB_CDC_MBB_TYPE		0x1b	/* mbb_desc */
 
 /* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
 struct usb_cdc_header_desc {
@@ -187,6 +188,21 @@
 	__le16	bcdNcmVersion;
 	__u8	bmNetworkCapabilities;
 } __attribute__ ((packed));
+
+/* "MBIM Functional Descriptor" */
+struct usb_cdc_mbb_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__le16	bcdMbbVersion;
+	__le16	wMaxControlMessage;
+	__u8	bNumberFilters;
+	__u8	bMaxFilterSize;
+	__le16	wMaxSegmentSize;
+	__u8	bmNetworkCapabilities;
+} __packed;
+
 /*-------------------------------------------------------------------------*/
 
 /*
@@ -201,6 +217,7 @@
 
 #define USB_CDC_SEND_ENCAPSULATED_COMMAND	0x00
 #define USB_CDC_GET_ENCAPSULATED_RESPONSE	0x01
+#define USB_CDC_RESET_FUNCTION			0x05
 #define USB_CDC_REQ_SET_LINE_CODING		0x20
 #define USB_CDC_REQ_GET_LINE_CODING		0x21
 #define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index de2b356..dfad18d 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -44,7 +44,14 @@
 /* default data access */
 #define DEFAULT_DATA_OFFSET 2
 #define DEFAULT_DATA_SIZE 249
-
+/* Power levels are 0-7, but SOC will expect values from 0-255
+ * So the each level step size will be 255/7 = 36 */
+#define FM_TX_PWR_LVL_STEP_SIZE 36
+#define FM_TX_PWR_LVL_0         0 /* Lowest power lvl that can be set for Tx */
+#define FM_TX_PWR_LVL_MAX       7 /* Max power lvl for Tx */
+#define FM_TX_PHY_CFG_MODE   0x3c
+#define FM_TX_PHY_CFG_LEN    0x10
+#define FM_TX_PWR_GAIN_OFFSET 14
 /* HCI timeouts */
 #define RADIO_HCI_TIMEOUT	(10000)	/* 10 seconds */
 
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d5645ff..d49e215 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -209,6 +209,15 @@
 	MBHC_STATE_RELEASE,
 };
 
+struct hpf_work {
+	struct tabla_priv *tabla;
+	u32 decimator;
+	u8 tx_hpf_cut_of_freq;
+	struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
 struct tabla_priv {
 	struct snd_soc_codec *codec;
 	struct tabla_reg_address reg_addr;
@@ -2279,6 +2288,9 @@
 
 		break;
 	case SND_SOC_DAPM_POST_PMU:
+
+		usleep_range(20000, 20000);
+
 		if (tabla->mbhc_polling_active &&
 		    tabla->mbhc_cfg.micbias == micb_line) {
 			TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
@@ -2310,14 +2322,73 @@
 	return 0;
 }
 
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+	struct delayed_work *hpf_delayed_work;
+	struct hpf_work *hpf_work;
+	struct tabla_priv *tabla;
+	struct snd_soc_codec *codec;
+	u16 tx_mux_ctl_reg;
+	u8 hpf_cut_of_freq;
+
+	hpf_delayed_work = to_delayed_work(work);
+	hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+	tabla = hpf_work->tabla;
+	codec = hpf_work->tabla->codec;
+	hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+	tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL +
+			(hpf_work->decimator - 1) * 8;
+
+	pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
+		hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+	snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+#define  TX_MUX_CTL_CUT_OFF_FREQ_MASK	0x30
+#define  CF_MIN_3DB_4HZ			0x0
+#define  CF_MIN_3DB_75HZ		0x1
+#define  CF_MIN_3DB_150HZ		0x2
+
 static int tabla_codec_enable_dec(struct snd_soc_dapm_widget *w,
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
-	u16 dec_reset_reg;
+	unsigned int decimator;
+	char *dec_name = NULL;
+	char *widget_name = NULL;
+	char *temp;
+	int ret = 0;
+	u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+	u8 dec_hpf_cut_of_freq;
 
 	pr_debug("%s %d\n", __func__, event);
 
+	widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+	if (!widget_name)
+		return -ENOMEM;
+	temp = widget_name;
+
+	dec_name = strsep(&widget_name, " ");
+	widget_name = temp;
+	if (!dec_name) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+	if (ret < 0) {
+		pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+		ret =  -EINVAL;
+		goto out;
+	}
+
+	pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+			w->name, dec_name, decimator);
+
 	if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
 		dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
 	else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
@@ -2327,14 +2398,68 @@
 		return -EINVAL;
 	}
 
+	tx_vol_ctl_reg = TABLA_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator -1);
+	tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
+
+		// Enableable TX digital mute */
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
 		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
 			1 << w->shift);
 		snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+		dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+
+		dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+		tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+			dec_hpf_cut_of_freq;
+
+		if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+
+			/* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+			snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+					    CF_MIN_3DB_150HZ << 4);
+		}
+
+		/* enable HPF */
+		snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
+
+		break;
+
+	case SND_SOC_DAPM_POST_PMU:
+
+		/* Disable TX digital mute */
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+		if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+				CF_MIN_3DB_150HZ) {
+
+			schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+					msecs_to_jiffies(300));
+		}
+		break;
+
+	case SND_SOC_DAPM_PRE_PMD:
+
+		snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+		cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+		break;
+
+	case SND_SOC_DAPM_POST_PMD:
+
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+		snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+			(tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+
 		break;
 	}
-	return 0;
+out:
+	kfree(widget_name);
+	return ret;
 }
 
 static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
@@ -3858,34 +3983,54 @@
 		tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
 
 	SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
-		&dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec1_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
-		&dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec2_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
-		&dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec3_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
-		&dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec4_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
-		&dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec5_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
-		&dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec6_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
-		&dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec7_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
-		&dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec8_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
-		&dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec9_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
-		&dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+		&dec10_mux, tabla_codec_enable_dec,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
 	SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
@@ -6470,6 +6615,12 @@
 		dev_err(codec->dev, "Failed to allocate private data\n");
 		return -ENOMEM;
 	}
+	for (i = 0 ; i < NUM_DECIMATORS; i++) {
+		tx_hpf_work[i].tabla = tabla;
+		tx_hpf_work[i].decimator = i + 1;
+		INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+			tx_hpf_corner_freq_callback);
+	}
 
 	/* Make sure mbhc micbias register addresses are zeroed out */
 	memset(&tabla->mbhc_bias_regs, 0,
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index 6408cef..f814a21 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -197,6 +197,12 @@
 	} req;
 
 	snd_rpc_ids.device = (int)ucontrol->value.integer.value[0];
+
+	if (ucontrol->value.integer.value[1] > 1)
+		ucontrol->value.integer.value[1] = 1;
+	if (ucontrol->value.integer.value[2] > 1)
+		ucontrol->value.integer.value[2] = 1;
+
 	req.hdr.type = 0;
 	req.hdr.rpc_vers = 2;
 
@@ -221,6 +227,8 @@
 		printk(KERN_INFO "snd device connected\n");
 		snd_mute_ear_mute = ucontrol->value.integer.value[1];
 		snd_mute_mic_mute = ucontrol->value.integer.value[2];
+		printk(KERN_ERR "%s: snd_mute_ear_mute =%d, snd_mute_mic_mute = %d\n",
+				__func__, snd_mute_ear_mute, snd_mute_mic_mute);
 	}
 
 	return rc;
@@ -251,7 +259,7 @@
 static struct snd_kcontrol_new snd_msm_controls[] = {
 	MSM_EXT_TLV("PCM Playback Volume", 0, snd_msm_volume_info, \
 	snd_msm_volume_get, snd_msm_volume_put, 0, db_scale_linear),
-	MSM_EXT("device", 1, snd_msm_device_info, snd_msm_device_get, \
+	MSM_EXT("device", 0, snd_msm_device_info, snd_msm_device_get, \
 						 snd_msm_device_put, 0),
 };
 
@@ -331,6 +339,8 @@
 	}
 
 	ret = msm_snd_rpc_connect();
+	snd_mute_ear_mute = 0;
+	snd_mute_mic_mute = 0;
 
 	return ret;
 }
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 3063f3e..265df9e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -60,6 +60,7 @@
 	[snd_soc_dapm_pre] = 0,
 	[snd_soc_dapm_supply] = 1,
 	[snd_soc_dapm_micbias] = 2,
+	[snd_soc_dapm_adc] = 3,
 	[snd_soc_dapm_mic] = 4,
 	[snd_soc_dapm_mux] = 5,
 	[snd_soc_dapm_virt_mux] = 5,
@@ -70,7 +71,6 @@
 	[snd_soc_dapm_pga] = 8,
 	[snd_soc_dapm_aif_in] = 8,
 	[snd_soc_dapm_aif_out] = 8,
-	[snd_soc_dapm_adc] = 9,
 	[snd_soc_dapm_out_drv] = 10,
 	[snd_soc_dapm_hp] = 10,
 	[snd_soc_dapm_spk] = 10,