Merge "video: msm: Load correct default values to QSEED at init" into msm-3.0
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index cc94b69..3ee63c0 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -15,19 +15,21 @@
 KERNEL_USE_OF ?= $(shell $(PERL) -e '$$of = "n"; while (<>) { if (/CONFIG_USE_OF=y/) { $$of = "y"; break; } } print $$of;' kernel/arch/arm/configs/$(KERNEL_DEFCONFIG))
 
 ifeq "$(KERNEL_USE_OF)" "y"
+DTS_NAME ?= $(MSM_ARCH)
+DTS_FILES = $(wildcard $(TOP)/kernel/arch/arm/boot/dts/$(DTS_NAME)*.dts)
+DTS_FILE = $(lastword $(subst /, ,$(1)))
+DTB_FILE = $(addprefix $(KERNEL_OUT)/arch/arm/boot/,$(patsubst %.dts,%.dtb,$(call DTS_FILE,$(1))))
+ZIMG_FILE = $(addprefix $(KERNEL_OUT)/arch/arm/boot/,$(patsubst %.dts,%-zImage,$(call DTS_FILE,$(1))))
 KERNEL_ZIMG = $(KERNEL_OUT)/arch/arm/boot/zImage
-DTB_FILE = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH).dtb
-DTS_FILE = $(TOP)/kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
-FULL_KERNEL = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH)-zImage
 DTC = $(KERNEL_OUT)/scripts/dtc/dtc
 
 define append-dtb
-md $(KERNEL_OUT)/arch/arm/boot;\
-$(DTC) -p 1024 -O dtb -o $(DTB_FILE) $(DTS_FILE);\
-cat $(KERNEL_ZIMG) $(DTB_FILE) > $(FULL_KERNEL)
+mkdir -p $(KERNEL_OUT)/arch/arm/boot;\
+$(foreach d, $(DTS_FILES), \
+   $(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \
+   cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));)
 endef
 else
-FULL_KERNEL = $(KERNEL_IMG)
 
 define append-dtb
 endef
diff --git a/arch/arm/boot/dts/msmcopper-rumi.dts b/arch/arm/boot/dts/msmcopper-rumi.dts
new file mode 100644
index 0000000..bb53ff8
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-rumi.dts
@@ -0,0 +1,60 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msmcopper.dtsi"
+
+/ {
+	model = "Qualcomm MSM Copper RUMI";
+	compatible = "qcom,msmcopper-rumi", "qcom,msmcopper";
+
+	timer {
+		clock-frequency = <5000000>;
+	};
+
+	serial@f991f000 {
+		status = "disable";
+	};
+
+	usb@f9a55000 {
+		status = "disable";
+	};
+
+	qcom,sdcc@f980b000 {
+		status = "disable";
+	};
+
+	qcom,sdcc@f984b000 {
+		status = "disable";
+	};
+
+	qcom,sps@f998000 {
+		status = "disable";
+	};
+
+	spi@f9924000 {
+		status = "disable";
+	};
+
+	slim@fe12f000 {
+		status = "disable";
+	};
+
+	qcom,spmi@fc4c0000 {
+		status = "disable";
+	};
+
+	i2c@f9966000 {
+		status = "disable";
+	};
+};
diff --git a/arch/arm/boot/dts/msmcopper-sim.dts b/arch/arm/boot/dts/msmcopper-sim.dts
new file mode 100644
index 0000000..ab6b8ba
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-sim.dts
@@ -0,0 +1,20 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msmcopper.dtsi"
+
+/ {
+	model = "Qualcomm MSM Copper Simulator";
+	compatible = "qcom,msmcopper-sim", "qcom,msmcopper";
+};
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dtsi
similarity index 89%
rename from arch/arm/boot/dts/msmcopper.dts
rename to arch/arm/boot/dts/msmcopper.dtsi
index 8c8cc12..4aa05e0 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -1,10 +1,20 @@
-/dts-v1/;
+/* 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/ "skeleton.dtsi"
 
 / {
 	model = "Qualcomm MSM Copper";
-	compatible = "qcom,msmcopper-sim", "qcom,msmcopper";
+	compatible = "qcom,msmcopper";
 	interrupt-parent = <&intc>;
 
 	intc: interrupt-controller@F9000000 {
@@ -34,6 +44,12 @@
 		interrupts = <0 109 0>;
 	};
 
+	serial@f995e000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf995e000 0x1000>;
+		interrupts = <0 114 0>;
+	};
+
 	usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
 		reg = <0xf9a55000 0x400>;
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 8594562..c6e314e 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -146,6 +146,8 @@
 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/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 3384b48..2bc922a 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -53,6 +53,7 @@
 CONFIG_MACH_APQ8064_CDP=y
 CONFIG_MACH_APQ8064_MTP=y
 CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_CDP=y
 CONFIG_MACH_MPQ8064_HRD=y
 CONFIG_MACH_MPQ8064_DTV=y
 # CONFIG_MSM_STACKED_MEMORY is not set
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index c186be4..706bc88 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -52,6 +52,7 @@
 CONFIG_MACH_APQ8064_CDP=y
 CONFIG_MACH_APQ8064_MTP=y
 CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_CDP=y
 CONFIG_MACH_MPQ8064_HRD=y
 CONFIG_MACH_MPQ8064_DTV=y
 # CONFIG_MSM_STACKED_MEMORY is not set
@@ -94,6 +95,7 @@
 CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_MSM_CACHE_DUMP=y
+CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
 CONFIG_STRICT_MEMORY_RWX=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index f5193da..f085d77 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -231,7 +231,8 @@
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_CI13XXX_MSM=m
+CONFIG_USB_CI13XXX_MSM_HSIC=m
 CONFIG_USB_G_ANDROID=y
 CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
 CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5bb5139..5668e75 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -50,8 +50,11 @@
 void gic_enable_ppi(unsigned int);
 bool gic_is_spi_pending(unsigned int irq);
 void gic_clear_spi_pending(unsigned int irq);
+#ifdef CONFIG_ARM_GIC
 void gic_set_irq_secure(unsigned int irq);
-
+#else
+static inline void gic_set_irq_secure(unsigned int irq) { }
+#endif
 static inline void gic_init(unsigned int nr, int start,
 			    void __iomem *dist , void __iomem *cpu)
 {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 2e37431..0202746 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -265,6 +265,7 @@
 	select MSM_XO
 	select MSM_QDSP6_APR
 	select MSM_AUDIO_QDSP6 if SND_SOC
+	select FIQ
 
 config ARCH_MSM8625
 	bool "MSM8625"
@@ -780,6 +781,12 @@
 	help
 	  Support for the Qualcomm APQ8064 LIQUID device.
 
+config MACH_MPQ8064_CDP
+	depends on ARCH_APQ8064
+	bool "MPQ8064 CDP"
+	help
+	  Support for the Qualcomm MPQ8064 CDP device.
+
 config MACH_MPQ8064_HRD
 	depends on ARCH_APQ8064
 	bool "MPQ8064 HRD"
@@ -2229,4 +2236,13 @@
 	  This allows for analysis of the caches in case cache corruption is
 	  suspected.
 
+config MSM_CACHE_DUMP_ON_PANIC
+	bool "Dump caches on panic"
+	depends on MSM_CACHE_DUMP
+	help
+	  By default, the caches are flushed on panic. This means that trying to
+	  look at them in a RAM dump will give useless data. Select this if you
+	  want to dump the L1 and L2 caches on panic before any flush occurs.
+	  If unsure, say N
+
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4c40e3c..f331c4e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -204,6 +204,7 @@
 obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o xo-fsm9xxx.o
 
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
+obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog_asm.o
 obj-$(CONFIG_MACH_MSM8X60_RUMI3) += board-msm8x60.o
 obj-$(CONFIG_MACH_MSM8X60_SIM) += board-msm8x60.o
 obj-$(CONFIG_MACH_MSM8X60_SURF) += board-msm8x60.o
@@ -258,7 +259,7 @@
 obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o
 obj-$(CONFIG_MACH_APQ8064_SIM) += board-8064-all.o board-8064-regulator.o
 obj-$(CONFIG_MACH_APQ8064_RUMI3) += board-8064-all.o board-8064-regulator.o
-obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o
+obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
 obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o
 
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 4dac062..89d7fc9 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -2036,6 +2036,7 @@
 		goto register_bam_failed;
 	}
 	a2_device_handle = h;
+	toggle_apps_ack();
 
 	return 0;
 
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 2708283..0ff931a 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -16,10 +16,36 @@
 #include <linux/msm_kgsl.h>
 #include <mach/msm_bus_board.h>
 #include <mach/board.h>
+#include <mach/msm_dcvs.h>
 
 #include "devices.h"
 #include "board-8064.h"
 
+#ifdef CONFIG_MSM_DCVS
+static struct msm_dcvs_freq_entry grp3d_freq[] = {
+	{0, 0, 333932},
+	{0, 0, 497532},
+	{0, 0, 707610},
+	{0, 0, 844545},
+};
+
+static struct msm_dcvs_core_info grp3d_core_info = {
+	.freq_tbl = &grp3d_freq[0],
+	.core_param = {
+		.max_time_us = 100000,
+		.num_freq = ARRAY_SIZE(grp3d_freq),
+	},
+	.algo_param = {
+		.slack_time_us = 39000,
+		.disable_pc_threshold = 86000,
+		.ss_window_size = 1000000,
+		.ss_util_pct = 95,
+		.em_max_util_pct = 97,
+		.ss_iobusy_conv = 100,
+	},
+};
+#endif /* CONFIG_MSM_DCVS */
+
 #ifdef CONFIG_MSM_BUS_SCALING
 static struct msm_bus_vectors grp3d_init_vectors[] = {
 	{
@@ -180,6 +206,9 @@
 #endif
 	.iommu_data = kgsl_3d0_iommu_data,
 	.iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
+#ifdef CONFIG_MSM_DCVS
+	.core_info = &grp3d_core_info,
+#endif
 };
 
 struct platform_device device_kgsl_3d0 = {
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 5a6db27..73f02f5 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1868,6 +1868,11 @@
 	&apq8064_msm_gov_device,
 	&apq8064_device_cache_erp,
 	&epm_adc_device,
+	&apq8064_qdss_device,
+	&msm_etb_device,
+	&msm_tpiu_device,
+	&msm_funnel_device,
+	&apq8064_etm_device,
 };
 
 static struct platform_device *sim_devices[] __initdata = {
@@ -2365,6 +2370,17 @@
 	.init_very_early = apq8064_early_reserve,
 MACHINE_END
 
+MACHINE_START(MPQ8064_CDP, "QCT MPQ8064 CDP")
+	.map_io = apq8064_map_io,
+	.reserve = apq8064_reserve,
+	.init_irq = apq8064_init_irq,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_timer,
+	.init_machine = apq8064_cdp_init,
+	.init_early = apq8064_allocate_memory_regions,
+	.init_very_early = apq8064_early_reserve,
+MACHINE_END
+
 MACHINE_START(MPQ8064_HRD, "QCT MPQ8064 HRD")
 	.map_io = apq8064_map_io,
 	.reserve = apq8064_reserve,
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index cd201ef..854f318 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -171,26 +171,6 @@
 	},
 };
 #endif
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct gpiomux_setting hsic_act_cfg = {
-	.func = GPIOMUX_FUNC_1,
-	.drv = GPIOMUX_DRV_12MA,
-	.pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting hsic_sus_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting hsic_hub_act_cfg = {
-	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_2MA,
-	.pull = GPIOMUX_PULL_NONE,
-};
-#endif
 
 static struct gpiomux_setting hap_lvl_shft_suspended_config = {
 	.func = GPIOMUX_FUNC_GPIO,
@@ -487,32 +467,6 @@
 	},
 };
 
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct msm_gpiomux_config msm8960_hsic_configs[] = {
-	{
-		.gpio = 150,               /*HSIC_STROBE */
-		.settings = {
-			[GPIOMUX_ACTIVE] = &hsic_act_cfg,
-			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
-		},
-	},
-	{
-		.gpio = 151,               /* HSIC_DATA */
-		.settings = {
-			[GPIOMUX_ACTIVE] = &hsic_act_cfg,
-			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
-		},
-	},
-	{
-		.gpio = 91,               /* HSIC_HUB_RESET */
-		.settings = {
-			[GPIOMUX_ACTIVE] = &hsic_hub_act_cfg,
-			[GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
-		},
-	},
-};
-#endif
-
 static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
 	{
 		.gpio = 47,
@@ -689,14 +643,6 @@
 		msm_gpiomux_install(msm8930_haptics_configs,
 			ARRAY_SIZE(msm8930_haptics_configs));
 
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-	if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) &&
-			!machine_is_msm8930_mtp() &&
-			!machine_is_msm8930_fluid())
-		msm_gpiomux_install(msm8960_hsic_configs,
-			ARRAY_SIZE(msm8960_hsic_configs));
-#endif
-
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
 	msm_gpiomux_install(msm8960_hdmi_configs,
 			ARRAY_SIZE(msm8960_hdmi_configs));
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index c713567..5493628 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1024,16 +1024,6 @@
 };
 #endif
 
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-#define HSIC_HUB_RESET_GPIO	91
-static struct msm_hsic_host_platform_data msm_hsic_pdata = {
-	.strobe		= 150,
-	.data		= 151,
-};
-#else
-static struct msm_hsic_host_platform_data msm_hsic_pdata;
-#endif
-
 #define PID_MAGIC_ID		0x71432909
 #define SERIAL_NUM_MAGIC_ID	0x61945374
 #define SERIAL_NUMBER_LENGTH	127
@@ -1693,6 +1683,7 @@
 	&msm_device_tz_log,
 
 #ifdef CONFIG_MSM_QDSS
+	&msm_qdss_device,
 	&msm_etb_device,
 	&msm_tpiu_device,
 	&msm_funnel_device,
@@ -1941,24 +1932,6 @@
 	int                    len;
 };
 
-static void __init msm8930_init_hsic(void)
-{
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-	uint32_t version = socinfo_get_version();
-
-	pr_info("%s: version:%d mtp:%d\n", __func__,
-			SOCINFO_VERSION_MAJOR(version),
-			machine_is_msm8930_mtp());
-
-	if ((SOCINFO_VERSION_MAJOR(version) == 1) ||
-			machine_is_msm8930_mtp() ||
-			machine_is_msm8930_fluid())
-		return;
-
-	platform_device_register(&msm_device_hsic_host);
-#endif
-}
-
 #ifdef CONFIG_ISL9519_CHARGER
 static struct isl_platform_data isl_data __initdata = {
 	.valid_n_gpio		= 0,	/* Not required when notify-by-pmic */
@@ -2058,7 +2031,6 @@
 	platform_device_register(&msm8930_device_rpm_regulator);
 	msm_clock_init(&msm8930_clock_init_data);
 	msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
-	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
 	msm8930_init_gpiomux();
 	msm8960_device_qup_spi_gsbi1.dev.platform_data =
 				&msm8960_qup_spi_gsbi1_pdata;
@@ -2094,7 +2066,6 @@
 	msm8930_pm8038_gpio_mpp_init();
 #endif
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
-	msm8930_init_hsic();
 	msm8930_init_cam();
 	msm8930_init_mmc();
 	acpuclk_init(&acpuclk_8930_soc_data);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 70a65d0..3f0d8df 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -612,6 +612,7 @@
 #ifdef CONFIG_MSM_CACHE_DUMP
 	unsigned int spare;
 	unsigned int l1_size;
+	unsigned int l2_size;
 	unsigned int total;
 	int ret;
 
@@ -622,10 +623,18 @@
 		/* Fall back to something reasonable here */
 		l1_size = L1_BUFFER_SIZE;
 
-	total = l1_size + L2_BUFFER_SIZE;
+	ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_GET_SIZE_COMMAND_ID, &spare,
+		sizeof(spare), &l2_size, sizeof(l2_size));
+
+	if (ret)
+		/* Fall back to something reasonable here */
+		l2_size = L2_BUFFER_SIZE;
+
+	total = l1_size + l2_size;
 
 	msm8960_reserve_table[MEMTYPE_EBI1].size += total;
 	msm_cache_dump_pdata.l1_size = l1_size;
+	msm_cache_dump_pdata.l2_size = l2_size;
 #endif
 }
 
@@ -2241,6 +2250,7 @@
 	&msm8960_rpm_stat_device,
 	&msm_device_tz_log,
 #ifdef CONFIG_MSM_QDSS
+	&msm_qdss_device,
 	&msm_etb_device,
 	&msm_tpiu_device,
 	&msm_funnel_device,
diff --git a/arch/arm/mach-msm/board-9615-display.c b/arch/arm/mach-msm/board-9615-display.c
new file mode 100644
index 0000000..74bc984
--- /dev/null
+++ b/arch/arm/mach-msm/board-9615-display.c
@@ -0,0 +1,169 @@
+/* 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/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <linux/ion.h>
+#include <asm/mach-types.h>
+#include <mach/msm_memtypes.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/ion.h>
+#include <mach/msm_bus_board.h>
+
+#include "devices.h"
+#include "board-9615.h"
+
+/* prim = 240 x 320 x 4(bpp) x 2(pages) */
+#define MSM_FB_PRIM_BUF_SIZE roundup(240 * 320 * 4 * 2, 0x10000)
+#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE, 4096)
+
+#define GPIO_PIN_EBI2_LCD_A_D	21
+#define GPIO_PIN_EBI2_LCD_CS	22
+#define GPIO_PIN_EBI2_LCD_RS	24
+
+
+#ifdef CONFIG_FB_MSM
+
+static struct resource msm_fb_resources[] = {
+	{
+		.flags = IORESOURCE_MEM,
+	}
+};
+
+static int msm_fb_detect_panel(const char *name)
+{
+	return 0;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+	.detect_client = msm_fb_detect_panel,
+};
+
+static struct platform_device msm_fb_device = {
+	.name              = "msm_fb",
+	.id                = 0,
+	.num_resources     = ARRAY_SIZE(msm_fb_resources),
+	.resource          = msm_fb_resources,
+	.dev.platform_data = &msm_fb_pdata,
+};
+
+void __init mdm9615_allocate_fb_region(void)
+{
+	void *addr;
+	unsigned long size;
+
+	size = MSM_FB_SIZE;
+	addr = alloc_bootmem_align(size, 0x1000);
+	msm_fb_resources[0].start = __pa(addr);
+	msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+	pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
+			size, addr, __pa(addr));
+}
+
+
+static bool ebi2_power_init;
+static int ebi2_panel_power(int on)
+{
+	static struct regulator *panel_power;
+	int rc;
+
+	pr_debug("%s: on=%d\n", __func__, on);
+
+	if (!ebi2_power_init) {
+		panel_power = regulator_get(&msm_ebi2_lcdc_device.dev,
+				"VDDI2");
+		if (IS_ERR_OR_NULL(panel_power)) {
+			pr_err("could not get L14, rc = %ld\n",
+				PTR_ERR(panel_power));
+			return -ENODEV;
+		}
+
+		rc = regulator_set_voltage(panel_power, 2800000, 3800000);
+		if (rc) {
+			pr_err("set_voltage L14 failed, rc=%d\n", rc);
+			return -EINVAL;
+		}
+
+		ebi2_power_init = true;
+	}
+
+	if (on) {
+		rc = regulator_enable(panel_power);
+		if (rc) {
+			pr_err("enable L14 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+		rc = gpio_request(GPIO_PIN_EBI2_LCD_A_D, "disp_a_d");
+		if (rc) {
+			pr_err("request gpio EBI2_LCD_A_D failed, rc=%d\n", rc);
+			goto error1;
+		}
+		rc = gpio_request(GPIO_PIN_EBI2_LCD_CS, "disp_cs");
+		if (rc) {
+			pr_err("request gpio EBI2_LCD_CS failed, rc=%d\n", rc);
+			goto error2;
+		}
+		rc = gpio_request(GPIO_PIN_EBI2_LCD_RS, "disp_rs");
+		if (rc) {
+			pr_err("request gpio EBI2_LCD_RS failed, rc=%d\n", rc);
+			goto error3;
+		}
+	} else {
+		gpio_free(GPIO_PIN_EBI2_LCD_RS);
+		gpio_free(GPIO_PIN_EBI2_LCD_CS);
+		gpio_free(GPIO_PIN_EBI2_LCD_A_D);
+
+		rc = regulator_disable(panel_power);
+		if (rc) {
+			pr_err("disable L14 failed, rc=%d\n", rc);
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+error3:
+	gpio_free(GPIO_PIN_EBI2_LCD_CS);
+error2:
+	gpio_free(GPIO_PIN_EBI2_LCD_A_D);
+error1:
+	regulator_disable(panel_power);
+	return rc;
+
+}
+
+static struct lcdc_platform_data ebi2_lcdc_pdata = {
+	.lcdc_power_save = ebi2_panel_power,
+};
+
+static struct lvds_panel_platform_data ebi2_epson_s1d_pdata;
+
+static struct platform_device ebi2_epson_s1d_panel_device = {
+	.name = "ebi2_epson_s1d_qvga",
+	.id = 0,
+	.dev = {
+		.platform_data = &ebi2_epson_s1d_pdata,
+	}
+};
+
+void __init mdm9615_init_fb(void)
+{
+	platform_device_register(&msm_fb_device);
+	platform_device_register(&ebi2_epson_s1d_panel_device);
+
+	msm_fb_register_device("ebi2_lcd", &ebi2_lcdc_pdata);
+}
+#endif
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index e61f001..0e18918 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -85,6 +85,26 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+#ifdef CONFIG_FB_MSM_EBI2
+static struct gpiomux_setting ebi2_lcdc_a_d = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_12MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ebi2_lcdc_cs = {
+	.func = GPIOMUX_FUNC_2,
+	.drv = GPIOMUX_DRV_12MA,
+	.pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ebi2_lcdc_rs = {
+	.func = GPIOMUX_FUNC_3,
+	.drv = GPIOMUX_DRV_12MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+#endif
+
 static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
 	{
 		.gpio = 24,
@@ -263,6 +283,29 @@
 	},
 };
 
+#ifdef CONFIG_FB_MSM_EBI2
+static struct msm_gpiomux_config msm9615_ebi2_lcdc_configs[] __initdata = {
+	{
+		.gpio      = 21,	/* a_d */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ebi2_lcdc_a_d,
+		},
+	},
+	{
+		.gpio      = 22,	/* cs */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ebi2_lcdc_cs,
+		},
+	},
+	{
+		.gpio      = 24,	/* rs */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &ebi2_lcdc_rs,
+		},
+	},
+};
+#endif
+
 int __init msm9615_init_gpiomux(void)
 {
 	int rc;
@@ -289,5 +332,10 @@
 	msm_gpiomux_install(msm9615_audio_codec_configs,
 			ARRAY_SIZE(msm9615_audio_codec_configs));
 
+#ifdef CONFIG_FB_MSM_EBI2
+	msm_gpiomux_install(msm9615_ebi2_lcdc_configs,
+			ARRAY_SIZE(msm9615_ebi2_lcdc_configs));
+#endif
+
 	return 0;
 }
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index dd83d6f..8328501 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -65,6 +65,7 @@
 };
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8018_l14",		NULL),
+	REGULATOR_SUPPLY("VDDI2",		"ebi2_lcd.0"),
 };
 VREG_CONSUMERS(S1) = {
 	REGULATOR_SUPPLY("8018_s1",		NULL),
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 77ee09f..e0bfc16 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -722,6 +722,9 @@
 static void __init msm9615_cdp_init(void)
 {
 	msm9615_common_init();
+#ifdef CONFIG_FB_MSM
+	mdm9615_init_fb();
+#endif
 }
 
 static void __init msm9615_mtp_init(void)
@@ -729,6 +732,13 @@
 	msm9615_common_init();
 }
 
+#ifdef CONFIG_FB_MSM
+static void __init mdm9615_allocate_memory_regions(void)
+{
+	mdm9615_allocate_fb_region();
+}
+#endif
+
 MACHINE_START(MSM9615_CDP, "QCT MSM9615 CDP")
 	.map_io = msm9615_map_io,
 	.init_irq = msm9615_init_irq,
@@ -736,6 +746,9 @@
 	.timer = &msm_timer,
 	.init_machine = msm9615_cdp_init,
 	.reserve = msm9615_reserve,
+#ifdef CONFIG_FB_MSM
+	.init_early = mdm9615_allocate_memory_regions,
+#endif
 MACHINE_END
 
 MACHINE_START(MSM9615_MTP, "QCT MSM9615 MTP")
diff --git a/arch/arm/mach-msm/board-9615.h b/arch/arm/mach-msm/board-9615.h
index 27f5d81..239453f 100644
--- a/arch/arm/mach-msm/board-9615.h
+++ b/arch/arm/mach-msm/board-9615.h
@@ -40,4 +40,6 @@
 
 int msm9615_init_gpiomux(void);
 void msm9615_init_mmc(void);
+void mdm9615_allocate_fb_region(void);
+void mdm9615_init_fb(void);
 #endif
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index fcbf2a6..81abbc0 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -20,6 +20,7 @@
 #include <asm/gpio.h>
 #include <asm/mach-types.h>
 #include <mach/rpc_pmapp.h>
+#include <mach/socinfo.h>
 
 #include "board-msm7627a.h"
 #include "devices-msm7x2xa.h"
@@ -98,12 +99,19 @@
 int gpio_bt_sys_rest_en = 133;
 static void gpio_bt_config(void)
 {
+	u32 socinfo = socinfo_get_platform_version();
 	if (machine_is_msm7627a_qrd1())
 		gpio_bt_sys_rest_en = 114;
 	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		gpio_bt_sys_rest_en = 16;
 	if (machine_is_msm8625_qrd7())
 		gpio_bt_sys_rest_en = 88;
+	if (machine_is_msm7627a_qrd3()) {
+		if (socinfo == 0x70002)
+			gpio_bt_sys_rest_en = 88;
+		 else
+			gpio_bt_sys_rest_en = 85;
+	}
 }
 
 static int bt_set_gpio(int on)
@@ -962,8 +970,6 @@
 	int i, rc = 0;
 	struct device *dev;
 
-	if (machine_is_msm7627a_qrd3())
-		return;
 
 	gpio_bt_config();
 
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 757c166..8a2f53a 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -142,7 +142,7 @@
 };
 
 static struct gpio_event_platform_data kp_pdata_8625 = {
-	.name           = "8625_kp",
+	.name           = "7x27a_kp",
 	.info           = kp_info_8625,
 	.info_count     = ARRAY_SIZE(kp_info_8625)
 };
