Merge "msm: kgsl: Create a separate pool for mapping kgsl allocations" 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/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index ad4f12a..0202746 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -781,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"
@@ -2230,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 0f438e1..f331c4e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -259,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/acpuclock-7x30.c b/arch/arm/mach-msm/acpuclock-7x30.c
index 54d2aa9..29b0065 100644
--- a/arch/arm/mach-msm/acpuclock-7x30.c
+++ b/arch/arm/mach-msm/acpuclock-7x30.c
@@ -461,6 +461,14 @@
 	BUG_ON(IS_ERR(acpuclk_sources[PLL_2]));
 	acpuclk_sources[PLL_3] = clk_get_sys("acpu", "pll3_clk");
 	BUG_ON(IS_ERR(acpuclk_sources[PLL_3]));
+	/*
+	 * Prepare all the PLLs because we enable/disable them
+	 * from atomic context and can't always ensure they're
+	 * all prepared in non-atomic context.
+	 */
+	BUG_ON(clk_prepare(acpuclk_sources[PLL_1]));
+	BUG_ON(clk_prepare(acpuclk_sources[PLL_2]));
+	BUG_ON(clk_prepare(acpuclk_sources[PLL_3]));
 }
 
 static struct acpuclk_data acpuclk_7x30_data = {
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/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index 5488a2f..f362a72 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -65,10 +65,11 @@
 	},
 };
 