@@ -612,6 +612,47 @@
 				ARRAY_SIZE(ft5x06_device_info));
 }
 
+/* SKU3/SKU7 keypad device information */
+#define KP_INDEX_SKU3(row, col) ((row)*ARRAY_SIZE(kp_col_gpios_sku3) + (col))
+static unsigned int kp_row_gpios_sku3[] = {31, 32};
+static unsigned int kp_col_gpios_sku3[] = {36, 37};
+
+static const unsigned short keymap_sku3[] = {
+	[KP_INDEX_SKU3(0, 0)] = KEY_VOLUMEUP,
+	[KP_INDEX_SKU3(0, 1)] = KEY_VOLUMEDOWN,
+	[KP_INDEX_SKU3(1, 1)] = KEY_CAMERA,
+};
+
+static struct gpio_event_matrix_info kp_matrix_info_sku3 = {
+	.info.func      = gpio_event_matrix_func,
+	.keymap         = keymap_sku3,
+	.output_gpios   = kp_row_gpios_sku3,
+	.input_gpios    = kp_col_gpios_sku3,
+	.noutputs       = ARRAY_SIZE(kp_row_gpios_sku3),
+	.ninputs        = ARRAY_SIZE(kp_col_gpios_sku3),
+	.settle_time.tv_nsec = 40 * NSEC_PER_USEC,
+	.poll_time.tv_nsec = 20 * NSEC_PER_MSEC,
+	.flags          = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
+				GPIOKPF_PRINT_UNMAPPED_KEYS,
+};
+
+static struct gpio_event_info *kp_info_sku3[] = {
+	&kp_matrix_info_sku3.info,
+};
+static struct gpio_event_platform_data kp_pdata_sku3 = {
+	.name           = "7x27a_kp",
+	.info           = kp_info_sku3,
+	.info_count     = ARRAY_SIZE(kp_info_sku3)
+};
+
+static struct platform_device kp_pdev_sku3 = {
+	.name   = GPIO_EVENT_DEV_NAME,
+	.id     = -1,
+	.dev    = {
+		.platform_data  = &kp_pdata_sku3,
+	},
+};
+
 void __init msm7627a_add_io_devices(void)
 {
 	/* touchscreen */
@@ -689,6 +730,8 @@
 	/* keypad */
 	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
 		platform_device_register(&kp_pdev_8625);
+	else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())
+		platform_device_register(&kp_pdev_sku3);
 
 	/* leds */
 	if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index e4ee52e..564c59d 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -151,7 +151,9 @@
 static void gpio_sdc1_config(void)
 {
 	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
-					|| machine_is_msm8625_evb())
+					|| machine_is_msm8625_evb()
+					|| machine_is_msm7627a_qrd3()
+					|| machine_is_msm8625_qrd7())
 		gpio_sdc1_hw_det = 42;
 }
 
@@ -253,7 +255,9 @@
 		if (!status) {
 			if (machine_is_msm7627a_qrd1() ||
 					machine_is_msm7627a_evb() ||
-					machine_is_msm8625_evb())
+					machine_is_msm8625_evb()  ||
+					machine_is_msm7627a_qrd3() ||
+					machine_is_msm8625_qrd7())
 				status = !gpio_get_value(gpio_sdc1_hw_det);
 			else
 				status = gpio_get_value(gpio_sdc1_hw_det);
@@ -367,11 +371,15 @@
 {
 	/* eMMC slot */
 #ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
-	if (mmc_regulator_init(3, "emmc", 3000000))
-		return;
-	sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
+
+	/* There is no eMMC on SDC3 for QRD3 based devices */
+	if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
+		if (mmc_regulator_init(3, "emmc", 3000000))
+			return;
+		sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
 			MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
-	msm_add_sdcc(3, &sdc3_plat_data);
+		msm_add_sdcc(3, &sdc3_plat_data);
+	}
 #endif
 	/* Micro-SD slot */
 #ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
@@ -392,9 +400,12 @@
 	/* Not Used */
 #if (defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\
 		&& !defined(CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT))
-	if (mmc_regulator_init(4, "smps3", 1800000))
-		return;
-	msm_add_sdcc(4, &sdc4_plat_data);
+	/* There is no SDC4 for QRD3/7 based devices */
+	if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
+		if (mmc_regulator_init(4, "smps3", 1800000))
+			return;
+		msm_add_sdcc(4, &sdc4_plat_data);
+	}
 #endif
 }
 #endif
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 53d3c56..b72ecd4 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -49,7 +49,9 @@
 static void gpio_wlan_config(void)
 {
 	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
-					|| machine_is_msm8625_evb())
+					|| machine_is_msm8625_evb()
+					|| machine_is_msm7627a_qrd3()
+					|| machine_is_msm8625_qrd7())
 		gpio_wlan_sys_rest_en = 124;
 }
 
@@ -231,7 +233,9 @@
 	 * EVB1.0 and QRD8625,so the below step is required for those devices.
 	 */
 	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
-					|| machine_is_msm8625_evb()) {
+					|| machine_is_msm8625_evb()
+					|| machine_is_msm7627a_qrd3()
+					|| machine_is_msm8625_qrd7()) {
 		rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
 					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
 					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
@@ -305,7 +309,9 @@
 	 * EVB1.0 and QRD8625,so the below step is required for those devices.
 	 */
 	if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
-					|| machine_is_msm8625_evb()) {
+					|| machine_is_msm8625_evb()
+					|| machine_is_msm7627a_qrd3()
+					|| machine_is_msm8625_qrd7()) {
 		rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
 					GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
 					GPIO_CFG_2MA), GPIO_CFG_ENABLE);
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index 48848d5..e3c9469 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -22,7 +22,7 @@
 void __init msm_fb_add_devices(void);
 
 #define PMEM_KERNEL_EBI1_SIZE	0x3A000
-#define MSM_PMEM_AUDIO_SIZE	0x5B000
+#define MSM_PMEM_AUDIO_SIZE	0x1F4000
 
 #define MSM_PMEM_MDP_SIZE		0x2300000
 #define MSM_PMEM_ADSP_SIZE		0x1100000
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 44138a5e..b203c29 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -809,6 +809,8 @@
 	msm7627a_add_io_devices();
 	/*7x25a kgsl initializations*/
 	msm7x25a_kgsl_3d0_init();
+	/*8x25 kgsl initializations*/
+	msm8x25_kgsl_3d0_init();
 }
 
 static void __init msm7x2x_init_early(void)
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 44ba518..f3b2178 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -566,6 +566,7 @@
 	msm7627a_camera_init();
 	qrd7627a_add_io_devices();
 	msm7x25a_kgsl_3d0_init();
+	msm8x25_kgsl_3d0_init();
 }
 
 static void __init qrd7627a_init_early(void)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index a2882a5..e3447b8 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2965,8 +2965,7 @@
 	{USBH3_NS_REG, BIT(6), BIT(6)},
 };
 
-/* Local clock driver initialization. */
-static void __init msm7x30_clock_init(void)
+static void __init msm7x30_clock_pre_init(void)
 {
 	int i;
 	uint32_t val;
@@ -2979,15 +2978,17 @@
 	 * function is a NOP since writes to shadow regions that we don't own
 	 * are ignored. */
 
-	clk_set_rate(&usb_hs_src_clk.c, clk_tbl_usb[1].freq_hz);
-
 	for (i = 0; i < ARRAY_SIZE(ri_list); i++) {
 		val = readl_relaxed(ri_list[i].reg);
 		val &= ~ri_list[i].mask;
 		val |= ri_list[i].val;
 		writel_relaxed(val, ri_list[i].reg);
 	}
+}
 
+static void __init msm7x30_clock_post_init(void)
+{
+	clk_set_rate(&usb_hs_src_clk.c, 60000000);
 	clk_set_rate(&i2c_clk.c, 19200000);
 	clk_set_rate(&i2c_2_clk.c, 19200000);
 	clk_set_rate(&qup_i2c_clk.c, 19200000);
@@ -3006,7 +3007,8 @@
 struct clock_init_data msm7x30_clock_init_data __initdata = {
 	.table = msm_clocks_7x30,
 	.size = ARRAY_SIZE(msm_clocks_7x30),
-	.init = msm7x30_clock_init,
+	.pre_init = msm7x30_clock_pre_init,
+	.post_init = msm7x30_clock_post_init,
 };
 
 /*
@@ -3035,5 +3037,4 @@
 	.set_flags = soc_clk_set_flags,
 	.is_local = local_clk_is_local,
 	.get_parent = branch_clk_get_parent,
-	.set_parent = branch_clk_set_parent,
 };
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 67d5618..3c06f98 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -581,7 +581,6 @@
 	.reset = branch_clk_reset,
 	.is_local = local_clk_is_local,
 	.get_parent = branch_clk_get_parent,
-	.set_parent = branch_clk_set_parent,
 	.handoff = branch_clk_handoff,
 	.set_flags = branch_clk_set_flags,
 };
@@ -2866,16 +2865,22 @@
 	return -ENXIO;
 }
 
-static int pix_rdi_clk_handoff(struct clk *c)
+static enum handoff pix_rdi_clk_handoff(struct clk *c)
 {
 	u32 reg;
 	struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
+	enum handoff ret;
+
+	ret = branch_handoff(&clk->b, &clk->c);
+	if (ret == HANDOFF_DISABLED_CLK)
+		return ret;
 
 	reg = readl_relaxed(clk->s_reg);
 	clk->cur_rate = reg & clk->s_mask ? 1 : 0;
 	reg = readl_relaxed(clk->s2_reg);
 	clk->cur_rate = reg & clk->s2_mask ? 2 : clk->cur_rate;
-	return 0;
+
+	return HANDOFF_ENABLED_CLK;
 }
 
 static struct clk_ops clk_ops_pix_rdi_8960 = {
@@ -5479,7 +5484,7 @@
 };
 
 static struct clk_lookup msm_clocks_8930[] = {
-	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_otg"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_xo"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"wcnss_wlan.0"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"pil_riva"),
 	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
@@ -5996,12 +6001,8 @@
 	}
 }
 
-/* Local clock driver initialization. */
-static void __init msm8960_clock_init(void)
+static void __init msm8960_clock_pre_init(void)
 {
-	/* Keep PXO on whenever APPS cpu is active */
-	clk_prepare_enable(&pxo_a_clk.c);
-
 	if (cpu_is_apq8064()) {
 		vdd_sr2_pll.set_vdd = set_vdd_sr2_pll_8064;
 	} else if (cpu_is_msm8930() || cpu_is_msm8627()) {
@@ -6050,6 +6051,12 @@
 
 	/* Initialize clock registers. */
 	reg_init();
+}
+
+static void __init msm8960_clock_post_init(void)
+{
+	/* Keep PXO on whenever APPS cpu is active */
+	clk_prepare_enable(&pxo_a_clk.c);
 
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 27000000);
@@ -6131,20 +6138,23 @@
 struct clock_init_data msm8960_clock_init_data __initdata = {
 	.table = msm_clocks_8960,
 	.size = ARRAY_SIZE(msm_clocks_8960),
-	.init = msm8960_clock_init,
+	.pre_init = msm8960_clock_pre_init,
+	.post_init = msm8960_clock_post_init,
 	.late_init = msm8960_clock_late_init,
 };
 
 struct clock_init_data apq8064_clock_init_data __initdata = {
 	.table = msm_clocks_8064,
 	.size = ARRAY_SIZE(msm_clocks_8064),
-	.init = msm8960_clock_init,
+	.pre_init = msm8960_clock_pre_init,
+	.post_init = msm8960_clock_post_init,
 	.late_init = msm8960_clock_late_init,
 };
 
 struct clock_init_data msm8930_clock_init_data __initdata = {
 	.table = msm_clocks_8930,
 	.size = ARRAY_SIZE(msm_clocks_8930),
-	.init = msm8960_clock_init,
+	.pre_init = msm8960_clock_pre_init,
+	.post_init = msm8960_clock_post_init,
 	.late_init = msm8960_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index c2632ee..771a4bf 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -452,7 +452,6 @@
 	.reset = branch_clk_reset,
 	.is_local = local_clk_is_local,
 	.get_parent = branch_clk_get_parent,
-	.set_parent = branch_clk_set_parent,
 	.set_flags = branch_clk_set_flags,
 };
 
@@ -3751,8 +3750,10 @@
 	writel_relaxed(regval, reg);
 }
 
-static void __init reg_init(void)
+static void __init msm8660_clock_pre_init(void)
 {
+	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+
 	/* Setup MM_PLL2 (PLL3), but turn it off. Rate set by set_rate_tv(). */
 	rmwreg(0, MM_PLL2_MODE_REG, BIT(0)); /* Disable output */
 	/* Set ref, bypass, assert reset, disable output, disable test mode */
@@ -3836,14 +3837,10 @@
 	rmwreg(0x400001, MISC_CC2_REG, 0x424003);
 }
 
-/* Local clock driver initialization. */
-static void __init msm8660_clock_init(void)
+static void __init msm8660_clock_post_init(void)
 {
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
 	/* Keep PXO on whenever APPS cpu is active */
 	clk_prepare_enable(&pxo_a_clk.c);
-	/* Initialize clock registers. */
-	reg_init();
 
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 27000000);
@@ -3885,6 +3882,7 @@
 struct clock_init_data msm8x60_clock_init_data __initdata = {
 	.table = msm_clocks_8x60,
 	.size = ARRAY_SIZE(msm_clocks_8x60),
-	.init = msm8660_clock_init,
+	.pre_init = msm8660_clock_pre_init,
+	.post_init = msm8660_clock_post_init,
 	.late_init = msm8660_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index cc71c0b..48ee4a9 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -388,7 +388,6 @@
 	.reset = branch_clk_reset,
 	.is_local = local_clk_is_local,
 	.get_parent = branch_clk_get_parent,
-	.set_parent = branch_clk_set_parent,
 };
 
 /*
@@ -1739,10 +1738,14 @@
 /*
  * Miscellaneous clock register initializations
  */
-static void __init reg_init(void)
+static void __init msm9615_clock_pre_init(void)
 {
 	u32 regval, is_pll_enabled, pll9_lval;
 
+	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+
+	clk_ops_pll.enable = sr_pll_clk_enable;
+
 	/* Enable PDM CXO source. */
 	regval = readl_relaxed(PDM_CLK_NS_REG);
 	writel_relaxed(BIT(13) | regval, PDM_CLK_NS_REG);
@@ -1831,18 +1834,11 @@
 	writel_relaxed(regval, DMA_BAM_HCLK_CTL);
 }
 
-/* Local clock driver initialization. */
-static void __init msm9615_clock_init(void)
+static void __init msm9615_clock_post_init(void)
 {
-	vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
 	/* Keep CXO on whenever APPS cpu is active */
 	clk_prepare_enable(&cxo_a_clk.c);
 
-	clk_ops_pll.enable = sr_pll_clk_enable;
-
-	/* Initialize clock registers. */
-	reg_init();
-
 	/* Initialize rates for clocks that only support one. */
 	clk_set_rate(&pdm_clk.c, 19200000);
 	clk_set_rate(&prng_clk.c, 32000000);
@@ -1868,6 +1864,7 @@
 struct clock_init_data msm9615_clock_init_data __initdata = {
 	.table = msm_clocks_9615,
 	.size = ARRAY_SIZE(msm_clocks_9615),
-	.init = msm9615_clock_init,
+	.pre_init = msm9615_clock_pre_init,
+	.post_init = msm9615_clock_post_init,
 	.late_init = msm9615_clock_late_init,
 };
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 3546ce0..f990998 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -567,34 +567,36 @@
 }
 
 /* Disable hw clock gating if not set at boot */
-static void branch_handoff(struct branch *clk, struct clk *c)
+enum handoff branch_handoff(struct branch *clk, struct clk *c)
 {
 	if (!branch_in_hwcg_mode(clk)) {
 		clk->hwcg_mask = 0;
 		c->flags &= ~CLKFLAG_HWCG;
+		if (readl_relaxed(clk->ctl_reg) & clk->en_mask)
+			return HANDOFF_ENABLED_CLK;
 	} else {
 		c->flags |= CLKFLAG_HWCG;
 	}
+	return HANDOFF_DISABLED_CLK;
 }
 
-int branch_clk_handoff(struct clk *c)
+enum handoff branch_clk_handoff(struct clk *c)
 {
 	struct branch_clk *clk = to_branch_clk(c);
-	branch_handoff(&clk->b, &clk->c);
-	return 0;
+	return branch_handoff(&clk->b, &clk->c);
 }
 
-int rcg_clk_handoff(struct clk *c)
+enum handoff rcg_clk_handoff(struct clk *c)
 {
 	struct rcg_clk *clk = to_rcg_clk(c);
 	uint32_t ctl_val, ns_val, md_val, ns_mask;
 	struct clk_freq_tbl *freq;
-
-	branch_handoff(&clk->b, &clk->c);
+	enum handoff ret;
 
 	ctl_val = readl_relaxed(clk->b.ctl_reg);
-	if (!(ctl_val & clk->root_en_mask))
-		return 0;
+	ret = branch_handoff(&clk->b, &clk->c);
+	if (ret == HANDOFF_DISABLED_CLK)
+		return HANDOFF_DISABLED_CLK;
 
 	if (clk->bank_info) {
 		const struct bank_masks *bank_masks = clk->bank_info;
@@ -611,7 +613,8 @@
 		ns_mask = clk->ns_mask;
 		md_val = clk->md_reg ? readl_relaxed(clk->md_reg) : 0;
 	}
-
+	if (!ns_mask)
+		return HANDOFF_UNKNOWN_RATE;
 	ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
 	for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
 		if ((freq->ns_val & ns_mask) == ns_val &&
@@ -621,12 +624,12 @@
 		}
 	}
 	if (freq->freq_hz == FREQ_END)
-		return 0;
+		return HANDOFF_UNKNOWN_RATE;
 
 	clk->current_freq = freq;
 	c->rate = freq->freq_hz;
 
-	return 1;
+	return HANDOFF_ENABLED_CLK;
 }
 
 int pll_vote_clk_enable(struct clk *clk)
@@ -829,19 +832,6 @@
 	return branch->parent;
 }
 
-int branch_clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	/*
-	 * We setup the parent pointer at init time in msm_clock_init().
-	 * This check is to make sure drivers can't change the parent.
-	 */
-	if (parent && list_empty(&clk->siblings)) {
-		list_add(&clk->siblings, &parent->children);
-		return 0;
-	}
-	return -EINVAL;
-}
-
 int branch_clk_is_enabled(struct clk *clk)
 {
 	struct branch_clk *branch = to_branch_clk(clk);
@@ -1058,12 +1048,15 @@
 	return n > clk->max_div ? -ENXIO : n;
 }
 
-static int cdiv_clk_handoff(struct clk *c)
+static enum handoff cdiv_clk_handoff(struct clk *c)
 {
 	struct cdiv_clk *clk = to_cdiv_clk(c);
+	enum handoff ret;
 	u32 reg_val;
 
-	branch_handoff(&clk->b, &clk->c);
+	ret = branch_handoff(&clk->b, &clk->c);
+	if (ret == HANDOFF_DISABLED_CLK)
+		return ret;
 
 	reg_val = readl_relaxed(clk->ns_reg);
 	if (reg_val & clk->ext_mask) {
@@ -1073,7 +1066,7 @@
 		clk->cur_div = (reg_val & (clk->max_div - 1)) + 1;
 	}
 
-	return 0;
+	return HANDOFF_ENABLED_CLK;
 }
 
 static void cdiv_clk_enable_hwcg(struct clk *c)
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 44e86b1..bc9298f 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -171,7 +171,8 @@
 int branch_reset(struct branch *b, enum clk_reset_action action);
 void __branch_clk_enable_reg(const struct branch *clk, const char *name);
 u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
-int branch_clk_handoff(struct clk *c);
+enum handoff branch_clk_handoff(struct clk *c);
+enum handoff branch_handoff(struct branch *clk, struct clk *c);
 int branch_clk_set_flags(struct clk *clk, unsigned flags);
 
 /*
@@ -211,7 +212,7 @@
 int rcg_clk_is_enabled(struct clk *clk);
 long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
 struct clk *rcg_clk_get_parent(struct clk *c);
-int rcg_clk_handoff(struct clk *c);
+enum handoff rcg_clk_handoff(struct clk *c);
 int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
 void rcg_clk_enable_hwcg(struct clk *clk);
 void rcg_clk_disable_hwcg(struct clk *clk);
@@ -330,7 +331,6 @@
 int branch_clk_enable(struct clk *clk);
 void branch_clk_disable(struct clk *clk);
 struct clk *branch_clk_get_parent(struct clk *clk);
-int branch_clk_set_parent(struct clk *clk, struct clk *parent);
 int branch_clk_is_enabled(struct clk *clk);
 int branch_clk_reset(struct clk *c, enum clk_reset_action action);
 void branch_clk_enable_hwcg(struct clk *clk);
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index a0defe3..ed3b8c2 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -307,7 +307,7 @@
 struct clock_init_data msm7x27_clock_init_data __initdata = {
 	.table = msm_clocks_7x27,
 	.size = ARRAY_SIZE(msm_clocks_7x27),
-	.init = msm_shared_pll_control_init,
+	.pre_init = msm_shared_pll_control_init,
 };
 
 /* Clock table for common clocks between 7627a and 7625a */
@@ -413,7 +413,7 @@
 static struct clk_lookup msm_clk_7627a_7625a[ARRAY_SIZE(msm_cmn_clk_7625a_7627a)
 					+ ARRAY_SIZE(msm_clk_7627a)];
 
-static void __init msm7627a_clock_init(void)
+static void __init msm7627a_clock_pre_init(void)
 {
 	int size = ARRAY_SIZE(msm_cmn_clk_7625a_7627a);
 
@@ -432,7 +432,7 @@
 
 struct clock_init_data msm7x27a_clock_init_data __initdata = {
 	.table = msm_clk_7627a_7625a,
-	.init = msm7627a_clock_init,
+	.pre_init = msm7627a_clock_pre_init,
 };
 
 static struct clk_lookup msm_clocks_8x50[] = {
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index b5b6ca7..68c390a 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -156,7 +156,7 @@
 	return true;
 }
 
-static int pll_clk_handoff(struct clk *clk)
+static enum handoff pll_clk_handoff(struct clk *clk)
 {
 	struct pll_shared_clk *pll = to_pll_shared_clk(clk);
 	unsigned int pll_lval;
@@ -184,7 +184,7 @@
 		BUG();
 	}
 
-	return 0;
+	return HANDOFF_ENABLED_CLK;
 }
 
 struct clk_ops clk_pll_ops = {
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index ef502b3..9ad653d 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -148,18 +148,6 @@
 	return clk_round_rate(v->parent, rate);
 }
 
-static int voter_clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&voter_clk_lock, flags);
-	if (list_empty(&clk->siblings))
-		list_add(&clk->siblings, &parent->children);
-	spin_unlock_irqrestore(&voter_clk_lock, flags);
-
-	return 0;
-}
-
 static struct clk *voter_clk_get_parent(struct clk *clk)
 {
 	struct clk_voter *v = to_clk_voter(clk);
@@ -178,7 +166,6 @@
 	.get_rate = voter_clk_get_rate,
 	.is_enabled = voter_clk_is_enabled,
 	.round_rate = voter_clk_round_rate,
-	.set_parent = voter_clk_set_parent,
 	.get_parent = voter_clk_get_parent,
 	.is_local = voter_clk_is_local,
 };
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 884a27e..dcded38 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -401,8 +401,8 @@
 	size_t num_clocks;
 
 	clk_init_data = data;
-	if (clk_init_data->init)
-		clk_init_data->init();
+	if (clk_init_data->pre_init)
+		clk_init_data->pre_init();
 
 	clock_tbl = data->table;
 	num_clocks = data->size;
@@ -410,9 +410,10 @@
 	for (n = 0; n < num_clocks; n++) {
 		struct clk *clk = clock_tbl[n].clk;
 		struct clk *parent = clk_get_parent(clk);
-		clk_set_parent(clk, parent);
+		if (parent && list_empty(&clk->siblings))
+			list_add(&clk->siblings, &parent->children);
 		if (clk->ops->handoff && !(clk->flags & CLKFLAG_HANDOFF_RATE)) {
-			if (clk->ops->handoff(clk)) {
+			if (clk->ops->handoff(clk) == HANDOFF_ENABLED_CLK) {
 				clk->flags |= CLKFLAG_HANDOFF_RATE;
 				clk_prepare_enable(clk);
 			}
@@ -420,6 +421,9 @@
 	}
 
 	clkdev_add_table(clock_tbl, num_clocks);
+
+	if (clk_init_data->post_init)
+		clk_init_data->post_init();
 }
 
 /*
@@ -439,24 +443,24 @@
 		bool handoff = false;
 
 		clock_debug_add(clk);
+		spin_lock_irqsave(&clk->lock, flags);
 		if (!(clk->flags & CLKFLAG_SKIP_AUTO_OFF)) {
-			spin_lock_irqsave(&clk->lock, flags);
 			if (!clk->count && clk->ops->auto_off) {
 				count++;
 				clk->ops->auto_off(clk);
 			}
-			if (clk->flags & CLKFLAG_HANDOFF_RATE) {
-				clk->flags &= ~CLKFLAG_HANDOFF_RATE;
-				handoff = true;
-			}
-			spin_unlock_irqrestore(&clk->lock, flags);
-			/*
-			 * Calling this outside the lock is safe since
-			 * it doesn't need to be atomic with the flag change.
-			 */
-			if (handoff)
-				clk_disable_unprepare(clk);
 		}
+		if (clk->flags & CLKFLAG_HANDOFF_RATE) {
+			clk->flags &= ~CLKFLAG_HANDOFF_RATE;
+			handoff = true;
+		}
+		spin_unlock_irqrestore(&clk->lock, flags);
+		/*
+		 * Calling this outside the lock is safe since
+		 * it doesn't need to be atomic with the flag change.
+		 */
+		if (handoff)
+			clk_disable_unprepare(clk);
 	}
 	pr_info("clock_late_init() disabled %d unused clocks\n", count);
 	if (clk_init_data->late_init)
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 785e838..60be654 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -63,6 +63,12 @@
 		.lock = __SPIN_LOCK_UNLOCKED(lock) \
 	}
 
+enum handoff {
+	HANDOFF_ENABLED_CLK,
+	HANDOFF_DISABLED_CLK,
+	HANDOFF_UNKNOWN_RATE,
+};
+
 struct clk_ops {
 	int (*prepare)(struct clk *clk);
 	int (*enable)(struct clk *clk);
@@ -72,7 +78,7 @@
 	void (*enable_hwcg)(struct clk *clk);
 	void (*disable_hwcg)(struct clk *clk);
 	int (*in_hwcg_mode)(struct clk *clk);
-	int (*handoff)(struct clk *clk);
+	enum handoff (*handoff)(struct clk *clk);
 	int (*reset)(struct clk *clk, enum clk_reset_action action);
 	int (*set_rate)(struct clk *clk, unsigned long rate);
 	int (*set_max_rate)(struct clk *clk, unsigned long rate);
@@ -126,13 +132,15 @@
  * struct clock_init_data - SoC specific clock initialization data
  * @table: table of lookups to add
  * @size: size of @table
- * @init: called before registering @table
+ * @pre_init: called before initializing the clock driver.
+ * @post_init: called after registering @table. clock APIs can be called inside.
  * @late_init: called during late init
  */
 struct clock_init_data {
 	struct clk_lookup *table;
 	size_t size;
-	void (*init)(void);
+	void (*pre_init)(void);
+	void (*post_init)(void);
 	int (*late_init)(void);
 };
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 3965413..7c2fca4 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -31,6 +31,7 @@
 #include <mach/mdm2.h>
 #include <mach/msm_smd.h>
 #include <mach/msm_dcvs.h>
+#include <mach/qdss.h>
 #include <linux/ion.h>
 #include "clock.h"
 #include "devices.h"
@@ -2210,3 +2211,42 @@
 	.num_resources	= ARRAY_SIZE(msm_cache_erp_resources),
 	.resource	= msm_cache_erp_resources,
 };
+
+#define MSM_QDSS_PHYS_BASE		0x01A00000
+#define MSM_ETM_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1C000)
+
+#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
+
+static struct qdss_source msm_qdss_sources[] = {
+	QDSS_SOURCE("msm_etm", 0x33),
+	QDSS_SOURCE("msm_oxili", 0x80),
+};
+
+static struct msm_qdss_platform_data qdss_pdata = {
+	.src_table = msm_qdss_sources,
+	.size = ARRAY_SIZE(msm_qdss_sources),
+	.afamily = 1,
+};
+
+struct platform_device apq8064_qdss_device = {
+	.name          = "msm_qdss",
+	.id            = -1,
+	.dev           = {
+		.platform_data = &qdss_pdata,
+	},
+};
+
+static struct resource msm_etm_resources[] = {
+	{
+		.start = MSM_ETM_PHYS_BASE,
+		.end   = MSM_ETM_PHYS_BASE + (SZ_4K * 4) - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device apq8064_etm_device = {
+	.name          = "msm_etm",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(msm_etm_resources),
+	.resource      = msm_etm_resources,
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index b03f137..a653353 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -31,9 +31,11 @@
 #include <mach/msm_bus_board.h>
 #include <mach/msm_memtypes.h>
 #include <mach/msm_smd.h>
+#include <mach/msm_dcvs.h>
 #include <sound/msm-dai-q6.h>
 #include <sound/apr_audio.h>
 #include <mach/msm_tsif.h>
+#include <mach/qdss.h>
 #include "clock.h"
 #include "devices.h"
 #include "devices-msm8x60.h"
@@ -2402,6 +2404,49 @@
 	},
 };
 
+static struct msm_dcvs_freq_entry grp3d_freq[] = {
+	{0, 0, 333932},
+	{0, 0, 497532},
+	{0, 0, 707610},
+	{0, 0, 844545},
+};
+
+static struct msm_dcvs_freq_entry grp2d_freq[] = {
+	{0, 0, 86000},
+	{0, 0, 200000},
+};
+
+static struct msm_dcvs_core_info grp3d_core_info = {
+	.freq_tbl = &grp3d_freq[0],
+	.core_param = {
+		.max_time_us = 100000,
+		.num_freq = ARRAY_SIZE(grp3d_freq),
+	},
+	.algo_param = {
+		.slack_time_us = 39000,
+		.disable_pc_threshold = 86000,
+		.ss_window_size = 1000000,
+		.ss_util_pct = 95,
+		.em_max_util_pct = 97,
+		.ss_iobusy_conv = 100,
+	},
+};
+
+static struct msm_dcvs_core_info grp2d_core_info = {
+	.freq_tbl = &grp2d_freq[0],
+	.core_param = {
+		.max_time_us = 100000,
+		.num_freq = ARRAY_SIZE(grp2d_freq),
+	},
+	.algo_param = {
+		.slack_time_us = 39000,
+		.disable_pc_threshold = 90000,
+		.ss_window_size = 1000000,
+		.ss_util_pct = 90,
+		.em_max_util_pct = 95,
+	},
+};
+
 #ifdef CONFIG_MSM_BUS_SCALING
 static struct msm_bus_vectors grp3d_init_vectors[] = {
 	{
@@ -2631,7 +2676,7 @@
 		},
 	},
 	.init_level = 0,
-	.num_levels = 5,
+	.num_levels = ARRAY_SIZE(grp3d_freq) + 1,
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/20,
 	.nap_allowed = true,
@@ -2641,6 +2686,7 @@
 #endif
 	.iommu_data = kgsl_3d0_iommu_data,
 	.iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
+	.core_info = &grp3d_core_info,
 };
 
 struct platform_device msm_kgsl_3d0 = {
@@ -2697,7 +2743,7 @@
 		},
 	},
 	.init_level = 0,
-	.num_levels = 3,
+	.num_levels = ARRAY_SIZE(grp2d_freq) + 1,
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/5,
 	.nap_allowed = true,
@@ -2707,6 +2753,7 @@
 #endif
 	.iommu_data = kgsl_2d0_iommu_data,
 	.iommu_count = ARRAY_SIZE(kgsl_2d0_iommu_data),
+	.core_info = &grp2d_core_info,
 };
 
 struct platform_device msm_kgsl_2d0 = {
@@ -2763,7 +2810,7 @@
 		},
 	},
 	.init_level = 0,
-	.num_levels = 3,
+	.num_levels = ARRAY_SIZE(grp2d_freq) + 1,
 	.set_grp_async = NULL,
 	.idle_timeout = HZ/5,
 	.nap_allowed = true,
@@ -2773,6 +2820,7 @@
 #endif
 	.iommu_data = kgsl_2d1_iommu_data,
 	.iommu_count = ARRAY_SIZE(kgsl_2d1_iommu_data),
+	.core_info = &grp2d_core_info,
 };
 
 struct platform_device msm_kgsl_2d1 = {
@@ -3167,6 +3215,26 @@
 #define MSM_FUNNEL_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x4000)
 #define MSM_ETM_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1C000)
 
+#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
+
+static struct qdss_source msm_qdss_sources[] = {
+	QDSS_SOURCE("msm_etm", 0x3),
+};
+
+static struct msm_qdss_platform_data qdss_pdata = {
+	.src_table = msm_qdss_sources,
+	.size = ARRAY_SIZE(msm_qdss_sources),
+	.afamily = 1,
+};
+
+struct platform_device msm_qdss_device = {
+	.name          = "msm_qdss",
+	.id            = -1,
+	.dev           = {
+		.platform_data = &qdss_pdata,
+	},
+};
+
 static struct resource msm_etb_resources[] = {
 	{
 		.start = MSM_ETB_PHYS_BASE,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 1acc833..f7306d2 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -64,7 +64,8 @@
 static struct msm_watchdog_pdata msm_watchdog_pdata = {
 	.pet_time = 10000,
 	.bark_time = 11000,
-	.has_secure = true,
+	.has_secure = false,
+	.use_kernel_fiq = true,
 };
 
 struct platform_device msm9615_device_watchdog = {
@@ -849,6 +850,30 @@
 	return platform_device_register(pdev);
 }
 
+#ifdef CONFIG_FB_MSM_EBI2
+static struct resource msm_ebi2_lcdc_resources[] = {
+	{
+		.name   = "base",
+		.start  = 0x1B300000,
+		.end    = 0x1B300000 + PAGE_SIZE - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.name   = "lcd01",
+		.start  = 0x1FC00000,
+		.end    = 0x1FC00000 + 0x80000 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm_ebi2_lcdc_device = {
+	.name   = "ebi2_lcd",
+	.id     = 0,
+	.num_resources  = ARRAY_SIZE(msm_ebi2_lcdc_resources),
+	.resource       = msm_ebi2_lcdc_resources,
+};
+#endif
+
 #ifdef CONFIG_CACHE_L2X0
 static int __init l2x0_cache_init(void)
 {
@@ -1272,3 +1297,26 @@
 	.name  = "msm_bus_fabric",
 	.id    =  MSM_BUS_FAB_DEFAULT,
 };
+
+#ifdef CONFIG_FB_MSM_EBI2
+static void __init msm_register_device(struct platform_device *pdev, void *data)
+{
+	int ret;
+
+	pdev->dev.platform_data = data;
+
+	ret = platform_device_register(pdev);
+	if (ret)
+		dev_err(&pdev->dev,
+			  "%s: platform_device_register() failed = %d\n",
+			  __func__, ret);
+}
+
+void __init msm_fb_register_device(char *name, void *data)
+{
+	if (!strncmp(name, "ebi2", 4))
+		msm_register_device(&msm_ebi2_lcdc_device, data);
+	else
+		pr_err("%s: unknown device! %s\n", __func__, name);
+}
+#endif
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 96ee564..29e8180 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -364,11 +364,13 @@
 static struct msm_iommu_dev gfx3d_iommu = {
 	.name = "gfx3d",
 	.ncb = 3,
+	.ttbr_split = 2,
 };
 
 static struct msm_iommu_dev gfx3d1_iommu = {
 	.name = "gfx3d1",
 	.ncb = 3,
+	.ttbr_split = 2,
 };
 
 static struct msm_iommu_dev gfx2d0_iommu = {
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 3008fe9..77314e7 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -854,7 +854,7 @@
 	.init_level = 0,
 	.num_levels = 1,
 	.set_grp_async = NULL,
-	.idle_timeout = HZ/5,
+	.idle_timeout = HZ,
 	.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 8236e1e..4575166 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -808,7 +808,7 @@
 	.init_level = 0,
 	.num_levels = 3,
 	.set_grp_async = set_grp_xbar_async,
-	.idle_timeout = HZ/5,
+	.idle_timeout = HZ,
 	.nap_allowed = false,
 	.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
 };
@@ -834,6 +834,12 @@
 	}
 }
 
+void __init msm8x25_kgsl_3d0_init(void)
+{
+	if (cpu_is_msm8625())
+		kgsl_3d0_pdata.idle_timeout = HZ/5;
+}
+
 static void __init msm_register_device(struct platform_device *pdev, void *data)
 {
 	int ret;
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index 3c81ccf..407554c 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -31,4 +31,5 @@
 void __init msm8625_map_io(void);
 int  ar600x_wlan_power(bool on);
 void __init msm8x25_spm_device_init(void);
+void __init msm8x25_kgsl_3d0_init(void);
 #endif
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 3ad3ee4..ba7ac2a 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -331,6 +331,7 @@
 	.config_gpio	= 1,
 	.uart_tx_gpio	= 67,
 	.uart_rx_gpio	= 66,
+	.line		= 1,
 };
 
 static struct resource msm_uart_gsbi9_resources[] = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index ac9feee..3c7b22a 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -267,6 +267,7 @@
 
 extern struct platform_device msm_mipi_dsi1_device;
 extern struct platform_device msm_lvds_device;
+extern struct platform_device msm_ebi2_lcdc_device;
 
 extern struct clk_lookup msm_clocks_fsm9xxx[];
 extern unsigned msm_num_clocks_fsm9xxx;
@@ -318,10 +319,13 @@
 extern struct platform_device msm9615_device_watchdog;
 extern struct platform_device fsm9xxx_device_watchdog;
 
+extern struct platform_device apq8064_qdss_device;
+extern struct platform_device msm_qdss_device;
 extern struct platform_device msm_etb_device;
 extern struct platform_device msm_tpiu_device;
 extern struct platform_device msm_funnel_device;
 extern struct platform_device msm_etm_device;
+extern struct platform_device apq8064_etm_device;
 #endif
 
 extern struct platform_device msm_bus_8064_apps_fabric;
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index d5a2ed4..994150f 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -41,6 +41,7 @@
 struct msm_iommu_dev {
 	const char *name;
 	int ncb;
+	int ttbr_split;
 };
 
 /**
@@ -74,6 +75,7 @@
 	void __iomem *base;
 	int irq;
 	int ncb;
+	int ttbr_split;
 	struct clk *clk;
 	struct clk *pclk;
 	const char *name;
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index 6252cef..39058a6 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -21,6 +21,7 @@
  * 32+:   SPI (shared peripheral interrupts)
  */
 
+#define FIQ_START     16
 #define GIC_PPI_START 16
 #define GIC_SPI_START 32
 
diff --git a/arch/arm/mach-msm/include/mach/msm_cache_dump.h b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
index a8d2987..6e4f628 100644
--- a/arch/arm/mach-msm/include/mach/msm_cache_dump.h
+++ b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
@@ -58,12 +58,15 @@
 };
 
 #define L1_BUFFER_SIZE	SZ_1M
-#define L2_BUFFER_SIZE	(sizeof(struct l2_cache_dump))
+#define L2_BUFFER_SIZE	SZ_4M
 
 #define CACHE_BUFFER_DUMP_SIZE (L1_BUFFER_SIZE + L2_BUFFER_SIZE)
 
 #define L1C_SERVICE_ID 3
 #define L1C_BUFFER_SET_COMMAND_ID 4
+#define CACHE_BUFFER_DUMP_COMMAND_ID 5
 #define L1C_BUFFER_GET_SIZE_COMMAND_ID	6
+#define L2C_BUFFER_SET_COMMAND_ID 7
+#define L2C_BUFFER_GET_SIZE_COMMAND_ID 8
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h b/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h
index e2bdaea..577a097 100644
--- a/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h
+++ b/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h
@@ -18,6 +18,7 @@
 	unsigned config_gpio;
 	unsigned uart_tx_gpio;
 	unsigned uart_rx_gpio;
+	int line;
 };
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/qdss.h b/arch/arm/mach-msm/include/mach/qdss.h
index 530bcb2..3b236b8 100644
--- a/arch/arm/mach-msm/include/mach/qdss.h
+++ b/arch/arm/mach-msm/include/mach/qdss.h
@@ -13,10 +13,30 @@
 #ifndef __MACH_QDSS_H
 #define __MACH_QDSS_H
 
+struct qdss_source {
+	struct list_head link;
+	const char *name;
+	uint32_t fport_mask;
+};
+
+struct msm_qdss_platform_data {
+	struct qdss_source *src_table;
+	size_t size;
+	uint8_t afamily;
+};
+
 #ifdef CONFIG_MSM_QDSS
+extern struct qdss_source *qdss_get(const char *name);
+extern void qdss_put(struct qdss_source *src);
+extern int qdss_enable(struct qdss_source *src);
+extern void qdss_disable(struct qdss_source *src);
 extern int qdss_clk_enable(void);
 extern void qdss_clk_disable(void);
 #else
+static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
+static inline void qdss_put(struct qdss_source *src) {}
+static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
+static inline void qdss_disable(struct qdss_source *src) {}
 static inline int qdss_clk_enable(void) { return -ENOSYS; }
 static inline void qdss_clk_disable(void) {}
 #endif
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index a310ba0..d495c1b 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -176,7 +176,8 @@
 }
 
 static void __program_context(void __iomem *base, int ctx, int ncb,
-			      phys_addr_t pgtable, int redirect)
+			      phys_addr_t pgtable, int redirect,
+			      int ttbr_split)
 {
 	unsigned int prrr, nmrr;
 	int i, j, found;
@@ -189,8 +190,10 @@
 	/* V2P configuration: HTW for access */
 	SET_V2PCFG(base, ctx, 0x3);
 
-	SET_TTBCR(base, ctx, 0);
+	SET_TTBCR(base, ctx, ttbr_split);
 	SET_TTBR0_PA(base, ctx, (pgtable >> TTBR0_PA_SHIFT));
+	if (ttbr_split)
+		SET_TTBR1_PA(base, ctx, (pgtable >> TTBR1_PA_SHIFT));
 
 	/* Enable context fault interrupt */
 	SET_CFEIE(base, ctx, 1);
@@ -365,7 +368,8 @@
 		goto fail;
 
 	__program_context(iommu_drvdata->base, ctx_dev->num, iommu_drvdata->ncb,
-			  __pa(priv->pgtable), priv->redirect);
+			  __pa(priv->pgtable), priv->redirect,
+			  iommu_drvdata->ttbr_split);
 
 	__disable_clocks(iommu_drvdata);
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 70e96b0..6633cae 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -239,6 +239,7 @@
 	drvdata->base = regs_base;
 	drvdata->irq = irq;
 	drvdata->ncb = iommu_dev->ncb;
+	drvdata->ttbr_split = iommu_dev->ttbr_split;
 	drvdata->name = iommu_dev->name;
 
 	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index d26d76b..8dbf304 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -146,7 +146,7 @@
 	flush_axi_bus_buffer();
 }
 
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
+void * __init alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
 {
 	void *unused_addr = NULL;
 	unsigned long addr, tmp_size, unused_size;
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
index 40c358a..404c8f0 100644
--- a/arch/arm/mach-msm/msm_cache_dump.c
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm.h>
 #include <linux/memory_alloc.h>
+#include <linux/notifier.h>
 #include <mach/scm.h>
 #include <mach/msm_cache_dump.h>
 #include <mach/memory.h>
@@ -38,6 +39,25 @@
 static struct l1_cache_dump __used *l1_dump;
 static struct l2_cache_dump __used *l2_dump;
 
+static int msm_cache_dump_panic(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+#ifdef CONFIG_MSM_CACHE_DUMP_ON_PANIC
+	scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 2);
+	scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 1);
+#endif
+	return 0;
+}
+
+static struct notifier_block msm_cache_dump_blk = {
+	.notifier_call  = msm_cache_dump_panic,
+	/*
+	 * higher priority to ensure this runs before another panic handler
+	 * flushes the caches.
+	 */
+	.priority = 1,
+};
+
 static int msm_cache_dump_probe(struct platform_device *pdev)
 {
 	struct msm_cache_dump_platform_data *d = pdev->dev.platform_data;
@@ -46,7 +66,9 @@
 		unsigned long buf;
 		unsigned long size;
 	} l1_cache_data;
+#ifndef CONFIG_MSM_CACHE_DUMP_ON_PANIC
 	unsigned int *imem_loc;
+#endif
 	void *temp;
 	unsigned long total_size = d->l1_size + d->l2_size;
 
@@ -72,14 +94,36 @@
 		pr_err("%s: could not register L1 buffer ret = %d.\n",
 			__func__, ret);
 
+#if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
+	l1_cache_data.buf = msm_cache_dump_addr + d->l1_size;
+	l1_cache_data.size = d->l2_size;
+
+	ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_SET_COMMAND_ID,
+			&l1_cache_data, sizeof(l1_cache_data), NULL, 0);
+
+	if (ret)
+		pr_err("%s: could not register L2 buffer ret = %d.\n",
+			__func__, ret);
+#else
 	imem_loc = ioremap(L2C_IMEM_ADDR, SZ_4K);
 	__raw_writel(msm_cache_dump_addr + d->l1_size, imem_loc);
 	iounmap(imem_loc);
+#endif
 
+	atomic_notifier_chain_register(&panic_notifier_list,
+						&msm_cache_dump_blk);
+	return 0;
+}
+
+static int msm_cache_dump_remove(struct platform_device *pdev)
+{
+	atomic_notifier_chain_unregister(&panic_notifier_list,
+					&msm_cache_dump_blk);
 	return 0;
 }
 
 static struct platform_driver msm_cache_dump_driver = {
+	.remove		= __devexit_p(msm_cache_dump_remove),
 	.driver         = {
 		.name = "msm_cache_dump",
 		.owner = THIS_MODULE
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 994dca6..aabb644 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -23,6 +23,8 @@
 #include <linux/suspend.h>
 #include <linux/percpu.h>
 #include <linux/interrupt.h>
+#include <asm/fiq.h>
+#include <asm/hardware/gic.h>
 #include <mach/msm_iomap.h>
 #include <asm/mach-types.h>
 #include <mach/scm.h>
@@ -42,6 +44,8 @@
 
 #define WDT_HZ		32768
 
+struct msm_watchdog_dump msm_dump_cpu_ctx;
+
 static void __iomem *msm_tmr0_base;
 
 static unsigned long delay_time;
@@ -78,6 +82,8 @@
 static int appsbark;
 module_param(appsbark, int, 0);
 
+static int appsbark_fiq;
+
 /*
  * Use /sys/module/msm_watchdog/parameters/print_all_stacks
  * to control whether stacks of all running
@@ -96,6 +102,13 @@
 static DECLARE_DELAYED_WORK(dogwork_struct, pet_watchdog_work);
 static DECLARE_WORK(init_dogwork_struct, init_watchdog_work);
 
+/* Called from the FIQ bark handler */
+void msm_wdog_bark_fin(void)
+{
+	pr_crit("\nApps Watchdog bark received - Calling Panic\n");
+	panic("Apps Watchdog Bark received\n");
+}
+
 static int msm_watchdog_suspend(struct device *dev)
 {
 	if (!enable)
@@ -166,9 +179,11 @@
 				free_irq(WDT0_ACCSCSSNBARK_INT, 0);
 			} else {
 				disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
-				free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
-					percpu_pdata);
-				free_percpu(percpu_pdata);
+				if (!appsbark_fiq) {
+					free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+							percpu_pdata);
+					free_percpu(percpu_pdata);
+				}
 			}
 			enable = 0;
 			atomic_notifier_chain_unregister(&panic_notifier_list,
@@ -231,8 +246,11 @@
 			free_irq(WDT0_ACCSCSSNBARK_INT, 0);
 		} else {
 			disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
-			free_percpu_irq(WDT0_ACCSCSSNBARK_INT, percpu_pdata);
-			free_percpu(percpu_pdata);
+			if (!appsbark_fiq) {
+				free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+						percpu_pdata);
+				free_percpu(percpu_pdata);
+			}
 		}
 		enable = 0;
 		/* In case we got suspended mid-exit */
@@ -329,26 +347,35 @@
 	__raw_writel(1, msm_tmr0_base + WDT0_RST);
 	last_pet = sched_clock();
 
+	if (!has_vic)
+		enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
+
 	printk(KERN_INFO "MSM Watchdog Initialized\n");
 
 	return;
 }
 
+struct fiq_handler wdog_fh = {
+	.name = MODULE_NAME,
+};
+
 static int msm_watchdog_probe(struct platform_device *pdev)
 {
 	struct msm_watchdog_pdata *pdata = pdev->dev.platform_data;
 	int ret;
+	void *stack;
 
 	if (!enable || !pdata || !pdata->pet_time || !pdata->bark_time) {
 		printk(KERN_INFO "MSM Watchdog Not Initialized\n");
 		return -ENODEV;
 	}
 
-	if (!pdata->has_secure)
-		appsbark = 1;
-
 	bark_time = pdata->bark_time;
 	has_vic = pdata->has_vic;
+	if (!pdata->has_secure) {
+		appsbark = 1;
+		appsbark_fiq = pdata->use_kernel_fiq;
+	}
 
 	msm_tmr0_base = msm_timer_get_timer0_base();
 
@@ -357,6 +384,18 @@
 				  "apps_wdog_bark", NULL);
 		if (ret)
 			return ret;
+	} else if (appsbark_fiq) {
+		claim_fiq(&wdog_fh);
+		set_fiq_handler(&msm_wdog_fiq_start, msm_wdog_fiq_length);
+		stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
+		if (!stack) {
+			pr_info("No free pages available - %s fails\n",
+					__func__);
+			return -ENOMEM;
+		}
+
+		msm_wdog_fiq_setup(stack);
+		gic_set_irq_secure(WDT0_ACCSCSSNBARK_INT);
 	} else {
 		percpu_pdata = alloc_percpu(struct msm_watchdog_pdata *);
 		if (!percpu_pdata) {
@@ -373,8 +412,6 @@
 			free_percpu(percpu_pdata);
 			return ret;
 		}
-
-		enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
 	}
 
 	/*
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 7156dfc..00ff0b6 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -21,8 +21,53 @@
 	bool has_secure;
 	bool needs_expired_enable;
 	bool has_vic;
+	/* You have to be running in secure mode to use FIQ */
+	bool use_kernel_fiq;
 };
 
+struct msm_watchdog_dump {
+	uint32_t magic;
+	uint32_t curr_cpsr;
+	uint32_t usr_r0;
+	uint32_t usr_r1;
+	uint32_t usr_r2;
+	uint32_t usr_r3;
+	uint32_t usr_r4;
+	uint32_t usr_r5;
+	uint32_t usr_r6;
+	uint32_t usr_r7;
+	uint32_t usr_r8;
+	uint32_t usr_r9;
+	uint32_t usr_r10;
+	uint32_t usr_r11;
+	uint32_t usr_r12;
+	uint32_t usr_r13;
+	uint32_t usr_r14;
+	uint32_t irq_spsr;
+	uint32_t irq_r13;
+	uint32_t irq_r14;
+	uint32_t svc_spsr;
+	uint32_t svc_r13;
+	uint32_t svc_r14;
+	uint32_t abt_spsr;
+	uint32_t abt_r13;
+	uint32_t abt_r14;
+	uint32_t und_spsr;
+	uint32_t und_r13;
+	uint32_t und_r14;
+	uint32_t fiq_spsr;
+	uint32_t fiq_r8;
+	uint32_t fiq_r9;
+	uint32_t fiq_r10;
+	uint32_t fiq_r11;
+	uint32_t fiq_r12;
+	uint32_t fiq_r13;
+	uint32_t fiq_r14;
+};
+
+void msm_wdog_fiq_setup(void *stack);
+extern unsigned int msm_wdog_fiq_length, msm_wdog_fiq_start;
+
 #ifdef CONFIG_MSM_WATCHDOG
 void pet_watchdog(void);
 #else