-static struct pc_sf_lut desay_5200_pc_sf = {
+static struct sf_lut desay_5200_pc_sf = {
 	.rows		= 1,
 	.cols		= 1,
-	.cycles		= {0},
+	/* row_entries are cycles here */
+	.row_entries		= {0},
 	.percent	= {100},
 	.sf			= {
 				{100}
@@ -81,4 +82,5 @@
 	.fcc_sf_lut		= &desay_5200_fcc_sf,
 	.pc_temp_ocv_lut	= &desay_5200_pc_temp_ocv,
 	.pc_sf_lut		= &desay_5200_pc_sf,
+	.default_rbatt_mohm	= 156,
 };
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index e71e350..2960a8b 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -24,10 +24,11 @@
 	.cols	= 5,
 };
 
-static struct pc_sf_lut palladium_1500_pc_sf = {
+static struct sf_lut palladium_1500_pc_sf = {
 	.rows		= 10,
 	.cols		= 5,
-	.cycles		= {100, 200, 300, 400, 500},
+	/* row_entries are chargecycles */
+	.row_entries	= {100, 200, 300, 400, 500},
 	.percent	= {100, 90, 80, 70, 60, 50, 40, 30, 20, 10},
 	.sf		= {
 			{97, 93, 93, 90, 87},
@@ -43,6 +44,36 @@
 	},
 };
 
+static struct sf_lut palladium_1500_rbatt_sf = {
+	.rows		= 19,
+	.cols		= 5,
+	/* row_entries are temperature */
+	.row_entries	= {-20, 0, 20, 40, 65},
+	.percent	= {100, 95, 90, 85, 80, 75, 70, 65, 60, 55, 50,
+				45, 40, 35, 30, 25, 20, 15, 10
+	},
+	.sf		= {
+					{645, 301, 100, 80, 69},
+					{616, 290, 100, 79, 69},
+					{586, 279, 100, 78, 68},
+					{564, 270, 100, 78, 68},
+					{546, 262, 100, 78, 68},
+					{537, 256, 100, 79, 68},
+					{536, 253, 100, 79, 69},
+					{552, 258, 100, 81, 71},
+					{618, 284, 100, 80, 72},
+					{643, 290, 100, 77, 68},
+					{673, 294, 100, 77, 68},
+					{720, 296, 100, 77, 69},
+					{769, 294, 100, 76, 68},
+					{821, 288, 100, 74, 67},
+					{892, 284, 100, 74, 61},
+					{1003, 290, 100, 71, 58},
+					{1192, 307, 100, 70, 58},
+					{1579, 345, 100, 68, 57},
+					{1261, 324, 100, 68, 57},
+	}
+};
 static struct pc_temp_ocv_lut palladium_1500_pc_temp_ocv = {
 	.rows		= 29,
 	.cols		= 8,
@@ -90,4 +121,6 @@
 	.fcc_sf_lut		= &palladium_1500_fcc_sf,
 	.pc_temp_ocv_lut	= &palladium_1500_pc_temp_ocv,
 	.pc_sf_lut		= &palladium_1500_pc_sf,
+	.rbatt_sf_lut		= &palladium_1500_rbatt_sf,
+	.default_rbatt_mohm	= 254,
 };
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 93cfc099..73f02f5 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2370,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-display.c b/arch/arm/mach-msm/board-8930-display.c
index c8c631e..42b20b2 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -496,6 +496,7 @@
 	.fpga_ctrl_mode = FPGA_SPI_INTF,
 	.phy_ctrl_settings = &dsi_novatek_cmd_mode_phy_db,
 	.dlane_swap = 0x1,
+	.enable_wled_bl_ctrl = 0x1,
 };
 
 static struct platform_device mipi_dsi_novatek_panel_device = {
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-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index 6be2637..86c0438 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -236,6 +236,7 @@
 static struct led_info pm8038_led_info[] = {
 	[0] = {
 		.name			= "wled",
+		.default_trigger	= "bkl_trigger",
 	},
 	[1] = {
 		.name			= "led:rgb_red",
@@ -285,7 +286,7 @@
 		.id = PM8XXX_ID_WLED,
 		.mode = PM8XXX_LED_MODE_MANUAL,
 		.max_current = PM8038_WLED_MAX_CURRENT,
-		.default_state = 1,
+		.default_state = 0,
 		.wled_cfg = &wled_cfg,
 	},
 	[1] = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 864d7b6..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
@@ -1942,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 */
@@ -2059,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;
@@ -2095,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 724dd80..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
 }
 
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-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-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-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 044bd79..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 = {
@@ -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-8960.c b/arch/arm/mach-msm/devices-8960.c
index 0ab81a4..a653353 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -31,6 +31,7 @@
 #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>
@@ -2403,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[] = {
 	{
@@ -2632,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,
@@ -2642,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 = {
@@ -2698,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,
@@ -2708,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 = {
@@ -2764,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,
@@ -2774,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 = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 5e62507..f7306d2 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -850,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)
 {
@@ -1273,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-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.h b/arch/arm/mach-msm/devices.h
index 18b0a52..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;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 98fa233..5b3f297 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -431,6 +431,7 @@
 	struct mipi_dsi_phy_ctrl *phy_ctrl_settings;
 	char dlane_swap;
 	void (*dsi_pwm_cfg)(void);
+	char enable_wled_bl_ctrl;
 };
 
 struct lvds_panel_platform_data {
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/msm_bus/msm_bus_dbg.c b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
index e63df1b..a936e6f 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_dbg.c
@@ -550,7 +550,7 @@
 	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n%d.%d\n",
 		(int)ts.tv_sec, (int)ts.tv_nsec);
 
-	msm_bus_rpm_fill_cdata_buffer(&i, buf + i, MAX_BUFF_SIZE, cdata,
+	msm_bus_rpm_fill_cdata_buffer(&i, buf, MAX_BUFF_SIZE, cdata,
 		nmasters, nslaves, ntslaves);
 	i += scnprintf(buf + i, MAX_BUFF_SIZE - i, "\n");
 	mutex_lock(&msm_bus_dbg_fablist_lock);
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_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/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/adreno.h b/drivers/gpu/msm/adreno.h
index e08088d..b7c3032 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -30,8 +30,10 @@
 #define KGSL_CMD_FLAGS_NOT_KERNEL_CMD	0x00000004
 
 /* Command identifiers */
-#define KGSL_CONTEXT_TO_MEM_IDENTIFIER	0xDEADBEEF
-#define KGSL_CMD_IDENTIFIER		0xFEEDFACE
+#define KGSL_CONTEXT_TO_MEM_IDENTIFIER	0x2EADBEEF
+#define KGSL_CMD_IDENTIFIER		0x2EEDFACE
+#define KGSL_START_OF_IB_IDENTIFIER	0x2EADEABE
+#define KGSL_END_OF_IB_IDENTIFIER	0x2ABEDEAD
 
 #ifdef CONFIG_MSM_SCM
 #define ADRENO_DEFAULT_PWRSCALE_POLICY  (&kgsl_pwrscale_policy_tz)
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index d6648e2..9542dfc 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -575,11 +575,12 @@
 			drawctxt);
 		return -EDEADLK;
 	}
-	link = kzalloc(sizeof(unsigned int) * numibs * 3, GFP_KERNEL);
-	cmds = link;
+
+	cmds = link = kzalloc(sizeof(unsigned int) * (numibs * 3 + 4),
+				GFP_KERNEL);
 	if (!link) {
-		KGSL_MEM_ERR(device, "Failed to allocate memory for for command"
-			" submission, size %x\n", numibs * 3);
+		KGSL_CORE_ERR("kzalloc(%d) failed\n",
+			sizeof(unsigned int) * (numibs * 3 + 4));
 		return -ENOMEM;
 	}
 
@@ -591,6 +592,16 @@
 		adreno_dev->drawctxt_active == drawctxt)
 		start_index = 1;
 
+	if (!start_index) {
+		*cmds++ = cp_nop_packet(1);
+		*cmds++ = KGSL_START_OF_IB_IDENTIFIER;
+	} else {
+		*cmds++ = cp_nop_packet(4);
+		*cmds++ = KGSL_START_OF_IB_IDENTIFIER;
+		*cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
+		*cmds++ = ibdesc[0].gpuaddr;
+		*cmds++ = ibdesc[0].sizedwords;
+	}
 	for (i = start_index; i < numibs; i++) {
 		(void)kgsl_cffdump_parse_ibs(dev_priv, NULL,
 			ibdesc[i].gpuaddr, ibdesc[i].sizedwords, false);
@@ -600,6 +611,9 @@
 		*cmds++ = ibdesc[i].sizedwords;
 	}
 
+	*cmds++ = cp_nop_packet(1);
+	*cmds++ = KGSL_END_OF_IB_IDENTIFIER;
+
 	kgsl_setstate(device,
 		      kgsl_mmu_pt_get_flags(device->mmu.hwpagetable,
 					device->id));
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/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index 6770ec8..fa42c2c 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -71,7 +71,7 @@
 #define WLED_OP_FDBCK_MASK		0x1C
 #define WLED_OP_FDBCK_BIT_SHFT		0x02
 
-#define WLED_MAX_LEVEL			100
+#define WLED_MAX_LEVEL			255
 #define WLED_8_BIT_MASK			0xFF
 #define WLED_8_BIT_SHFT			0x08
 #define WLED_MAX_DUTY_CYCLE		0xFFF
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/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 1778d62..c275a06 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -90,7 +90,8 @@
 	struct single_row_lut	*fcc_temp_lut;
 	struct single_row_lut	*fcc_sf_lut;
 	struct pc_temp_ocv_lut	*pc_temp_ocv_lut;
-	struct pc_sf_lut	*pc_sf_lut;
+	struct sf_lut		*pc_sf_lut;
+	struct sf_lut		*rbatt_sf_lut;
 	struct work_struct	calib_hkadc_work;
 	struct delayed_work	calib_ccadc_work;
 	unsigned int		calib_delay_ms;
@@ -118,6 +119,9 @@
 	int			max_voltage_uv;
 
 	int			batt_temp_suspend;
+	int			soc_rbatt_suspend;
+	int			default_rbatt_mohm;
+	uint16_t		prev_last_good_ocv_raw;
 };
 
 static struct pm8921_bms_chip *the_chip;
@@ -620,8 +624,9 @@
 		return 100;
 }
 
-static int interpolate_scalingfactor_pc(struct pm8921_bms_chip *chip,
-				int cycles, int pc)
+static int interpolate_scalingfactor(struct pm8921_bms_chip *chip,
+				struct sf_lut *sf_lut,
+				int row_entry, int pc)
 {
 	int i, scalefactorrow1, scalefactorrow2, scalefactor;
 	int rows, cols;
@@ -632,71 +637,71 @@
 	 * sf table could be null when no battery aging data is available, in
 	 * that case return 100%
 	 */
-	if (!chip->pc_sf_lut)
+	if (!sf_lut)
 		return 100;
 
-	rows = chip->pc_sf_lut->rows;
-	cols = chip->pc_sf_lut->cols;
-	if (pc > chip->pc_sf_lut->percent[0]) {
+	rows = sf_lut->rows;
+	cols = sf_lut->cols;
+	if (pc > sf_lut->percent[0]) {
 		pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
 		row1 = 0;
 		row2 = 0;
 	}
-	if (pc < chip->pc_sf_lut->percent[rows - 1]) {
+	if (pc < sf_lut->percent[rows - 1]) {
 		pr_debug("pc %d less than known pc ranges for sf", pc);
 		row1 = rows - 1;
 		row2 = rows - 1;
 	}
 	for (i = 0; i < rows; i++) {
-		if (pc == chip->pc_sf_lut->percent[i]) {
+		if (pc == sf_lut->percent[i]) {
 			row1 = i;
 			row2 = i;
 			break;
 		}
-		if (pc > chip->pc_sf_lut->percent[i]) {
+		if (pc > sf_lut->percent[i]) {
 			row1 = i - 1;
 			row2 = i;
 			break;
 		}
 	}
 
-	if (cycles < chip->pc_sf_lut->cycles[0])
-		cycles = chip->pc_sf_lut->cycles[0];
-	if (cycles > chip->pc_sf_lut->cycles[cols - 1])
-		cycles = chip->pc_sf_lut->cycles[cols - 1];
+	if (row_entry < sf_lut->row_entries[0])
+		row_entry = sf_lut->row_entries[0];
+	if (row_entry > sf_lut->row_entries[cols - 1])
+		row_entry = sf_lut->row_entries[cols - 1];
 
 	for (i = 0; i < cols; i++)
-		if (cycles <= chip->pc_sf_lut->cycles[i])
+		if (row_entry <= sf_lut->row_entries[i])
 			break;
-	if (cycles == chip->pc_sf_lut->cycles[i]) {
+	if (row_entry == sf_lut->row_entries[i]) {
 		scalefactor = linear_interpolate(
-				chip->pc_sf_lut->sf[row1][i],
-				chip->pc_sf_lut->percent[row1],
-				chip->pc_sf_lut->sf[row2][i],
-				chip->pc_sf_lut->percent[row2],
+				sf_lut->sf[row1][i],
+				sf_lut->percent[row1],
+				sf_lut->sf[row2][i],
+				sf_lut->percent[row2],
 				pc);
 		return scalefactor;
 	}
 
 	scalefactorrow1 = linear_interpolate(
-				chip->pc_sf_lut->sf[row1][i - 1],
-				chip->pc_sf_lut->cycles[i - 1],
-				chip->pc_sf_lut->sf[row1][i],
-				chip->pc_sf_lut->cycles[i],
-				cycles);
+				sf_lut->sf[row1][i - 1],
+				sf_lut->row_entries[i - 1],
+				sf_lut->sf[row1][i],
+				sf_lut->row_entries[i],
+				row_entry);
 
 	scalefactorrow2 = linear_interpolate(
-				chip->pc_sf_lut->sf[row2][i - 1],
-				chip->pc_sf_lut->cycles[i - 1],
-				chip->pc_sf_lut->sf[row2][i],
-				chip->pc_sf_lut->cycles[i],
-				cycles);
+				sf_lut->sf[row2][i - 1],
+				sf_lut->row_entries[i - 1],
+				sf_lut->sf[row2][i],
+				sf_lut->row_entries[i],
+				row_entry);
 
 	scalefactor = linear_interpolate(
 				scalefactorrow1,
-				chip->pc_sf_lut->percent[row1],
+				sf_lut->percent[row1],
 				scalefactorrow2,
-				chip->pc_sf_lut->percent[row2],
+				sf_lut->percent[row2],
 				pc);
 
 	return scalefactor;
@@ -913,8 +918,16 @@
 	mutex_unlock(&chip->bms_output_lock);
 
 	usb_chg =  usb_chg_plugged_in();
-	convert_vbatt_raw_to_uv(chip, usb_chg,
+
+	if (chip->prev_last_good_ocv_raw == 0 ||
+		chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
+		chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
+		convert_vbatt_raw_to_uv(chip, usb_chg,
 			raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
+		last_ocv_uv = raw->last_good_ocv_uv;
+	} else {
+		raw->last_good_ocv_uv = last_ocv_uv;
+	}
 
 	if (raw->last_good_ocv_uv)
 		last_ocv_uv = raw->last_good_ocv_uv;
@@ -927,6 +940,27 @@
 	return 0;
 }
 
+static int get_rbatt(struct pm8921_bms_chip *chip, int soc_rbatt, int batt_temp)
+{
+	int rbatt, scalefactor;
+
+	rbatt = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
+	pr_debug("rbatt before scaling = %d\n", rbatt);
+	if (chip->rbatt_sf_lut == NULL)  {
+		pr_debug("RBATT = %d\n", rbatt);
+		return rbatt;
+	}
+
+	scalefactor = interpolate_scalingfactor(chip, chip->rbatt_sf_lut,
+							batt_temp, soc_rbatt);
+	pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
+				scalefactor, batt_temp, soc_rbatt);
+	rbatt = (rbatt * scalefactor) / 100;
+
+	pr_debug("RBATT = %d\n", rbatt);
+	return rbatt;
+}
+
 static int calculate_rbatt_resume(struct pm8921_bms_chip *chip,
 				struct pm8921_rbatt_params *raw)
 {
@@ -1000,7 +1034,7 @@
 		return rc;
 	}
 
-	rbatt = (last_rbatt < 0) ? DEFAULT_RBATT_MOHMS : last_rbatt;
+	rbatt = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
 	*ocv = vbatt + (ibatt_ua * rbatt)/1000;
 	return 0;
 }
@@ -1014,7 +1048,8 @@
 	pr_debug("pc = %u for ocv = %dmicroVolts batt_temp = %d\n",
 					pc, ocv_uv, batt_temp);
 
-	scalefactor = interpolate_scalingfactor_pc(chip, chargecycles, pc);
+	scalefactor = interpolate_scalingfactor(chip,
+					chip->pc_sf_lut, chargecycles, pc);
 	pr_debug("scalefactor = %u batt_temp = %d\n", scalefactor, batt_temp);
 
 	/* Multiply the initial FCC value by the scale factor. */
@@ -1051,12 +1086,10 @@
 }
 
 static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
-					struct pm8921_soc_params *raw,
-				 int fcc_uah, int batt_temp, int chargecycles)
+				int rbatt, int fcc_uah,
+				int batt_temp, int chargecycles)
 {
-	int rbatt, voltage_unusable_uv, pc_unusable;
-
-	rbatt = (last_rbatt < 0) ? DEFAULT_RBATT_MOHMS : last_rbatt;
+	int voltage_unusable_uv, pc_unusable;
 
 	/* calculate unusable charge */
 	voltage_unusable_uv = (rbatt * chip->i_test)
@@ -1106,18 +1139,16 @@
 						int *fcc_uah,
 						int *unusable_charge_uah,
 						int *remaining_charge_uah,
-						int *cc_uah)
+						int *cc_uah,
+						int *rbatt)
 {
 	unsigned long flags;
+	int soc_rbatt;
 
 	*fcc_uah = calculate_fcc_uah(chip, batt_temp, chargecycles);
 	pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
 					*fcc_uah, batt_temp, chargecycles);
 
-	*unusable_charge_uah = calculate_unusable_charge_uah(chip, raw,
-					*fcc_uah, batt_temp, chargecycles);
-
-	pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
 
 	spin_lock_irqsave(&chip->bms_100_lock, flags);
 	/* calculate remainging charge */
@@ -1132,6 +1163,15 @@
 				(int64_t)raw->cc - chip->cc_reading_at_100,
 				chip->cc_reading_at_100);
 	spin_unlock_irqrestore(&chip->bms_100_lock, flags);