diff --git a/arch/arm/mach-msm/msm_watchdog_asm.S b/arch/arm/mach-msm/msm_watchdog_asm.S
new file mode 100644
index 0000000..c0377d6
--- /dev/null
+++ b/arch/arm/mach-msm/msm_watchdog_asm.S
@@ -0,0 +1,84 @@
+/* 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/linkage.h>
+#include <asm/assembler.h>
+
+#define VERSION_ID 0x1
+#define MAGIC 0xDEAD0000 | VERSION_ID
+
+	.text
+
+	.align 3
+
+ENTRY(msm_wdog_fiq_start)
+	mov	sp, r8		@get stack
+	ldr	r8, Ldump_cpu_ctx
+	@ store magic to indicate a valid dump
+	ldr	r9, Lmagic
+	str	r9, [r8], #4
+	@ get the current cpsr
+	mrs	r9, cpsr
+	str	r9, [r8],#4
+	@ get the USR r0-r7
+	stmia	r8!, {r0-r7}
+	mov	r4, r8
+	mov	r5, #PSR_I_BIT | PSR_F_BIT | SYSTEM_MODE
+	msr	cpsr_c, r5	@ select SYSTEM mode
+	stmia	r4!, {r8-r14}
+	mov	r5, #PSR_I_BIT | PSR_F_BIT | IRQ_MODE
+	msr	cpsr_c, r5	@ select IRQ mode
+	mrs	r5, spsr
+	str	r5, [r4], #4
+	stmia	r4!, {r13-r14}
+	mov	r5, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+	msr	cpsr_c, r5	@ select SVC mode
+	mrs	r5, spsr
+	str	r5, [r4], #4
+	stmia	r4!, {r13-r14}
+	mov	r5, #PSR_I_BIT | PSR_F_BIT | ABT_MODE
+	msr	cpsr_c, r5	@ select ABT mode
+	mrs	r5, spsr
+	str	r5, [r4], #4
+	stmia	r4!, {r13-r14}
+	mov	r5, #PSR_I_BIT | PSR_F_BIT | UND_MODE
+	msr	cpsr_c, r5	@ select UND mode
+	mrs	r5, spsr
+	str	r5, [r4], #4
+	stmia	r4!, {r13-r14}
+	mov	r5, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
+	msr	cpsr_c, r5	@ select FIQ mode
+	mrs	r5, spsr
+	str	r5, [r4], #4
+	stmia	r4!, {r8-r14}
+	dsb
+	mov	r5, #PSR_F_BIT | SVC_MODE
+	msr	cpsr_c, r5	@ select SVC mode
+	ldr	r2, Lwatchdog_bark_fin
+	blx	r2
+Ldump_cpu_ctx:
+	.word	msm_dump_cpu_ctx
+Lmagic:
+	.word	MAGIC
+Lwatchdog_bark_fin:
+	.word	msm_wdog_bark_fin
+ENTRY(msm_wdog_fiq_length)
+	.word	. - msm_wdog_fiq_start
+
+/* setup the stack */
+ENTRY(msm_wdog_fiq_setup)
+	mrs	r3, cpsr
+	msr	cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
+	mov	r8, r0
+	msr	cpsr_c, r3
+	bx	lr
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 86776d3..407231a 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include <linux/list.h>
 #include <linux/seq_file.h>
@@ -29,7 +29,7 @@
 
 #include "rpm_resources.h"
 