+
+	soc_rbatt = ((*remaining_charge_uah - *cc_uah) * 100) / *fcc_uah;
+	if (soc_rbatt < 0)
+		soc_rbatt = 0;
+	*rbatt = get_rbatt(chip, soc_rbatt, batt_temp);
+
+	*unusable_charge_uah = calculate_unusable_charge_uah(chip, *rbatt,
+					*fcc_uah, batt_temp, chargecycles);
+	pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
 }
 
 static int calculate_real_fcc_uah(struct pm8921_bms_chip *chip,
@@ -1143,12 +1183,14 @@
 	int remaining_charge_uah;
 	int cc_uah;
 	int real_fcc_uah;
+	int rbatt;
 
 	calculate_soc_params(chip, raw, batt_temp, chargecycles,
 						&fcc_uah,
 						&unusable_charge_uah,
 						&remaining_charge_uah,
-						&cc_uah);
+						&cc_uah,
+						&rbatt);
 
 	real_fcc_uah = remaining_charge_uah - cc_uah;
 	*ret_fcc_uah = fcc_uah;
@@ -1170,12 +1212,14 @@
 	int remaining_charge_uah, soc;
 	int update_userspace = 1;
 	int cc_uah;
+	int rbatt;
 
 	calculate_soc_params(chip, raw, batt_temp, chargecycles,
 						&fcc_uah,
 						&unusable_charge_uah,
 						&remaining_charge_uah,
-						&cc_uah);
+						&cc_uah,
+						&rbatt);
 
 	/* calculate remaining usable charge */
 	remaining_usable_charge_uah = remaining_charge_uah
@@ -1384,6 +1428,44 @@
 }
 EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
 
+int pm8921_bms_get_rbatt(void)
+{
+	int batt_temp, rc;
+	struct pm8xxx_adc_chan_result result;
+	struct pm8921_soc_params raw;
+	int fcc_uah;
+	int unusable_charge_uah;
+	int remaining_charge_uah;
+	int cc_uah;
+	int rbatt;
+
+	if (!the_chip) {
+		pr_err("called before initialization\n");
+		return -EINVAL;
+	}
+
+	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
+	if (rc) {
+		pr_err("error reading adc channel = %d, rc = %d\n",
+					the_chip->batt_temp_channel, rc);
+		return rc;
+	}
+	pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
+						result.measurement);
+	batt_temp = (int)result.physical;
+
+	read_soc_params_raw(the_chip, &raw);
+
+	calculate_soc_params(the_chip, &raw, batt_temp, last_chargecycles,
+						&fcc_uah,
+						&unusable_charge_uah,
+						&remaining_charge_uah,
+						&cc_uah,
+						&rbatt);
+	return rbatt;
+}
+EXPORT_SYMBOL_GPL(pm8921_bms_get_rbatt);
+
 int pm8921_bms_get_fcc(void)
 {
 	int batt_temp, rc;
@@ -1441,6 +1523,7 @@
 EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
 
 #define DELTA_FCC_PERCENT	3
+#define MIN_START_PERCENT_FOR_LEARNING	30
 void pm8921_bms_charging_end(int is_battery_full)
 {
 	int batt_temp, rc;
@@ -1464,7 +1547,8 @@
 
 	calculate_cc_uah(the_chip, raw.cc, &bms_end_cc_uah);
 
-	if (is_battery_full) {
+	if (is_battery_full
+		&& the_chip->start_percent <= MIN_START_PERCENT_FOR_LEARNING) {
 		unsigned long flags;
 		int fcc_uah, new_fcc_uah, delta_fcc_uah;
 
@@ -1475,18 +1559,25 @@
 		if (delta_fcc_uah < 0)
 			delta_fcc_uah = -delta_fcc_uah;
 
-		if (delta_fcc_uah * 100  <= (DELTA_FCC_PERCENT * fcc_uah)) {
-			pr_debug("delta_fcc=%d < %d percent of fcc=%d\n",
-				delta_fcc_uah, DELTA_FCC_PERCENT, fcc_uah);
-			last_real_fcc_mah = new_fcc_uah/1000;
-			last_real_fcc_batt_temp = batt_temp;
-			readjust_fcc_table();
-		} else {
+		if (delta_fcc_uah * 100  > (DELTA_FCC_PERCENT * fcc_uah)) {
+			/* new_fcc_uah is outside the scope limit it */
+			if (new_fcc_uah > fcc_uah)
+				new_fcc_uah
+				= (fcc_uah + DELTA_FCC_PERCENT * fcc_uah);
+			else
+				new_fcc_uah
+				= (fcc_uah - DELTA_FCC_PERCENT * fcc_uah);
+
 			pr_debug("delta_fcc=%d > %d percent of fcc=%d"
-				"will not update real fcc\n",
-				delta_fcc_uah, DELTA_FCC_PERCENT, fcc_uah);
+					"restring it to %d\n",
+					delta_fcc_uah, DELTA_FCC_PERCENT,
+					fcc_uah, new_fcc_uah);
 		}
 
+		last_real_fcc_mah = new_fcc_uah/1000;
+		last_real_fcc_batt_temp = batt_temp;
+		readjust_fcc_table();
+
 		spin_lock_irqsave(&the_chip->bms_100_lock, flags);
 		the_chip->ocv_reading_at_100 = raw.last_good_ocv_raw;
 		the_chip->cc_reading_at_100 = raw.cc;
@@ -1652,6 +1743,10 @@
 	int rc;
 	struct pm8xxx_adc_chan_result result;
 	struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
+	struct pm8921_soc_params raw;
+	int fcc_uah;
+	int remaining_charge_uah;
+	int cc_uah;
 
 	chip->batt_temp_suspend = 0;
 	rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
@@ -1660,20 +1755,66 @@
 					chip->batt_temp_channel, rc);
 	}
 	chip->batt_temp_suspend = (int)result.physical;
+	read_soc_params_raw(chip, &raw);
+
+	fcc_uah = calculate_fcc_uah(chip,
+			chip->batt_temp_suspend, last_chargecycles);
+	pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
+			fcc_uah, chip->batt_temp_suspend, last_chargecycles);
+	/* calculate remainging charge */
+	remaining_charge_uah = calculate_remaining_charge_uah(chip, &raw,
+					fcc_uah, chip->batt_temp_suspend,
+					last_chargecycles);
+	pr_debug("RC = %uuAh\n", remaining_charge_uah);
+
+	/* calculate cc micro_volt_hour */
+	calculate_cc_uah(chip, raw.cc, &cc_uah);
+	pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %d\n",
+				cc_uah, raw.cc,
+				(int64_t)raw.cc - chip->cc_reading_at_100,
+				chip->cc_reading_at_100);
+	chip->soc_rbatt_suspend = ((remaining_charge_uah - cc_uah) * 100)
+						/ fcc_uah;
 	return 0;
 }
 