-static DEFINE_SPINLOCK(msm_xo_lock);
+static DEFINE_MUTEX(msm_xo_lock);
 
 struct msm_xo {
 	unsigned votes[NUM_MSM_XO_MODES];
@@ -151,13 +151,12 @@
 
 static int msm_xo_show_voters(struct seq_file *m, void *v)
 {
-	unsigned long flags;
 	int i;
 
-	spin_lock_irqsave(&msm_xo_lock, flags);
+	mutex_lock(&msm_xo_lock);
 	for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
 		msm_xo_dump_xo(m, &msm_xo_sources[i], msm_xo_to_str[i]);
-	spin_unlock_irqrestore(&msm_xo_lock, flags);
+	mutex_unlock(&msm_xo_lock);
 
 	return 0;
 }
@@ -221,7 +220,7 @@
 		     */
 		    ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 20) |
 		    ((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 18);
-	ret = msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
+	ret = msm_rpm_set(MSM_RPM_CTX_SET_0, &cmd, 1);
 
 	if (ret)
 		xo->mode = prev_vote;
@@ -281,7 +280,6 @@
 int msm_xo_mode_vote(struct msm_xo_voter *xo_voter, enum msm_xo_modes mode)
 {
 	int ret;
-	unsigned long flags;
 
 	if (!xo_voter)
 		return 0;
@@ -289,9 +287,9 @@
 	if (mode >= NUM_MSM_XO_MODES || IS_ERR(xo_voter))
 		return -EINVAL;
 
-	spin_lock_irqsave(&msm_xo_lock, flags);
+	mutex_lock(&msm_xo_lock);
 	ret = __msm_xo_mode_vote(xo_voter, mode);
-	spin_unlock_irqrestore(&msm_xo_lock, flags);
+	mutex_unlock(&msm_xo_lock);
 
 	return ret;
 }
@@ -310,7 +308,6 @@
 struct msm_xo_voter *msm_xo_get(enum msm_xo_ids xo_id, const char *voter)
 {
 	int ret;
-	unsigned long flags;
 	struct msm_xo_voter *xo_voter;
 
 	if (xo_id >= NUM_MSM_XO_IDS) {
@@ -333,10 +330,10 @@
 	xo_voter->xo = &msm_xo_sources[xo_id];
 
 	/* Voters vote for OFF by default */
-	spin_lock_irqsave(&msm_xo_lock, flags);
+	mutex_lock(&msm_xo_lock);
 	xo_voter->xo->votes[MSM_XO_MODE_OFF]++;
 	list_add(&xo_voter->list, &xo_voter->xo->voters);
-	spin_unlock_irqrestore(&msm_xo_lock, flags);
+	mutex_unlock(&msm_xo_lock);
 
 	return xo_voter;
 
@@ -357,16 +354,14 @@
  */
 void msm_xo_put(struct msm_xo_voter *xo_voter)
 {
-	unsigned long flags;
-
 	if (!xo_voter || IS_ERR(xo_voter))
 		return;
 
-	spin_lock_irqsave(&msm_xo_lock, flags);
+	mutex_lock(&msm_xo_lock);
 	__msm_xo_mode_vote(xo_voter, MSM_XO_MODE_OFF);
 	xo_voter->xo->votes[MSM_XO_MODE_OFF]--;
 	list_del(&xo_voter->list);
-	spin_unlock_irqrestore(&msm_xo_lock, flags);
+	mutex_unlock(&msm_xo_lock);
 
 	kfree(xo_voter->name);
 	kfree(xo_voter);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 92339e9..ecbbcb9 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -80,7 +80,6 @@
 	void __iomem *base;
 	unsigned long start_addr;
 	struct clk *xo;
-	bool use_cxo;
 	struct regulator *pll_supply;
 	struct pil_device *pil;
 };
@@ -97,18 +96,15 @@
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	int ret;
 
-	drv->use_cxo = cxo_is_needed(drv);
 	ret = regulator_enable(drv->pll_supply);
 	if (ret) {
 		dev_err(pil->dev, "failed to enable pll supply\n");
 		goto err;
 	}
-	if (drv->use_cxo) {
-		ret = clk_prepare_enable(drv->xo);
-		if (ret) {
-			dev_err(pil->dev, "failed to enable xo\n");
-			goto err_clk;
-		}
+	ret = clk_prepare_enable(drv->xo);
+	if (ret) {
+		dev_err(pil->dev, "failed to enable xo\n");
+		goto err_clk;
 	}
 	return 0;
 err_clk:
@@ -121,8 +117,7 @@
 {
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	regulator_disable(drv->pll_supply);
-	if (drv->use_cxo)
-		clk_disable_unprepare(drv->xo);
+	clk_disable_unprepare(drv->xo);
 }
 
 static int pil_riva_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -140,11 +135,8 @@
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
 	unsigned long start_addr = drv->start_addr;
-	int ret;
+	bool use_cxo = cxo_is_needed(drv);
 
-	ret = clk_prepare_enable(drv->xo);
-	if (ret)
-		return ret;
 	/* Enable A2XB bridge */
 	reg = readl_relaxed(base + RIVA_PMU_A2XB_CFG);
 	reg |= RIVA_PMU_A2XB_CFG_EN;
@@ -155,7 +147,7 @@
 	reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
 	writel_relaxed(reg, RIVA_PLL_MODE);
 
-	if (drv->use_cxo)
+	if (use_cxo)
 		writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
 	else
 		writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
@@ -165,7 +157,7 @@
 
 	reg = readl_relaxed(RIVA_PLL_MODE);
 	reg &= ~(PLL_MODE_REF_XO_SEL);
-	reg |= drv->use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
+	reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
 	writel_relaxed(reg, RIVA_PLL_MODE);
 
 	/* Enable PLL 13 */
@@ -230,7 +222,6 @@
 	/* Take cCPU out of reset */
 	reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET;
 	writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
-	clk_disable_unprepare(drv->xo);
 
 	return 0;
 }
@@ -239,11 +230,7 @@
 {
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	u32 reg;
-	int ret;
 
-	ret = clk_prepare_enable(drv->xo);
-	if (ret)
-		return ret;
 	/* Put cCPU and cCPU clock into reset */
 	reg = readl_relaxed(drv->base + RIVA_PMU_OVRD_VAL);
 	reg &= ~(RIVA_PMU_OVRD_VAL_CCPU_RESET | RIVA_PMU_OVRD_VAL_CCPU_CLK);
@@ -262,8 +249,6 @@
 	writel_relaxed(0, RIVA_RESET);
 	mb();
 
-	clk_disable_unprepare(drv->xo);
-
 	return 0;
 }
 
@@ -283,30 +268,12 @@
 
 static int pil_riva_reset_trusted(struct pil_desc *pil)
 {
-	struct riva_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-
-	ret = clk_prepare_enable(drv->xo);
-	if (ret)
-		return ret;
-	/* Proxy-vote for resources RIVA needs */
-	ret = pas_auth_and_reset(PAS_RIVA);
-	clk_disable_unprepare(drv->xo);
-	return ret;
+	return pas_auth_and_reset(PAS_RIVA);
 }
 
 static int pil_riva_shutdown_trusted(struct pil_desc *pil)
 {
-	int ret;
-	struct riva_data *drv = dev_get_drvdata(pil->dev);
-
-	ret = clk_prepare_enable(drv->xo);
-	if (ret)
-		return ret;
-	ret = pas_shutdown(PAS_RIVA);
-	clk_disable_unprepare(drv->xo);
-
-	return ret;
+	return pas_shutdown(PAS_RIVA);
 }
 
 static struct pil_reset_ops pil_riva_ops_trusted = {
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index 9521e87..8760e443 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -73,7 +73,7 @@
 
 /* Size must be power of 2 */
 #define MAX_BUF 2
-#define BUFSZ (167210)
+#define BUFSZ (1024000)
 
 #define AUDDEC_DEC_PCM 0
 
diff --git a/arch/arm/mach-msm/qdss-etb.c b/arch/arm/mach-msm/qdss-etb.c
index 8b5f8db..96eba26 100644
--- a/arch/arm/mach-msm/qdss-etb.c
+++ b/arch/arm/mach-msm/qdss-etb.c
@@ -318,7 +318,7 @@
 	return ret;
 }
 
-static void etb_sysfs_exit(void)
+static void __exit etb_sysfs_exit(void)
 {
 	sysfs_remove_file(etb.kobj, &trigger_cntr_attr.attr);
 	kobject_put(etb.kobj);
@@ -371,7 +371,7 @@
 	return ret;
 }
 
-static int etb_remove(struct platform_device *pdev)
+static int __devexit etb_remove(struct platform_device *pdev)
 {
 	if (etb.enabled)
 		etb_disable();
@@ -386,18 +386,23 @@
 
 static struct platform_driver etb_driver = {
 	.probe          = etb_probe,
-	.remove         = etb_remove,
+	.remove         = __devexit_p(etb_remove),
 	.driver         = {
 		.name   = "msm_etb",
 	},
 };
 
-int __init etb_init(void)
+static int __init etb_init(void)
 {
 	return platform_driver_register(&etb_driver);
 }
+module_init(etb_init);
 
-void etb_exit(void)
+static void __exit etb_exit(void)
 {
 	platform_driver_unregister(&etb_driver);
 }
+module_exit(etb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
diff --git a/arch/arm/mach-msm/qdss-etm.c b/arch/arm/mach-msm/qdss-etm.c
index eeb7519..251db45 100644
--- a/arch/arm/mach-msm/qdss-etm.c
+++ b/arch/arm/mach-msm/qdss-etm.c
@@ -156,6 +156,7 @@
 	bool				enabled;
 	struct wake_lock		wake_lock;
 	struct pm_qos_request_list	qos_req;
+	struct qdss_source		*src;
 	struct mutex			mutex;
 	struct device			*dev;
 	struct kobject			*kobj;
@@ -339,10 +340,6 @@
 		goto err;
 	}
 
-	ret = qdss_clk_enable();
-	if (ret)
-		goto err;
-
 	wake_lock(&etm.wake_lock);
 	/* 1. causes all online cpus to come out of idle PC
 	 * 2. prevents idle PC until save restore flag is enabled atomically
@@ -353,11 +350,10 @@
 	 */
 	pm_qos_update_request(&etm.qos_req, 0);
 
-	etb_disable();
-	tpiu_disable();
-	/* enable ETB first to avoid loosing any trace data */
-	etb_enable();
-	funnel_enable(0x0, 0x3);
+	ret = qdss_enable(etm.src);
+	if (ret)
+		goto err_qdss;
+
 	for_each_online_cpu(cpu)
 		__etm_enable(cpu);
 
@@ -368,6 +364,10 @@
 
 	dev_info(etm.dev, "ETM tracing enabled\n");
 	return 0;
+
+err_qdss:
+	pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
+	wake_unlock(&etm.wake_lock);
 err:
 	return ret;
 }
@@ -407,17 +407,14 @@
 
 	for_each_online_cpu(cpu)
 		__etm_disable(cpu);
-	etb_dump();
-	etb_disable();
-	funnel_disable(0x0, 0x3);
+
+	qdss_disable(etm.src);
 
 	etm.enabled = false;
 
 	pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
 	wake_unlock(&etm.wake_lock);
 
-	qdss_clk_disable();
-
 	dev_info(etm.dev, "ETM tracing disabled\n");
 	return 0;
 err:
@@ -1151,14 +1148,14 @@
 	return ret;
 }
 
-static void etm_sysfs_exit(void)
+static void __exit etm_sysfs_exit(void)
 {
 	sysfs_remove_group(etm.kobj, &etm_attr_grp);
 	sysfs_remove_file(etm.kobj, &enabled_attr.attr);
 	kobject_put(etm.kobj);
 }
 
-static bool etm_arch_supported(uint8_t arch)
+static bool __init etm_arch_supported(uint8_t arch)
 {
 	switch (arch) {
 	case PFT_ARCH_V1_1:
@@ -1249,6 +1246,12 @@
 	wake_lock_init(&etm.wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
 	pm_qos_add_request(&etm.qos_req, PM_QOS_CPU_DMA_LATENCY,
 						PM_QOS_DEFAULT_VALUE);
+	etm.src = qdss_get("msm_etm");
+	if (IS_ERR(etm.src)) {
+		ret = PTR_ERR(etm.src);
+		goto err_qdssget;
+	}
+
 	ret = qdss_clk_enable();
 	if (ret)
 		goto err_clk;
@@ -1276,6 +1279,8 @@
 err_arch:
 	qdss_clk_disable();
 err_clk:
+	qdss_put(etm.src);
+err_qdssget:
 	pm_qos_remove_request(&etm.qos_req);
 	wake_lock_destroy(&etm.wake_lock);
 	mutex_destroy(&etm.mutex);
@@ -1286,11 +1291,12 @@
 	return ret;
 }
 
-static int etm_remove(struct platform_device *pdev)
+static int __devexit etm_remove(struct platform_device *pdev)
 {
 	if (etm.enabled)
 		etm_disable();
 	etm_sysfs_exit();
+	qdss_put(etm.src);
 	pm_qos_remove_request(&etm.qos_req);
 	wake_lock_destroy(&etm.wake_lock);
 	mutex_destroy(&etm.mutex);
@@ -1301,7 +1307,7 @@
 
 static struct platform_driver etm_driver = {
 	.probe          = etm_probe,
-	.remove         = etm_remove,
+	.remove         = __devexit_p(etm_remove),
 	.driver         = {
 		.name   = "msm_etm",
 	},
@@ -1311,8 +1317,13 @@
 {
 	return platform_driver_register(&etm_driver);
 }
+module_init(etm_init);
 
-void etm_exit(void)
+void __exit etm_exit(void)
 {
 	platform_driver_unregister(&etm_driver);
 }
+module_exit(etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/arch/arm/mach-msm/qdss-funnel.c b/arch/arm/mach-msm/qdss-funnel.c
index 990295b..2d80603 100644
--- a/arch/arm/mach-msm/qdss-funnel.c
+++ b/arch/arm/mach-msm/qdss-funnel.c
@@ -159,7 +159,7 @@
 	return ret;
 }
 
-static void funnel_sysfs_exit(void)
+static void __exit funnel_sysfs_exit(void)
 {
 	sysfs_remove_file(funnel.kobj, &priority_attr.attr);
 	kobject_put(funnel.kobj);
@@ -197,7 +197,7 @@
 	return ret;
 }
 
-static int funnel_remove(struct platform_device *pdev)
+static int __devexit funnel_remove(struct platform_device *pdev)
 {
 	if (funnel.enabled)
 		funnel_disable(0x0, 0xFF);
@@ -210,18 +210,23 @@
 
 static struct platform_driver funnel_driver = {
 	.probe          = funnel_probe,
-	.remove         = funnel_remove,
+	.remove         = __devexit_p(funnel_remove),
 	.driver         = {
 		.name   = "msm_funnel",
 	},
 };
 
-int __init funnel_init(void)
+static int __init funnel_init(void)
 {
 	return platform_driver_register(&funnel_driver);
 }
+module_init(funnel_init);
 
-void funnel_exit(void)
+static void __exit funnel_exit(void)
 {
 	platform_driver_unregister(&funnel_driver);
 }
+module_exit(funnel_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Funnel driver");
diff --git a/arch/arm/mach-msm/qdss-priv.h b/arch/arm/mach-msm/qdss-priv.h
index b9f3072..f39bc52 100644
--- a/arch/arm/mach-msm/qdss-priv.h
+++ b/arch/arm/mach-msm/qdss-priv.h
@@ -58,15 +58,6 @@
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
 
-int etb_init(void);
-void etb_exit(void);
-int tpiu_init(void);
-void tpiu_exit(void);
-int funnel_init(void);
-void funnel_exit(void);
-int etm_init(void);
-void etm_exit(void);
-
 void etb_enable(void);
 void etb_disable(void);
 void etb_dump(void);
diff --git a/arch/arm/mach-msm/qdss-tpiu.c b/arch/arm/mach-msm/qdss-tpiu.c
index 4481a0a..fa15635 100644
--- a/arch/arm/mach-msm/qdss-tpiu.c
+++ b/arch/arm/mach-msm/qdss-tpiu.c
@@ -108,7 +108,7 @@
 	return ret;
 }
 
-static int tpiu_remove(struct platform_device *pdev)
+static int __devexit tpiu_remove(struct platform_device *pdev)
 {
 	if (tpiu.enabled)
 		tpiu_disable();
@@ -119,18 +119,23 @@
 
 static struct platform_driver tpiu_driver = {
 	.probe          = tpiu_probe,
-	.remove         = tpiu_remove,
+	.remove         = __devexit_p(tpiu_remove),
 	.driver         = {
 		.name   = "msm_tpiu",
 	},
 };
 
-int __init tpiu_init(void)
+static int __init tpiu_init(void)
 {
 	return platform_driver_register(&tpiu_driver);
 }
+module_init(tpiu_init);
 
-void tpiu_exit(void)
+static void __exit tpiu_exit(void)
 {
 	platform_driver_unregister(&tpiu_driver);
 }
+module_exit(tpiu_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");
diff --git a/arch/arm/mach-msm/qdss.c b/arch/arm/mach-msm/qdss.c
index 80ec65a..cfe65ad 100644
--- a/arch/arm/mach-msm/qdss.c
+++ b/arch/arm/mach-msm/qdss.c
@@ -24,26 +24,155 @@
 #include "rpm_resources.h"
 #include "qdss-priv.h"
 
+#define MAX_STR_LEN	(65535)
+
 enum {
 	QDSS_CLK_OFF,
 	QDSS_CLK_ON_DBG,
 	QDSS_CLK_ON_HSDBG,
 };
 
+/*
+ * Exclusion rules for structure fields.
+ *
+ * S: qdss.sources_mutex protected.
+ * I: qdss.sink_mutex protected.
+ * C: qdss.clk_mutex protected.
+ */
 struct qdss_ctx {
-	struct kobject	*modulekobj;
-	uint8_t		max_clk;
-	uint8_t		clk_count;
-	struct mutex	clk_mutex;
+	struct kobject			*modulekobj;
+	struct msm_qdss_platform_data	*pdata;
+	struct list_head		sources;	/* S: sources list */
+	struct mutex			sources_mutex;
+	uint8_t				sink_count;	/* I: sink count */
+	struct mutex			sink_mutex;
+	uint8_t				max_clk;
+	uint8_t				clk_count;	/* C: clk count */
+	struct mutex			clk_mutex;
 };
 
 static struct qdss_ctx qdss;
 
-
-struct kobject *qdss_get_modulekobj(void)
+/**
+ * qdss_get - get the qdss source handle
+ * @name: name of the qdss source
+ *
+ * Searches the sources list to get the qdss source handle for this source.
+ *
+ * CONTEXT:
+ * Typically called from init or probe functions
+ *
+ * RETURNS:
+ * pointer to struct qdss_source on success, %NULL on failure
+ */
+struct qdss_source *qdss_get(const char *name)
 {
-	return qdss.modulekobj;
+	struct qdss_source *src, *source = NULL;
+
+	mutex_lock(&qdss.sources_mutex);
+	list_for_each_entry(src, &qdss.sources, link) {
+		if (src->name) {
+			if (strncmp(src->name, name, MAX_STR_LEN))
+				continue;
+			source = src;
+			break;
+		}
+	}
+	mutex_unlock(&qdss.sources_mutex);
+
+	return source ? source : ERR_PTR(-ENOENT);
 }
+EXPORT_SYMBOL(qdss_get);
+
+/**
+ * qdss_put - release the qdss source handle
+ * @name: name of the qdss source
+ *
+ * CONTEXT:
+ * Typically called from driver remove or exit functions
+ */
+void qdss_put(struct qdss_source *src)
+{
+}
+EXPORT_SYMBOL(qdss_put);
+
+/**
+ * qdss_enable - enable qdss for the source
+ * @src: handle for the source making the call
+ *
+ * Enables qdss block (relevant funnel ports and sink) if not already
+ * enabled, otherwise increments the reference count
+ *
+ * CONTEXT:
+ * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
+ *
+ * RETURNS:
+ * 0 on success, non-zero on failure
+ */
+int qdss_enable(struct qdss_source *src)
+{
+	int ret;
+
+	if (!src)
+		return -EINVAL;
+
+	ret = qdss_clk_enable();
+	if (ret)
+		goto err;
+
+	if ((qdss.pdata)->afamily) {
+		mutex_lock(&qdss.sink_mutex);
+		if (qdss.sink_count == 0) {
+			etb_disable();
+			tpiu_disable();
+			/* enable ETB first to avoid losing any trace data */
+			etb_enable();
+		}
+		qdss.sink_count++;
+		mutex_unlock(&qdss.sink_mutex);
+	}
+
+	funnel_enable(0x0, src->fport_mask);
+	return 0;
+err:
+	return ret;
+}
+EXPORT_SYMBOL(qdss_enable);
+
+/**
+ * qdss_disable - disable qdss for the source
+ * @src: handle for the source making the call
+ *
+ * Disables qdss block (relevant funnel ports and sink) if the reference count
+ * is one, otherwise decrements the reference count
+ *
+ * CONTEXT:
+ * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
+ */
+void qdss_disable(struct qdss_source *src)
+{
+	if (!src)
+		return;
+
+	if ((qdss.pdata)->afamily) {
+		mutex_lock(&qdss.sink_mutex);
+		if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
+			goto out;
+		if (qdss.sink_count == 1) {
+			etb_dump();
+			etb_disable();
+		}
+		qdss.sink_count--;
+		mutex_unlock(&qdss.sink_mutex);
+	}
+
+	funnel_disable(0x0, src->fport_mask);
+	qdss_clk_disable();
+	return;
+out:
+	mutex_unlock(&qdss.sink_mutex);
+}
+EXPORT_SYMBOL(qdss_disable);
 
 /**
  * qdss_clk_enable - enable qdss clocks
@@ -111,6 +240,11 @@
 }
 EXPORT_SYMBOL(qdss_clk_disable);
 
+struct kobject *qdss_get_modulekobj(void)
+{
+	return qdss.modulekobj;
+}
+
 #define QDSS_ATTR(name)						\
 static struct kobj_attribute name##_attr =				\
 		__ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
@@ -136,6 +270,16 @@
 }
 QDSS_ATTR(max_clk);
 
+static void __init qdss_add_sources(struct qdss_source *srcs, size_t num)
+{
+	mutex_lock(&qdss.sources_mutex);
+	while (num--) {
+		list_add_tail(&srcs->link, &qdss.sources);
+		srcs++;
+	}
+	mutex_unlock(&qdss.sources_mutex);
+}
+
 static int __init qdss_sysfs_init(void)
 {
 	int ret;
@@ -158,58 +302,85 @@
 	return ret;
 }
 
-static void qdss_sysfs_exit(void)
+static void __exit qdss_sysfs_exit(void)
 {
 	sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
 }
 
-static int __init qdss_init(void)
+static int __devinit qdss_probe(struct platform_device *pdev)
 {
 	int ret;
+	struct qdss_source *src_table;
+	size_t num_srcs;
 
+	mutex_init(&qdss.sources_mutex);
 	mutex_init(&qdss.clk_mutex);
+	mutex_init(&qdss.sink_mutex);
+
+	if (pdev->dev.platform_data == NULL) {
+		pr_err("%s: platform data is NULL\n", __func__);
+		ret = -ENODEV;
+		goto err_pdata;
+	}
+	qdss.pdata = pdev->dev.platform_data;
+
+	INIT_LIST_HEAD(&qdss.sources);
+	src_table = (qdss.pdata)->src_table;
+	num_srcs = (qdss.pdata)->size;
+	qdss_add_sources(src_table, num_srcs);
+
+	pr_info("QDSS arch initialized\n");
+	return 0;
+err_pdata:
+	mutex_destroy(&qdss.sink_mutex);
+	mutex_destroy(&qdss.clk_mutex);
+	mutex_destroy(&qdss.sources_mutex);
+	pr_err("QDSS init failed\n");
+	return ret;
+}
+
+static int __devexit qdss_remove(struct platform_device *pdev)
+{
+	qdss_sysfs_exit();
+	mutex_destroy(&qdss.sink_mutex);
+	mutex_destroy(&qdss.clk_mutex);
+	mutex_destroy(&qdss.sources_mutex);
+
+	return 0;
+}
+
+static struct platform_driver qdss_driver = {
+	.probe          = qdss_probe,
+	.remove         = __devexit_p(qdss_remove),
+	.driver         = {
+		.name   = "msm_qdss",
+	},
+};
+
+static int __init qdss_init(void)
+{
+	return platform_driver_register(&qdss_driver);
+}
+arch_initcall(qdss_init);
+
+static int __init qdss_module_init(void)
+{
+	int ret;
 
 	ret = qdss_sysfs_init();
 	if (ret)
 		goto err_sysfs;
-	ret = etb_init();
-	if (ret)
-		goto err_etb;
-	ret = tpiu_init();
-	if (ret)
-		goto err_tpiu;
-	ret = funnel_init();
-	if (ret)
-		goto err_funnel;
-	ret = etm_init();
-	if (ret)
-		goto err_etm;
 
-	pr_info("QDSS initialized\n");
+	pr_info("QDSS module initialized\n");
 	return 0;
-err_etm:
-	funnel_exit();
-err_funnel:
-	tpiu_exit();
-err_tpiu:
-	etb_exit();
-err_etb:
-	qdss_sysfs_exit();
 err_sysfs:
-	mutex_destroy(&qdss.clk_mutex);
-	pr_err("QDSS init failed\n");
 	return ret;
 }
-module_init(qdss_init);
+module_init(qdss_module_init);
 
 static void __exit qdss_exit(void)
 {
-	qdss_sysfs_exit();
-	etm_exit();
-	funnel_exit();
-	tpiu_exit();
-	etb_exit();
-	mutex_destroy(&qdss.clk_mutex);
+	platform_driver_unregister(&qdss_driver);
 }
 module_exit(qdss_exit);
 
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index 2eac3c1..b0fa3d2 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -437,7 +437,6 @@
  *
  * Return value:
  *   0: success
- *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
  *   -ENOSPC: request rejected
  *   -ENODEV: RPM driver not initialized
@@ -464,10 +463,7 @@
 		rc = msm_rpm_set_exclusive_noirq(ctx, sel_masks, req, count);
 		spin_unlock_irqrestore(&msm_rpm_lock, flags);
 	} else {
-		rc = mutex_lock_interruptible(&msm_rpm_mutex);
-		if (rc)
-			goto set_common_exit;
-
+		mutex_lock(&msm_rpm_mutex);
 		rc = msm_rpm_set_exclusive(ctx, sel_masks, req, count);
 		mutex_unlock(&msm_rpm_mutex);
 	}
@@ -479,7 +475,6 @@
 /*
  * Return value:
  *   0: success
- *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
  *   -ENODEV: RPM driver not initialized.
  */
@@ -518,10 +513,7 @@
 		spin_unlock_irqrestore(&msm_rpm_lock, flags);
 		BUG_ON(rc);
 	} else {
-		rc = mutex_lock_interruptible(&msm_rpm_mutex);
-		if (rc)
-			goto clear_common_exit;
-
+		mutex_lock(&msm_rpm_mutex);
 		rc = msm_rpm_set_exclusive(ctx, sel_masks, r, ARRAY_SIZE(r));
 		mutex_unlock(&msm_rpm_mutex);
 		BUG_ON(rc);
@@ -683,7 +675,6 @@
  *
  * Return value:
  *   0: success
- *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
  *   -ENOSPC: request rejected
  *   -ENODEV: RPM driver not initialized
@@ -724,7 +715,6 @@
  *
  * Return value:
  *   0: success
- *   -EINTR: interrupted
  *   -EINVAL: invalid <ctx> or invalid id in <req> array
  */
 int msm_rpm_clear(int ctx, struct msm_rpm_iv_pair *req, int count)
@@ -769,7 +759,6 @@
  *
  * Return value:
  *   0: success
- *   -EINTR: interrupted
  *   -EINVAL: invalid id in <req> array
  *   -ENODEV: RPM driver not initialized
  */
@@ -787,9 +776,7 @@
 	if (rc)
 		goto register_notification_exit;
 
-	rc = mutex_lock_interruptible(&msm_rpm_mutex);
-	if (rc)
-		goto register_notification_exit;
+	mutex_lock(&msm_rpm_mutex);
 
 	if (!msm_rpm_init_notif_done) {
 		msm_rpm_initialize_notification();
@@ -823,7 +810,6 @@
  *
  * Return value:
  *   0: success
- *   -EINTR: interrupted
  *   -ENODEV: RPM driver not initialized
  */
 int msm_rpm_unregister_notification(struct msm_rpm_notification *n)
@@ -831,13 +817,10 @@
 	unsigned long flags;
 	unsigned int ctx;
 	struct msm_rpm_notif_config cfg;
-	int rc;
+	int rc = 0;
 	int i;
 
-	rc = mutex_lock_interruptible(&msm_rpm_mutex);
-	if (rc)
-		goto unregister_notification_exit;
-
+	mutex_lock(&msm_rpm_mutex);
 	ctx = MSM_RPM_CTX_SET_0;
 	cfg = msm_rpm_notif_cfgs[ctx];
 
@@ -854,7 +837,6 @@
 	msm_rpm_update_notification(ctx, &msm_rpm_notif_cfgs[ctx], &cfg);
 	mutex_unlock(&msm_rpm_mutex);
 
-unregister_notification_exit:
 	return rc;
 }
 EXPORT_SYMBOL(msm_rpm_unregister_notification);
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 546a917..6282eca 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -895,6 +895,9 @@
 		if (latency_us < level->latency_us)
 			continue;
 
+		if (sleep_us <= level->time_overhead_us)
+			continue;
+
 		if (!msm_rpmrs_irqs_detectable(&level->rs_limits,
 					irqs_detectable, gpio_detectable))
 			continue;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 04dc392..bc4bd21 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -23,6 +23,8 @@
 #include <linux/io.h>
 #include <linux/kthread.h>
 #include <linux/time.h>
+#include <linux/wakelock.h>
+#include <linux/suspend.h>
 
 #include <asm/current.h>
 
@@ -43,9 +45,12 @@
 	struct subsys_data *subsys_ptrs[];
 };
 
-struct restart_thread_data {
+struct restart_wq_data {
 	struct subsys_data *subsys;
+	struct wake_lock ssr_wake_lock;
+	char wakelockname[64];
 	int coupled;
+	struct work_struct work;
 };
 
 struct restart_log {
@@ -56,6 +61,7 @@
 
 static int restart_level;
 static int enable_ramdumps;
+struct workqueue_struct *ssr_wq;
 
 static LIST_HEAD(restart_log_list);
 static LIST_HEAD(subsystem_list);
@@ -297,9 +303,10 @@
 	mutex_unlock(&restart_log_mutex);
 }
 
-static int subsystem_restart_thread(void *data)
+static void subsystem_restart_wq_func(struct work_struct *work)
 {
-	struct restart_thread_data *r_work = data;
+	struct restart_wq_data *r_work = container_of(work,
+						struct restart_wq_data, work);
 	struct subsys_data **restart_list;
 	struct subsys_data *subsys = r_work->subsys;
 	struct subsys_soc_restart_order *soc_restart_order = NULL;
@@ -334,10 +341,8 @@
 	/* Try to acquire shutdown_lock. If this fails, these subsystems are
 	 * already being restarted - return.
 	 */
-	if (!mutex_trylock(shutdown_lock)) {
-		kfree(data);
-		do_exit(0);
-	}
+	if (!mutex_trylock(shutdown_lock))
+		goto out;
 
 	pr_debug("[%p]: Attempting to get powerup lock!\n", current);
 
@@ -430,15 +435,17 @@
 
 	pr_debug("[%p]: Released powerup lock!\n", current);
 
-	kfree(data);
-	do_exit(0);
+out:
+	wake_unlock(&r_work->ssr_wake_lock);
+	wake_lock_destroy(&r_work->ssr_wake_lock);
+	kfree(r_work);
 }
 
 int subsystem_restart(const char *subsys_name)
 {
 	struct subsys_data *subsys;
-	struct task_struct *tsk;
-	struct restart_thread_data *data = NULL;
+	struct restart_wq_data *data = NULL;
+	int rc;
 
 	if (!subsys_name) {
 		pr_err("Invalid subsystem name.\n");
@@ -459,7 +466,7 @@
 	}
 
 	if (restart_level != RESET_SOC) {
-		data = kzalloc(sizeof(struct restart_thread_data), GFP_KERNEL);
+		data = kzalloc(sizeof(struct restart_wq_data), GFP_KERNEL);
 		if (!data) {
 			restart_level = RESET_SOC;
 			pr_warn("Failed to alloc restart data. Resetting.\n");
@@ -482,18 +489,18 @@
 		pr_debug("Restarting %s [level=%d]!\n", subsys_name,
 				restart_level);
 
-		/* Let the kthread handle the actual restarting. Using a
-		 * workqueue will not work since all restart requests are
-		 * serialized and it prevents the short circuiting of
-		 * restart requests for subsystems already in a restart
-		 * sequence.
-		 */
-		tsk = kthread_run(subsystem_restart_thread, data,
-				"subsystem_restart_thread");
-		if (IS_ERR(tsk))
-			panic("%s: Unable to create thread to restart %s",
-				__func__, subsys->name);
+		snprintf(data->wakelockname, sizeof(data->wakelockname),
+				"ssr(%s)", subsys_name);
+		wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND,
+			data->wakelockname);
+		wake_lock(&data->ssr_wake_lock);
 
+		INIT_WORK(&data->work, subsystem_restart_wq_func);
+		rc = schedule_work(&data->work);
+
+		if (rc < 0)
+			panic("%s: Unable to schedule work to restart %s",
+			     __func__, subsys->name);
 		break;
 
 	case RESET_SOC:
@@ -597,6 +604,11 @@
 
 	restart_level = RESET_SOC;
 
+	ssr_wq = alloc_workqueue("ssr_wq", 0, 0);
+
+	if (!ssr_wq)
+		panic("Couldn't allocate workqueue for subsystem restart.\n");
+
 	ret = ssr_init_soc_restart_orders();
 
 	return ret;
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 1bdec12..90948ea 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -84,7 +84,6 @@
 						MODULE_NAME);
 		return IRQ_HANDLED;
 	}
-	disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
 	ss_restart_inprogress = true;
 	ret = schedule_work(&riva_fatal_work);
 	return IRQ_HANDLED;
@@ -115,6 +114,7 @@
 {
 	pil_force_shutdown("wcnss");
 	flush_delayed_work(&cancel_vote_work);
+	disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
 
 	return 0;
 }
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index cde8031..0ff30c3 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,6 +1136,7 @@
 apq8064_cdp		MACH_APQ8064_CDP	APQ8064_CDP		3948
 apq8064_mtp		MACH_APQ8064_MTP	APQ8064_MTP		3949
 apq8064_liquid		MACH_APQ8064_LIQUID	APQ8064_LIQUID		3951
+mpq8064_cdp		MACH_MPQ8064_CDP	MPQ8064_CDP		3993
 mpq8064_hrd		MACH_MPQ8064_HRD	MPQ8064_HRD		3994
 mpq8064_dtv		MACH_MPQ8064_DTV	MPQ8064_DTV		3995
 msm7627a_qrd3		MACH_MSM7627A_QRD3	MSM7627A_QRD3		4005
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 5189388..c3367b5 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -16,6 +16,7 @@
 msm_kgsl_core-$(CONFIG_MSM_KGSL_DRM) += kgsl_drm.o
 msm_kgsl_core-$(CONFIG_MSM_SCM) += kgsl_pwrscale_trustzone.o
 msm_kgsl_core-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += kgsl_pwrscale_idlestats.o
+msm_kgsl_core-$(CONFIG_MSM_DCVS) += kgsl_pwrscale_msm.o
 
 msm_adreno-y += \
 	adreno_ringbuffer.o \
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 8ccd462..6f575ec 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -601,9 +601,7 @@
 
 	mutex_lock(&device->mutex);
 	if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
-		if ((device->requested_state != KGSL_STATE_SLEEP) &&
-			(device->requested_state != KGSL_STATE_SLUMBER))
-			kgsl_pwrscale_idle(device);
+		kgsl_pwrscale_idle(device);
 
 		if (kgsl_pwrctrl_sleep(device) != 0) {
 			mod_timer(&device->idle_timer,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index f474c21..2222cdf 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
 
 #define KGSL_PWRLEVEL_TURBO 0
 #define KGSL_PWRLEVEL_NOMINAL 1
+#define KGSL_PWRLEVEL_LAST_OFFSET 2
 
 #define KGSL_MAX_CLKS 5
 
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index d0b2a41..1cecbc7 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -45,6 +45,9 @@
 #ifdef CONFIG_MSM_SLEEP_STATS_DEVICE
 	&kgsl_pwrscale_policy_idlestats,
 #endif
+#ifdef CONFIG_MSM_DCVS
+	&kgsl_pwrscale_policy_msm,
+#endif
 	NULL
 };
 
diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h
index b4f831e..6023476 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.h
+++ b/drivers/gpu/msm/kgsl_pwrscale.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -54,6 +54,7 @@
 
 extern struct kgsl_pwrscale_policy kgsl_pwrscale_policy_tz;
 extern struct kgsl_pwrscale_policy kgsl_pwrscale_policy_idlestats;
+extern struct kgsl_pwrscale_policy kgsl_pwrscale_policy_msm;
 
 int kgsl_pwrscale_init(struct kgsl_device *device);
 void kgsl_pwrscale_close(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
new file mode 100644
index 0000000..f77a02b
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -0,0 +1,195 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/slab.h>
+#include <mach/msm_dcvs.h>
+#include "kgsl.h"
+#include "kgsl_pwrscale.h"
+#include "kgsl_device.h"
+
+struct msm_priv {
+	struct kgsl_device *device;
+	int enabled;
+	int handle;
+	unsigned int cur_freq;
+	struct msm_dcvs_idle idle_source;
+	struct msm_dcvs_freq freq_sink;
+	struct msm_dcvs_core_info *core_info;
+};
+
+static int msm_idle_enable(struct msm_dcvs_idle *self,
+					enum msm_core_control_event event)
+{
+	struct msm_priv *priv = container_of(self, struct msm_priv,
+								idle_source);
+
+	switch (event) {
+	case MSM_DCVS_ENABLE_IDLE_PULSE:
+		priv->enabled = true;
+		break;
+	case MSM_DCVS_DISABLE_IDLE_PULSE:
+		priv->enabled = false;
+		break;
+	case MSM_DCVS_ENABLE_HIGH_LATENCY_MODES:
+	case MSM_DCVS_DISABLE_HIGH_LATENCY_MODES:
+		break;
+	}
+	return 0;
+}
+
+/* Set the requested frequency if it is within 5MHz (delta) of a
+ * supported frequency.
+ */
+static int msm_set_freq(struct msm_dcvs_freq *self,
+						unsigned int freq)
+{
+	int i, delta = 5000000;
+	struct msm_priv *priv = container_of(self, struct msm_priv,
+								freq_sink);
+	struct kgsl_device *device = priv->device;
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+	/* msm_dcvs manager uses frequencies in kHz */
+	freq *= 1000;
+	for (i = 0; i < pwr->num_pwrlevels; i++)
+		if (abs(pwr->pwrlevels[i].gpu_freq - freq) < delta)
+			break;
+	if (i == pwr->num_pwrlevels)
+		return 0;
+
+	mutex_lock(&device->mutex);
+	kgsl_pwrctrl_pwrlevel_change(device, i);
+	priv->cur_freq = pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq;
+	mutex_unlock(&device->mutex);
+
+	/* return current frequency in kHz */
+	return priv->cur_freq / 1000;
+}
+
+static unsigned int msm_get_freq(struct msm_dcvs_freq *self)
+{
+	struct msm_priv *priv = container_of(self, struct msm_priv,
+								freq_sink);
+	/* return current frequency in kHz */
+	return priv->cur_freq / 1000;
+}
+
+static void msm_busy(struct kgsl_device *device,
+			struct kgsl_pwrscale *pwrscale)
+{
+	struct msm_priv *priv = pwrscale->priv;
+	if (priv->enabled)
+		msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_EXIT, 0);
+	return;
+}
+
+static void msm_idle(struct kgsl_device *device,
+			struct kgsl_pwrscale *pwrscale)
+{
+	struct msm_priv *priv = pwrscale->priv;
+	if (priv->enabled && pwrscale->gpu_busy)
+		msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+
+	return;
+}
+
+static void msm_sleep(struct kgsl_device *device,
+			struct kgsl_pwrscale *pwrscale)
+{
+	/* do we need to reset any parameters here? */
+}
+
+static int msm_init(struct kgsl_device *device,
+		     struct kgsl_pwrscale *pwrscale)
+{
+	struct msm_priv *priv;
+	struct msm_dcvs_freq_entry *tbl;
+	int i, ret, low_level;
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	struct platform_device *pdev =
+		container_of(device->parentdev, struct platform_device, dev);
+	struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+
+	priv = pwrscale->priv = kzalloc(sizeof(struct msm_priv),
+		GFP_KERNEL);
+	if (pwrscale->priv == NULL)
+		return -ENOMEM;
+
+	priv->core_info = pdata->core_info;
+	tbl = priv->core_info->freq_tbl;
+	/* Fill in frequency table from low to high, reversing order. */
+	low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
+	for (i = 0; i <= low_level; i++)
+		tbl[i].freq =
+			pwr->pwrlevels[low_level - i].gpu_freq / 1000;
+	ret = msm_dcvs_register_core(device->name, 0, priv->core_info);
+	if (ret) {
+		KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
+		goto err;
+	}
+
+	priv->device = device;
+	priv->idle_source.enable = msm_idle_enable;
+	priv->idle_source.core_name = device->name;
+	priv->handle = msm_dcvs_idle_source_register(&priv->idle_source);
+	if (priv->handle < 0) {
+		ret = priv->handle;
+		KGSL_PWR_ERR(device, "msm_dcvs_idle_source_register failed\n");
+		goto err;
+	}
+
+	priv->freq_sink.core_name = device->name;
+	priv->freq_sink.set_frequency = msm_set_freq;
+	priv->freq_sink.get_frequency = msm_get_freq;
+	ret = msm_dcvs_freq_sink_register(&priv->freq_sink);
+	if (ret >= 0) {
+		if (device->ftbl->isidle(device)) {
+			device->pwrscale.gpu_busy = 0;
+			msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+		} else {
+			device->pwrscale.gpu_busy = 1;
+		}
+		return 0;
+	}
+
+	KGSL_PWR_ERR(device, "msm_dcvs_freq_sink_register failed\n");
+	msm_dcvs_idle_source_unregister(&priv->idle_source);
+
+err:
+	kfree(pwrscale->priv);
+	pwrscale->priv = NULL;
+
+	return ret;
+}
+
+static void msm_close(struct kgsl_device *device,
+		      struct kgsl_pwrscale *pwrscale)
+{
+	struct msm_priv *priv = pwrscale->priv;
+
+	if (pwrscale->priv == NULL)
+		return;
+	msm_dcvs_idle_source_unregister(&priv->idle_source);
+	msm_dcvs_freq_sink_unregister(&priv->freq_sink);
+	kfree(pwrscale->priv);
+	pwrscale->priv = NULL;
+}
+
+struct kgsl_pwrscale_policy kgsl_pwrscale_policy_msm = {
+	.name = "msm",
+	.init = msm_init,
+	.idle = msm_idle,
+	.busy = msm_busy,
+	.sleep = msm_sleep,
+	.close = msm_close,
+};
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index d083702..5634a19 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -443,7 +443,7 @@
 		sg_set_page(&memdesc->sg[i], page, PAGE_SIZE, 0);
 	}
 
-	kgsl_cache_range_op(memdesc, KGSL_CACHE_OP_INV);
+	kgsl_cache_range_op(memdesc, KGSL_CACHE_OP_FLUSH);
 
 	ret = kgsl_mmu_map(pagetable, memdesc, protflags);
 
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index a9b8e40..6744479 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -21,27 +21,22 @@
 #include <media/rc-core.h>
 #include <media/gpio-ir-recv.h>
 
-#define TSOP_DRIVER_NAME	"gpio-rc-recv"
-#define TSOP_DEVICE_NAME	"gpio_ir_recv"
+#define GPIO_IR_DRIVER_NAME	"gpio-rc-recv"
+#define GPIO_IR_DEVICE_NAME	"gpio_ir_recv"
 
 struct gpio_rc_dev {
 	struct rc_dev *rcdev;
-	struct mutex lock;
 	unsigned int gpio_nr;
 	bool active_low;
-	bool can_wakeup;
-	struct work_struct work;
 };
 
-static void ir_decoder_work(struct work_struct *work)
+static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
 {
-	struct gpio_rc_dev *gpio_dev = container_of(work,
-			struct gpio_rc_dev, work);
+	struct gpio_rc_dev *gpio_dev = dev_id;
 	unsigned int gval;
 	int rc = 0;
 	enum raw_event_type type = IR_SPACE;
 
-	mutex_lock(&gpio_dev->lock);
 	gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
 
 	if (gval < 0)
@@ -60,15 +55,6 @@
 	ir_raw_event_handle(gpio_dev->rcdev);
 
 err_get_value:
-	mutex_unlock(&gpio_dev->lock);
-}
-
-static irqreturn_t gpio_ir_recv_irq_handler(int irq, void *data)
-{
-	struct gpio_rc_dev *gpio_dev = data;
-
-	schedule_work(&gpio_dev->work);
-
 	return IRQ_HANDLED;
 }
 
@@ -78,7 +64,7 @@
 	struct rc_dev *rcdev;
 	const struct gpio_ir_recv_platform_data *pdata =
 					pdev->dev.platform_data;
-	int rc = 0;
+	int rc;
 
 	if (!pdata)
 		return -EINVAL;
@@ -90,8 +76,6 @@
 	if (!gpio_dev)
 		return -ENOMEM;
 
-	mutex_init(&gpio_dev->lock);
-
 	rcdev = rc_allocate_device();
 	if (!rcdev) {
 		rc = -ENOMEM;
@@ -99,18 +83,15 @@
 	}
 
 	rcdev->driver_type = RC_DRIVER_IR_RAW;
-	rcdev->allowed_protos = RC_TYPE_NEC;
-	rcdev->input_name = TSOP_DEVICE_NAME;
+	rcdev->allowed_protos = RC_TYPE_ALL;
+	rcdev->input_name = GPIO_IR_DEVICE_NAME;
 	rcdev->input_id.bustype = BUS_HOST;
-	rcdev->driver_name = TSOP_DRIVER_NAME;
-	rcdev->map_name = RC_MAP_SAMSUNG_NECX;
+	rcdev->driver_name = GPIO_IR_DRIVER_NAME;
+	rcdev->map_name = RC_MAP_EMPTY;
 
 	gpio_dev->rcdev = rcdev;
 	gpio_dev->gpio_nr = pdata->gpio_nr;
 	gpio_dev->active_low = pdata->active_low;
-	gpio_dev->can_wakeup = pdata->can_wakeup;
-
-	INIT_WORK(&gpio_dev->work, ir_decoder_work);
 
 	rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
 	if (rc < 0)
@@ -127,22 +108,15 @@
 
 	platform_set_drvdata(pdev, gpio_dev);
 
-	rc = request_irq(gpio_to_irq(pdata->gpio_nr), gpio_ir_recv_irq_handler,
+	rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),
+				gpio_ir_recv_irq,
 			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-			"gpio-ir-recv-irq", gpio_dev);
+					"gpio-ir-recv-irq", gpio_dev);
 	if (rc < 0)
 		goto err_request_irq;
 
-	if (pdata->can_wakeup == true) {
-		rc = enable_irq_wake(gpio_to_irq(pdata->gpio_nr));
-		if (rc < 0)
-			goto err_enable_irq_wake;
-	}
-
 	return 0;
 
-err_enable_irq_wake:
-	free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
 err_request_irq:
 	platform_set_drvdata(pdev, NULL);
 	rc_unregister_device(rcdev);
@@ -153,7 +127,6 @@
 	rc_free_device(rcdev);
 	rcdev = NULL;
 err_allocate_device:
-	mutex_destroy(&gpio_dev->lock);
 	kfree(gpio_dev);
 	return rc;
 }
@@ -162,24 +135,57 @@
 {
 	struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
 
-	flush_work_sync(&gpio_dev->work);
-	disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
 	free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
 	platform_set_drvdata(pdev, NULL);
 	rc_unregister_device(gpio_dev->rcdev);
 	gpio_free(gpio_dev->gpio_nr);
 	rc_free_device(gpio_dev->rcdev);
-	mutex_destroy(&gpio_dev->lock);
 	kfree(gpio_dev);
 	return 0;
 }
 
+#ifdef CONFIG_PM
+static int gpio_ir_recv_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
+	else
+		disable_irq(gpio_to_irq(gpio_dev->gpio_nr));
+
+	return 0;
+}
+
+static int gpio_ir_recv_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
+	else
+		enable_irq(gpio_to_irq(gpio_dev->gpio_nr));
+
+	return 0;
+}
+
+static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
+	.suspend        = gpio_ir_recv_suspend,
+	.resume         = gpio_ir_recv_resume,
+};
+#endif
+
 static struct platform_driver gpio_ir_recv_driver = {
 	.probe  = gpio_ir_recv_probe,
 	.remove = __devexit_p(gpio_ir_recv_remove),
 	.driver = {
-		.name   = TSOP_DRIVER_NAME,
+		.name   = GPIO_IR_DRIVER_NAME,
 		.owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &gpio_ir_recv_pm_ops,
+#endif
 	},
 };
 
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 175a441..8d59590 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1366,6 +1366,14 @@
 		return rc;
 	}
 
+	/* The number of camera instance should be controlled by the
+		resource manager. Currently supporting one active instance
+		until multiple instances are supported */
+	if (atomic_read(&ps->number_pcam_active) > 0) {
+		pr_err("%s Cannot have more than one active camera %d\n",
+			__func__, atomic_read(&ps->number_pcam_active));
+		return -EINVAL;
+	}
 	/* book keeping this camera session*/
 	ps->pcam_active = pcam;
 	atomic_inc(&ps->number_pcam_active);
@@ -1411,6 +1419,9 @@
 {
 	int i;
 	int rc = -EINVAL;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+	int ion_client_created = 0;
+#endif
 	/*struct msm_isp_ops *p_isp = 0;*/
 	/* get the video device */
 	struct msm_cam_v4l2_device *pcam  = video_drvdata(f);
@@ -1442,7 +1453,9 @@
 	pcam_inst->pcam = pcam;
 	pcam->dev_inst[i] = pcam_inst;
 
-	D("%s for %s\n", __func__, pcam->pdev->name);
+	D("%s index %d nodeid %d count %d\n", __func__,
+			pcam_inst->my_index,
+			pcam->vnode_id, pcam->use_count);
 	pcam->use_count++;
 	if (pcam->use_count == 1) {
 
@@ -1450,19 +1463,19 @@
 		if (rc < 0) {
 			pr_err("%s: cam_server_open_session failed %d\n",
 			__func__, rc);
-			mutex_unlock(&pcam->vid_lock);
-			return rc;
+			goto err;
 		}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		pcam->mctl.client = msm_ion_client_create(-1, "camera");
 		kref_init(&pcam->mctl.refcount);
+		ion_client_created = 1;
 #endif
 		/* Should be set to sensor ops if any but right now its OK!! */
 		if (!pcam->mctl.mctl_open) {
 			D("%s: media contoller is not inited\n",
 				 __func__);
-			mutex_unlock(&pcam->vid_lock);
-			return -ENODEV;
+			rc = -ENODEV;
+			goto err;
 		}
 
 		/* Now we really have to activate the camera */
@@ -1470,9 +1483,8 @@
 		rc = pcam->mctl.mctl_open(&(pcam->mctl), MSM_APPS_ID_V4L2);
 
 		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s: HW open failed rc = 0x%x\n",  __func__, rc);
-			return rc;
+			goto err;
 		}
 		pcam->mctl.sync.pcam_sync = pcam;
 
@@ -1480,24 +1492,21 @@
 		rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
 					pcam->mctl.isp_sdev->sd);
 		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
 			pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
 				__func__, rc);
-			return rc;
+			goto err;
 		}
 		if (pcam->mctl.isp_sdev->sd_vpe) {
 			rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
 						pcam->mctl.isp_sdev->sd_vpe);
 			if (rc < 0) {
-				mutex_unlock(&pcam->vid_lock);
-				return rc;
+				goto err;
 			}
 		}
 		rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
 							pcam->pvdev);
 		if (rc < 0) {
-			mutex_unlock(&pcam->vid_lock);
-			return rc;
+			goto err;
 		}
 	}
 	pcam_inst->vbqueue_initialized = 0;
@@ -1522,6 +1531,21 @@
 	D("%s: end", __func__);
 	/* rc = msm_cam_server_open_session(g_server_dev, pcam);*/
 	return rc;
+
+err:
+	if (pcam->use_count == 1) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		if (ion_client_created) {
+			pr_err("%s: destroy ion client", __func__);
+			kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+		}
+#endif
+		pcam->dev_inst[i] = NULL;
+		pcam->use_count = 0;
+	}
+	mutex_unlock(&pcam->vid_lock);
+	kfree(pcam_inst);
+	return rc;
 }
 
 static int msm_addr_remap(struct msm_cam_v4l2_dev_inst *pcam_inst,
@@ -1622,6 +1646,8 @@
 	if (pcam_inst->vbqueue_initialized)
 		vb2_queue_release(&pcam_inst->vid_bufq);
 	D("%s Closing down instance %p ", __func__, pcam_inst);
+	D("%s index %d nodeid %d count %d\n", __func__, pcam_inst->my_index,
+		pcam->vnode_id, pcam->use_count);
 	pcam->dev_inst[pcam_inst->my_index] = NULL;
 	if (pcam_inst->my_index == 0) {
 		v4l2_fh_del(&pcam_inst->eventHandle);
@@ -2638,7 +2664,7 @@
 
 	D("%s done, rc = %d\n", __func__, rc);
 	D("%s number of sensors connected is %d\n", __func__,
-			g_server_dev.camera_info.num_cameras);
+		g_server_dev.camera_info.num_cameras);
 
 	/* register the subdevice, must be done for callbacks */
 	rc = v4l2_device_register_subdev(&pcam->v4l2_dev, sensor_sd);
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index b655848..64c0bd1 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -999,6 +999,10 @@
 {
 	int rc;
 
+	/* dVdd preloading is not needed for PMIC PM8901 rev 2.3 and beyond. */
+	if (pm8xxx_get_revision(chip->dev->parent) >= PM8XXX_REVISION_8901_2p3)
+		return 0;
+
 	rc = pm8xxx_writeb(chip->dev->parent, 0x0BD, 0x0F);
 	if (rc)
 		pr_err("pm8xxx_writeb failed for 0x0BD, rc=%d\n", rc);
diff --git a/drivers/mfd/pmic8901.c b/drivers/mfd/pmic8901.c
index aec382a..63ea55a 100644
--- a/drivers/mfd/pmic8901.c
+++ b/drivers/mfd/pmic8901.c
@@ -270,11 +270,23 @@
 	return rc;
 }
 
+static const char * const pm8901_rev_names[] = {
+	[PM8XXX_REVISION_8901_TEST]	= "test",
+	[PM8XXX_REVISION_8901_1p0]	= "1.0",
+	[PM8XXX_REVISION_8901_1p1]	= "1.1",
+	[PM8XXX_REVISION_8901_2p0]	= "2.0",
+	[PM8XXX_REVISION_8901_2p1]	= "2.1",
+	[PM8XXX_REVISION_8901_2p2]	= "2.2",
+	[PM8XXX_REVISION_8901_2p3]	= "2.3",
+};
+
 static int __devinit pm8901_probe(struct platform_device *pdev)
 {
 	int rc;
 	struct pm8901_platform_data *pdata = pdev->dev.platform_data;
+	const char *revision_name = "unknown";
 	struct pm8901_chip *pmic;
+	int revision;
 
 	if (pdata == NULL) {
 		pr_err("%s: No platform_data or IRQ.\n", __func__);
@@ -298,7 +310,11 @@
 		pr_err("%s: Failed reading version register rc=%d.\n",
 			__func__, rc);
 
-	pr_info("%s: PMIC REVISION = %X\n", __func__, pmic->revision);
+	pr_info("%s: PMIC revision reg: %02X\n", __func__, pmic->revision);
+	revision =  pm8xxx_get_revision(pmic->dev);
+	if (revision >= 0 && revision < ARRAY_SIZE(pm8901_rev_names))
+		revision_name = pm8901_rev_names[revision];
+	pr_info("%s: PMIC version: PM8901 rev %s\n", __func__, revision_name);
 
 	(void) memcpy((void *)&pmic->pdata, (const void *)pdata,
 		      sizeof(pmic->pdata));
diff --git a/drivers/misc/pmic8058-xoadc.c b/drivers/misc/pmic8058-xoadc.c
index 14b790f..3452672 100644
--- a/drivers/misc/pmic8058-xoadc.c
+++ b/drivers/misc/pmic8058-xoadc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -650,23 +650,6 @@
 #define PM8058_XOADC_DEV_PM_OPS NULL
 #endif
 
-static int __devexit pm8058_xoadc_teardown(struct platform_device *pdev)
-{
-	struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
-
-	if (adc_pmic->pdata->xoadc_vreg_shutdown != NULL)
-		adc_pmic->pdata->xoadc_vreg_shutdown();
-
-	wake_lock_destroy(&adc_pmic->adc_wakelock);
-	msm_xo_put(adc_pmic->adc_voter);
-	platform_set_drvdata(pdev, NULL);
-	device_init_wakeup(&pdev->dev, 0);
-	kfree(adc_pmic);
-	xoadc_initialized = false;
-
-	return 0;
-}
-
 static int __devinit pm8058_xoadc_probe(struct platform_device *pdev)
 {
 	struct xoadc_platform_data *pdata = pdev->dev.platform_data;
@@ -678,7 +661,7 @@
 		return -EINVAL;
 	}
 
-	adc_pmic = kzalloc(sizeof(struct pmic8058_adc), GFP_KERNEL);
+	adc_pmic = devm_kzalloc(&pdev->dev, sizeof(*adc_pmic), GFP_KERNEL);
 	if (!adc_pmic) {
 		dev_err(&pdev->dev, "Unable to allocate memory\n");
 		return -ENOMEM;
@@ -693,17 +676,16 @@
 
 	if (adc_pmic->xoadc_num > XOADC_PMIC_0) {
 		dev_err(&pdev->dev, "ADC device not supported\n");
-		rc = -EINVAL;
-		goto err_cleanup;
+		return -EINVAL;
 	}
 
 	adc_pmic->pdata = pdata;
-	adc_pmic->adc_graph = kzalloc(sizeof(struct linear_graph)
-			* MAX_CHANNEL_PROPERTIES_QUEUE, GFP_KERNEL);
+	adc_pmic->adc_graph = devm_kzalloc(&pdev->dev,
+		sizeof(struct linear_graph) * MAX_CHANNEL_PROPERTIES_QUEUE,
+		GFP_KERNEL);
 	if (!adc_pmic->adc_graph) {
 		dev_err(&pdev->dev, "Unable to allocate memory\n");
-		rc = -ENOMEM;
-		goto err_cleanup;
+		return -ENOMEM;
 	}
 
 	/* Will be replaced by individual channel calibration */
@@ -739,32 +721,29 @@
 	INIT_LIST_HEAD(&adc_pmic->conv_queue_list->slots);
 
 	adc_pmic->adc_irq = platform_get_irq(pdev, 0);
-	if (adc_pmic->adc_irq < 0) {
-		rc = -ENXIO;
-		goto err_cleanup;
-	}
+	if (adc_pmic->adc_irq < 0)
+		return -ENXIO;
 
 	rc = request_threaded_irq(adc_pmic->adc_irq,
 				NULL, pm8058_xoadc,
 		IRQF_TRIGGER_RISING, "pm8058_adc_interrupt", adc_pmic);
 	if (rc) {
 		dev_err(&pdev->dev, "failed to request adc irq\n");
-		goto err_cleanup;
+		return rc;
 	}
 
 	disable_irq(adc_pmic->adc_irq);
 
-	device_init_wakeup(&pdev->dev, pdata->xoadc_wakeup);
-
 	if (adc_pmic->adc_voter == NULL) {
 		adc_pmic->adc_voter = msm_xo_get(MSM_XO_TCXO_D1,
 							"pmic8058_xoadc");
 		if (IS_ERR(adc_pmic->adc_voter)) {
 			dev_err(&pdev->dev, "Failed to get XO vote\n");
-			goto err_cleanup;
+			return PTR_ERR(adc_pmic->adc_voter);
 		}
 	}
 
+	device_init_wakeup(&pdev->dev, pdata->xoadc_wakeup);
 	wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
 					"pmic8058_xoadc_wakelock");
 
@@ -777,11 +756,21 @@
 	xoadc_calib_first_adc = false;
 
 	return 0;
+}
 
-err_cleanup:
-	pm8058_xoadc_teardown(pdev);
+static int __devexit pm8058_xoadc_teardown(struct platform_device *pdev)
+{
+	struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
 
-	return rc;
+	if (adc_pmic->pdata->xoadc_vreg_shutdown != NULL)
+		adc_pmic->pdata->xoadc_vreg_shutdown();
+
+	wake_lock_destroy(&adc_pmic->adc_wakelock);
+	msm_xo_put(adc_pmic->adc_voter);
+	device_init_wakeup(&pdev->dev, 0);
+	xoadc_initialized = false;
+
+	return 0;
 }
 
 static struct platform_driver pm8058_xoadc_driver = {
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 26a69f1..60e1e55 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1132,11 +1132,13 @@
 	int ret = 0;
 
 	if (!qsee_perf_client)
-		return -EINVAL;
+		return ret;
 
 	/* Check if the clk is valid */
-	if (IS_ERR_OR_NULL(qseecom_bus_clk))
+	if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
+		pr_warn("qseecom bus clock is null or error");
 		return -EINVAL;
+	}
 
 	mutex_lock(&qsee_bw_mutex);
 	if (!qsee_bw_count) {
@@ -1166,8 +1168,10 @@
 		return;
 
 	/* Check if the clk is valid */
-	if (IS_ERR_OR_NULL(qseecom_bus_clk))
+	if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
+		pr_warn("qseecom bus clock is null or error");
 		return;
+	}
 
 	mutex_lock(&qsee_bw_mutex);
 	if (qsee_bw_count > 0) {
@@ -1420,6 +1424,10 @@
 	char qsee_not_legacy = 0;
 	uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
 
+	qsee_bw_count = 0;
+	qseecom_bus_clk = NULL;
+	qsee_perf_client = 0;
+
 	rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
 	if (rc < 0) {
 		pr_err("alloc_chrdev_region failed %d\n", rc);
@@ -1483,8 +1491,8 @@
 					&qsee_bus_pdata);
 	if (!qsee_perf_client) {
 		pr_err("Unable to register bus client\n");
-
-		qseecom_bus_clk = clk_get(class_dev, "qseecom");
+	} else {
+		qseecom_bus_clk = clk_get(class_dev, "bus_clk");
 		if (IS_ERR(qseecom_bus_clk)) {
 			qseecom_bus_clk = NULL;
 		} else if (qseecom_bus_clk != NULL) {
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
index 112497c..61085c9 100644
--- a/drivers/of/of_spmi.c
+++ b/drivers/of/of_spmi.c
@@ -203,9 +203,18 @@
 	struct device_node *node;
 	int rc, i, num_dev_node = 0;
 
-	/* first count the total number of device_nodes */
-	for_each_child_of_node(container, node)
+	if (!of_device_is_available(container))
+		return;
+
+	/*
+	 * Count the total number of device_nodes so we know how much
+	 * device_store to allocate.
+	 */
+	for_each_child_of_node(container, node) {
+		if (!of_device_is_available(node))
+			continue;
 		num_dev_node++;
+	}
 
 	rc = of_spmi_alloc_device_store(d_info, num_dev_node);
 	if (rc) {
@@ -214,9 +223,10 @@
 		return;
 	}
 
-	/* allocate resources per device_node */
 	i = 0;
 	for_each_child_of_node(container, node) {
+		if (!of_device_is_available(node))
+			continue;
 		of_spmi_init_resource(&r_info, node);
 		of_spmi_sum_node_resources(&r_info, 1);
 		rc = of_spmi_allocate_node_resources(d_info, &r_info, i);
@@ -226,17 +236,6 @@
 			of_spmi_free_device_resources(d_info);
 			return;
 		}
-		i++;
-	}
-
-	/**
-	 * Now we need to cycle through again and actually populate
-	 * the resources for each node.
-	 */
-	i = 0;
-	for_each_child_of_node(container, node) {
-		of_spmi_init_resource(&r_info, node);
-		of_spmi_sum_node_resources(&r_info, 1);
 		of_spmi_populate_node_resources(d_info, &r_info, i);
 		i++;
 	}
@@ -265,6 +264,9 @@
 	for_each_child_of_node(container, node) {
 		struct of_spmi_res_info r_info;
 
+		if (!of_device_is_available(node))
+			continue;
+
 		/**
 		 * Check to see if this node contains children which
 		 * should be all created as the same spmi_device.
@@ -365,6 +367,9 @@
 				continue;
 			}
 
+			if (!of_device_is_available(node))
+				continue;
+
 			rc = of_spmi_alloc_device_store(&d_info, 1);
 			if (rc) {
 				dev_err(&ctrl->dev, "%s: unable to allocate"
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 9a8d552..285d1de 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -141,6 +141,16 @@
 	return UART_TO_MSM(port)->is_uartdm;
 }
 
+static int get_line(struct platform_device *pdev)
+{
+	const struct msm_serial_hslite_platform_data *pdata =
+					pdev->dev.platform_data;
+	if (pdata)
+		return pdata->line;
+
+	return pdev->id;
+}
+
 static int clk_en(struct uart_port *port, int enable)
 {
 	struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
@@ -1243,7 +1253,7 @@
 	struct uart_port *port;
 
 	struct platform_device *pdev = to_platform_device(dev);
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 
 	enable = get_console_state(port);
 
@@ -1264,7 +1274,7 @@
 	struct uart_port *port;
 
 	struct platform_device *pdev = to_platform_device(dev);
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 
 	cur_state = get_console_state(port);
 	enable = buf[0] - '0';
@@ -1332,12 +1342,12 @@
 	if (pdev->id == -1)
 		pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;
 
-	if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
+	if (unlikely(get_line(pdev) < 0 || get_line(pdev) >= UART_NR))
 		return -ENXIO;
 
 	printk(KERN_INFO "msm_serial_hsl: detected port #%d\n", pdev->id);
 
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 	port->dev = &pdev->dev;
 	msm_hsl_port = UART_TO_MSM(port);
 
@@ -1395,7 +1405,7 @@
 	if (unlikely(ret))
 		pr_err("%s():Can't create console attribute\n", __func__);
 #endif
-	msm_hsl_debugfs_init(msm_hsl_port, pdev->id);
+	msm_hsl_debugfs_init(msm_hsl_port, get_line(pdev));
 
 	/* Temporarily increase the refcount on the GSBI clock to avoid a race
 	 * condition with the earlyprintk handover mechanism.
@@ -1413,7 +1423,7 @@
 	struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
 	struct uart_port *port;
 
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 #ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
 	device_remove_file(&pdev->dev, &dev_attr_console);
 #endif
@@ -1436,7 +1446,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct uart_port *port;
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 
 	if (port) {
 
@@ -1455,7 +1465,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct uart_port *port;
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 
 	if (port) {
 
@@ -1478,7 +1488,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct uart_port *port;
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 
 	dev_dbg(dev, "pm_runtime: suspending\n");
 	msm_hsl_deinit_clock(port);
@@ -1489,7 +1499,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct uart_port *port;
-	port = get_port_from_line(pdev->id);
+	port = get_port_from_line(get_line(pdev));
 
 	dev_dbg(dev, "pm_runtime: resuming\n");
 	msm_hsl_init_clock(port);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index ee44846..3e5c6f1 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -183,6 +183,12 @@
 	.bConfigurationValue = 1,
 };
 
+enum android_device_state {
+	USB_DISCONNECTED,
+	USB_CONNECTED,
+	USB_CONFIGURED,
+};
+
 static void android_work(struct work_struct *data)
 {
 	struct android_dev *dev = container_of(data, struct android_dev, work);
@@ -191,18 +197,45 @@
 	char *connected[2]    = { "USB_STATE=CONNECTED", NULL };
 	char *configured[2]   = { "USB_STATE=CONFIGURED", NULL };
 	char **uevent_envp = NULL;
+	static enum android_device_state last_uevent, next_state;
 	unsigned long flags;
 
 	spin_lock_irqsave(&cdev->lock, flags);
-        if (cdev->config)
+	if (cdev->config) {
 		uevent_envp = configured;
-	else if (dev->connected != dev->sw_connected)
+		next_state = USB_CONFIGURED;
+	} else if (dev->connected != dev->sw_connected) {
 		uevent_envp = dev->connected ? connected : disconnected;
+		next_state = dev->connected ? USB_CONNECTED : USB_DISCONNECTED;
+	}
 	dev->sw_connected = dev->connected;
 	spin_unlock_irqrestore(&cdev->lock, flags);
 
 	if (uevent_envp) {
+		/*
+		 * Some userspace modules, e.g. MTP, work correctly only if
+		 * CONFIGURED uevent is preceded by DISCONNECT uevent.
+		 * Check if we missed sending out a DISCONNECT uevent. This can
+		 * happen if host PC resets and configures device really quick.
+		 */
+		if (((uevent_envp == connected) &&
+		      (last_uevent != USB_DISCONNECTED)) ||
+		    ((uevent_envp == configured) &&
+		      (last_uevent == USB_CONFIGURED))) {
+			pr_info("%s: sent missed DISCONNECT event\n", __func__);
+			kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
+								disconnected);
+			msleep(20);
+		}
+		/*
+		 * Before sending out CONFIGURED uevent give function drivers
+		 * a chance to wakeup userspace threads and notify disconnect
+		 */
+		if (uevent_envp == configured)
+			msleep(50);
+
 		kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
+		last_uevent = next_state;
 		pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
 	} else {
 		pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index c4c7941..72bff49 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -664,21 +664,20 @@
 	struct usb_diag_ch *ch;
 
 	list_for_each_entry(ch, &usb_diag_ch_list, list) {
-		struct diag_context *ctxt;
+		struct diag_context *ctxt = ch->priv_usb;
 
-		ctxt = ch->priv_usb;
-
-		temp += scnprintf(buf + temp, PAGE_SIZE - temp,
-				"---Name: %s---\n"
-				"endpoints: %s, %s\n"
-				"dpkts_tolaptop: %lu\n"
-				"dpkts_tomodem:  %lu\n"
-				"pkts_tolaptop_pending: %u\n",
-				ch->name,
-				ctxt->in->name, ctxt->out->name,
-				ctxt->dpkts_tolaptop,
-				ctxt->dpkts_tomodem,
-				ctxt->dpkts_tolaptop_pending);
+		if (ctxt)
+			temp += scnprintf(buf + temp, PAGE_SIZE - temp,
+					"---Name: %s---\n"
+					"endpoints: %s, %s\n"
+					"dpkts_tolaptop: %lu\n"
+					"dpkts_tomodem:  %lu\n"
+					"pkts_tolaptop_pending: %u\n",
+					ch->name,
+					ctxt->in->name, ctxt->out->name,
+					ctxt->dpkts_tolaptop,
+					ctxt->dpkts_tomodem,
+					ctxt->dpkts_tolaptop_pending);
 	}
 
 	return simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -690,13 +689,13 @@
 	struct usb_diag_ch *ch;
 
 	list_for_each_entry(ch, &usb_diag_ch_list, list) {
-		struct diag_context *ctxt;
+		struct diag_context *ctxt = ch->priv_usb;
 
-		ctxt = ch->priv_usb;
-
-		ctxt->dpkts_tolaptop = 0;
-		ctxt->dpkts_tomodem = 0;
-		ctxt->dpkts_tolaptop_pending = 0;
+		if (ctxt) {
+			ctxt->dpkts_tolaptop = 0;
+			ctxt->dpkts_tomodem = 0;
+			ctxt->dpkts_tolaptop_pending = 0;
+		}
 	}
 
 	return count;
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index e6c869f..5a72ad4 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -3,6 +3,8 @@
 obj-$(CONFIG_FB_MSM_LOGO) += logo.o
 obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
 
+ifeq ($(CONFIG_FB_MSM_MDP_HW),y)
+
 # MDP
 obj-y += mdp.o
 
@@ -177,6 +179,12 @@
 
 obj-$(CONFIG_MSM_VIDC_1080P) += vidc/
 obj-$(CONFIG_MSM_VIDC_720P) += vidc/
+else
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_host.o
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL) += ebi2_epson_s1d_qvga.o
+endif
 
 clean:
 	rm *.o .*cmd
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
index 7386983..df501dd 100644
--- a/drivers/video/msm/adv7520.c
+++ b/drivers/video/msm/adv7520.c
@@ -874,11 +874,11 @@
 	} else
 		DEV_ERR("adv7520_probe: failed to add fb device\n");
 
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-	external_common_state->sdev.name = "hdmi_as_primary";
-#else
-	external_common_state->sdev.name = "hdmi";
-#endif
+	if (hdmi_prim_display)
+		external_common_state->sdev.name = "hdmi_as_primary";
+	else
+		external_common_state->sdev.name = "hdmi";
+
 	if (switch_dev_register(&external_common_state->sdev) < 0)
 		DEV_ERR("Hdmi switch registration failed\n");
 
diff --git a/drivers/video/msm/ebi2_epson_s1d_qvga.c b/drivers/video/msm/ebi2_epson_s1d_qvga.c
new file mode 100644
index 0000000..8821eab
--- /dev/null
+++ b/drivers/video/msm/ebi2_epson_s1d_qvga.c
@@ -0,0 +1,374 @@
+/* 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 "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#define CMD_NOP_C							0x00
+#define CMD_SOFT_RESET_C					0x99
+#define CMD_DISPLAY_ON_C					0xAF
+#define CMD_DISPLAY_OFF_C					0xAE
+#define CMD_SET_DISPLAY_C					0xCA
+#define CMD_SET_DISPLAY_TIMING_C			0xA1
+#define CMD_SET_DATA_C						0xBC
+#define CMD_SET_START_ADDRESS_C				0x15
+#define CMD_SET_END_ADDRESS_C				0x75
+#define CMD_RAM_WRITE_C						0x5C
+#define CMD_RAM_READ_C						0x5D
+#define CMD_SET_AREA_SCROLLING_C			0xAA
+#define CMD_SET_DISPLAY_START_LINE_C		0xAB
+#define CMD_PARTIAL_DISPLAY_IN_C			0xA8
+#define CMD_PARTIAL_DISPLAY_OUT_C			0xA9
+#define CMD_SET_DISPLAY_DATA_INTERFACE_C	0x31
+#define CMD_SET_DISPLAY_COLOR_MODE_C		0x8B
+#define CMD_SELECT_MTP_ROM_MODE_C			0x65
+#define CMD_MTP_ROM_MODE_IN_C				0x67
+#define CMD_MTP_ROM_MODE_OUT_C				0x68
+#define CMD_MTP_ROM_OPERATION_IN_C			0x69
+#define CMD_MTP_ROM_OPERATION_OUT_C			0x70
+#define CMD_GATE_LINE_SCAN_MODE_C			0x6F
+#define CMD_SET_AC_OPERATION_DRIVE_C		0x8C
+#define CMD_SET_ELECTRONIC_CONTROL_C		0x20
+#define CMD_SET_POSITIVE_CORRECTION_CHARS_C	0x22
+#define CMD_SET_NEGATIVE_CORRECTION_CHARS_C	0x25
+#define CMD_SET_POWER_CONTROL_C				0x21
+#define CMD_SET_PARTIAL_POWER_CONTROL_C		0x23
+#define CMD_SET_8_COLOR_CONTROL_C			0x24
+#define CMD_SLEEP_IN_C						0x95
+#define CMD_SLEEP_OUT_C						0x94
+#define CMD_VDD_OFF_C						0x97
+#define CMD_VDD_ON_C						0x96
+#define CMD_STOP_OSCILLATION_C				0x93
+#define CMD_START_OSCILLATION_C				0x92
+#define CMD_TEST_SOURCE_C					0xFD
+#define CMD_TEST_FUSE_C						0xFE
+#define CMD_TEST_C							0xFF
+#define CMD_STATUS_READ_C					0xE8
+#define CMD_REVISION_READ_C					0xE9
+
+#define PANEL_WIDTH			240
+#define PANEL_HEIGHT		320
+#define ACTIVE_WIN_WIDTH	PANEL_WIDTH
+#define ACTIVE_WIN_HEIGHT	PANEL_HEIGHT
+
+#define ACTIVE_WIN_H_START	0
+#define ACTIVE_WIN_V_START	0
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, (cmd << 1));
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, (data << 1));
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+static boolean disp_initialized;
+static boolean display_on;
+static struct msm_panel_common_pdata *ebi2_epson_pdata;
+
+static void epson_s1d_disp_init(struct platform_device *pdev);
+static int epson_s1d_disp_off(struct platform_device *pdev);
+static int epson_s1d_disp_on(struct platform_device *pdev);
+static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres);
+
+static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres)
+{
+	int right, bottom;
+
+	if (!disp_initialized)
+		return;
+
+	right = x + xres - 1;
+	bottom = y + yres - 1;
+
+	x += ACTIVE_WIN_H_START;
+	y += ACTIVE_WIN_V_START;
+	right += ACTIVE_WIN_H_START;
+	bottom += ACTIVE_WIN_V_START;
+
+	if ((PANEL_WIDTH  > x) &&
+		(PANEL_HEIGHT > y) &&
+		(PANEL_WIDTH > right) &&
+		(PANEL_HEIGHT > bottom)) {
+		DISP_CMD_OUT(CMD_SET_START_ADDRESS_C);
+		DISP_DATA_OUT((uint8)x);
+		DISP_DATA_OUT((uint8)(y>>8));
+		DISP_DATA_OUT((uint8)y);
+
+		DISP_CMD_OUT(CMD_SET_END_ADDRESS_C);
+		DISP_DATA_OUT((uint8)right);
+		DISP_DATA_OUT((uint8)(bottom>>8));
+		DISP_DATA_OUT((uint8)bottom);
+		DISP_CMD_OUT(CMD_RAM_WRITE_C);
+	}
+}
+
+static void epson_s1d_disp_init(struct platform_device *pdev)
+{
+	struct msm_fb_data_type *mfd;
+
+	if (disp_initialized)
+		return;
+
+	mfd = platform_get_drvdata(pdev);
+
+	DISP_CMD_PORT = mfd->cmd_port;
+	DISP_DATA_PORT = mfd->data_port;
+
+	disp_initialized = TRUE;
+}
+
+static int epson_s1d_disp_off(struct platform_device *pdev)
+{
+	if (!disp_initialized)
+		epson_s1d_disp_init(pdev);
+
+	if (display_on) {
+		DISP_CMD_OUT(CMD_SOFT_RESET_C);
+		DISP_CMD_OUT(CMD_VDD_OFF_C);
+		display_on = FALSE;
+	}
+
+	return 0;
+}
+
+static int epson_s1d_disp_on(struct platform_device *pdev)
+{
+	int i;
+	if (!disp_initialized)
+		epson_s1d_disp_init(pdev);
+
+	if (!display_on) {
+		/* Enable Vdd regulator */
+		DISP_CMD_OUT(CMD_VDD_ON_C);
+		msleep(20);
+
+		/* Soft Reset before configuring display */
+		DISP_CMD_OUT(CMD_SOFT_RESET_C);
+		msleep(20);
+
+		/* Set display attributes */
+
+		/* GATESCAN */
+		DISP_CMD_OUT(CMD_GATE_LINE_SCAN_MODE_C);
+		DISP_DATA_OUT(0x0);
+
+		/* DISSET */
+		DISP_CMD_OUT(CMD_SET_DISPLAY_C);
+		DISP_DATA_OUT(0x31);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT((uint8)((PANEL_HEIGHT - 1)>>8));
+		DISP_DATA_OUT((uint8)(PANEL_HEIGHT - 1));
+		DISP_DATA_OUT(0x03);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x08);
+
+		/* VOLSET */
+		DISP_CMD_OUT(
+				   CMD_SET_ELECTRONIC_CONTROL_C);
+		DISP_DATA_OUT(0x10);
+		DISP_DATA_OUT(0x80);
+		DISP_DATA_OUT(0x11);
+		DISP_DATA_OUT(0x1B);
+		DISP_DATA_OUT(0x02);
+		DISP_DATA_OUT(0x0D);
+		DISP_DATA_OUT(0x00);
+
+		/* PWRCTL */
+		DISP_CMD_OUT(CMD_SET_POWER_CONTROL_C);
+		DISP_DATA_OUT(0x01);
+		DISP_DATA_OUT(0x24);
+		DISP_DATA_OUT(0x0F);
+		DISP_DATA_OUT(0xFE);
+		DISP_DATA_OUT(0x33);
+		DISP_DATA_OUT(0x31);
+		DISP_DATA_OUT(0xFF);
+		DISP_DATA_OUT(0x03);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x77);
+		DISP_DATA_OUT(0x33);
+		DISP_DATA_OUT(0x11);
+		DISP_DATA_OUT(0x44);
+		DISP_DATA_OUT(0x00);
+
+		/* PPWRCTL */
+		DISP_CMD_OUT(CMD_SET_PARTIAL_POWER_CONTROL_C);
+		DISP_DATA_OUT(0x33);
+		DISP_DATA_OUT(0xFF);
+		DISP_DATA_OUT(0x03);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x44);
+		DISP_DATA_OUT(0x00);
+
+		/* SPLOUT */
+		DISP_CMD_OUT(CMD_SLEEP_OUT_C);
+		msleep(100);
+
+		/* DATSET */
+		DISP_CMD_OUT(CMD_SET_DATA_C);
+		DISP_DATA_OUT(0x00);
+
+		/* DISTMEMSET */
+		DISP_CMD_OUT(CMD_SET_DISPLAY_TIMING_C);
+		DISP_DATA_OUT(0x01);
+		DISP_DATA_OUT(0x2E);
+		DISP_DATA_OUT(0x0A);
+		DISP_DATA_OUT(0x2C);
+		DISP_DATA_OUT(0x23);
+		DISP_DATA_OUT(0x2F);
+		DISP_DATA_OUT(0x00);
+
+		/* GAMSETP */
+		DISP_CMD_OUT(CMD_SET_POSITIVE_CORRECTION_CHARS_C);
+		DISP_DATA_OUT(0x37);
+		DISP_DATA_OUT(0xFF);
+		DISP_DATA_OUT(0x7F);
+		DISP_DATA_OUT(0x15);
+		DISP_DATA_OUT(0x37);
+		DISP_DATA_OUT(0x05);
+
+		/* GAMSETN */
+		DISP_CMD_OUT(CMD_SET_NEGATIVE_CORRECTION_CHARS_C);
+		DISP_DATA_OUT(0x37);
+		DISP_DATA_OUT(0xFF);
+		DISP_DATA_OUT(0x7F);
+		DISP_DATA_OUT(0x15);
+		DISP_DATA_OUT(0x37);
+		DISP_DATA_OUT(0x05);
+
+		/* ACDRIVE */
+		DISP_CMD_OUT(CMD_SET_AC_OPERATION_DRIVE_C);
+		DISP_DATA_OUT(0x00);
+
+		/* TEST */
+		DISP_CMD_OUT(CMD_TEST_C);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x01);
+
+		/* COLMOD */
+		DISP_CMD_OUT(CMD_SET_DISPLAY_COLOR_MODE_C);
+		DISP_DATA_OUT(0x00);
+
+		/* STADDSET */
+		DISP_CMD_OUT(CMD_SET_START_ADDRESS_C);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x00);
+
+		/* EDADDSET */
+		DISP_CMD_OUT(CMD_SET_END_ADDRESS_C);
+		DISP_DATA_OUT(0xEF);
+		DISP_DATA_OUT(0x01);
+		DISP_DATA_OUT(0x3F);
+
+		/* Set Display Start Line */
+		DISP_CMD_OUT(CMD_SET_DISPLAY_START_LINE_C);
+		DISP_DATA_OUT(0x00);
+
+		/* Set Display Data Interface */
+		DISP_CMD_OUT(CMD_SET_DISPLAY_DATA_INTERFACE_C);
+		DISP_DATA_OUT(0x00);
+		DISP_DATA_OUT(0x04);
+
+		epson_s1d_disp_set_rect(0,
+						 0,
+						 ACTIVE_WIN_WIDTH,
+						 ACTIVE_WIN_HEIGHT);
+
+		for (i = 0; i < (ACTIVE_WIN_WIDTH * ACTIVE_WIN_HEIGHT); i++)
+			outpdw(DISP_DATA_PORT, 0);
+
+		/* DISON */
+		DISP_CMD_OUT(CMD_DISPLAY_ON_C);
+		msleep(60);
+
+		display_on = TRUE;
+	}
+
+	return 0;
+}
+
+static int epson_s1d_probe(struct platform_device *pdev)
+{
+	if (pdev->id == 0) {
+		ebi2_epson_pdata = pdev->dev.platform_data;
+		return 0;
+	}
+
+	msm_fb_add_device(pdev);
+	return 0;
+}
+
+static struct platform_driver this_driver = {
+	.probe  = epson_s1d_probe,
+	.driver = {
+		.name   = "ebi2_epson_s1d_qvga",
+	},
+};
+
+static struct msm_fb_panel_data epson_s1d_panel_data = {
+	.on = epson_s1d_disp_on,
+	.off = epson_s1d_disp_off,
+	.set_rect = epson_s1d_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+	.name   = "ebi2_epson_s1d_qvga",
+	.id	= 1,
+	.dev	= {
+		.platform_data = &epson_s1d_panel_data,
+	}
+};
+
+static int __init epson_s1d_init(void)
+{
+	int ret;
+	struct msm_panel_info *pinfo;
+
+	ret = platform_driver_register(&this_driver);
+	if (!ret) {
+		pinfo = &epson_s1d_panel_data.panel_info;
+		pinfo->xres = PANEL_WIDTH;
+		pinfo->yres = PANEL_HEIGHT;
+		MSM_FB_SINGLE_MODE_PANEL(pinfo);
+		pinfo->type = EBI2_PANEL;
+		pinfo->pdest = DISPLAY_1;
+		pinfo->wait_cycle = 0x048423E8;
+		pinfo->bpp = 18;
+		pinfo->fb_num = 2;
+		pinfo->lcd.vsync_enable = FALSE;
+
+		ret = platform_device_register(&this_device);
+		if (ret)
+			platform_driver_unregister(&this_driver);
+	}
+
+	return ret;
+}
+
+module_init(epson_s1d_init);
diff --git a/drivers/video/msm/ebi2_host.c b/drivers/video/msm/ebi2_host.c
new file mode 100644
index 0000000..8ba5506
--- /dev/null
+++ b/drivers/video/msm/ebi2_host.c
@@ -0,0 +1,307 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/clk.h>
+#include <mach/hardware.h>
+#include "msm_fb.h"
+
+struct mdp_ccs mdp_ccs_rgb2yuv;
+struct mdp_ccs mdp_ccs_yuv2rgb;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static int ebi2_host_resource_initialized;
+static struct msm_panel_common_pdata *ebi2_host_pdata;
+
+static int ebi2_host_probe(struct platform_device *pdev);
+static int ebi2_host_remove(struct platform_device *pdev);
+
+static int ebi2_host_runtime_suspend(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: suspending...\n");
+	return 0;
+}
+
+static int ebi2_host_runtime_resume(struct device *dev)
+{
+	dev_dbg(dev, "pm_runtime: resuming...\n");
+	return 0;
+}
+
+static const struct dev_pm_ops ebi2_host_dev_pm_ops = {
+	.runtime_suspend = ebi2_host_runtime_suspend,
+	.runtime_resume = ebi2_host_runtime_resume,
+};
+
+
+static struct platform_driver ebi2_host_driver = {
+	.probe = ebi2_host_probe,
+	.remove = ebi2_host_remove,
+	.shutdown = NULL,
+	.driver = {
+		/*
+		 * Simulate mdp hw
+		 */
+		.name = "mdp",
+		.pm = &ebi2_host_dev_pm_ops,
+	},
+};
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+		   boolean isr)
+{
+	return;
+}
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+	return 0;
+}
+int mdp_start_histogram(struct fb_info *info)
+{
+	return 0;
+}
+int mdp_stop_histogram(struct fb_info *info)
+{
+	return 0;
+}
+void mdp_refresh_screen(unsigned long data)
+{
+	return;
+}
+
+static int ebi2_host_off(struct platform_device *pdev)
+{
+	int ret;
+	ret = panel_next_off(pdev);
+	return ret;
+}
+
+static int ebi2_host_on(struct platform_device *pdev)
+{
+	int ret;
+	ret = panel_next_on(pdev);
+	return ret;
+}
+
+
+static int ebi2_host_probe(struct platform_device *pdev)
+{
+	struct platform_device *msm_fb_dev = NULL;
+	struct msm_fb_data_type *mfd;
+	struct msm_fb_panel_data *pdata = NULL;
+	int rc;
+
+	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+
+		ebi2_host_pdata = pdev->dev.platform_data;
+
+		ebi2_host_resource_initialized = 1;
+		return 0;
+	}
+
+	ebi2_host_resource_initialized = 1;
+	if (!ebi2_host_resource_initialized)
+		return -EPERM;
+
+	mfd = platform_get_drvdata(pdev);
+
+	if (!mfd)
+		return -ENODEV;
+
+	if (mfd->key != MFD_KEY)
+		return -EINVAL;
+
+	if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+		return -ENOMEM;
+
+	msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
+	if (!msm_fb_dev)
+		return -ENOMEM;
+
+	/* link to the latest pdev */
+	mfd->pdev = msm_fb_dev;
+
+	if (ebi2_host_pdata) {
+		mfd->mdp_rev = ebi2_host_pdata->mdp_rev;
+		mfd->mem_hid = ebi2_host_pdata->mem_hid;
+	}
+
+	/* add panel data */
+	if (platform_device_add_data
+	    (msm_fb_dev, pdev->dev.platform_data,
+	     sizeof(struct msm_fb_panel_data))) {
+		pr_err("ebi2_host_probe: platform_device_add_data failed!\n");
+		rc = -ENOMEM;
+		goto ebi2_host_probe_err;
+	}
+	/* data chain */
+	pdata = msm_fb_dev->dev.platform_data;
+	pdata->on = ebi2_host_on;
+	pdata->off = ebi2_host_off;
+	pdata->next = pdev;
+
+	/* set driver data */
+	platform_set_drvdata(msm_fb_dev, mfd);
+
+	rc = platform_device_add(msm_fb_dev);
+	if (rc)
+		goto ebi2_host_probe_err;
+
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	pdev_list[pdev_list_cnt++] = pdev;
+	return 0;
+
+ebi2_host_probe_err:
+	platform_device_put(msm_fb_dev);
+	return rc;
+}
+
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+			  boolean sync)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	struct fb_info *fbi = mfd->fbi;
+	struct msm_panel_info *panel_info = &mfd->panel_info;
+	MDPIBUF *iBuf;
+	int bpp = info->var.bits_per_pixel / 8;
+	int yres, remainder;
+
+	if (panel_info->mode2_yres != 0) {
+		yres = panel_info->mode2_yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	} else {
+		yres = panel_info->yres;
+		remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+	}
+
+	if (!remainder)
+		remainder = PAGE_SIZE;
+
+	down(&mfd->sem);
+
+	iBuf = &mfd->ibuf;
+	/* use virtual address */
+	iBuf->buf = (uint8 *) fbi->screen_base;
+
+	if (fbi->var.yoffset < yres) {
+		iBuf->buf += fbi->var.xoffset * bpp;
+	} else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+		iBuf->buf += fbi->var.xoffset * bpp + yres *
+		fbi->fix.line_length + PAGE_SIZE - remainder;
+	} else {
+		iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+		fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+	}
+
+	iBuf->ibuf_width = info->var.xres_virtual;
+	iBuf->bpp = bpp;
+
+	iBuf->vsync_enable = sync;
+
+	if (dirty) {
+		/*
+		 * ToDo: dirty region check inside var.xoffset+xres
+		 * <-> var.yoffset+yres
+		 */
+		iBuf->dma_x = dirty->xoffset % info->var.xres;
+		iBuf->dma_y = dirty->yoffset % info->var.yres;
+		iBuf->dma_w = dirty->width;
+		iBuf->dma_h = dirty->height;
+	} else {
+		iBuf->dma_x = 0;
+		iBuf->dma_y = 0;
+		iBuf->dma_w = info->var.xres;
+		iBuf->dma_h = info->var.yres;
+	}
+	mfd->ibuf_flushed = FALSE;
+	up(&mfd->sem);
+}
+
+void mdp_dma_pan_update(struct fb_info *info)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+	MDPIBUF *iBuf;
+	int i, j;
+	uint32 data;
+	uint8 *src;
+	struct msm_fb_panel_data *pdata =
+	    (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+	struct fb_info *fbi = mfd->fbi;
+
+	iBuf = &mfd->ibuf;
+
+	invalidate_caches((unsigned long)fbi->screen_base,
+		(unsigned long)info->fix.smem_len,
+		(unsigned long)info->fix.smem_start);
+
+	pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+			iBuf->dma_h);
+	for (i = 0; i < iBuf->dma_h; i++) {
+		src = iBuf->buf + (fbi->fix.line_length * (iBuf->dma_y + i))
+			+ (iBuf->dma_x * iBuf->bpp);
+		for (j = 0; j < iBuf->dma_w; j++) {
+			data = (uint32)(*src++ >> 2) << 12;
+			data |= (uint32)(*src++ >> 2) << 6;
+			data |= (uint32)(*src++ >> 2);
+			data = ((data&0x1FF)<<16) | ((data&0x3FE00)>>9);
+			outpdw(mfd->data_port, data);
+		}
+	}
+}
+
+static int ebi2_host_remove(struct platform_device *pdev)
+{
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static int ebi2_host_register_driver(void)
+{
+	return platform_driver_register(&ebi2_host_driver);
+}
+
+static int __init ebi2_host_driver_init(void)
+{
+	int ret;
+
+	ret = ebi2_host_register_driver();
+	if (ret) {
+		pr_err("ebi2_host_register_driver() failed!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+module_init(ebi2_host_driver_init);
diff --git a/drivers/video/msm/ebi2_lcd.c b/drivers/video/msm/ebi2_lcd.c
index 68590af..966f974 100644
--- a/drivers/video/msm/ebi2_lcd.c
+++ b/drivers/video/msm/ebi2_lcd.c
@@ -56,8 +56,6 @@
 	.probe = ebi2_lcd_probe,
 	.remove = ebi2_lcd_remove,
 	.suspend = NULL,
-	.suspend_late = NULL,
-	.resume_early = NULL,
 	.resume = NULL,
 	.shutdown = NULL,
 	.driver = {
@@ -71,17 +69,42 @@
 static void *ebi2_lcd_cfg1;
 static void __iomem *lcd01_base;
 static void __iomem *lcd02_base;
+static int lcd01_base_phys;
 static int ebi2_lcd_resource_initialized;
 
 static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
 static int pdev_list_cnt;
+static struct lcdc_platform_data *ebi2_pdata;
+
+static int ebi2_lcd_on(struct platform_device *pdev)
+{
+	int ret;
+
+	if (ebi2_pdata && ebi2_pdata->lcdc_power_save)
+		ebi2_pdata->lcdc_power_save(1);
+
+	ret = panel_next_on(pdev);
+	return ret;
+}
+
+static int ebi2_lcd_off(struct platform_device *pdev)
+{
+	int ret;
+
+	ret = panel_next_off(pdev);
+
+	if (ebi2_pdata && ebi2_pdata->lcdc_power_save)
+		ebi2_pdata->lcdc_power_save(0);
+
+	return ret;
+}
 
 static int ebi2_lcd_probe(struct platform_device *pdev)
 {
 	struct msm_fb_data_type *mfd;
 	struct platform_device *mdp_dev = NULL;
 	struct msm_fb_panel_data *pdata = NULL;
-	int rc, i;
+	int rc, i, hw_version;
 
 	if (pdev->id == 0) {
 		for (i = 0; i < pdev->num_resources; i++) {
@@ -98,6 +121,7 @@
 				ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
 			} else if (!strncmp(pdev->resource[i].name,
 						"lcd01", 5)) {
+				lcd01_base_phys = pdev->resource[i].start;
 				lcd01_base = ioremap(pdev->resource[i].start,
 						pdev->resource[i].end -
 						pdev->resource[i].start + 1);
@@ -118,7 +142,9 @@
 				}
 			}
 		}
+		ebi2_pdata = pdev->dev.platform_data;
 		ebi2_lcd_resource_initialized = 1;
+
 		return 0;
 	}
 
@@ -158,15 +184,19 @@
 
 	/* data chain */
 	pdata = mdp_dev->dev.platform_data;
-	pdata->on = panel_next_on;
-	pdata->off = panel_next_off;
+	pdata->on = ebi2_lcd_on;
+	pdata->off = ebi2_lcd_off;
 	pdata->next = pdev;
 
 	/* get/set panel specific fb info */
 	mfd->panel_info = pdata->panel_info;
 
+	hw_version = inp32((int)ebi2_base + 8);
+
 	if (mfd->panel_info.bpp == 24)
 		mfd->fb_imgType = MDP_RGB_888;
+	else if (mfd->panel_info.bpp == 18)
+		mfd->fb_imgType = MDP_RGB_888;
 	else
 		mfd->fb_imgType = MDP_RGB_565;
 
@@ -181,10 +211,12 @@
 		 * configure both.
 		 */
 		outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
-		if (mfd->panel_info.bpp == 18)
-			outp32(ebi2_lcd_cfg1, 0x01000000);
-		else
-			outp32(ebi2_lcd_cfg1, 0x0);
+		if (hw_version < 0x2020) {
+			if (mfd->panel_info.bpp == 18)
+				outp32(ebi2_lcd_cfg1, 0x01000000);
+			else
+				outp32(ebi2_lcd_cfg1, 0x0);
+		}
 	} else {
 #ifdef DEBUG_EBI2_LCD
 		/*
@@ -201,10 +233,18 @@
 	 */
 	if (mfd->panel_info.pdest == DISPLAY_1) {
 		mfd->cmd_port = lcd01_base;
-		mfd->data_port =
-		    (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
-		mfd->data_port_phys =
-		    (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+		if (hw_version >= 0x2020) {
+			mfd->data_port =
+				(void *)((uint32) mfd->cmd_port + 0x80);
+			mfd->data_port_phys =
+				(void *)(lcd01_base_phys + 0x80);
+		} else {
+			mfd->data_port =
+			    (void *)((uint32) mfd->cmd_port +
+				    EBI2_PRIM_LCD_RS_PIN);
+			mfd->data_port_phys =
+			    (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+		}
 	} else {
 		mfd->cmd_port = lcd01_base;
 		mfd->data_port =
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 90702f3..f6e43bf 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -18,6 +18,9 @@
 /* #define DEBUG */
 #define DEV_DBG_PREFIX "EXT_COMMON: "
 
+/* The start of the data block collection within the CEA Extension Version 3 */
+#define DBC_START_OFFSET 4
+
 #include "msm_fb.h"
 #include "hdmi_msm.h"
 #include "external_common.h"
@@ -317,6 +320,29 @@
 	return ret;
 }
 
+static ssize_t hdmi_common_rda_edid_physical_address(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+		external_common_state->physical_address);
+
+	DEV_DBG("%s: '%d'\n", __func__,
+			external_common_state->physical_address);
+	return ret;
+}
+
+
+static ssize_t hdmi_common_rda_edid_scan_info(struct device *dev,
+	struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = snprintf(buf, PAGE_SIZE, "%d, %d, %d\n",
+		external_common_state->pt_scan_info,
+		external_common_state->it_scan_info,
+		external_common_state->ce_scan_info);
+	DEV_DBG("%s: '%s'\n", __func__, buf);
+	return ret;
+}
+
 static ssize_t hdmi_common_rda_hdcp(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
@@ -681,6 +707,10 @@
 static DEVICE_ATTR(hpd, S_IRUGO | S_IWUGO, hdmi_common_rda_hpd,
 	hdmi_common_wta_hpd);
 static DEVICE_ATTR(hdcp, S_IRUGO, hdmi_common_rda_hdcp, NULL);
+static DEVICE_ATTR(pa, S_IRUGO,
+	hdmi_common_rda_edid_physical_address, NULL);
+static DEVICE_ATTR(scan_info, S_IRUGO,
+	hdmi_common_rda_edid_scan_info, NULL);
 static DEVICE_ATTR(3d_present, S_IRUGO, hdmi_common_rda_3d_present, NULL);
 static DEVICE_ATTR(hdcp_present, S_IRUGO, hdmi_common_rda_hdcp_present, NULL);
 #endif
@@ -699,6 +729,8 @@
 	&dev_attr_edid_modes.attr,
 	&dev_attr_hdcp.attr,
 	&dev_attr_hpd.attr,
+	&dev_attr_pa.attr,
+	&dev_attr_scan_info.attr,
 	&dev_attr_3d_present.attr,
 	&dev_attr_hdcp_present.attr,
 #endif
@@ -926,11 +958,12 @@
 	 31500, 60000, 108108, 60000, TRUE},
 };
 
-static const uint8 *hdmi_edid_find_block(const uint8 *in_buf, uint8 type,
-	uint8 *len)
+static const uint8 *hdmi_edid_find_block(const uint8 *in_buf,
+		uint32 start_offset, uint8 type, uint8 *len)
 {
 	/* the start of data block collection, start of Video Data Block */
-	uint32 offset = 4;
+	uint32 offset = start_offset;
+	uint32 end_dbc_offset = in_buf[2];
 
 	*len = 0;
 
@@ -938,11 +971,11 @@
 	  present.
 	  edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block collection
 	  present and no DTD data present.*/
-	if ((in_buf[2] == 0) || (in_buf[2] == 4)) {
+	if ((end_dbc_offset == 0) || (end_dbc_offset == 4)) {
 		DEV_WARN("EDID: no DTD or non-DTD data present\n");
 		return NULL;
 	}
-	while (offset < 0x80) {
+	while (offset < end_dbc_offset) {
 		uint8 block_len = in_buf[offset] & 0x1F;
 		if ((in_buf[offset] >> 5) == type) {
 			*len = block_len;
@@ -970,20 +1003,24 @@
 static uint32 hdmi_edid_extract_ieee_reg_id(const uint8 *in_buf)
 {
 	uint8 len;
-	const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+	const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3,
+			&len);
 
 	if (vsd == NULL)
 		return 0;
 
 	DEV_DBG("EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n",
-		((uint32)vsd[6] << 8) + (uint32)vsd[5], (uint32)vsd[7] * 5);
+		((uint32)vsd[4] << 8) + (uint32)vsd[5], (uint32)vsd[7] * 5);
+	external_common_state->physical_address =
+		((uint16)vsd[4] << 8) + (uint16)vsd[5];
 	return ((uint32)vsd[3] << 16) + ((uint32)vsd[2] << 8) + (uint32)vsd[1];
 }
 
 static void hdmi_edid_extract_3d_present(const uint8 *in_buf)
 {
 	uint8 len, offset;
-	const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+	const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3,
+			&len);
 
 	external_common_state->present_3d = 0;
 	if (vsd == NULL || len < 9) {
@@ -1003,7 +1040,8 @@
 static void hdmi_edid_extract_latency_fields(const uint8 *in_buf)
 {
 	uint8 len;
-	const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+	const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3,
+			&len);
 
 	if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) {
 		external_common_state->video_latency = (uint16)-1;
@@ -1021,7 +1059,8 @@
 static void hdmi_edid_extract_speaker_allocation_data(const uint8 *in_buf)
 {
 	uint8 len;
-	const uint8 *sad = hdmi_edid_find_block(in_buf, 4, &len);
+	const uint8 *sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4,
+			&len);
 
 	if (sad == NULL)
 		return;
@@ -1041,7 +1080,8 @@
 static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
 {
 	uint8 len;
-	const uint8 *sad = hdmi_edid_find_block(in_buf, 1, &len);
+	const uint8 *sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1,
+			&len);
 	uint32 *adb = external_common_state->audio_data_blocks;
 
 	if (sad == NULL)
@@ -1060,6 +1100,63 @@
 	}
 }
 
+static void hdmi_edid_extract_extended_data_blocks(const uint8 *in_buf)
+{
+	uint8 len = 0;
+	uint8 const *prev_etag = in_buf;
+	uint32 start_offset = DBC_START_OFFSET;
+
+	/* A Tage code of 7 identifies extended data blocks */
+	uint8 const *etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+
+	while (etag != NULL) {
+		/* The extended data block should at least be 2 bytes long */
+		if (len < 2) {
+			DEV_DBG("EDID: Found an extended data block of length"
+				"less than 2 bytes. Ignoring ...\n");
+		} else {
+			/*
+			 * The second byte of the extended data block has the
+			 * extended tag code
+			 */
+			switch (etag[1]) {
+			case 0:
+				/* Video Capability Data Block */
+				DEV_DBG("EDID: VCDB=%02X %02X\n", etag[1],
+						etag[2]);
+
+				/*
+				 * Check if the sink specifies underscan
+				 * support for:
+				 * BIT 5: preferred video format
+				 * BIT 3: IT video format
+				 * BIT 1: CE video format
+				 */
+				external_common_state->pt_scan_info = (etag[2] &
+							(BIT(4) | BIT(5))) >> 4;
+				external_common_state->it_scan_info = (etag[2] &
+							(BIT(3) | BIT(2))) >> 2;
+				external_common_state->ce_scan_info = etag[2] &
+							(BIT(1) | BIT(0));
+				DEV_DBG("EDID: Scan Information (pt|it|ce): "
+					"(%d|%d|%d)",
+					external_common_state->pt_scan_info,
+					external_common_state->it_scan_info,
+					external_common_state->ce_scan_info);
+				break;
+			default:
+				DEV_DBG("EDID: Extend Tag Code %d not"
+						"supported\n", etag[1]);
+				break;
+			}
+		}
+
+		/* There could be more that one extended data block */
+		start_offset = etag - prev_etag + len + 1;
+		prev_etag = etag;
+		etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+	}
+}
 
 static void hdmi_edid_detail_desc(const uint8 *data_buf, uint32 *disp_mode)
 {
@@ -1204,7 +1301,8 @@
 	const uint8 *edid_blk0 = &data_buf[0x0];
 	const uint8 *edid_blk1 = &data_buf[0x80];
 	const uint8 *svd = num_og_cea_blocks ?
-		hdmi_edid_find_block(data_buf+0x80, 2, &len) : NULL;
+		hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+				2, &len) : NULL;
 
 	disp_mode_list->num_of_elements = 0;
 	if (svd != NULL) {
@@ -1216,6 +1314,11 @@
 			video_format = (*svd & 0x7F) - 1;
 			add_supported_video_format(disp_mode_list,
 				video_format);
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				external_common_state->preferred_video_format =
+					video_format;
+			}
 			if (video_format == HDMI_VFRMT_640x480p60_4_3)
 				has480p = TRUE;
 		}
@@ -1238,6 +1341,11 @@
 				video_format);
 			if (video_format == HDMI_VFRMT_640x480p60_4_3)
 				has480p = TRUE;
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				external_common_state->preferred_video_format =
+					video_format;
+			}
 			desc_offset += 0x12;
 			++i;
 		}
@@ -1258,6 +1366,11 @@
 				video_format);
 			if (video_format == HDMI_VFRMT_640x480p60_4_3)
 				has480p = TRUE;
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				external_common_state->preferred_video_format =
+					video_format;
+			}
 			desc_offset += 0x12;
 			++i;
 		}