+#define DELTA_RBATT_PERCENT	10
 static int pm8921_bms_resume(struct device *dev)
 {
 	struct pm8921_rbatt_params raw;
 	struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
 	int rbatt;
+	int expected_rbatt;
+	int scalefactor;
+	int delta_rbatt;
 
 	read_rbatt_params_raw(chip, &raw);
 	rbatt = calculate_rbatt_resume(chip, &raw);
-	if (rbatt > 0) /* TODO Check for rbatt values bound based on cycles */
+
+	if (rbatt < 0)
+		return 0;
+
+	expected_rbatt
+		= (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
+
+	if (chip->rbatt_sf_lut) {
+		scalefactor = interpolate_scalingfactor(chip,
+						chip->rbatt_sf_lut,
+						chip->batt_temp_suspend,
+						chip->soc_rbatt_suspend);
+		rbatt = rbatt * 100 / scalefactor;
+	}
+
+	delta_rbatt = expected_rbatt - rbatt;
+	if (delta_rbatt)
+		delta_rbatt = -delta_rbatt;
+	/*
+	 * only update last_rbatt if rbatt is within some
+	 * percent of expected_rbatt
+	 */
+	if (delta_rbatt * 100 <= DELTA_RBATT_PERCENT * expected_rbatt)
 		last_rbatt = rbatt;
-	chip->batt_temp_suspend = -EINVAL;
+
 	return 0;
 }
 
@@ -1767,7 +1908,9 @@
 				battery_id)) {
 		goto desay;
 	} else {
-		goto unknown;
+		pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
+				battery_id);
+		goto palladium;
 	}
 
 palladium:
@@ -1776,22 +1919,17 @@
 		chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
 		chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
 		chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
+		chip->rbatt_sf_lut = palladium_1500_data.rbatt_sf_lut;
+		chip->default_rbatt_mohm
+				= palladium_1500_data.default_rbatt_mohm;
 		return 0;
 desay:
 		chip->fcc = desay_5200_data.fcc;
 		chip->fcc_temp_lut = desay_5200_data.fcc_temp_lut;
-		chip->fcc_sf_lut = desay_5200_data.fcc_sf_lut;
 		chip->pc_temp_ocv_lut = desay_5200_data.pc_temp_ocv_lut;
 		chip->pc_sf_lut = desay_5200_data.pc_sf_lut;
-		return 0;
-unknown:
-		pr_warn("invalid battery id, palladium 1500 assumed batt_id %llx\n",
-				battery_id);
-		chip->fcc = palladium_1500_data.fcc;
-		chip->fcc_temp_lut = palladium_1500_data.fcc_temp_lut;
-		chip->fcc_sf_lut = palladium_1500_data.fcc_sf_lut;
-		chip->pc_temp_ocv_lut = palladium_1500_data.pc_temp_ocv_lut;
-		chip->pc_sf_lut = palladium_1500_data.pc_sf_lut;
+		chip->rbatt_sf_lut = desay_5200_data.rbatt_sf_lut;
+		chip->default_rbatt_mohm = desay_5200_data.default_rbatt_mohm;
 		return 0;
 }
 