@@ -1281,6 +1394,11 @@
 				video_format);
 			if (video_format == HDMI_VFRMT_640x480p60_4_3)
 				has480p = TRUE;
+			/* Make a note of the preferred video format */
+			if (i == 0) {
+				external_common_state->preferred_video_format =
+					video_format;
+			}
 			desc_offset += 0x12;
 			++i;
 		}
@@ -1359,6 +1477,7 @@
 	/* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
 	uint8 edid_buf[0x80 * 4];
 
+	external_common_state->preferred_video_format = 0;
 	external_common_state->present_3d = 0;
 	memset(&external_common_state->disp_mode_list, 0,
 		sizeof(external_common_state->disp_mode_list));
@@ -1410,6 +1529,7 @@
 				edid_buf+0x80);
 			hdmi_edid_extract_audio_data_blocks(edid_buf+0x80);
 			hdmi_edid_extract_3d_present(edid_buf+0x80);
+			hdmi_edid_extract_extended_data_blocks(edid_buf+0x80);
 		}
 		break;
 	case 2:
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index c9ab88e..b8d2e5f 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -216,6 +216,11 @@
 	uint8 speaker_allocation_block;
 	uint16 video_latency, audio_latency;
 	uint8 audio_data_block_cnt;
+	uint16 physical_address;
+	uint32 preferred_video_format;
+	uint8 pt_scan_info;
+	uint8 it_scan_info;
+	uint8 ce_scan_info;
 	boolean present_3d;
 	boolean present_hdcp;
 	uint32 audio_data_blocks[16];
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 1ea6403..918f8f2 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3675,6 +3675,7 @@
 	uint32 regVal;
 	int i;
 	int mode = 0;
+	boolean use_ce_scan_info = TRUE;
 
 	switch (external_common_state->video_resolution) {
 	case HDMI_VFRMT_720x480p60_4_3:
@@ -3740,6 +3741,48 @@
 
 	/* Data Byte 01: 0 Y1 Y0 A0 B1 B0 S1 S0 */
 	aviInfoFrame[3]  = hdmi_msm_avi_iframe_lut[0][mode];