@@ -2087,6 +2225,16 @@
 		goto free_chip;
 	}
 
+	if (chip->pc_temp_ocv_lut == NULL) {
+		pr_err("temp ocv lut table is NULL\n");
+		rc = -EINVAL;
+		goto free_chip;
+	}
+
+	/* set defaults in the battery data */
+	if (chip->default_rbatt_mohm <= 0)
+		chip->default_rbatt_mohm = DEFAULT_RBATT_MOHMS;
+
 	chip->batt_temp_channel = pdata->bms_cdata.batt_temp_channel;
 	chip->vbat_channel = pdata->bms_cdata.vbat_channel;
 	chip->ref625mv_channel = pdata->bms_cdata.ref625mv_channel;
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 eec600e..f6e43bf 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -320,6 +320,18 @@
 	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)
 {
@@ -328,7 +340,6 @@
 		external_common_state->it_scan_info,
 		external_common_state->ce_scan_info);
 	DEV_DBG("%s: '%s'\n", __func__, buf);
-
 	return ret;
 }
 
@@ -696,6 +707,8 @@
 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);
@@ -716,6 +729,7 @@
 	&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,
@@ -996,7 +1010,9 @@
 		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];
 }
 
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index c6dfeb1..b8d2e5f 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -216,6 +216,7 @@
 	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;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 30ce90b..918f8f2 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -4457,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/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 9b8f60f..1f5904b 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -592,7 +592,7 @@
 };
 
 static uint32 vg_qseed_table1[] = {
-	0x76543210, 0xfedcba98
+	0x00000000, 0x20000000,
 };
 
 static uint32 vg_qseed_table2[] = {
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_novatek.c b/drivers/video/msm/mipi_novatek.c
index ed0dee4..0070757 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -14,6 +14,7 @@
 #ifdef CONFIG_SPI_QUP
 #include <linux/spi/spi.h>
 #endif
+#include <linux/leds.h>
 #include "msm_fb.h"
 #include "mipi_dsi.h"
 #include "mipi_novatek.h"
@@ -26,6 +27,8 @@
 static struct dsi_buf novatek_rx_buf;
 static int mipi_novatek_lcd_init(void);
 
+static int wled_trigger_initialized;
+
 #define MIPI_DSI_NOVATEK_SPI_DEVICE_NAME	"dsi_novatek_3d_panel_spi"
 #define HPCI_FPGA_READ_CMD	0x84
 #define HPCI_FPGA_WRITE_CMD	0x04
@@ -427,12 +430,17 @@
 	return 0;
 }
 