+
+	/*
+	 * If the sink specified support for both underscan/overscan
+	 * then, by default, set the underscan bit.
+	 * Only checking underscan support for preferred format and cea formats
+	 */
+	if ((external_common_state->video_resolution ==
+			external_common_state->preferred_video_format)) {
+		use_ce_scan_info = FALSE;
+		switch (external_common_state->pt_scan_info) {
+		case 0:
+			/*
+			 * Need to use the info specified for the corresponding
+			 * IT or CE format
+			 */
+			DEV_DBG("%s: No underscan information specified for the"
+				" preferred video format\n", __func__);
+			use_ce_scan_info = TRUE;
+			break;
+		case 3:
+			DEV_DBG("%s: Setting underscan bit for the preferred"
+				" video format\n", __func__);
+			aviInfoFrame[3] |= 0x02;
+			break;
+		default:
+			DEV_DBG("%s: Underscan information not set for the"
+				" preferred video format\n", __func__);
+			break;
+		}
+	}
+
+	if (use_ce_scan_info) {
+		if (3 == external_common_state->ce_scan_info) {
+			DEV_DBG("%s: Setting underscan bit for the CE video"
+					" format\n", __func__);
+			aviInfoFrame[3] |= 0x02;
+		} else {
+			DEV_DBG("%s: Not setting underscan bit for the CE video"
+				       " format\n", __func__);
+		}
+	}
+
 	/* Data Byte 02: C1 C0 M1 M0 R3 R2 R1 R0 */
 	aviInfoFrame[4]  = hdmi_msm_avi_iframe_lut[1][mode];
 	/* Data Byte 03: ITC EC2 EC1 EC0 Q1 Q0 SC1 SC0 */
@@ -4414,11 +4457,10 @@
 	queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_read_work);
 
 	/* Initialize hdmi node and register with switch driver */
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-	external_common_state->sdev.name = "hdmi_as_primary";
-#else
-	external_common_state->sdev.name = "hdmi";
-#endif
+	if (hdmi_prim_display)
+		external_common_state->sdev.name = "hdmi_as_primary";
+	else
+		external_common_state->sdev.name = "hdmi";
 	if (switch_dev_register(&external_common_state->sdev) < 0)
 		DEV_ERR("Hdmi switch registration failed\n");
 
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index e93b238..d9785d8 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -181,6 +181,8 @@
 			lvds_intf = 0x0001078c;
 			lvds_phy_cfg0 = BIT(6);
 		}
+	} else {
+		BUG();
 	}
 
 	/* MDP_LVDSPHY_CFG0 */
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 199e472..a6f03ba 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1417,7 +1417,7 @@
 		iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
 
 	if (req->flags & MDP_BLEND_FG_PREMULT) {
-#ifdef CONFIG_FB_MSM_MDP31
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP303)
 		iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
 #else
 		put_img(p_src_file);
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index fd04009..fe237ee 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -2429,37 +2429,102 @@
 			uint32 *tpVal,
 			uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
 {
-	if (perPixelAlpha) {
-		*pppop_reg_ptr |= PPP_OP_ROT_ON |
-		    PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+	if (mdp_rev == MDP_REV_303) {
+		int bg_alpha;
+
+		*alpha = iBuf->mdpImg.alpha;
+		*tpVal = iBuf->mdpImg.tpVal;
+
+		if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
+			if (perPixelAlpha) {
+				*pppop_reg_ptr |= PPP_OP_ROT_ON |
+						  PPP_OP_BLEND_ON |
+						  PPP_OP_BLEND_CONSTANT_ALPHA;
+			} else {
+				if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+					&& (iBuf->mdpImg.alpha == 0xff)) {
+					iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+				}
+
+				if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+				   || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+
+					*pppop_reg_ptr |= PPP_OP_ROT_ON |
+						PPP_OP_BLEND_ON |
+						PPP_OP_BLEND_CONSTANT_ALPHA |
+						PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+				}
+			}
+
+			bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+				PPP_BLEND_BG_ALPHA_REVERSE;
+
+			if (perPixelAlpha) {
+				bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+			} else {
+				bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+				bg_alpha |= iBuf->mdpImg.alpha << 24;
+			}
+			outpdw(MDP_BASE + 0x70010, bg_alpha);
+
+			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+				*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+		} else if (perPixelAlpha) {
+				*pppop_reg_ptr |= PPP_OP_ROT_ON |
+						  PPP_OP_BLEND_ON |
+						  PPP_OP_BLEND_SRCPIXEL_ALPHA;
+			} else {
+				if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+					&& (iBuf->mdpImg.alpha == 0xff)) {
+						iBuf->mdpImg.mdpOp &=
+							~(MDPOP_ALPHAB);
+				}
+
+				if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+				   || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+					*pppop_reg_ptr |= PPP_OP_ROT_ON |
+						PPP_OP_BLEND_ON |
+						PPP_OP_BLEND_CONSTANT_ALPHA |
+						PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+				}
+
+				if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+					*pppop_reg_ptr |=
+						PPP_BLEND_CALPHA_TRNASP;
+			}
 	} else {
-		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
-		    && (iBuf->mdpImg.alpha == 0xff)) {
-			iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
-		}
-
-		if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
-		    && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
-			*pppop_reg_ptr |=
-			    PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
-			    PPP_OP_BLEND_CONSTANT_ALPHA |
-			    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
-			    PPP_BLEND_CALPHA_TRNASP;
-
-			*alpha = iBuf->mdpImg.alpha;
-			*tpVal = iBuf->mdpImg.tpVal;
+		if (perPixelAlpha) {
+			*pppop_reg_ptr |= PPP_OP_ROT_ON |
+			    PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
 		} else {
-			if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
-				*pppop_reg_ptr |= PPP_OP_ROT_ON |
-				    PPP_OP_BLEND_ON |
-				    PPP_OP_BLEND_SRCPIXEL_TRANSP;
-				*tpVal = iBuf->mdpImg.tpVal;
-			} else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
-				*pppop_reg_ptr |= PPP_OP_ROT_ON |
-				    PPP_OP_BLEND_ON |
+			if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+			    && (iBuf->mdpImg.alpha == 0xff)) {
+				iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+			}
+
+			if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+			    && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+				*pppop_reg_ptr |=
+				    PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+				    PPP_OP_BLEND_CONSTANT_ALPHA |
 				    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
-				    PPP_OP_BLEND_CONSTANT_ALPHA;
+				    PPP_BLEND_CALPHA_TRNASP;
+
 				*alpha = iBuf->mdpImg.alpha;
+				*tpVal = iBuf->mdpImg.tpVal;
+			} else {
+				if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+					*pppop_reg_ptr |= PPP_OP_ROT_ON |
+					    PPP_OP_BLEND_ON |
+					    PPP_OP_BLEND_SRCPIXEL_TRANSP;
+					*tpVal = iBuf->mdpImg.tpVal;
+				} else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
+					*pppop_reg_ptr |= PPP_OP_ROT_ON |
+					    PPP_OP_BLEND_ON |
+					    PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+					    PPP_OP_BLEND_CONSTANT_ALPHA;
+					*alpha = iBuf->mdpImg.alpha;
+				}
 			}
 		}
 	}
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e.c b/drivers/video/msm/mipi_truly_tft540960_1_e.c
index 937a598..30e255e 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e.c
@@ -59,7 +59,7 @@
 
 /* add 0X BD command */
 static char cmd26_2[6] = {
-	0xBD, 0x01, 0x60, 0x10, 0x38, 0x01 /* 55 HZ */
+	0xBD, 0x01, 0x48, 0x10, 0x38, 0x01 /* 59 HZ */
 };
 
 static char cmd5[5] = {
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
index 82efbef..b3805c5 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
@@ -64,7 +64,7 @@
 
 	pinfo.lcd.vsync_enable = TRUE;
 	pinfo.lcd.hw_vsync_mode = TRUE;
-	pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+	pinfo.lcd.refx100 = 6100; /* adjust refx100 to prevent tearing */
 
 	pinfo.mipi.mode = DSI_CMD_MODE;
 	pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 91dc16c..6ec5d70 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1239,6 +1239,8 @@
 	snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
 #elif defined(CONFIG_FB_MSM_MDP40)
 	snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP_NONE)
+	snprintf(fix->id, sizeof(fix->id), "msmfb0_%x", (__u32) *id);
 #else
 	error CONFIG_FB_MSM_MDP undefined !
 #endif
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
index e7bf820..b907219 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.h
@@ -42,6 +42,8 @@
 #define PM8XXX_REVISION_8901_1p1	2
 #define PM8XXX_REVISION_8901_2p0	3
 #define PM8XXX_REVISION_8901_2p1	4
+#define PM8XXX_REVISION_8901_2p2	5
+#define PM8XXX_REVISION_8901_2p3	6
 
 #define PM8XXX_REVISION_8921_TEST	0
 #define PM8XXX_REVISION_8921_1p0	1
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index c90d8d1..77683ce 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -79,7 +79,7 @@
 };
 
 enum pm8xxx_aux_clk_div {
-	X0_DIV_NONE,
+	XO_DIV_NONE,
 	XO_DIV_1,
 	XO_DIV_2,
 	XO_DIV_4,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 0e62644..22c3772 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -170,6 +170,7 @@
 	struct msm_bus_scale_pdata *bus_scale_table;
 	struct kgsl_device_iommu_data *iommu_data;
 	int iommu_count;
+	struct msm_dcvs_core_info *core_info;
 };
 
 #endif
diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h
index 3eab611..61a7fbb 100644
--- a/include/media/gpio-ir-recv.h
+++ b/include/media/gpio-ir-recv.h
@@ -16,7 +16,6 @@
 struct gpio_ir_recv_platform_data {
 	unsigned int gpio_nr;
 	bool active_low;
-	bool can_wakeup;
 };
 
 #endif /* __GPIO_IR_RECV_H__ */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4c86f24..d98a79d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -586,10 +586,7 @@
 }
 int hci_chan_put(struct hci_chan *chan);
 
-struct hci_chan *hci_chan_accept(struct hci_conn *hcon,
-				struct hci_ext_fs *tx_fs,
-				struct hci_ext_fs *rx_fs);
-struct hci_chan *hci_chan_create(struct hci_conn *hcon,
+struct hci_chan *hci_chan_create(struct hci_chan *chan,
 				struct hci_ext_fs *tx_fs,
 				struct hci_ext_fs *rx_fs);
 void hci_chan_modify(struct hci_chan *chan,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 2854395..f87be20 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -520,6 +520,7 @@
 
 	return chan;
 }
+EXPORT_SYMBOL(hci_chan_add);
 
 int hci_chan_del(struct hci_chan *chan)
 {
@@ -1001,18 +1002,12 @@
 	}
 }
 
-struct hci_chan *hci_chan_accept(struct hci_conn *conn,
+struct hci_chan *hci_chan_create(struct hci_chan *chan,
 			struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
 {
-	struct hci_chan *chan;
 	struct hci_cp_create_logical_link cp;
 
-	chan = hci_chan_add(conn->hdev);
-	if (!chan)
-		return NULL;
-
 	chan->state = BT_CONNECT;
-	chan->conn = conn;
 	chan->tx_fs = *tx_fs;
 	chan->rx_fs = *rx_fs;
 	cp.phy_handle = chan->conn->handle;
@@ -1029,40 +1024,12 @@
 	cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
 	cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
 	hci_conn_hold(chan->conn);
-	hci_send_cmd(conn->hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp), &cp);
-	return chan;
-}
-EXPORT_SYMBOL(hci_chan_accept);
-
-struct hci_chan *hci_chan_create(struct hci_conn *conn,
-			struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
-{
-	struct hci_chan *chan;
-	struct hci_cp_create_logical_link cp;
-
-	chan = hci_chan_add(conn->hdev);
-	if (!chan)
-		return NULL;
-
-	chan->state = BT_CONNECT;
-	chan->conn = conn;
-	chan->tx_fs = *tx_fs;
-	chan->rx_fs = *rx_fs;
-	cp.phy_handle = chan->conn->handle;
-	cp.tx_fs.id = chan->tx_fs.id;
-	cp.tx_fs.type = chan->tx_fs.type;
-	cp.tx_fs.max_sdu = cpu_to_le16(chan->tx_fs.max_sdu);
-	cp.tx_fs.sdu_arr_time = cpu_to_le32(chan->tx_fs.sdu_arr_time);
-	cp.tx_fs.acc_latency = cpu_to_le32(chan->tx_fs.acc_latency);
-	cp.tx_fs.flush_to = cpu_to_le32(chan->tx_fs.flush_to);
-	cp.rx_fs.id = chan->rx_fs.id;
-	cp.rx_fs.type = chan->rx_fs.type;
-	cp.rx_fs.max_sdu = cpu_to_le16(chan->rx_fs.max_sdu);
-	cp.rx_fs.sdu_arr_time = cpu_to_le32(chan->rx_fs.sdu_arr_time);
-	cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
-	cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
-	hci_conn_hold(chan->conn);
-	hci_send_cmd(conn->hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp), &cp);
+	if (chan->conn->out)
+		hci_send_cmd(chan->conn->hdev, HCI_OP_CREATE_LOGICAL_LINK,
+							sizeof(cp), &cp);
+	else
+		hci_send_cmd(chan->conn->hdev, HCI_OP_ACCEPT_LOGICAL_LINK,
+							sizeof(cp), &cp);
 	return chan;
 }
 EXPORT_SYMBOL(hci_chan_create);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 739b04c..de3ab22 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3186,8 +3186,9 @@
 	return 1;
 }
 
-static struct hci_chan *l2cap_chan_admit(u8 amp_id, struct l2cap_pinfo *pi)
+static struct hci_chan *l2cap_chan_admit(u8 amp_id, struct sock *sk)
 {
+	struct l2cap_pinfo *pi = l2cap_pi(sk);
 	struct hci_dev *hdev;
 	struct hci_conn *hcon;
 	struct hci_chan *chan;
@@ -3207,19 +3208,23 @@
 	chan = hci_chan_list_lookup_id(hdev, hcon->handle);
 	if (chan) {
 		l2cap_aggregate(chan, pi);
+		sock_hold(sk);
+		chan->l2cap_sk = sk;
+		hci_chan_hold(chan);
+		pi->ampchan = chan;
 		goto done;
 	}
 
-	if (bt_sk(pi)->parent) {
-		/* Incoming connection */
-		chan = hci_chan_accept(hcon,
-					(struct hci_ext_fs *) &pi->local_fs,
-					(struct hci_ext_fs *) &pi->remote_fs);
-	} else {
-		/* Outgoing connection */
-		chan = hci_chan_create(hcon,
-					(struct hci_ext_fs *) &pi->local_fs,
-					(struct hci_ext_fs *) &pi->remote_fs);
+	chan = hci_chan_add(hdev);
+	if (chan) {
+		chan->conn = hcon;
+		sock_hold(sk);
+		chan->l2cap_sk = sk;
+		hci_chan_hold(chan);
+		pi->ampchan = chan;
+		hci_chan_create(chan,
+			(struct hci_ext_fs *) &pi->local_fs,
+			(struct hci_ext_fs *) &pi->remote_fs);
 	}
 done:
 	hci_dev_put(hdev);
@@ -3625,14 +3630,10 @@
 				struct hci_chan *chan;
 				/* Trigger logical link creation only on AMP */
 
-				chan = l2cap_chan_admit(pi->amp_id, pi);
+				chan = l2cap_chan_admit(pi->amp_id, sk);
 				if (!chan)
 					return -ECONNREFUSED;
 
-				hci_chan_hold(chan);
-				pi->ampchan = chan;
-				chan->l2cap_sk = sk;
-
 				if (chan->state == BT_CONNECTED)
 					l2cap_create_cfm(chan, 0);
 			}
@@ -4466,17 +4467,13 @@
 			/* Already sent a 'pending' response, so set up
 			 * the logical link now
 			 */
-			chan = l2cap_chan_admit(pi->amp_id, pi);
+			chan = l2cap_chan_admit(pi->amp_id, sk);
 			if (!chan) {
 				l2cap_send_disconn_req(pi->conn, sk,
 							ECONNRESET);
 				goto done;
 			}
 
-			hci_chan_hold(chan);
-			pi->ampchan = chan;
-			chan->l2cap_sk = sk;
-
 			if (chan->state == BT_CONNECTED)
 				l2cap_create_cfm(chan, 0);
 		}
@@ -5004,7 +5001,7 @@
 			}
 			pi->remote_fs = default_fs;
 			pi->local_fs = default_fs;
-			chan = l2cap_chan_admit(pi->amp_move_id, pi);
+			chan = l2cap_chan_admit(pi->amp_move_id, sk);
 			if (!chan) {
 				/* Logical link not available */
 				l2cap_send_move_chan_cfm(conn, pi, pi->scid,
@@ -5012,10 +5009,6 @@
 				break;
 			}
 
-			hci_chan_hold(chan);
-			pi->ampchan = chan;
-			chan->l2cap_sk = sk;
-
 			if (chan->state == BT_CONNECTED) {
 				/* Logical link is already ready to go */
 				pi->ampcon = chan->conn;
@@ -5323,12 +5316,8 @@
 				0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
 		pi->remote_fs = default_fs;
 		pi->local_fs = default_fs;
-		chan = l2cap_chan_admit(local_id, pi);
+		chan = l2cap_chan_admit(local_id, sk);
 		if (chan) {
-			hci_chan_hold(chan);
-			pi->ampchan = chan;
-			chan->l2cap_sk = sk;
-
 			if (chan->state == BT_CONNECTED) {
 				/* Logical link is ready to go */
 				pi->ampcon = chan->conn;
@@ -5465,7 +5454,9 @@
 		} else if ((pi->amp_move_state !=
 				L2CAP_AMP_STATE_WAIT_MOVE_RSP_SUCCESS) &&
 			(pi->amp_move_state !=
-				L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM)) {
+				L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM) &&
+			(pi->amp_move_state !=
+				L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM_RSP)) {
 			/* Move was not in expected state, free the channel */
 			ampchan = pi->ampchan;
 			ampcon = pi->ampcon;
@@ -5544,9 +5535,7 @@
 {
 	struct l2cap_logical_link_work *amp_work;
 
-	if (chan->l2cap_sk) {
-		sock_hold(chan->l2cap_sk);
-	} else {
+	if (!chan->l2cap_sk) {
 		BT_ERR("Expected l2cap_sk to point to connecting socket");
 		return -EFAULT;
 	}
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 2c43792..74e2dc0 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -3591,6 +3591,7 @@
 			ret = wcd9xxx_close_slim_sch_rx(tabla,
 						tabla_p->dai[j].ch_num,
 						tabla_p->dai[j].ch_tot);
+			usleep_range(5000, 5000);
 			tabla_p->dai[j].rate = 0;
 			memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
 					tabla_p->dai[j].ch_tot));