-
+DEFINE_LED_TRIGGER(bkl_led_trigger);
 
 static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
 {
 	struct mipi_panel_info *mipi;
 
+	if ((mipi_novatek_pdata->enable_wled_bl_ctrl)
+	    && (wled_trigger_initialized)) {
+		led_trigger_event(bkl_led_trigger, mfd->bl_level);
+		return;
+	}
 	mipi  = &mfd->panel_info.mipi;
 
 	mutex_lock(&mfd->dma->ov_mutex);
@@ -639,6 +647,10 @@
 		pr_info("%s: SUCCESS (SPI)\n", __func__);
 #endif
 
+	led_trigger_register_simple("bkl_trigger", &bkl_led_trigger);
+	pr_info("%s: SUCCESS (WLED TRIGGER)\n", __func__);
+	wled_trigger_initialized = 1;
+
 	mipi_dsi_buf_alloc(&novatek_tx_buf, DSI_BUF_SIZE);
 	mipi_dsi_buf_alloc(&novatek_rx_buf, DSI_BUF_SIZE);
 
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/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 818eeca..d4aaa4b 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -20,8 +20,8 @@
 #define FCC_CC_COLS		5
 #define FCC_TEMP_COLS		8
 
-#define PC_CC_ROWS		10
-#define PC_CC_COLS		5
+#define PC_CC_ROWS             29
+#define PC_CC_COLS             13
 
 #define PC_TEMP_ROWS		29
 #define PC_TEMP_COLS		8
@@ -35,19 +35,20 @@
 };
 
 /**
- * struct pc_sf_lut -
+ * struct sf_lut -
  * @rows:	number of percent charge entries should be <= PC_CC_ROWS
  * @cols:	number of charge cycle entries should be <= PC_CC_COLS
- * @cycles:	the charge cycles at which sf data is available in the table.
+ * @row_entries:	the charge cycles/temperature at which sf data
+ *			is available in the table.
  *		The charge cycles must be in increasing order from 0 to rows.
  * @percent:	the percent charge at which sf data is available in the table
  *		The  percentcharge must be in decreasing order from 0 to cols.
  * @sf:		the scaling factor data
  */
-struct pc_sf_lut {
+struct sf_lut {
 	int rows;
 	int cols;
-	int cycles[PC_CC_COLS];
+	int row_entries[PC_CC_COLS];
 	int percent[PC_CC_ROWS];
 	int sf[PC_CC_ROWS][PC_CC_COLS];
 };
@@ -74,17 +75,22 @@
  * struct pm8921_bms_battery_data -
  * @fcc:		full charge capacity (mAmpHour)
  * @fcc_temp_lut:	table to get fcc at a given temp
- * @fcc_sf_lut:		table to get fcc scaling factor for given charge cycles
  * @pc_temp_ocv_lut:	table to get percent charge given batt temp and cycles
  * @pc_sf_lut:		table to get percent charge scaling factor given cycles
  *			and percent charge
+ * @rbatt_sf_lut:	table to get battery resistance scaling factor given
+ *			temperature and percent charge
+ * default_rbatt_mohm:	the default value of battery resistance to use when
+ *			readings from bms are not available.
  */
 struct pm8921_bms_battery_data {
-	unsigned int			fcc;
-	struct single_row_lut		*fcc_temp_lut;
-	struct single_row_lut		*fcc_sf_lut;
-	struct pc_temp_ocv_lut		*pc_temp_ocv_lut;
-	struct pc_sf_lut		*pc_sf_lut;
+	unsigned int		fcc;
+	struct single_row_lut	*fcc_temp_lut;
+	struct single_row_lut	*fcc_sf_lut;
+	struct pc_temp_ocv_lut	*pc_temp_ocv_lut;
+	struct sf_lut		*pc_sf_lut;
+	struct sf_lut		*rbatt_sf_lut;
+	int			default_rbatt_mohm;
 };
 
 struct pm8xxx_bms_core_data {
@@ -185,6 +191,10 @@
  */
 int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
 								int *vbat_uv);
+/**
+ * pm8921_bms_get_rbatt - function to get the battery resistance in mOhm.
+ */
+int pm8921_bms_get_rbatt(void);
 #else
 static inline int pm8921_bms_get_vsense_avg(int *result)
 {
@@ -216,6 +226,10 @@
 {
 	return -ENXIO;
 }
+static inline int pm8921_bms_get_rbatt(void)
+{
+	return -EINVAL;
+}
 #endif
 
 #endif
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/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 47b6d4d..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;
@@ -5546,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/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index ed880e8..dd194d6 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -638,6 +638,8 @@
 		return -ENOMEM;
 	}
 	buf = prtd->audio_client->port[dir].buf;
+	if (buf == NULL || buf[0].data == NULL)
+		return -ENOMEM;
 
 	pr_debug("%s:buf = %p\n", __func__, buf);
 	dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;