Merge "ASoC: msm: Fix the register address of TX4 registers"
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index 25219cd..ce797d3 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -19,7 +19,8 @@
 	"arm,coresight-stm" for coresight stm trace device,
 	"arm,coresight-etm" for coresight etm trace devices,
 	"qcom,coresight-csr" for coresight csr device,
-	"arm,coresight-cti" for coresight cti devices
+	"arm,coresight-cti" for coresight cti devices,
+	"qcom,coresight-hwevent" for coresight hardware event devices
 - reg : physical base address and length of the register set(s) of the component
 - reg-names : names corresponding to each reg property value. The reg-names that
 	need to be used with corresponding compatible string for a coresight device
@@ -61,6 +62,12 @@
 		compatible : should be "arm,coresight-cti"
 		reg-names  : should be:
 			"cti<num>-base" - physical base address of cti registers
+	- for coresight hardware event devices:
+		compatible : should be "qcom,coresight-hwevent"
+		reg-names  : should be:
+			"<ss-mux>" - physical base address of hardware event mux
+				control registers where <ss-mux> is subsystem mux it
+				represents
 - coresight-id : unique integer identifier for the component
 - coresight-name : unique descriptive name of the component
 - coresight-nr-inports : number of input ports on the component
@@ -105,6 +112,7 @@
 - qcom,setb-gpios-drv : active drive strength for set B gpios
 - qcom,setb-gpios-pull : active pull configuration for set B gpios
 - qcom,setb-gpios-dir : active direction for set B gpios
+- qcom,hwevent-clks : list of clocks required by hardware event driver
 
 Examples:
 
@@ -213,3 +221,17 @@
 		coresight-name = "coresight-cti1";
 		coresight-nr-inports = <0>;
 	};
+
+	hwevent: hwevent@fdf30018 {
+		compatible = "qcom,coresight-hwevent";
+		reg = <0xfdf30018 0x80>,
+		      <0xf9011080 0x80>,
+		      <0xfd4ab160 0x80>;
+		reg-names = "mmss-mux", "apcs-mux", "ppss-mux";
+
+		coresight-id = <29>;
+		coresight-name = "coresight-hwevent";
+		coresight-nr-inports = <0>;
+
+		qcom,hwevent-clks = "core_mmss_clk";
+	};
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
index 3c3a242..af5cbc6 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -11,6 +11,8 @@
 - qcom,iommu-pmu-ngroups: Number of Performance Monitor Unit (PMU) groups.
 - qcom,iommu-pmu-ncounters: Number of PMU counters per group.
 - qcom,iommu-pmu-event-classes: List of event classes supported.
+- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
+  access to the IOMMU configuration registers
 
 - List of sub nodes, one for each of the translation context banks supported.
     Required properties for each sub-node:
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index c3d929c..4a312a8 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -12,7 +12,6 @@
 - reg-names:	      Names of the bases for the above registers. "qdsp6_base",
 		      "halt_base", "rmb_base", and "restart_reg" are expected.
 - interrupts:         The modem watchdog interrupt
-- vdd_mss-supply:     Reference to the regulator that supplies the processor.
 - vdd_cx-supply:      Reference to the regulator that supplies the vdd_cx domain.
 - vdd_mx-supply:      Reference to the regulator that supplies the memory rail.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
@@ -23,6 +22,10 @@
 - qcom,gpio-force-stop: GPIO used by the apps to force the modem to shutdown.
 
 Optional properties:
+- vdd_mss-supply:     Reference to the regulator that supplies the processor.
+		      This may be a shared regulator that is already voted
+		      on in the PIL proxy voting code (and also managed by the
+		      modem on its own), hence we mark it as as optional.
 - vdd_pll-supply:     Reference to the regulator that supplies the PLL's rail.
 - qcom,vdd_pll:       Voltage to be set for the PLL's rail.
 - reg-names:          "cxrail_bhs_reg" - control register for modem power
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
index 1cc3c59..b0257d0 100644
--- a/arch/arm/boot/dts/msm-iommu-v0.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -207,6 +207,7 @@
 		reg = <0xfd880000 0x10000>;
 		interrupts = <0 38 0>;
 		qcom,glb-offset = <0xF000>;
+		qcom,needs-alt-core-clk;
 		label = "gfx_iommu";
 		qcom,iommu-pmu-ngroups = <1>;
 		qcom,iommu-pmu-ncounters = <4>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 53e4392..3cd9cb5 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -800,7 +800,6 @@
 			    "restart_reg", "cxrail_bhs_reg";
 
 		interrupts = <0 24 1>;
-		vdd_mss-supply = <&pm8226_s1>;
 		vdd_cx-supply = <&pm8226_s1_corner>;
 		vdd_mx-supply = <&pm8226_l3>;
 		vdd_pll-supply = <&pm8226_l8>;
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 4b861ed..6a2855d 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -676,7 +676,6 @@
 			    "restart_reg", "cxrail_bhs_reg";
 
 		interrupts = <0 24 1>;
-		vdd_mss-supply = <&pm8110_s1>;
 		vdd_cx-supply = <&pm8110_s1_corner>;
 		vdd_mx-supply = <&pm8110_l3>;
 		vdd_pll-supply = <&pm8110_l10>;
@@ -721,8 +720,6 @@
 		qcom,sensors = <2>;
 		qcom,slope = <2901 2846>;
 		qcom,calib-mode = "fuse_map3";
-		qcom,calibration-less-mode;
-		qcom,tsens-local-init;
 		qcom,sensor-id = <0 5>;
 	};
 
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index cccedd8..1610f1f 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -364,4 +364,18 @@
 		coresight-name = "coresight-cti-cpu3";
 		coresight-nr-inports = <0>;
 	};
+
+	hwevent: hwevent@fdf30018 {
+		compatible = "qcom,coresight-hwevent";
+		reg = <0xfdf30018 0x80>,
+		      <0xf9011080 0x80>,
+		      <0xfd4ab160 0x80>;
+		reg-names = "mmss-mux", "apcs-mux", "ppss-mux";
+
+		coresight-id = <29>;
+		coresight-name = "coresight-hwevent";
+		coresight-nr-inports = <0>;
+
+		qcom,hwevent-clks = "core_mmss_clk";
+	};
 };
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index a6f772d..5793326 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -80,8 +80,8 @@
 	{ 1,  384000, ACPUPLL, 5, 0,   CPR_CORNER_SVS,    0, 3 },
 	{ 1,  600000, PLL0,    4, 0,   CPR_CORNER_NORMAL, 0, 4 },
 	{ 1,  787200, ACPUPLL, 5, 0,   CPR_CORNER_NORMAL, 0, 4 },
-	{ 0,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 5 },
-	{ 0, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 5 },
+	{ 1,  998400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 5 },
+	{ 1, 1190400, ACPUPLL, 5, 0,   CPR_CORNER_TURBO,  0, 5 },
 	{ 0 }
 };
 
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 5e60bd5..aa9368d 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -3061,6 +3061,7 @@
 	CLK_DUMMY("core_clk",   NULL, "fd870000.qcom,iommu", OFF),
 	CLK_DUMMY("iface_clk",  NULL, "fd880000.qcom,iommu", OFF),
 	CLK_DUMMY("core_clk",   NULL, "fd880000.qcom,iommu", OFF),
+	CLK_DUMMY("alt_core_clk",   NULL, "fd880000.qcom,iommu", OFF),
 	CLK_DUMMY("iface_clk",  NULL, "fd000000.qcom,iommu", OFF),
 	CLK_DUMMY("core_clk",   NULL, "fd000000.qcom,iommu", OFF),
 	CLK_DUMMY("iface_clk",  NULL, "fd010000.qcom,iommu", OFF),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 4fb348d..ec94f00 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -3194,7 +3194,9 @@
 	F_HDMI( 25200000, hdmipll, 1, 0, 0),
 	F_HDMI( 27000000, hdmipll, 1, 0, 0),
 	F_HDMI( 27030000, hdmipll, 1, 0, 0),
+	F_HDMI( 65000000, hdmipll, 1, 0, 0),
 	F_HDMI( 74250000, hdmipll, 1, 0, 0),
+	F_HDMI(108000000, hdmipll, 1, 0, 0),
 	F_HDMI(148500000, hdmipll, 1, 0, 0),
 	F_HDMI(268500000, hdmipll, 1, 0, 0),
 	F_HDMI(297000000, hdmipll, 1, 0, 0),
@@ -5207,6 +5209,7 @@
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc342000.cti"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc343000.cti"),
 	CLK_LOOKUP("core_clk", qdss_clk.c, "fc344000.cti"),
+	CLK_LOOKUP("core_clk", qdss_clk.c, "fdf30018.hwevent"),
 
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc318000.tpiu"),
@@ -5236,6 +5239,9 @@
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc342000.cti"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc343000.cti"),
 	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
+	CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fdf30018.hwevent"),
+
+	CLK_LOOKUP("core_mmss_clk", mmss_misc_ahb_clk.c, "fdf30018.hwevent"),
 
 	CLK_LOOKUP("l2_m_clk",		l2_m_clk,     ""),
 	CLK_LOOKUP("krait0_m_clk",	krait0_m_clk, ""),
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index d866874..bf95615 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -648,7 +648,49 @@
 		REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
 		udelay(200);
 	break;
+	case 65000000:
+		REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
+		REG_W(0x19, hdmi_phy_pll_base + HDMI_UNI_PLL_VCOLPF_CFG);
+		REG_W(0x0E, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFR_CFG);
+		REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC1_CFG);
+		REG_W(0x0D, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC2_CFG);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG0);
+		REG_W(0x4F, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG1);
+		REG_W(0x55, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG2);
+		REG_W(0xED, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG3);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG4);
+		REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
+		REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
+		REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
+		REG_W(0x60, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG8);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG9);
+		REG_W(0x8A, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG10);
+		REG_W(0x02, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG11);
+		REG_W(0x1F, hdmi_phy_base + HDMI_PHY_PD_CTRL0);
+		udelay(50);
 
+		REG_W(0x0F, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_PD_CTRL1);
+		REG_W(0x10, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+		REG_W(0xDB, hdmi_phy_base + HDMI_PHY_ANA_CFG0);
+		REG_W(0x43, hdmi_phy_base + HDMI_PHY_ANA_CFG1);
+		REG_W(0x02, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+		REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
+		REG_W(0xD0, hdmi_phy_base + HDMI_PHY_DCC_CFG0);
+		REG_W(0x1A, hdmi_phy_base + HDMI_PHY_DCC_CFG1);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG0);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG1);
+		REG_W(0x02, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
+		REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
+		udelay(200);
+	break;
 	case 74250000:
 		/*
 		 * 720p60/720p50/1080i60/1080i50
@@ -697,6 +739,50 @@
 		udelay(200);
 	break;
 
+	case 108000000:
+		REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
+		REG_W(0x19, hdmi_phy_pll_base + HDMI_UNI_PLL_VCOLPF_CFG);
+		REG_W(0x0E, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFR_CFG);
+		REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC1_CFG);
+		REG_W(0x0D, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC2_CFG);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG0);
+		REG_W(0x5B, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG1);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG2);
+		REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG3);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG4);
+		REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
+		REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
+		REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
+		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
+		REG_W(0x60, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG8);
+		REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG9);
+		REG_W(0x38, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG10);
+		REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG11);
+		REG_W(0x1F, hdmi_phy_base + HDMI_PHY_PD_CTRL0);
+		udelay(50);
+
+		REG_W(0x0F, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_PD_CTRL1);
+		REG_W(0x10, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+		REG_W(0xDB, hdmi_phy_base + HDMI_PHY_ANA_CFG0);
+		REG_W(0x43, hdmi_phy_base + HDMI_PHY_ANA_CFG1);
+		REG_W(0x02, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+		REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
+		REG_W(0xD0, hdmi_phy_base + HDMI_PHY_DCC_CFG0);
+		REG_W(0x1A, hdmi_phy_base + HDMI_PHY_DCC_CFG1);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG0);
+		REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG1);
+		REG_W(0x02, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
+		REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
+		udelay(200);
+	break;
+
 	case 148500000:
 		REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
 		REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
diff --git a/arch/arm/mach-msm/include/mach/msm_ipc_router.h b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
index c68c783..894379e 100644
--- a/arch/arm/mach-msm/include/mach/msm_ipc_router.h
+++ b/arch/arm/mach-msm/include/mach/msm_ipc_router.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,6 +31,11 @@
 	MSM_IPC_ROUTER_WRITE_DONE,
 };
 
+struct comm_mode_info {
+	int mode;
+	void *xprt_info;
+};
+
 struct msm_ipc_port {
 	struct list_head list;
 
@@ -39,6 +44,7 @@
 	uint32_t type;
 	unsigned flags;
 	spinlock_t port_lock;
+	struct comm_mode_info mode_info;
 
 	struct list_head incomplete;
 	struct mutex incomplete_lock;
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index c31c969..a328b2b 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -1245,6 +1245,67 @@
 	return 0;
 }
 
+static int msm_ipc_router_send_remove_client(struct comm_mode_info *mode_info,
+					uint32_t node_id, uint32_t port_id)
+{
+	union rr_control_msg msg;
+	struct msm_ipc_router_xprt_info *tmp_xprt_info;
+	int mode;
+	void *xprt_info;
+	int rc = 0;
+
+	if (!mode_info) {
+		pr_err("%s: NULL mode_info\n", __func__);
+		return -EINVAL;
+	}
+	mode = mode_info->mode;
+	xprt_info = mode_info->xprt_info;
+
+	msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
+	msg.cli.node_id = node_id;
+	msg.cli.port_id = port_id;
+
+	if ((mode == SINGLE_LINK_MODE) && xprt_info) {
+		mutex_lock(&xprt_info_list_lock);
+		list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) {
+			if (tmp_xprt_info != xprt_info)
+				continue;
+			msm_ipc_router_send_control_msg(tmp_xprt_info, &msg);
+			break;
+		}
+		mutex_unlock(&xprt_info_list_lock);
+	} else if ((mode == SINGLE_LINK_MODE) && !xprt_info) {
+		broadcast_ctl_msg_locally(&msg);
+	} else if (mode == MULTI_LINK_MODE) {
+		broadcast_ctl_msg(&msg);
+		broadcast_ctl_msg_locally(&msg);
+	} else if (mode != NULL_MODE) {
+		pr_err("%s: Invalid mode(%d) + xprt_inf(%p) for %08x:%08x\n",
+			__func__, mode, xprt_info, node_id, port_id);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+static void update_comm_mode_info(struct comm_mode_info *mode_info,
+				  struct msm_ipc_router_xprt_info *xprt_info)
+{
+	if (!mode_info) {
+		pr_err("%s: NULL mode_info\n", __func__);
+		return;
+	}
+
+	if (mode_info->mode == NULL_MODE) {
+		mode_info->xprt_info = xprt_info;
+		mode_info->mode = SINGLE_LINK_MODE;
+	} else if (mode_info->mode == SINGLE_LINK_MODE &&
+		   mode_info->xprt_info != xprt_info) {
+		mode_info->mode = MULTI_LINK_MODE;
+	}
+
+	return;
+}
+
 static void reset_remote_port_info(uint32_t node_id, uint32_t port_id)
 {
 	struct msm_ipc_router_remote_port *rport_ptr;
@@ -1915,6 +1976,7 @@
 	broadcast_ctl_msg(&ctl);
 	spin_lock_irqsave(&port_ptr->port_lock, flags);
 	port_ptr->type = SERVER_PORT;
+	port_ptr->mode_info.mode = MULTI_LINK_MODE;
 	port_ptr->port_name.service = server->name.service;
 	port_ptr->port_name.instance = server->name.instance;
 	spin_unlock_irqrestore(&port_ptr->port_lock, flags);
@@ -2026,6 +2088,7 @@
 	ret_len = pkt->length;
 	wake_up(&port_ptr->port_rx_wait_q);
 	mutex_unlock(&port_ptr->port_rx_q_lock);
+	update_comm_mode_info(&src->mode_info, NULL);
 	mutex_unlock(&local_ports_lock);
 
 	return ret_len;
@@ -2118,6 +2181,7 @@
 		pr_err("%s: Write on XPRT failed\n", __func__);
 		return ret;
 	}
+	update_comm_mode_info(&src->mode_info, xprt_info);
 
 	RAW_HDR("[w rr_h] "
 		"ver=%i,type=%s,src_nid=%08x,src_port_id=%08x,"
@@ -2407,13 +2471,11 @@
 		 * Server port could have been a client port earlier.
 		 * Send REMOVE_CLIENT message in either case.
 		 */
-		msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
-		msg.cli.node_id = port_ptr->this_port.node_id;
-		msg.cli.port_id = port_ptr->this_port.port_id;
 		RR("x REMOVE_CLIENT id=%d:%08x\n",
-		   msg.cli.node_id, msg.cli.port_id);
-		broadcast_ctl_msg(&msg);
-		broadcast_ctl_msg_locally(&msg);
+		   port_ptr->this_port.node_id, port_ptr->this_port.port_id);
+		msm_ipc_router_send_remove_client(&port_ptr->mode_info,
+			port_ptr->this_port.node_id,
+			port_ptr->this_port.port_id);
 	} else if (port_ptr->type == CONTROL_PORT) {
 		mutex_lock(&control_ports_lock);
 		list_del(&port_ptr->list);
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index cafcdd2..32832dd 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -62,6 +62,12 @@
 	IRSC_PORT,
 };
 
+enum {
+	NULL_MODE,
+	SINGLE_LINK_MODE,
+	MULTI_LINK_MODE,
+};
+
 union rr_control_msg {
 	uint32_t cmd;
 	struct {
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index e993282..d657b05 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -104,13 +104,15 @@
 
 static int pil_mss_power_up(struct q6v5_data *drv)
 {
-	int ret;
+	int ret = 0;
 	struct device *dev = drv->desc.dev;
 	u32 regval;
 
-	ret = regulator_enable(drv->vreg);
-	if (ret)
-		dev_err(dev, "Failed to enable modem regulator.\n");
+	if (drv->vreg) {
+		ret = regulator_enable(drv->vreg);
+		if (ret)
+			dev_err(dev, "Failed to enable modem regulator.\n");
+	}
 
 	if (drv->cxrail_bhs) {
 		regval = readl_relaxed(drv->cxrail_bhs);
@@ -134,7 +136,10 @@
 		writel_relaxed(regval, drv->cxrail_bhs);
 	}
 
-	return regulator_disable(drv->vreg);
+	if (drv->vreg)
+		return regulator_disable(drv->vreg);
+
+	return 0;
 }
 
 static int pil_mss_enable_clks(struct q6v5_data *drv)
@@ -724,6 +729,7 @@
 	struct q6v5_data *q6;
 	struct pil_desc *q6_desc, *mba_desc;
 	struct resource *res;
+	struct property *prop;
 	int ret;
 
 	int clk_ready = of_get_named_gpio(pdev->dev.of_node,
@@ -761,31 +767,36 @@
 	if (!q6->restart_reg)
 		return -ENOMEM;
 
-	q6->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
-	if (IS_ERR(q6->vreg))
-		return PTR_ERR(q6->vreg);
+	q6->vreg = NULL;
+
+	prop = of_find_property(pdev->dev.of_node, "vdd_mss-supply", NULL);
+	if (prop) {
+		q6->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
+		if (IS_ERR(q6->vreg))
+			return PTR_ERR(q6->vreg);
+
+		ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV,
+						MAX_VDD_MSS_UV);
+		if (ret)
+			dev_err(&pdev->dev, "Failed to set vreg voltage.\n");
+
+		ret = regulator_set_optimum_mode(q6->vreg, 100000);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Failed to set vreg mode.\n");
+			return ret;
+		}
+	}
 
 	q6->vreg_mx = devm_regulator_get(&pdev->dev, "vdd_mx");
 	if (IS_ERR(q6->vreg_mx))
 		return PTR_ERR(q6->vreg_mx);
 
-	ret = regulator_set_voltage(q6->vreg, VDD_MSS_UV, MAX_VDD_MSS_UV);
-	if (ret)
-		dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
-
-	ret = regulator_set_optimum_mode(q6->vreg, 100000);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to set regulator's mode.\n");
-		return ret;
-	}
-
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 		"cxrail_bhs_reg");
 	if (res)
 		q6->cxrail_bhs = devm_ioremap(&pdev->dev, res->start,
 					  resource_size(res));
 
-
 	q6->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
 	if (IS_ERR(q6->ahb_clk))
 		return PTR_ERR(q6->ahb_clk);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 12a3ceb..d316496 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -279,6 +279,8 @@
 	/* 8974 IDs */
 	[126] = MSM_CPU_8974,
 	[184] = MSM_CPU_8974,
+	[185] = MSM_CPU_8974,
+	[186] = MSM_CPU_8974,
 
 	/* 8625 IDs */
 	[127] = MSM_CPU_8625,
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 5e00570..7ec83dd 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -105,6 +105,16 @@
 	  If unsure, say 'N' here to avoid potential power and performance
 	  penalty.
 
+config CORESIGHT_HWEVENT
+	bool "CoreSight Hardware Event driver"
+	depends on CORESIGHT_STM
+	select CORESIGHT_CSR
+	help
+	  This driver provides support for monitoring and tracing CoreSight
+	  Hardware Event across STM interface. It configures Coresight
+	  Hardware Event mux control registers to select hardware events
+	  based on user input.
+
 config CORESIGHT_ETM
 	bool "CoreSight Embedded Trace Macrocell driver"
 	help
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 0595064..0e2e2d9 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -11,5 +11,6 @@
 obj-$(CONFIG_CORESIGHT_FUNNEL) += coresight-funnel.o
 obj-$(CONFIG_CORESIGHT_REPLICATOR) += coresight-replicator.o
 obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
+obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o
 obj-$(CONFIG_CORESIGHT_ETM) += coresight-etm.o coresight-etm-cp14.o
 obj-$(CONFIG_CORESIGHT_EVENT) += coresight-event.o
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 1c2ab25..8195184 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -73,6 +73,7 @@
 
 struct csr_drvdata {
 	void __iomem		*base;
+	phys_addr_t		pbase;
 	struct device		*dev;
 	struct coresight_device	*csdev;
 	uint32_t		blksize;
@@ -134,6 +135,30 @@
 }
 EXPORT_SYMBOL(msm_qdss_csr_disable_flush);
 
+int coresight_csr_hwctrl_set(phys_addr_t addr, uint32_t val)
+{
+	struct csr_drvdata *drvdata = csrdrvdata;
+	int ret = 0;
+
+	CSR_UNLOCK(drvdata);
+
+	if (addr == (drvdata->pbase + CSR_STMEXTHWCTRL0))
+		csr_writel(drvdata, val, CSR_STMEXTHWCTRL0);
+	else if (addr == (drvdata->pbase + CSR_STMEXTHWCTRL1))
+		csr_writel(drvdata, val, CSR_STMEXTHWCTRL1);
+	else if (addr == (drvdata->pbase + CSR_STMEXTHWCTRL2))
+		csr_writel(drvdata, val, CSR_STMEXTHWCTRL2);
+	else if (addr == (drvdata->pbase + CSR_STMEXTHWCTRL3))
+		csr_writel(drvdata, val, CSR_STMEXTHWCTRL3);
+	else
+		ret = -EINVAL;
+
+	CSR_LOCK(drvdata);
+
+	return ret;
+}
+EXPORT_SYMBOL(coresight_csr_hwctrl_set);
+
 static int __devinit csr_probe(struct platform_device *pdev)
 {
 	int ret;
@@ -161,6 +186,7 @@
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr-base");
 	if (!res)
 		return -ENODEV;
+	drvdata->pbase = res->start;
 
 	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
 	if (!drvdata->base)
diff --git a/drivers/coresight/coresight-hwevent.c b/drivers/coresight/coresight-hwevent.c
new file mode 100644
index 0000000..777484d
--- /dev/null
+++ b/drivers/coresight/coresight-hwevent.c
@@ -0,0 +1,341 @@
+/* Copyright (c) 2013, The Linux Foundation. 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+#include <linux/of.h>
+
+#include "coresight-priv.h"
+
+struct hwevent_mux {
+	phys_addr_t				start;
+	phys_addr_t				end;
+};
+
+struct hwevent_drvdata {
+	struct device				*dev;
+	struct coresight_device			*csdev;
+	struct clk				*clk;
+	struct mutex				mutex;
+	int					nr_hclk;
+	struct clk				**hclk;
+	int					nr_hmux;
+	struct hwevent_mux			*hmux;
+	bool					enable;
+};
+
+static int hwevent_enable(struct hwevent_drvdata *drvdata)
+{
+	int ret, i;
+
+	mutex_lock(&drvdata->mutex);
+
+	if (drvdata->enable)
+		goto out;
+
+	ret = clk_prepare_enable(drvdata->clk);
+	if (ret)
+		goto err0;
+	for (i = 0; i < drvdata->nr_hclk; i++) {
+		ret = clk_prepare_enable(drvdata->hclk[i]);
+		if (ret)
+			goto err1;
+	}
+	drvdata->enable = true;
+	dev_info(drvdata->dev, "Hardware Event driver enabled\n");
+out:
+	mutex_unlock(&drvdata->mutex);
+	return 0;
+err1:
+	clk_disable_unprepare(drvdata->clk);
+	for (i--; i >= 0; i--)
+		clk_disable_unprepare(drvdata->hclk[i]);
+err0:
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+}
+
+static void hwevent_disable(struct hwevent_drvdata *drvdata)
+{
+	int i;
+
+	mutex_lock(&drvdata->mutex);
+
+	if (!drvdata->enable)
+		goto out;
+
+	drvdata->enable = false;
+	clk_disable_unprepare(drvdata->clk);
+	for (i = 0; i < drvdata->nr_hclk; i++)
+		clk_disable_unprepare(drvdata->hclk[i]);
+	dev_info(drvdata->dev, "Hardware Event driver disabled\n");
+out:
+	mutex_unlock(&drvdata->mutex);
+}
+
+static ssize_t hwevent_show_enable(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct hwevent_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->enable;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t hwevent_store_enable(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct hwevent_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+
+	if (val)
+		ret = hwevent_enable(drvdata);
+	else
+		hwevent_disable(drvdata);
+
+	if (ret)
+		return ret;
+	return size;
+}
+static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, hwevent_show_enable,
+		   hwevent_store_enable);
+
+static ssize_t hwevent_store_setreg(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t size)
+{
+	struct hwevent_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	void *hwereg;
+	phys_addr_t addr;
+	uint32_t val;
+	int ret, i;
+
+	if (sscanf(buf, "%x %x", &addr, &val) != 2)
+		return -EINVAL;
+
+	mutex_lock(&drvdata->mutex);
+
+	if (!drvdata->enable) {
+		dev_err(dev, "Hardware Event driver not enabled\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	for (i = 0; i < drvdata->nr_hmux; i++) {
+		if ((addr >= drvdata->hmux[i].start) &&
+		    (addr < drvdata->hmux[i].end)) {
+			hwereg = devm_ioremap(dev,
+					      drvdata->hmux[i].start,
+					      drvdata->hmux[i].end -
+					      drvdata->hmux[i].start);
+			if (!hwereg) {
+				dev_err(dev, "unable to map address 0x%x\n",
+					addr);
+				ret = -ENOMEM;
+				goto err;
+			}
+			writel_relaxed(val, hwereg + addr -
+				       drvdata->hmux[i].start);
+			/* Ensure writes to hwevent control registers
+			   are completed before unmapping the address
+			*/
+			mb();
+			devm_iounmap(dev, hwereg);
+			break;
+		}
+	}
+
+	if (i == drvdata->nr_hmux) {
+		ret = coresight_csr_hwctrl_set(addr, val);
+		if (ret) {
+			dev_err(dev, "invalid mux control register address\n");
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+
+	mutex_unlock(&drvdata->mutex);
+	return size;
+err:
+	mutex_unlock(&drvdata->mutex);
+	return ret;
+}
+static DEVICE_ATTR(setreg, S_IWUSR, NULL, hwevent_store_setreg);
+
+static struct attribute *hwevent_attrs[] = {
+	&dev_attr_enable.attr,
+	&dev_attr_setreg.attr,
+	NULL,
+};
+
+static struct attribute_group hwevent_attr_grp = {
+	.attrs = hwevent_attrs,
+};
+
+static const struct attribute_group *hwevent_attr_grps[] = {
+	&hwevent_attr_grp,
+	NULL,
+};
+
+static int __devinit hwevent_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct hwevent_drvdata *drvdata;
+	struct coresight_desc *desc;
+	struct coresight_platform_data *pdata;
+	struct resource *res;
+	int ret, i;
+	const char *hmux_name, *hclk_name;
+
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	if (pdev->dev.of_node)
+		drvdata->nr_hmux = of_property_count_strings(pdev->dev.of_node,
+							     "reg-names");
+
+	if (drvdata->nr_hmux > 0) {
+		drvdata->hmux = devm_kzalloc(dev, drvdata->nr_hmux *
+					     sizeof(*drvdata->hmux),
+					     GFP_KERNEL);
+		if (!drvdata->hmux)
+			return -ENOMEM;
+		for (i = 0; i < drvdata->nr_hmux; i++) {
+			ret = of_property_read_string_index(pdev->dev.of_node,
+							    "reg-names", i,
+							    &hmux_name);
+			if (ret)
+				return ret;
+			res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+							   hmux_name);
+			if (!res)
+				return -ENODEV;
+			drvdata->hmux[i].start = res->start;
+			drvdata->hmux[i].end = res->end;
+		}
+	} else if (drvdata->nr_hmux < 0) {
+		return drvdata->nr_hmux;
+	} else {
+		/* return error if reg-names in dt node is empty string */
+		return -ENODEV;
+	}
+
+	mutex_init(&drvdata->mutex);
+
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
+
+	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+	if (ret)
+		return ret;
+
+	if (pdev->dev.of_node)
+		drvdata->nr_hclk = of_property_count_strings(pdev->dev.of_node,
+							     "qcom,hwevent-clks");
+	if (drvdata->nr_hclk > 0) {
+		drvdata->hclk = devm_kzalloc(dev, drvdata->nr_hclk *
+					     sizeof(*drvdata->hclk),
+					     GFP_KERNEL);
+		if (!drvdata->hclk)
+			return -ENOMEM;
+		for (i = 0; i < drvdata->nr_hclk; i++) {
+			ret = of_property_read_string_index(pdev->dev.of_node,
+							    "qcom,hwevent-clks",
+							    i, &hclk_name);
+			if (ret)
+				return ret;
+			drvdata->hclk[i] = devm_clk_get(dev, hclk_name);
+			if (IS_ERR(drvdata->hclk[i]))
+				return PTR_ERR(drvdata->hclk[i]);
+		}
+	}
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+
+	desc->type = CORESIGHT_DEV_TYPE_NONE;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->groups = hwevent_attr_grps;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
+
+	dev_info(dev, "Hardware Event driver initialized\n");
+	return 0;
+}
+
+static int __devexit hwevent_remove(struct platform_device *pdev)
+{
+	struct hwevent_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
+	return 0;
+}
+
+static struct of_device_id hwevent_match[] = {
+	{.compatible = "qcom,coresight-hwevent"},
+	{}
+};
+
+static struct platform_driver hwevent_driver = {
+	.probe		= hwevent_probe,
+	.remove		= __devexit_p(hwevent_remove),
+	.driver		= {
+		.name	= "coresight-hwevent",
+		.owner	= THIS_MODULE,
+		.of_match_table	= hwevent_match,
+	},
+};
+
+static int __init hwevent_init(void)
+{
+	return platform_driver_register(&hwevent_driver);
+}
+module_init(hwevent_init);
+
+static void __exit hwevent_exit(void)
+{
+	platform_driver_unregister(&hwevent_driver);
+}
+module_exit(hwevent_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Hardware Event driver");
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index 258ff09..f208185 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -40,10 +40,13 @@
 extern void msm_qdss_csr_enable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_bam_to_usb(void);
 extern void msm_qdss_csr_disable_flush(void);
+extern int coresight_csr_hwctrl_set(phys_addr_t addr, uint32_t val);
 #else
 static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_flush(void) {}
+static inline int coresight_csr_hwctrl_set(phys_addr_t addr,
+					   uint32_t val) { return -ENOSYS; }
 #endif
 #ifdef CONFIG_CORESIGHT_ETM
 extern unsigned int etm_readl_cp14(uint32_t off);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7cd9943..2b674ab 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -308,16 +308,28 @@
 
 static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
 {
+	bool had_gpuaddr = false;
+
 	if (entry == NULL)
 		return;
 
+	/*
+	 * Unmap the entry first so that there isn't a period of
+	 * time where kgsl doesn't know about the address range
+	 * but it is still present in the pagetable. Unmapping will
+	 * clear the gpuaddr field, so remember if we had a mapping,
+	 * and an rbtree entry for later.
+	 */
+	had_gpuaddr = entry->memdesc.gpuaddr != 0;
+	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
+
 	spin_lock(&entry->priv->mem_lock);
 
 	if (entry->id != 0)
 		idr_remove(&entry->priv->mem_idr, entry->id);
 	entry->id = 0;
 
-	if (entry->memdesc.gpuaddr != 0)
+	if (had_gpuaddr)
 		rb_erase(&entry->node, &entry->priv->mem_rb);
 
 	spin_unlock(&entry->priv->mem_lock);
@@ -325,7 +337,6 @@
 	entry->priv->stats[entry->memtype].cur -= entry->memdesc.size;
 	entry->priv = NULL;
 
-	kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc);
 
 	kgsl_mem_entry_put(entry);
 }
@@ -1346,6 +1357,12 @@
 				"invalid gpuaddr %08x\n", gpuaddr);
 		return -EINVAL;
 	}
+	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+		kgsl_mem_entry_put(entry);
+		return -EBUSY;
+	}
+	entry->memdesc.priv |= KGSL_MEMDESC_FREE_PENDING;
+
 	trace_kgsl_mem_timestamp_queue(device, entry, context_id,
 				       kgsl_readtimestamp(device, context,
 						  KGSL_TIMESTAMP_RETIRED),
@@ -1445,6 +1462,11 @@
 		return -EINVAL;
 	}
 
+	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+		kgsl_mem_entry_put(entry);
+		return -EBUSY;
+	}
+
 	trace_kgsl_mem_free(entry);
 
 	kgsl_memfree_hist_set_event(entry->priv->pid,
@@ -1470,6 +1492,12 @@
 		KGSL_MEM_INFO(dev_priv->device, "invalid id %d\n", param->id);
 		return -EINVAL;
 	}
+
+	if (entry->memdesc.priv & KGSL_MEMDESC_FREE_PENDING) {
+		kgsl_mem_entry_put(entry);
+		return -EBUSY;
+	}
+
 	trace_kgsl_mem_free(entry);
 
 	kgsl_memfree_hist_set_event(entry->priv->pid,
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index d63aa79..debba18 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -151,6 +151,8 @@
 #define KGSL_MEMDESC_GLOBAL BIT(1)
 /* The memdesc is frozen during a snapshot */
 #define KGSL_MEMDESC_FROZEN BIT(2)
+/* The memdesc is scheduled to be freed on a timestamp */
+#define KGSL_MEMDESC_FREE_PENDING BIT(3)
 
 /* shared memory allocation */
 struct kgsl_memdesc {
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 4165690..f09c623 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -347,6 +347,9 @@
 	int offset;
 	int ret = -EINVAL;
 
+	if (!gpuaddr)
+		return 0;
+
 	entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, size);
 
 	if (entry == NULL) {
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index b1960c6..b92ec7f 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -148,12 +148,26 @@
 		if (ret)
 			clk_disable_unprepare(drvdata->pclk);
 	}
+
+	if (ret)
+		goto fail;
+
+	if (drvdata->aclk) {
+		ret = clk_prepare_enable(drvdata->aclk);
+		if (ret) {
+			clk_disable_unprepare(drvdata->clk);
+			clk_disable_unprepare(drvdata->pclk);
+		}
+	}
+
 fail:
 	return ret;
 }
 
 static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
 {
+	if (drvdata->aclk)
+		clk_disable_unprepare(drvdata->aclk);
 	if (drvdata->clk)
 		clk_disable_unprepare(drvdata->clk);
 	clk_disable_unprepare(drvdata->pclk);
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 7ae0b21..059216e 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -129,7 +129,8 @@
 }
 
 static int msm_iommu_parse_dt(struct platform_device *pdev,
-				struct msm_iommu_drvdata *drvdata)
+				struct msm_iommu_drvdata *drvdata,
+				int *needs_alt_core_clk)
 {
 #ifdef CONFIG_OF_DEVICE
 	struct device_node *child;
@@ -169,6 +170,10 @@
 		pr_err("%s: Missing property label\n", __func__);
 		return -EINVAL;
 	}
+
+	*needs_alt_core_clk = of_property_read_bool(pdev->dev.of_node,
+						   "qcom,needs-alt-core-clk");
+
 	drvdata->sec_id = -1;
 	drvdata->ttbr_split = 0;
 #endif
@@ -176,7 +181,8 @@
 }
 
 static int __get_clocks(struct platform_device *pdev,
-				 struct msm_iommu_drvdata *drvdata)
+			struct msm_iommu_drvdata *drvdata,
+			int needs_alt_core_clk)
 {
 	int ret = 0;
 
@@ -199,6 +205,18 @@
 	} else {
 		drvdata->clk = NULL;
 	}
+
+	if (needs_alt_core_clk) {
+		drvdata->aclk = devm_clk_get(&pdev->dev, "alt_core_clk");
+		if (IS_ERR(drvdata->aclk))
+			return PTR_ERR(drvdata->aclk);
+	}
+
+	if (drvdata->aclk && clk_get_rate(drvdata->aclk) == 0) {
+		ret = clk_round_rate(drvdata->aclk, 1000);
+		clk_set_rate(drvdata->aclk, ret);
+	}
+
 	return 0;
 fail:
 	return ret;
@@ -206,35 +224,13 @@
 
 static void __put_clocks(struct msm_iommu_drvdata *drvdata)
 {
+	if (drvdata->aclk)
+		clk_put(drvdata->aclk);
 	if (drvdata->clk)
 		clk_put(drvdata->clk);
 	clk_put(drvdata->pclk);
 }
 
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	int ret;
-
-	ret = clk_prepare_enable(drvdata->pclk);
-	if (ret)
-		goto fail;
-
-	if (drvdata->clk) {
-		ret = clk_prepare_enable(drvdata->clk);
-		if (ret)
-			clk_disable_unprepare(drvdata->pclk);
-	}
-fail:
-	return ret;
-}
-
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
-{
-	if (drvdata->clk)
-		clk_disable_unprepare(drvdata->clk);
-	clk_disable_unprepare(drvdata->pclk);
-}
-
 /*
  * Do a basic check of the IOMMU by performing an ATS operation
  * on context bank 0.
@@ -326,6 +322,7 @@
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
 	int ret;
+	int needs_alt_core_clk = 0;
 
 	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
 
@@ -335,7 +332,7 @@
 	}
 
 	if (pdev->dev.of_node) {
-		ret = msm_iommu_parse_dt(pdev, drvdata);
+		ret = msm_iommu_parse_dt(pdev, drvdata, &needs_alt_core_clk);
 		if (ret)
 			goto fail;
 	} else if (pdev->dev.platform_data) {
@@ -382,12 +379,12 @@
 
 	drvdata->dev = &pdev->dev;
 
-	ret = __get_clocks(pdev, drvdata);
+	ret = __get_clocks(pdev, drvdata, needs_alt_core_clk);
 
 	if (ret)
 		goto fail;
 
-	__enable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_on(drvdata);
 
 	msm_iommu_reset(drvdata->base, drvdata->glb_base, drvdata->ncb);
 
@@ -401,7 +398,7 @@
 	msm_iommu_add_drv(drvdata);
 	platform_set_drvdata(pdev, drvdata);
 
-	__disable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
 
 	pmon_info = msm_iommu_pm_alloc(&pdev->dev);
 	if (pmon_info != NULL) {
@@ -430,7 +427,7 @@
 	return 0;
 
 fail_clk:
-	__disable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
 	__put_clocks(drvdata);
 fail:
 	return ret;
@@ -618,9 +615,9 @@
 		goto fail;
 	}
 
-	__enable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_on(drvdata);
 	__program_m2v_tables(drvdata, ctx_drvdata);
-	__disable_clocks(drvdata);
+	iommu_access_ops_v0.iommu_clk_off(drvdata);
 
 	dev_info(&pdev->dev, "context %s using bank %d\n", ctx_drvdata->name,
 							   ctx_drvdata->num);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 7347b37..2a750a6 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1796,19 +1796,10 @@
 	return 0;
 }
 
-static void dvb_dmxdev_ts_insertion_timer(unsigned long data)
-{
-	struct ts_insertion_buffer *ts_buffer =
-		(struct ts_insertion_buffer *)data;
-
-	if (ts_buffer && !ts_buffer->abort)
-		schedule_work(&ts_buffer->work);
-}
-
 static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
 {
 	struct ts_insertion_buffer *ts_buffer =
-		container_of(worker, struct ts_insertion_buffer, work);
+		container_of(worker, struct ts_insertion_buffer, dwork.work);
 	struct dmxdev_feed *feed;
 	size_t free_bytes;
 	struct dmx_ts_feed *ts;
@@ -1832,8 +1823,8 @@
 		ts->ts_insertion_insert_buffer(ts,
 			ts_buffer->buffer, ts_buffer->size);
 
-	if (ts_buffer->repetition_time)
-		mod_timer(&ts_buffer->timer, jiffies +
+	if (ts_buffer->repetition_time && !ts_buffer->abort)
+		schedule_delayed_work(&ts_buffer->dwork,
 				msecs_to_jiffies(ts_buffer->repetition_time));
 }
 
@@ -1854,7 +1845,7 @@
 	}
 
 	ts_buffer->abort = 0;
-	schedule_work(&ts_buffer->work);
+	schedule_delayed_work(&ts_buffer->dwork, 0);
 }
 
 static void dvb_dmxdev_cancel_ts_insertion(
@@ -1873,16 +1864,10 @@
 		return;
 	}
 
-	/*
-	 * Work should be stopped first as it might re-trigger the timer
-	 * until it is stopped. Timer would not re-schedule the work
-	 * due to the abort flag.
-	 */
 	ts_buffer->abort = 1;
 
 	mutex_unlock(&ts_buffer->dmxdevfilter->mutex);
-	cancel_work_sync(&ts_buffer->work);
-	del_timer_sync(&ts_buffer->timer);
+	cancel_delayed_work_sync(&ts_buffer->dwork);
 	mutex_lock(&ts_buffer->dmxdevfilter->mutex);
 }
 
@@ -1928,11 +1913,7 @@
 	ts_buffer->identifier = params->identifier;
 	ts_buffer->repetition_time = params->repetition_time;
 	ts_buffer->dmxdevfilter = dmxdevfilter;
-	init_timer(&ts_buffer->timer);
-	ts_buffer->timer.function = dvb_dmxdev_ts_insertion_timer;
-	ts_buffer->timer.data = (unsigned long)ts_buffer;
-	ts_buffer->timer.expires = 0xffffffffL;
-	INIT_WORK(&ts_buffer->work, dvb_dmxdev_ts_insertion_work);
+	INIT_DELAYED_WORK(&ts_buffer->dwork, dvb_dmxdev_ts_insertion_work);
 
 	first_buffer = list_empty(&dmxdevfilter->insertion_buffers);
 	list_add_tail(&ts_buffer->next, &dmxdevfilter->insertion_buffers);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index d8cd982..49e5e1b 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -117,7 +117,7 @@
 #define DMX_MIN_INSERTION_REPETITION_TIME	25 /* in msec */
 struct ts_insertion_buffer {
 	/* work scheduled for insertion of this buffer */
-	struct work_struct work;
+	struct delayed_work dwork;
 
 	struct list_head next;
 
@@ -133,9 +133,6 @@
 	/* repetition time for the buffer insertion */
 	u32 repetition_time;
 
-	/* timer used for insertion of the buffer */
-	struct timer_list timer;
-
 	/* the recording filter to which this buffer belongs */
 	struct dmxdev_filter *dmxdevfilter;
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 613ad86..dd8db03 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -230,12 +230,12 @@
 	return rc;
 }
 
-static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, uint32_t rate)
+static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, long *rate)
 {
 	int rc = 0;
 	int clk_idx = vfe_dev->hw_info->vfe_clk_idx;
 	long round_rate =
-		clk_round_rate(vfe_dev->vfe_clk[clk_idx], rate);
+		clk_round_rate(vfe_dev->vfe_clk[clk_idx], *rate);
 	if (round_rate < 0) {
 		pr_err("%s: Invalid vfe clock rate\n", __func__);
 		return round_rate;
@@ -246,6 +246,7 @@
 		pr_err("%s: Vfe set rate error\n", __func__);
 		return rc;
 	}
+	*rate = round_rate;
 	return 0;
 }
 
@@ -266,7 +267,7 @@
 		input_cfg->d.pix_cfg.camif_cfg.pixels_per_line;
 
 	rc = msm_isp_set_clk_rate(vfe_dev,
-		vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock);
+		&vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock);
 	if (rc < 0) {
 		pr_err("%s: clock set rate failed\n", __func__);
 		return rc;
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 7fc8810..82a4f3c 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -316,6 +316,9 @@
 	case HAL_EXTRADATA_ASPECT_RATIO:
 		ret = HFI_PROPERTY_PARAM_INDEX_EXTRADATA;
 		break;
+	case HAL_EXTRADATA_MPEG2_SEQDISP:
+		ret = HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
 		break;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 43a3dad..19f5dcd 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1018,6 +1018,41 @@
 	callback(SESSION_END_DONE, &cmd_done);
 }
 
+static void hfi_process_session_abort_done(
+	msm_vidc_callback callback, u32 device_id,
+	struct hfi_msg_sys_session_abort_done_packet *pkt)
+{
+	struct msm_vidc_cb_cmd_done cmd_done;
+	struct hal_session *sess_close;
+
+	dprintk(VIDC_DBG, "RECEIVED:SESSION_ABORT_DONE");
+
+	if (!pkt || pkt->size !=
+		sizeof(struct hfi_msg_sys_session_abort_done_packet)) {
+		dprintk(VIDC_ERR, "%s: bad packet/packet size: %d",
+				__func__, pkt ? pkt->size : 0);
+		return;
+	}
+	memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
+	cmd_done.device_id = device_id;
+	cmd_done.session_id =
+		((struct hal_session *) pkt->session_id)->session_id;
+	cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
+	cmd_done.data = NULL;
+	cmd_done.size = 0;
+
+	sess_close = (struct hal_session *)pkt->session_id;
+	if (!sess_close) {
+		dprintk(VIDC_ERR, "%s: invalid session pointer\n", __func__);
+		return;
+	}
+	dprintk(VIDC_ERR, "deleted the session: 0x%x",
+		sess_close->session_id);
+	list_del(&sess_close->list);
+	kfree(sess_close);
+	callback(SESSION_ABORT_DONE, &cmd_done);
+}
+
 static void hfi_process_session_get_seq_hdr_done(
 	msm_vidc_callback callback, u32 device_id,
 	struct hfi_msg_session_get_sequence_header_done_packet *pkt)
@@ -1134,6 +1169,10 @@
 			hfi_msg_session_release_buffers_done_packet*)
 			msg_hdr);
 		break;
+	case HFI_MSG_SYS_SESSION_ABORT_DONE:
+		hfi_process_session_abort_done(callback, device_id, (struct
+			hfi_msg_sys_session_abort_done_packet*) msg_hdr);
+		break;
 	default:
 		dprintk(VIDC_ERR, "UNKNOWN_MSG_TYPE : %d", msg_hdr->packet);
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 62f09d0..511a478 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -66,6 +66,7 @@
 	"Extradata input crop",
 	"Extradata digital zoom",
 	"Extradata aspect ratio",
+	"Extradata mpeg2 seqdisp",
 };
 
 static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
@@ -203,7 +204,7 @@
 		.name = "Extradata Type",
 		.type = V4L2_CTRL_TYPE_MENU,
 		.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
-		.maximum = V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+		.maximum = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP,
 		.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
 		.menu_skip_mask = ~(
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -223,7 +224,8 @@
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM) |
-			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO)
+			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO) |
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP)
 			),
 		.qmenu = mpeg_video_vidc_extradata,
 		.step = 0,
@@ -1132,11 +1134,24 @@
 	int rc = 0;
 	struct v4l2_event dqevent = {0};
 	struct msm_vidc_core *core = inst->core;
+
+	if (!dec || !inst || !inst->core) {
+		dprintk(VIDC_ERR, "%s invalid params", __func__);
+		return -EINVAL;
+	}
 	switch (dec->cmd) {
 	case V4L2_DEC_QCOM_CMD_FLUSH:
 		rc = msm_comm_flush(inst, dec->flags);
 		break;
 	case V4L2_DEC_CMD_STOP:
+		if (core->state != VIDC_CORE_INVALID &&
+			inst->state ==  MSM_VIDC_CORE_INVALID) {
+			rc = msm_comm_recover_from_session_error(inst);
+			if (rc)
+				dprintk(VIDC_ERR,
+					"Failed to recover from session_error: %d\n",
+					rc);
+		}
 		rc = msm_comm_release_scratch_buffers(inst);
 		if (rc)
 			dprintk(VIDC_ERR,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index bd4854c..39d73ca 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -673,13 +673,17 @@
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
 			vb->v4l2_buf.flags &= ~V4L2_QCOM_BUF_FLAG_CODECCONFIG;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_SYNCFRAME)
-			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOSEQ)
 			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_EOSEQ;
 		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DECODEONLY)
 			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_DECODEONLY;
+		if (fill_buf_done->flags1 & HAL_BUFFERFLAG_DATACORRUPT)
+			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_DATA_CORRUPT;
 		switch (fill_buf_done->picture_type) {
 		case HAL_PICTURE_IDR:
+			vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_IDRFRAME;
+			break;
 		case HAL_PICTURE_I:
 			vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
 			break;
@@ -808,6 +812,7 @@
 		handle_release_res_done(cmd, data);
 		break;
 	case SESSION_END_DONE:
+	case SESSION_ABORT_DONE:
 		handle_session_close(cmd, data);
 		break;
 	case VIDC_EVENT_CHANGE:
@@ -2209,7 +2214,10 @@
 				kfree(temp);
 			}
 		}
-		rc = call_hfi_op(hdev, session_flush, inst->session,
+		/*Do not send flush in case of session_error */
+		if (!(inst->state == MSM_VIDC_CORE_INVALID &&
+			  core->state != VIDC_CORE_INVALID))
+			rc = call_hfi_op(hdev, session_flush, inst->session,
 				HAL_FLUSH_ALL);
 	}
 	mutex_unlock(&inst->sync_lock);
@@ -2270,6 +2278,9 @@
 	case V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO:
 		ret = HAL_EXTRADATA_ASPECT_RATIO;
 		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
+		ret = HAL_EXTRADATA_MPEG2_SEQDISP;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
 		break;
@@ -2379,3 +2390,33 @@
 	}
 	return rc;
 }
+
+int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst)
+{
+	struct hfi_device *hdev;
+	int rc = 0;
+
+	if (!inst || !inst->core || !inst->core->device) {
+		dprintk(VIDC_ERR, "%s: invalid input parameters", __func__);
+		return -EINVAL;
+	}
+	hdev = inst->core->device;
+
+	init_completion(&inst->completions[SESSION_MSG_INDEX
+		(SESSION_ABORT_DONE)]);
+
+	/* We have received session_error. Send session_abort to firmware
+	 *  to clean up and release the session
+	 */
+	rc = call_hfi_op(hdev, session_abort, (void *) inst->session);
+	if (rc) {
+		dprintk(VIDC_ERR, "session_abort failed rc: %d\n", rc);
+		return rc;
+	}
+
+	rc = wait_for_sess_signal_receipt(inst, SESSION_ABORT_DONE);
+	if (rc)
+		dprintk(VIDC_ERR, "%s: Wait interrupted or timeout: %d\n",
+			__func__, rc);
+	return rc;
+}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 862dfab..c018345 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -48,3 +48,4 @@
 		V4L2_CTRL_DRIVER_PRIV(idx))
 
 #endif
+int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 1311752..bb72da7 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -75,7 +75,8 @@
 #define HFI_EXTRADATA_PANSCAN_WINDOW		0x00000008
 #define HFI_EXTRADATA_RECOVERY_POINT_SEI	0x00000009
 #define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
-#define HFI_EXTRADATA_AFD_UD				0x0000000B
+#define HFI_EXTRADATA_AFD_UD			0x0000000B
+#define HFI_EXTRADATA_MPEG2_SEQDISP		0x0000000D
 #define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
 #define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
 #define HFI_EXTRADATA_INDEX					0x7F100002
@@ -191,6 +192,8 @@
 	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x014)
 #define HFI_PROPERTY_PARAM_VDEC_AVC_SESSION_SELECT \
 	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
+#define HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x016)
 
 #define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
 	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 3fbfec4..bf1c70b 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -95,6 +95,7 @@
 	HAL_EXTRADATA_NUM_CONCEALED_MB,
 	HAL_EXTRADATA_METADATA_FILLER,
 	HAL_EXTRADATA_ASPECT_RATIO,
+	HAL_EXTRADATA_MPEG2_SEQDISP
 };
 
 enum hal_property {
@@ -482,7 +483,7 @@
 	HAL_PICTURE_I = 0x01,
 	HAL_PICTURE_P = 0x02,
 	HAL_PICTURE_B = 0x04,
-	HAL_PICTURE_IDR = 0x7F001000,
+	HAL_PICTURE_IDR = 0x08,
 	HAL_FRAME_NOTCODED = 0x7F002000,
 	HAL_FRAME_YUV = 0x7F004000,
 	HAL_UNUSED_PICT = 0x10000000,
@@ -1020,7 +1021,7 @@
 };
 
 #define call_hfi_op(q, op, args...)			\
-	(((q)->op) ? ((q)->op(args)) : 0)
+	(((q) && (q)->op) ? ((q)->op(args)) : 0)
 
 struct hfi_device {
 	void *hfi_device_data;
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index 7e6cd4f..59a6b68 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -172,16 +172,13 @@
 		}
 
 		/* NV bit is set to indicate that platform driver is capable
-		 * of doing NV download. SSR should not set NV bit; during
-		 * SSR NV bin is downloaded by WLAN driver.
+		 * of doing NV download.
 		 */
-		if (!wcnss_cold_boot_done()) {
-			pr_debug("wcnss: Indicate NV bin download\n");
-			spare_reg = msm_wcnss_base + spare_offset;
-			reg = readl_relaxed(spare_reg);
-			reg |= NVBIN_DLND_BIT;
-			writel_relaxed(reg, spare_reg);
-		}
+		pr_debug("wcnss: Indicate NV bin download\n");
+		spare_reg = msm_wcnss_base + spare_offset;
+		reg = readl_relaxed(spare_reg);
+		reg |= NVBIN_DLND_BIT;
+		writel_relaxed(reg, spare_reg);
 
 		pmu_conf_reg = msm_wcnss_base + pmu_offset;
 		writel_relaxed(0, pmu_conf_reg);
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 1a175c9..f837a06 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -28,6 +28,9 @@
 #include <linux/of_gpio.h>
 #include <linux/clk.h>
 #include <linux/ratelimit.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
 
 #include <mach/msm_smd.h>
 #include <mach/msm_iomap.h>
@@ -48,6 +51,10 @@
 module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO);
 MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present");
 
+static int has_calibrated_data = WCNSS_CONFIG_UNSPECIFIED;
+module_param(has_calibrated_data, int, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(has_calibrated_data, "whether calibrated data file available");
+
 static int do_not_cancel_vote = WCNSS_CONFIG_UNSPECIFIED;
 module_param(do_not_cancel_vote, int, S_IWUSR | S_IRUGO);
 MODULE_PARM_DESC(do_not_cancel_vote, "Do not cancel votes for wcnss");
@@ -92,20 +99,27 @@
 #define CCU_PRONTO_LAST_ADDR2_OFFSET		0x14
 
 #define WCNSS_CTRL_CHANNEL			"WCNSS_CTRL"
-#define WCNSS_MAX_FRAME_SIZE		500
+#define WCNSS_MAX_FRAME_SIZE		(4*1024)
 #define WCNSS_VERSION_LEN			30
 
 /* message types */
 #define WCNSS_CTRL_MSG_START	0x01000000
-#define	WCNSS_VERSION_REQ		(WCNSS_CTRL_MSG_START + 0)
-#define	WCNSS_VERSION_RSP		(WCNSS_CTRL_MSG_START + 1)
-#define	WCNSS_NVBIN_DNLD_REQ		(WCNSS_CTRL_MSG_START + 2)
-#define	WCNSS_NVBIN_DNLD_RSP		(WCNSS_CTRL_MSG_START + 3)
+#define	WCNSS_VERSION_REQ             (WCNSS_CTRL_MSG_START + 0)
+#define	WCNSS_VERSION_RSP             (WCNSS_CTRL_MSG_START + 1)
+#define	WCNSS_NVBIN_DNLD_REQ          (WCNSS_CTRL_MSG_START + 2)
+#define	WCNSS_NVBIN_DNLD_RSP          (WCNSS_CTRL_MSG_START + 3)
+#define	WCNSS_CALDATA_UPLD_REQ        (WCNSS_CTRL_MSG_START + 4)
+#define	WCNSS_CALDATA_UPLD_RSP        (WCNSS_CTRL_MSG_START + 5)
+#define	WCNSS_CALDATA_DNLD_REQ        (WCNSS_CTRL_MSG_START + 6)
+#define	WCNSS_CALDATA_DNLD_RSP        (WCNSS_CTRL_MSG_START + 7)
 
 
 #define VALID_VERSION(version) \
 	((strncmp(version, "INVALID", WCNSS_VERSION_LEN)) ? 1 : 0)
 
+#define FW_CALDATA_CAPABLE() \
+	((penv->fw_major >= 1) && (penv->fw_minor >= 5) ? 1 : 0)
+
 struct smd_msg_hdr {
 	unsigned int msg_type;
 	unsigned int msg_len;
@@ -126,6 +140,13 @@
  * header, so NV fragment size as next multiple of 1Kb is 3Kb.
  */
 #define NV_FRAGMENT_SIZE  3072
+#define MAX_CALIBRATED_DATA_SIZE  (64*1024)
+#define LAST_FRAGMENT        (1 << 0)
+#define MESSAGE_TO_FOLLOW    (1 << 1)
+#define CAN_RECEIVE_CALDATA  (1 << 15)
+#define WCNSS_RESP_SUCCESS   1
+#define WCNSS_RESP_FAIL      0
+
 
 /* Macro to find the total number fragments of the NV bin Image */
 #define TOTALFRAGMENTS(x) (((x % NV_FRAGMENT_SIZE) == 0) ? \
@@ -144,11 +165,14 @@
 	unsigned short frag_number;
 
 	/*
-	 * When set to 1 it indicates that no more fragments will
-	 * be sent. Receiver shall send back response message after
-	 * the last fragment.
+	 * bit 0: When set to 1 it indicates that no more fragments will
+	 * be sent.
+	 * bit 1: When set, a new message will be followed by this message
+	 * bit 2- bit 14:  Reserved
+	 * bit 15: when set, it indicates that the sender is capable of
+	 * receiving Calibrated data.
 	 */
-	unsigned short is_last_fragment;
+	unsigned short msg_flags;
 
 	/* NV Image size (number of bytes) */
 	unsigned int nvbin_buffer_size;
@@ -160,6 +184,7 @@
 	 */
 };
 
+
 struct nvbin_dnld_req_msg {
 	/*
 	 * Note: The length specified in nvbin_dnld_req_msg messages
@@ -170,6 +195,39 @@
 	struct nvbin_dnld_req_params dnld_req_params;
 };
 
+struct cal_data_params {
+
+	/* The total size of the calibrated data, including all the
+	 * fragments.
+	 */
+	unsigned int total_size;
+	unsigned short frag_number;
+	/*
+	 * bit 0: When set to 1 it indicates that no more fragments will
+	 * be sent.
+	 * bit 1: When set, a new message will be followed by this message
+	 * bit 2- bit 15: Reserved
+	 */
+	unsigned short msg_flags;
+	/*
+	 * fragment size
+	 */
+	unsigned int frag_size;
+	/*
+	 * Following the frag_size, frag_size of fragmented
+	 * data will be followed.
+	 */
+};
+
+struct cal_data_msg {
+	/*
+	 * The length specified in cal_data_msg should be
+	 * hdr.msg_len = sizeof(cal_data_msg) + frag_size
+	 */
+	struct smd_msg_hdr hdr;
+	struct cal_data_params cal_params;
+};
+
 static struct {
 	struct platform_device *pdev;
 	void		*pil;
@@ -180,9 +238,10 @@
 	const struct dev_pm_ops *pm_ops;
 	int		triggered;
 	int		smd_channel_ready;
-	int		cold_boot_done;
 	smd_channel_t	*smd_ch;
 	unsigned char	wcnss_version[WCNSS_VERSION_LEN];
+	unsigned char   fw_major;
+	unsigned char   fw_minor;
 	unsigned int	serial_number;
 	int		thermal_mitigation;
 	enum wcnss_hw_type	wcnss_hw_type;
@@ -198,6 +257,20 @@
 	void __iomem *pronto_a2xb_base;
 	void __iomem *pronto_ccpu_base;
 	void __iomem *fiq_reg;
+	int	ssr_boot;
+	int	nv_downloaded;
+	unsigned char *fw_cal_data;
+	unsigned char *user_cal_data;
+	int	fw_cal_rcvd;
+	int	fw_cal_exp_frag;
+	int	fw_cal_available;
+	int	user_cal_read;
+	int	user_cal_available;
+	int	user_cal_rcvd;
+	int	user_cal_exp_size;
+	int	device_opened;
+	struct mutex dev_lock;
+	wait_queue_head_t read_wait;
 } *penv = NULL;
 
 static ssize_t wcnss_serial_number_show(struct device *dev,
@@ -459,21 +532,26 @@
 	switch (event) {
 	case SMD_EVENT_DATA:
 		len = smd_read_avail(penv->smd_ch);
-		if (len < 0)
+		if (len < 0) {
 			pr_err("wcnss: failed to read from smd %d\n", len);
+			return;
+		}
 		schedule_work(&penv->wcnssctrl_rx_work);
 		break;
 
 	case SMD_EVENT_OPEN:
 		pr_debug("wcnss: opening WCNSS SMD channel :%s",
 				WCNSS_CTRL_CHANNEL);
-		if (!VALID_VERSION(penv->wcnss_version))
-			schedule_work(&penv->wcnssctrl_version_work);
+		schedule_work(&penv->wcnssctrl_version_work);
+
 		break;
 
 	case SMD_EVENT_CLOSE:
 		pr_debug("wcnss: closing WCNSS SMD channel :%s",
 				WCNSS_CTRL_CHANNEL);
+		/* This SMD is closed only during SSR */
+		penv->ssr_boot = true;
+		penv->nv_downloaded = 0;
 		break;
 
 	default:
@@ -658,6 +736,15 @@
 }
 EXPORT_SYMBOL(wcnss_get_wlan_config);
 
+int wcnss_device_ready(void)
+{
+	if (penv && penv->pdev && penv->nv_downloaded)
+		return 1;
+	return 0;
+}
+EXPORT_SYMBOL(wcnss_device_ready);
+
+
 struct resource *wcnss_wlan_get_memory_map(struct device *dev)
 {
 	if (penv && dev && (dev == &penv->pdev->dev) && penv->smd_channel_ready)
@@ -837,15 +924,13 @@
 }
 EXPORT_SYMBOL(wcnss_hardware_type);
 
-int wcnss_cold_boot_done(void)
+int fw_cal_data_available(void)
 {
 	if (penv)
-		return penv->cold_boot_done;
+		return penv->fw_cal_available;
 	else
 		return -ENODEV;
 }
-EXPORT_SYMBOL(wcnss_cold_boot_done);
-
 
 static int wcnss_smd_tx(void *data, int len)
 {
@@ -864,14 +949,145 @@
 	return ret;
 }
 
+static unsigned char wcnss_fw_status(void)
+{
+	int len = 0;
+	int rc = 0;
+
+	unsigned char fw_status = 0xFF;
+
+	len = smd_read_avail(penv->smd_ch);
+	if (len < 1) {
+		pr_err("%s: invalid firmware status", __func__);
+		return fw_status;
+	}
+
+	rc = smd_read(penv->smd_ch, &fw_status, 1);
+	if (rc < 0) {
+		pr_err("%s: incomplete data read from smd\n", __func__);
+		return fw_status;
+	}
+	return fw_status;
+}
+
+static void wcnss_send_cal_rsp(unsigned char fw_status)
+{
+	struct smd_msg_hdr *rsphdr;
+	unsigned char *msg = NULL;
+	int rc;
+
+	msg = kmalloc((sizeof(struct smd_msg_hdr) + 1), GFP_KERNEL);
+	if (NULL == msg) {
+		pr_err("wcnss: %s: failed to get memory\n", __func__);
+		return;
+	}
+
+	rsphdr = (struct smd_msg_hdr *)msg;
+	rsphdr->msg_type = WCNSS_CALDATA_UPLD_RSP;
+	rsphdr->msg_len = sizeof(struct smd_msg_hdr) + 1;
+	memcpy(msg+sizeof(struct smd_msg_hdr), &fw_status, 1);
+
+	rc = wcnss_smd_tx(msg, rsphdr->msg_len);
+	if (rc < 0)
+		pr_err("wcnss: smd tx failed\n");
+}
+
+/* Collect calibrated data from WCNSS */
+void extract_cal_data(int len)
+{
+	int rc;
+	struct cal_data_params calhdr;
+	unsigned char fw_status = WCNSS_RESP_FAIL;
+
+	if (len < sizeof(struct cal_data_params)) {
+		pr_err("wcnss: incomplete cal header length\n");
+		return;
+	}
+
+	rc = smd_read(penv->smd_ch, (unsigned char *)&calhdr,
+			sizeof(struct cal_data_params));
+	if (rc < sizeof(struct cal_data_params)) {
+		pr_err("wcnss: incomplete cal header read from smd\n");
+		return;
+	}
+
+	if (penv->fw_cal_exp_frag != calhdr.frag_number) {
+		pr_err("wcnss: Invalid frgament");
+		goto exit;
+	}
+
+	if (calhdr.frag_size > WCNSS_MAX_FRAME_SIZE) {
+		pr_err("wcnss: Invalid fragment size");
+		goto exit;
+	}
+
+	if (0 == calhdr.frag_number) {
+		if (calhdr.total_size > MAX_CALIBRATED_DATA_SIZE) {
+			pr_err("wcnss: Invalid cal data size %d",
+				calhdr.total_size);
+			goto exit;
+		}
+		kfree(penv->fw_cal_data);
+		penv->fw_cal_rcvd = 0;
+		penv->fw_cal_data = kmalloc(calhdr.total_size,
+				GFP_KERNEL);
+		if (penv->fw_cal_data == NULL) {
+			smd_read(penv->smd_ch, NULL, calhdr.frag_size);
+			goto exit;
+		}
+	}
+
+	mutex_lock(&penv->dev_lock);
+	if (penv->fw_cal_rcvd + calhdr.frag_size >
+			MAX_CALIBRATED_DATA_SIZE) {
+		pr_err("calibrated data size is more than expected %d",
+				penv->fw_cal_rcvd + calhdr.frag_size);
+		penv->fw_cal_exp_frag = 0;
+		penv->fw_cal_rcvd = 0;
+		smd_read(penv->smd_ch, NULL, calhdr.frag_size);
+		goto unlock_exit;
+	}
+
+	rc = smd_read(penv->smd_ch, penv->fw_cal_data + penv->fw_cal_rcvd,
+			calhdr.frag_size);
+	if (rc < calhdr.frag_size)
+		goto unlock_exit;
+
+	penv->fw_cal_exp_frag++;
+	penv->fw_cal_rcvd += calhdr.frag_size;
+
+	if (calhdr.msg_flags & LAST_FRAGMENT) {
+		penv->fw_cal_exp_frag = 0;
+		penv->fw_cal_available = true;
+		pr_info("wcnss: cal data collection completed\n");
+	}
+	mutex_unlock(&penv->dev_lock);
+	wake_up(&penv->read_wait);
+
+	if (penv->fw_cal_available) {
+		fw_status = WCNSS_RESP_SUCCESS;
+		wcnss_send_cal_rsp(fw_status);
+	}
+	return;
+
+unlock_exit:
+	mutex_unlock(&penv->dev_lock);
+
+exit:
+	wcnss_send_cal_rsp(fw_status);
+	return;
+}
+
+
 static void wcnssctrl_rx_handler(struct work_struct *worker)
 {
 	int len = 0;
 	int rc = 0;
-	unsigned char buf[WCNSS_MAX_FRAME_SIZE];
+	unsigned char buf[sizeof(struct wcnss_version)];
 	struct smd_msg_hdr *phdr;
 	struct wcnss_version *pversion;
 	int hw_type;
+	unsigned char fw_status = 0;
 
 	len = smd_read_avail(penv->smd_ch);
 	if (len > WCNSS_MAX_FRAME_SIZE) {
@@ -882,23 +1098,33 @@
 	if (len <= 0)
 		return;
 
-	rc = smd_read(penv->smd_ch, buf, len);
-	if (rc < len) {
-		pr_err("wcnss: incomplete data read from smd\n");
+	rc = smd_read(penv->smd_ch, buf, sizeof(struct smd_msg_hdr));
+	if (rc < sizeof(struct smd_msg_hdr)) {
+		pr_err("wcnss: incomplete header read from smd\n");
 		return;
 	}
+	len -= sizeof(struct smd_msg_hdr);
 
 	phdr = (struct smd_msg_hdr *)buf;
 
 	switch (phdr->msg_type) {
 
 	case WCNSS_VERSION_RSP:
-		pversion = (struct wcnss_version *)buf;
-		if (len != sizeof(struct wcnss_version)) {
+		if (len != sizeof(struct wcnss_version)
+				- sizeof(struct smd_msg_hdr)) {
 			pr_err("wcnss: invalid version data from wcnss %d\n",
-				len);
+					len);
 			return;
 		}
+		rc = smd_read(penv->smd_ch, buf+sizeof(struct smd_msg_hdr),
+				len);
+		if (rc < len) {
+			pr_err("wcnss: incomplete data read from smd\n");
+			return;
+		}
+		pversion = (struct wcnss_version *)buf;
+		penv->fw_major = pversion->major;
+		penv->fw_minor = pversion->minor;
 		snprintf(penv->wcnss_version, WCNSS_VERSION_LEN,
 			"%02x%02x%02x%02x", pversion->major, pversion->minor,
 					pversion->version, pversion->revision);
@@ -930,7 +1156,22 @@
 		break;
 
 	case WCNSS_NVBIN_DNLD_RSP:
-		pr_info("wcnss: received WCNSS_NVBIN_DNLD_RSP from ccpu\n");
+		penv->nv_downloaded = true;
+		fw_status = wcnss_fw_status();
+		pr_debug("wcnss: received WCNSS_NVBIN_DNLD_RSP from ccpu %u\n",
+			fw_status);
+		break;
+
+	case WCNSS_CALDATA_DNLD_RSP:
+		penv->nv_downloaded = true;
+		fw_status = wcnss_fw_status();
+		pr_debug("wcnss: received WCNSS_CALDATA_DNLD_RSP from ccpu %u\n",
+			fw_status);
+		break;
+
+	case WCNSS_CALDATA_UPLD_REQ:
+		penv->fw_cal_available = 0;
+		extract_cal_data(len);
 		break;
 
 	default:
@@ -953,7 +1194,8 @@
 	return;
 }
 
-static void wcnss_nvbin_dnld_req(struct work_struct *worker)
+
+static void wcnss_nvbin_dnld(void)
 {
 	int ret = 0;
 	struct nvbin_dnld_req_msg *dnld_req_msg;
@@ -970,8 +1212,8 @@
 	ret = request_firmware(&nv, NVBIN_FILE, dev);
 
 	if (ret || !nv || !nv->data || !nv->size) {
-		pr_err("wcnss: wcnss_nvbin_dnld_req: request_firmware failed for %s\n",
-			NVBIN_FILE);
+		pr_err("wcnss: %s: request_firmware failed for %s\n",
+			__func__, NVBIN_FILE);
 		return;
 	}
 
@@ -992,13 +1234,14 @@
 		NV_FRAGMENT_SIZE), GFP_KERNEL);
 
 	if (NULL == outbuffer) {
-		pr_err("wcnss: wcnss_nvbin_dnld_req: failed to get buffer\n");
+		pr_err("wcnss: %s: failed to get buffer\n", __func__);
 		goto err_free_nv;
 	}
 
 	dnld_req_msg = (struct nvbin_dnld_req_msg *)outbuffer;
 
 	dnld_req_msg->hdr.msg_type = WCNSS_NVBIN_DNLD_REQ;
+	dnld_req_msg->dnld_req_params.msg_flags = 0;
 
 	for (count = 0; count < total_fragments; count++) {
 		dnld_req_msg->dnld_req_params.frag_number = count;
@@ -1009,10 +1252,14 @@
 			if (!cur_frag_size)
 				cur_frag_size = NV_FRAGMENT_SIZE;
 
-			dnld_req_msg->dnld_req_params.is_last_fragment = 1;
+			dnld_req_msg->dnld_req_params.msg_flags |=
+				LAST_FRAGMENT;
+			dnld_req_msg->dnld_req_params.msg_flags |=
+				CAN_RECEIVE_CALDATA;
 		} else {
 			cur_frag_size = NV_FRAGMENT_SIZE;
-			dnld_req_msg->dnld_req_params.is_last_fragment = 0;
+			dnld_req_msg->dnld_req_params.msg_flags &=
+				~LAST_FRAGMENT;
 		}
 
 		dnld_req_msg->dnld_req_params.nvbin_buffer_size =
@@ -1030,7 +1277,8 @@
 
 		retry_count = 0;
 		while ((ret == -ENOSPC) && (retry_count <= 3)) {
-			pr_debug("wcnss: wcnss_nvbin_dnld_req: smd tx failed, ENOSPC\n");
+			pr_debug("wcnss: %s: smd tx failed, ENOSPC\n",
+				__func__);
 			pr_debug("fragment: %d, len: %d, TotFragments: %d, retry_count: %d\n",
 				count, dnld_req_msg->hdr.msg_len,
 				total_fragments, retry_count);
@@ -1043,7 +1291,7 @@
 		}
 
 		if (ret < 0) {
-			pr_err("wcnss: wcnss_nvbin_dnld_req: smd tx failed\n");
+			pr_err("wcnss: %s: smd tx failed\n", __func__);
 			pr_err("fragment %d, len: %d, TotFragments: %d, retry_count: %d\n",
 				count, dnld_req_msg->hdr.msg_len,
 				total_fragments, retry_count);
@@ -1062,6 +1310,138 @@
 	return;
 }
 
+
+static void wcnss_caldata_dnld(const void *cal_data,
+		unsigned int cal_data_size, bool msg_to_follow)
+{
+	int ret = 0;
+	struct cal_data_msg *cal_msg;
+	unsigned short total_fragments = 0;
+	unsigned short count = 0;
+	unsigned short retry_count = 0;
+	unsigned short cur_frag_size = 0;
+	unsigned char *outbuffer = NULL;
+
+	total_fragments = TOTALFRAGMENTS(cal_data_size);
+
+	outbuffer = kmalloc((sizeof(struct cal_data_msg) +
+		NV_FRAGMENT_SIZE), GFP_KERNEL);
+
+	if (NULL == outbuffer) {
+		pr_err("wcnss: %s: failed to get buffer\n", __func__);
+		return;
+	}
+
+	cal_msg = (struct cal_data_msg *)outbuffer;
+
+	cal_msg->hdr.msg_type = WCNSS_CALDATA_DNLD_REQ;
+	cal_msg->cal_params.msg_flags = 0;
+
+	for (count = 0; count < total_fragments; count++) {
+		cal_msg->cal_params.frag_number = count;
+
+		if (count == (total_fragments - 1)) {
+			cur_frag_size = cal_data_size % NV_FRAGMENT_SIZE;
+			if (!cur_frag_size)
+				cur_frag_size = NV_FRAGMENT_SIZE;
+
+			cal_msg->cal_params.msg_flags
+			    |= LAST_FRAGMENT;
+			if (msg_to_follow)
+				cal_msg->cal_params.msg_flags |=
+					MESSAGE_TO_FOLLOW;
+		} else {
+			cur_frag_size = NV_FRAGMENT_SIZE;
+			cal_msg->cal_params.msg_flags &=
+				~LAST_FRAGMENT;
+		}
+
+		cal_msg->cal_params.total_size = cal_data_size;
+		cal_msg->cal_params.frag_size =
+			cur_frag_size;
+
+		cal_msg->hdr.msg_len =
+			sizeof(struct cal_data_msg) + cur_frag_size;
+
+		memcpy((outbuffer + sizeof(struct cal_data_msg)),
+			(cal_data + count * NV_FRAGMENT_SIZE),
+			cur_frag_size);
+
+		ret = wcnss_smd_tx(outbuffer, cal_msg->hdr.msg_len);
+
+		retry_count = 0;
+		while ((ret == -ENOSPC) && (retry_count <= 3)) {
+			pr_debug("wcnss: %s: smd tx failed, ENOSPC\n",
+					__func__);
+			pr_debug("fragment: %d, len: %d, TotFragments: %d, retry_count: %d\n",
+				count, cal_msg->hdr.msg_len,
+				total_fragments, retry_count);
+
+			/* wait and try again */
+			msleep(20);
+			retry_count++;
+			ret = wcnss_smd_tx(outbuffer,
+				cal_msg->hdr.msg_len);
+		}
+
+		if (ret < 0) {
+			pr_err("wcnss: %s: smd tx failed\n", __func__);
+			pr_err("fragment %d, len: %d, TotFragments: %d, retry_count: %d\n",
+				count, cal_msg->hdr.msg_len,
+				total_fragments, retry_count);
+			goto err_dnld;
+		}
+	}
+
+
+err_dnld:
+	/* free buffer */
+	kfree(outbuffer);
+
+	return;
+}
+
+
+static void wcnss_nvbin_dnld_main(struct work_struct *worker)
+{
+	int retry = 0;
+
+	if (!FW_CALDATA_CAPABLE())
+		goto nv_download;
+
+	if (!penv->fw_cal_available && WCNSS_CONFIG_UNSPECIFIED
+		!= has_calibrated_data && !penv->user_cal_available) {
+		while (!penv->user_cal_available && retry++ < 5)
+			msleep(500);
+	}
+
+	/* only cal data is sent during ssr (if available) */
+	if (penv->fw_cal_available && penv->ssr_boot) {
+		pr_info_ratelimited("wcnss: cal download during SSR, using fw cal");
+		wcnss_caldata_dnld(penv->fw_cal_data, penv->fw_cal_rcvd, false);
+		return;
+
+	} else if (penv->user_cal_available && penv->ssr_boot) {
+		pr_info_ratelimited("wcnss: cal download during SSR, using user cal");
+		wcnss_caldata_dnld(penv->user_cal_data,
+		penv->user_cal_rcvd, false);
+		return;
+
+	} else if (penv->user_cal_available) {
+		pr_info_ratelimited("wcnss: cal download during cold boot, using user cal");
+		wcnss_caldata_dnld(penv->user_cal_data,
+		penv->user_cal_rcvd, true);
+	}
+
+nv_download:
+	pr_info_ratelimited("wcnss: NV download");
+	wcnss_nvbin_dnld();
+
+	return;
+}
+
+
+
 static int
 wcnss_trigger_config(struct platform_device *pdev)
 {
@@ -1146,7 +1526,7 @@
 	}
 	INIT_WORK(&penv->wcnssctrl_rx_work, wcnssctrl_rx_handler);
 	INIT_WORK(&penv->wcnssctrl_version_work, wcnss_send_version_req);
-	INIT_WORK(&penv->wcnssctrl_nvbin_dnld_work, wcnss_nvbin_dnld_req);
+	INIT_WORK(&penv->wcnssctrl_nvbin_dnld_work, wcnss_nvbin_dnld_main);
 
 	wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");
 
@@ -1201,7 +1581,6 @@
 			goto fail_ioremap3;
 		}
 	}
-	penv->cold_boot_done = 1;
 
 	return 0;
 
@@ -1229,20 +1608,128 @@
 	return ret;
 }
 
-#ifndef MODULE
 static int wcnss_node_open(struct inode *inode, struct file *file)
 {
 	struct platform_device *pdev;
 
-	pr_info(DEVICE " triggered by userspace\n");
+	/* first open is only to trigger WCNSS platform driver */
+	if (!penv->triggered) {
+		pr_info(DEVICE " triggered by userspace\n");
+		pdev = penv->pdev;
+		return wcnss_trigger_config(pdev);
 
-	pdev = penv->pdev;
-	return wcnss_trigger_config(pdev);
+	} else if (penv->device_opened) {
+		pr_info(DEVICE " already opened\n");
+		return -EBUSY;
+	}
+
+	mutex_lock(&penv->dev_lock);
+	penv->user_cal_rcvd = 0;
+	penv->user_cal_read = 0;
+	penv->user_cal_available = false;
+	penv->user_cal_data = NULL;
+	penv->device_opened = 1;
+	mutex_unlock(&penv->dev_lock);
+
+	return 0;
 }
 
+static ssize_t wcnss_wlan_read(struct file *fp, char __user
+			*buffer, size_t count, loff_t *position)
+{
+	int rc = 0;
+
+	if (!penv->device_opened)
+		return -EFAULT;
+
+	rc = wait_event_interruptible(penv->read_wait, penv->fw_cal_rcvd
+			> penv->user_cal_read || penv->fw_cal_available);
+
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&penv->dev_lock);
+
+	if (penv->fw_cal_available && penv->fw_cal_rcvd
+			== penv->user_cal_read) {
+		rc = 0;
+		goto exit;
+	}
+
+	if (count > penv->fw_cal_rcvd - penv->user_cal_read)
+		count = penv->fw_cal_rcvd - penv->user_cal_read;
+
+	rc = copy_to_user(buffer, penv->fw_cal_data +
+			penv->user_cal_read, count);
+	if (rc == 0) {
+		penv->user_cal_read += count;
+		rc = count;
+	}
+
+exit:
+	mutex_unlock(&penv->dev_lock);
+	return rc;
+}
+
+/* first (valid) write to this device should be 4 bytes cal file size */
+static ssize_t wcnss_wlan_write(struct file *fp, const char __user
+			*user_buffer, size_t count, loff_t *position)
+{
+	int rc = 0;
+	int size = 0;
+
+	if (!penv->device_opened || penv->user_cal_available)
+		return -EFAULT;
+
+	if (penv->user_cal_rcvd == 0 && count >= 4
+			&& !penv->user_cal_data) {
+		rc = copy_from_user((void *)&size, user_buffer, 4);
+		if (size > MAX_CALIBRATED_DATA_SIZE) {
+			pr_err(DEVICE " invalid size to write %d\n", size);
+			return -EFAULT;
+		}
+
+		rc += count;
+		count -= 4;
+		penv->user_cal_exp_size =  size;
+		penv->user_cal_data = kmalloc(size, GFP_KERNEL);
+		if (penv->user_cal_data == NULL) {
+			pr_err(DEVICE " no memory to write\n");
+			return -ENOMEM;
+		}
+		if (0 == count)
+			goto exit;
+
+	} else if (penv->user_cal_rcvd == 0 && count < 4)
+		return -EFAULT;
+
+	if (MAX_CALIBRATED_DATA_SIZE < count + penv->user_cal_rcvd) {
+		pr_err(DEVICE " invalid size to write %d\n", count +
+				penv->user_cal_rcvd);
+		rc = -ENOMEM;
+		goto exit;
+	}
+	rc = copy_from_user((void *)penv->user_cal_data +
+			penv->user_cal_rcvd, user_buffer, count);
+	if (0 == rc) {
+		penv->user_cal_rcvd += count;
+		rc += count;
+	}
+	if (penv->user_cal_rcvd == penv->user_cal_exp_size) {
+		penv->user_cal_available = true;
+		pr_info_ratelimited("wcnss: user cal written");
+	}
+
+exit:
+	return rc;
+}
+
+
 static const struct file_operations wcnss_node_fops = {
 	.owner = THIS_MODULE,
 	.open = wcnss_node_open,
+	.read = wcnss_wlan_read,
+	.write = wcnss_wlan_write,
 };
 
 static struct miscdevice wcnss_misc = {
@@ -1250,8 +1737,6 @@
 	.name = DEVICE,
 	.fops = &wcnss_node_fops,
 };
-#endif /* ifndef MODULE */
-
 
 static int __devinit
 wcnss_wlan_probe(struct platform_device *pdev)
@@ -1279,18 +1764,8 @@
 		return -ENOENT;
 	}
 
-
-#ifdef MODULE
-
-	/* Since we were built as a module, we are running because
-	 * the module was loaded, therefore we assume userspace
-	 * applications are available to service PIL, so we can
-	 * trigger the WCNSS configuration now
-	 */
-	pr_info(DEVICE " probed in MODULE mode\n");
-	return wcnss_trigger_config(pdev);
-
-#else
+	mutex_init(&penv->dev_lock);
+	init_waitqueue_head(&penv->read_wait);
 
 	/* Since we were built into the kernel we'll be called as part
 	 * of kernel initialization.  We don't know if userspace
@@ -1303,7 +1778,6 @@
 	pr_info(DEVICE " probed in built-in mode\n");
 	return misc_register(&wcnss_misc);
 
-#endif
 }
 
 static int __devexit
diff --git a/drivers/platform/msm/ipa/a2_service.c b/drivers/platform/msm/ipa/a2_service.c
index 26353ec..fa71efc 100644
--- a/drivers/platform/msm/ipa/a2_service.c
+++ b/drivers/platform/msm/ipa/a2_service.c
@@ -92,11 +92,13 @@
 	bool bam_connect_in_progress;
 	int a2_mux_send_power_vote_on_init_once;
 	int a2_mux_sw_bridge_is_connected;
+	bool a2_mux_dl_wakeup;
 	u32 a2_device_handle;
 	struct mutex wakeup_lock;
 	struct completion ul_wakeup_ack_completion;
 	struct completion bam_connection_completion;
 	struct completion request_resource_completion;
+	struct completion dl_wakeup_completion;
 	rwlock_t ul_wakeup_lock;
 	int wait_for_ack;
 	struct wake_lock bam_wakelock;
@@ -431,6 +433,7 @@
 static void kickoff_ul_wakeup_func(struct work_struct *work)
 {
 	bool is_connected;
+	int ret;
 
 	ul_wakeup();
 	write_lock(&a2_mux_ctx->ul_wakeup_lock);
@@ -440,8 +443,19 @@
 	write_unlock(&a2_mux_ctx->ul_wakeup_lock);
 	if (is_connected)
 		ipa_rm_notify_completion(IPA_RM_RESOURCE_GRANTED,
-			IPA_RM_RESOURCE_A2_CONS);
-	else
+				IPA_RM_RESOURCE_A2_CONS);
+	INIT_COMPLETION(a2_mux_ctx->dl_wakeup_completion);
+	if (!a2_mux_ctx->a2_mux_dl_wakeup) {
+		ret = wait_for_completion_timeout(
+			&a2_mux_ctx->dl_wakeup_completion,
+			A2_MUX_COMPLETION_TIMEOUT);
+		if (unlikely(ret == 0)) {
+			IPAERR("%s timeout A2 PROD\n", __func__);
+			BUG();
+			return;
+		}
+	}
+	if (!is_connected)
 		msm_bam_dmux_kickoff_ul_power_down();
 }
 
@@ -468,6 +482,8 @@
 		}
 	}
 	toggle_apps_ack();
+	a2_mux_ctx->a2_mux_dl_wakeup = true;
+	complete_all(&a2_mux_ctx->dl_wakeup_completion);
 }
 
 static void ipa_embedded_notify(void *priv,
@@ -635,6 +651,7 @@
 	(void) ipa_rm_release_resource(IPA_RM_RESOURCE_A2_PROD);
 	if (a2_mux_ctx->disconnect_ack)
 		toggle_apps_ack();
+	a2_mux_ctx->a2_mux_dl_wakeup = false;
 	a2_mux_ctx->a2_mux_sw_bridge_is_connected = 0;
 	complete_all(&a2_mux_ctx->bam_connection_completion);
 	return 0;
@@ -1467,6 +1484,7 @@
 	init_completion(&a2_mux_ctx->ul_wakeup_ack_completion);
 	init_completion(&a2_mux_ctx->bam_connection_completion);
 	init_completion(&a2_mux_ctx->request_resource_completion);
+	init_completion(&a2_mux_ctx->dl_wakeup_completion);
 	wake_lock_init(&a2_mux_ctx->bam_wakelock,
 		       WAKE_LOCK_SUSPEND, "a2_mux_wakelock");
 	a2_mux_ctx->a2_mux_initialized = 1;
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index 67728c2..76aaad0 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -187,6 +187,7 @@
 	int inactive_cycles = 0;
 	int cnt;
 
+	ipa_inc_client_enable_clks();
 	do {
 		cnt = ipa_handle_tx_core(sys, true, true);
 		if (cnt == 0) {
@@ -199,6 +200,7 @@
 	} while (inactive_cycles <= POLLING_INACTIVITY_TX);
 
 	ipa_tx_switch_to_intr_mode(sys);
+	ipa_dec_client_disable_clks();
 }
 
 static void ipa_wq_handle_tx(struct work_struct *work)
@@ -914,6 +916,7 @@
 	int inactive_cycles = 0;
 	int cnt;
 
+	ipa_inc_client_enable_clks();
 	do {
 		cnt = ipa_handle_rx_core(sys, true, true);
 		if (cnt == 0) {
@@ -926,6 +929,7 @@
 	} while (inactive_cycles <= POLLING_INACTIVITY_RX);
 
 	ipa_rx_switch_to_intr_mode(sys);
+	ipa_dec_client_disable_clks();
 }
 
 static void switch_to_intr_rx_work_func(struct work_struct *work)
diff --git a/drivers/platform/msm/ipa/ipa_rm_resource.c b/drivers/platform/msm/ipa/ipa_rm_resource.c
index 0fc4826..8655d89 100644
--- a/drivers/platform/msm/ipa/ipa_rm_resource.c
+++ b/drivers/platform/msm/ipa/ipa_rm_resource.c
@@ -336,27 +336,28 @@
 int ipa_rm_resource_delete(struct ipa_rm_resource *resource)
 {
 	struct ipa_rm_resource *consumer, *producer;
-	int i, result = 0;
+	int peers_index, result = 0, list_size;
 
-	IPADBG("IPA RM: %s ENTER\n", __func__);
-
+	IPADBG("ipa_rm_resource_delete ENTER with resource %d\n",
+					resource->name);
 	if (!resource) {
 		IPADBG("ipa_rm_resource_delete ENTER with invalid param\n");
 		return -EINVAL;
 	}
 	if (resource->type == IPA_RM_PRODUCER) {
 		if (resource->peers_list) {
-			for (i = IPA_RM_RESOURCE_PROD_MAX;
-					i < IPA_RM_RESOURCE_MAX;
-						++i) {
+			list_size = ipa_rm_peers_list_get_size(
+				resource->peers_list);
+			for (peers_index = 0;
+				peers_index < list_size;
+				peers_index++) {
 				consumer = ipa_rm_peers_list_get_resource(
-						i,
+						peers_index,
 						resource->peers_list);
-				if (consumer) {
+				if (consumer)
 					ipa_rm_resource_delete_dependency(
 						resource,
 						consumer);
-				}
 			}
 			ipa_rm_peers_list_delete(resource->peers_list);
 		}
@@ -365,9 +366,13 @@
 		kfree((struct ipa_rm_resource_prod *) resource);
 	} else if (resource->type == IPA_RM_CONSUMER) {
 		if (resource->peers_list) {
-			for (i = 0; i < IPA_RM_RESOURCE_PROD_MAX; ++i) {
+			list_size = ipa_rm_peers_list_get_size(
+				resource->peers_list);
+			for (peers_index = 0;
+					peers_index < list_size;
+					peers_index++){
 				producer = ipa_rm_peers_list_get_resource(
-							i,
+							peers_index,
 							resource->peers_list);
 				if (producer)
 					ipa_rm_resource_delete_dependency(
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 419499d..eec6d39 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -1100,8 +1100,7 @@
 	if (rtc == NULL) {
 		pr_err("%s: unable to open rtc device (%s)\n",
 			__FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
-		rc = -EINVAL;
-		goto close_time;
+		return -EINVAL;
 	}
 
 	rc = rtc_read_time(rtc, &tm);
@@ -1523,10 +1522,6 @@
 		pr_debug("clamping soc to 1, vbat (%d) > cutoff (%d)\n",
 						vbat_uv, chip->v_cutoff_uv);
 		return 1;
-	} else if (soc > 0 && vbat_uv < chip->v_cutoff_uv) {
-		pr_debug("forcing soc to 0, vbat (%d) < cutoff (%d)\n",
-						vbat_uv, chip->v_cutoff_uv);
-		return 0;
 	} else {
 		pr_debug("not clamping, using soc = %d, vbat = %d and cutoff = %d\n",
 				soc, vbat_uv, chip->v_cutoff_uv);
@@ -2564,10 +2559,20 @@
 	return 0;
 }
 
+static int bms_suspend(struct device *dev)
+{
+	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
+
+	cancel_delayed_work_sync(&chip->calculate_soc_delayed_work);
+	chip->last_soc_unbound = true;
+	return 0;
+}
+
 static int bms_resume(struct device *dev)
 {
 	int rc;
-	unsigned long soc_calc_period;
+	int soc_calc_period;
+	int time_until_next_recalc;
 	unsigned long time_since_last_recalc;
 	unsigned long tm_now_sec;
 	struct qpnp_bms_chip *chip = dev_get_drvdata(dev);
@@ -2580,7 +2585,6 @@
 		 * unbind the last soc so that the next
 		 * recalculation is not limited to changing by 1%
 		 */
-		chip->last_soc_unbound = true;
 		time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
 		pr_debug("Time since last recalc: %lu\n",
 				time_since_last_recalc);
@@ -2589,16 +2593,19 @@
 		else
 			soc_calc_period = chip->calculate_soc_ms;
 
-		if (time_since_last_recalc >= soc_calc_period) {
-			chip->last_recalc_time = tm_now_sec;
-			recalculate_soc(chip);
-		}
+		time_until_next_recalc = max(0, soc_calc_period
+				- (int)(time_since_last_recalc * 1000));
+
+		schedule_delayed_work(&chip->calculate_soc_delayed_work,
+			round_jiffies_relative(msecs_to_jiffies
+			(time_until_next_recalc)));
 	}
 	return 0;
 }
 
 static const struct dev_pm_ops qpnp_bms_pm_ops = {
 	.resume		= bms_resume,
+	.suspend	= bms_suspend,
 };
 
 static struct spmi_driver qpnp_bms_driver = {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e12b9b4..c8fdc6b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1384,17 +1384,17 @@
 			 *  The result is saved with the response so that
 			 *  the ufs_core layer will handle it.
 			 */
-			result |= DID_OK << 16;
+			result = DID_OK << 16;
 			ufshcd_copy_query_response(hba, lrbp);
 			break;
 		case UPIU_TRANSACTION_REJECT_UPIU:
 			/* TODO: handle Reject UPIU Response */
-			result |= DID_ERROR << 16;
+			result = DID_ERROR << 16;
 			dev_err(hba->dev,
 				"Reject UPIU not fully implemented\n");
 			break;
 		default:
-			result |= DID_ERROR << 16;
+			result = DID_ERROR << 16;
 			dev_err(hba->dev,
 				"Unexpected request response code = %x\n",
 				result);
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index b89f608..c5aa7e5 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -2280,7 +2280,7 @@
 		bam_props.phys_addr = dd->bam.phys_addr;
 		bam_props.virt_addr = dd->bam.base;
 		bam_props.irq       = dd->bam.irq;
-		bam_props.manage    = SPS_BAM_MGR_LOCAL;
+		bam_props.manage    = SPS_BAM_MGR_DEVICE_REMOTE;
 		bam_props.summing_threshold = 0x10;
 
 		rc = sps_register_bam_device(&bam_props, &bam_handle);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 991cf2e..f01a078 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -199,8 +199,8 @@
 #define TSENS0_8X10_POINT1_SHIFT	16
 #define TSENS0_8X10_POINT2_SHIFT	22
 #define TSENS1_8X10_POINT2_SHIFT	6
-#define TSENS_8X10_BASE0_MASK		0xf
-#define TSENS_8X10_BASE1_MASK		0xf0
+#define TSENS_8X10_BASE0_MASK		0xff
+#define TSENS_8X10_BASE1_MASK		0xff00
 #define TSENS0_8X10_POINT1_MASK		0x3f0000
 #define TSENS0_8X10_POINT2_MASK		0xfc00000
 #define TSENS_8X10_TSENS_CAL_SEL	0x70000000
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index f695870..890a897 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -2739,7 +2739,7 @@
 
 		/* SPS driver wll handle the UART BAM IRQ */
 		bam.irq = (u32)msm_uport->bam_irq;
-		bam.manage = SPS_BAM_MGR_LOCAL;
+		bam.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 
 		pr_debug("msm_serial_hs: bam physical base=0x%x\n",
 							(u32)bam.phys_addr);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 01d8be1..38f08fc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -338,14 +338,17 @@
  */
 static int hw_device_reset(struct ci13xxx *udc)
 {
+	int delay_count = 25; /* 250 usec */
+
 	/* should flush & stop before reset */
 	hw_cwrite(CAP_ENDPTFLUSH, ~0, ~0);
 	hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
 
 	hw_cwrite(CAP_USBCMD, USBCMD_RST, USBCMD_RST);
-	while (hw_cread(CAP_USBCMD, USBCMD_RST))
-		udelay(10);             /* not RTOS friendly */
-
+	while (delay_count--  && hw_cread(CAP_USBCMD, USBCMD_RST))
+		udelay(10);
+	if (delay_count < 0)
+		pr_err("USB controller reset failed\n");
 
 	if (udc->udc_driver->notify_event)
 		udc->udc_driver->notify_event(udc,
@@ -814,6 +817,8 @@
  */
 static int hw_usb_reset(void)
 {
+	int delay_count = 10; /* 100 usec delay */
+
 	hw_usb_set_address(0);
 
 	/* ESS flushes only at end?!? */
@@ -826,8 +831,10 @@
 	hw_cwrite(CAP_ENDPTCOMPLETE,  0,  0);   /* writes its content */
 
 	/* wait until all bits cleared */
-	while (hw_cread(CAP_ENDPTPRIME, ~0))
-		udelay(10);             /* not RTOS friendly */
+	while (delay_count-- && hw_cread(CAP_ENDPTPRIME, ~0))
+		udelay(10);
+	if (delay_count < 0)
+		pr_err("ENDPTPRIME is not cleared during bus reset\n");
 
 	/* reset all endpoints ? */
 
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index f672bd4..290e317 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -32,6 +32,8 @@
 #include <linux/spinlock.h>
 #include <linux/semaphore.h>
 #include <linux/uaccess.h>
+#include <linux/file.h>
+#include <linux/msm_kgsl.h>
 
 #include <mach/board.h>
 #include <mach/clk.h>
@@ -125,7 +127,7 @@
 	pr_debug("mdp3_irq_handler irq=%d\n", mdp_interrupt);
 
 	spin_lock(&mdata->irq_lock);
-	mdp_interrupt &= mdata->irqMask;
+	mdp_interrupt &= mdata->irq_mask;
 
 	while (mdp_interrupt && i < MDP3_MAX_INTR) {
 		if ((mdp_interrupt & 0x1) && mdata->callbacks[i].cb)
@@ -145,14 +147,15 @@
 
 	pr_debug("mdp3_irq_enable type=%d\n", type);
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
-	if (mdp3_res->irqMask & BIT(type)) {
+	mdp3_res->irq_ref_count[type] += 1;
+	if (mdp3_res->irq_ref_count[type] > 1) {
 		pr_debug("interrupt %d already enabled\n", type);
 		spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 		return;
 	}
-	irqEnabled = mdp3_res->irqMask;
-	mdp3_res->irqMask |= BIT(type);
-	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
+	irqEnabled = mdp3_res->irq_mask;
+	mdp3_res->irq_mask |= BIT(type);
+	MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
 	if (!irqEnabled)
 		enable_irq(mdp3_res->irq);
 	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
@@ -163,26 +166,33 @@
 	unsigned long flag;
 
 	spin_lock_irqsave(&mdp3_res->irq_lock, flag);
-	if (mdp3_res->irqMask & BIT(type)) {
-		mdp3_res->irqMask &= ~BIT(type);
-		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
-		if (!mdp3_res->irqMask)
-			disable_irq(mdp3_res->irq);
-	} else {
+	if (mdp3_res->irq_ref_count[type] <= 0) {
 		pr_debug("interrupt %d not enabled\n", type);
+		spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
+		return;
+	}
+	mdp3_res->irq_ref_count[type] -= 1;
+	if (mdp3_res->irq_ref_count[type] == 0) {
+		mdp3_res->irq_mask &= ~BIT(type);
+		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
+		if (!mdp3_res->irq_mask)
+			disable_irq(mdp3_res->irq);
 	}
 	spin_unlock_irqrestore(&mdp3_res->irq_lock, flag);
 }
 
 void mdp3_irq_disable_nosync(int type)
 {
-	if (mdp3_res->irqMask & BIT(type)) {
-		mdp3_res->irqMask &= ~BIT(type);
-		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irqMask);
-		if (!mdp3_res->irqMask)
-			disable_irq_nosync(mdp3_res->irq);
-	} else {
+	if (mdp3_res->irq_ref_count[type] <= 0) {
 		pr_debug("interrupt %d not enabled\n", type);
+		return;
+	}
+	mdp3_res->irq_ref_count[type] -= 1;
+	if (mdp3_res->irq_ref_count[type] == 0) {
+		mdp3_res->irq_mask &= ~BIT(type);
+		MDP3_REG_WRITE(MDP3_REG_INTR_ENABLE, mdp3_res->irq_mask);
+		if (!mdp3_res->irq_mask)
+			disable_irq_nosync(mdp3_res->irq);
 	}
 }
 
@@ -688,6 +698,108 @@
 	return 0;
 }
 
+int mdp3_put_img(struct mdp3_img_data *data)
+{
+	struct ion_client *iclient = mdp3_res->ion_client;
+	int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+	if (!data->srcp_file) {
+		pr_debug("No img to put\n");
+		return 0;
+	}
+	if (data->flags & MDP_BLIT_SRC_GEM) {
+		pr_debug("memory source MDP_BLIT_SRC_GEM\n");
+	} else if (data->flags & MDP_MEMORY_ID_TYPE_FB) {
+		pr_debug("fb mem buf=0x%x\n", data->addr);
+		fput_light(data->srcp_file, data->p_need);
+		data->srcp_file = NULL;
+	} else {
+		ion_unmap_iommu(iclient, data->srcp_ihdl, dom, 0);
+		ion_free(iclient, data->srcp_ihdl);
+		data->srcp_ihdl = NULL;
+	}
+	return 0;
+}
+
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data)
+{
+	struct file *file;
+	int ret = -EINVAL;
+	int fb_num;
+	unsigned long *start, *len;
+	struct ion_client *iclient = mdp3_res->ion_client;
+	int dom = (mdp3_res->domains + MDP3_IOMMU_DOMAIN)->domain_idx;
+
+	start = (unsigned long *) &data->addr;
+	len = (unsigned long *) &data->len;
+	data->flags |= img->flags;
+	data->p_need = 0;
+
+	if (img->flags & MDP_BLIT_SRC_GEM) {
+		data->srcp_file = NULL;
+		ret = kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
+					&data->addr, &data->len);
+		if (!ret)
+			goto done;
+	}
+	if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+		file = fget_light(img->memory_id, &data->p_need);
+		if (file == NULL) {
+			pr_err("invalid framebuffer file (%d)\n",
+					img->memory_id);
+			return -EINVAL;
+		}
+		if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+			fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+			ret = mdss_fb_get_phys_info(start, len, fb_num);
+			if (ret) {
+				pr_err("mdss_fb_get_phys_info() failed\n");
+				fput_light(file, data->p_need);
+				file = NULL;
+			}
+		} else {
+			pr_err("invalid FB_MAJOR\n");
+			fput_light(file, data->p_need);
+			file = NULL;
+			ret = -EINVAL;
+		}
+		data->srcp_file = file;
+		if (!ret)
+			goto done;
+	}
+	if (iclient) {
+		data->srcp_ihdl = ion_import_dma_buf(iclient, img->memory_id);
+		if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
+			pr_err("error on ion_import_fd\n");
+			ret = PTR_ERR(data->srcp_ihdl);
+			data->srcp_ihdl = NULL;
+			return ret;
+		}
+
+		ret = ion_map_iommu(iclient, data->srcp_ihdl, dom,
+		    0, SZ_4K, 0, start, len, 0, 0);
+
+		if (IS_ERR_VALUE(ret)) {
+			ion_free(iclient, data->srcp_ihdl);
+			pr_err("failed to map ion handle (%d)\n", ret);
+			return ret;
+		}
+	}
+done:
+	if (!ret && (img->offset < data->len)) {
+		data->addr += img->offset;
+		data->len -= img->offset;
+
+		pr_debug("mem=%d ihdl=%p buf=0x%x len=0x%x\n", img->memory_id,
+			 data->srcp_ihdl, data->addr, data->len);
+	} else {
+		mdp3_put_img(data);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
 static int mdp3_init(struct msm_fb_data_type *mfd)
 {
 	return mdp3_ctrl_init(mfd);
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 5774e5a..7e395e1 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -23,6 +23,7 @@
 #include <mach/iommu_domains.h>
 
 #include "mdp3_dma.h"
+#include "mdss_fb.h"
 
 enum  {
 	MDP3_CLK_AHB,
@@ -100,12 +101,22 @@
 	struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
 
 	spinlock_t irq_lock;
-	u32 irqMask;
+	u32 irq_ref_count[MDP3_MAX_INTR];
+	u32 irq_mask;
 	struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
 
 	struct early_suspend suspend_handler;
 };
 
+struct mdp3_img_data {
+	u32 addr;
+	u32 len;
+	u32 flags;
+	int p_need;
+	struct file *srcp_file;
+	struct ion_handle *srcp_ihdl;
+};
+
 extern struct mdp3_hw_resource *mdp3_res;
 
 struct mdp3_dma *mdp3_get_dma_pipe(int capability);
@@ -117,6 +128,8 @@
 int mdp3_clk_set_rate(int clk_type, unsigned long clk_rate);
 int mdp3_clk_enable(int enable);
 int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
+int mdp3_put_img(struct mdp3_img_data *data);
+int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
 
 #define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
 #define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 929e5f8..f5ac5e9 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -26,37 +26,108 @@
 #define MDP_VSYNC_CLK_RATE	19200000
 #define VSYNC_PERIOD 16
 
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
+
+static void mdp3_bufq_init(struct mdp3_buffer_queue *bufq)
+{
+	bufq->count = 0;
+	bufq->push_idx = 0;
+	bufq->pop_idx = 0;
+}
+
+static void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
+{
+	int count = bufq->count;
+
+	if (!count)
+		return;
+
+	while (count--) {
+		struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
+		bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
+		mdp3_put_img(data);
+	}
+	bufq->count = 0;
+	bufq->push_idx = 0;
+	bufq->pop_idx = 0;
+}
+
+static int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
+			struct mdp3_img_data *data)
+{
+	if (bufq->count >= MDP3_MAX_BUF_QUEUE) {
+		pr_err("bufq full\n");
+		return -EPERM;
+	}
+
+	bufq->img_data[bufq->push_idx] = *data;
+	bufq->push_idx = (bufq->push_idx + 1) % MDP3_MAX_BUF_QUEUE;
+	bufq->count++;
+	return 0;
+}
+
+static struct mdp3_img_data *mdp3_bufq_pop(struct mdp3_buffer_queue *bufq)
+{
+	struct mdp3_img_data *data;
+	if (bufq->count == 0)
+		return NULL;
+
+	data = &bufq->img_data[bufq->pop_idx];
+	bufq->count--;
+	bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
+	return data;
+}
+
+static int mdp3_bufq_count(struct mdp3_buffer_queue *bufq)
+{
+	return bufq->count;
+}
+
 void vsync_notify_handler(void *arg)
 {
 	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
+	spin_lock(&session->vsync_lock);
+	session->vsync_time = ktime_get();
 	complete(&session->vsync_comp);
+	spin_unlock(&session->vsync_lock);
 }
 
 static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable)
 {
 	struct mdp3_session_data *mdp3_session;
 	struct mdp3_vsync_notification vsync_client;
+	struct mdp3_vsync_notification *arg = NULL;
+	unsigned long flag;
 
+	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
 		!mdp3_session->intf)
 		return -ENODEV;
 
-	vsync_client.handler = vsync_notify_handler;
-	vsync_client.arg = mdp3_session;
-
-	mutex_lock(&mdp3_session->lock);
 	if (!mdp3_session->status) {
 		pr_debug("fb%d is not on yet", mfd->index);
-		mutex_unlock(&mdp3_session->lock);
 		return -EINVAL;
 	}
+	if (enable) {
+		vsync_client.handler = vsync_notify_handler;
+		vsync_client.arg = mdp3_session;
+		arg = &vsync_client;
+	}
 
-	mdp3_session->dma->vsync_enable(mdp3_session->dma, &vsync_client);
+	mutex_lock(&mdp3_session->lock);
+	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
 	mutex_unlock(&mdp3_session->lock);
+	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
+	if (enable)
+		INIT_COMPLETION(mdp3_session->vsync_comp);
+	else
+		complete_all(&mdp3_session->vsync_comp);
+	spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
 	return 0;
 }
 
+
 static ssize_t mdp3_vsync_show_event(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -64,8 +135,8 @@
 	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
 	struct mdp3_session_data *mdp3_session = NULL;
 	u64 vsync_ticks;
-	ktime_t vsync_time;
 	int rc;
+	unsigned long flag;
 
 	if (!mfd || !mfd->mdp.private1)
 		return 0;
@@ -78,11 +149,11 @@
 	if (rc <= 0) {
 		pr_warn("vsync wait on fb%d interrupted (%d)\n",
 			mfd->index, rc);
-		return -EBUSY;
 	}
 
-	vsync_time = mdp3_session->dma->get_vsync_time(mdp3_session->dma);
-	vsync_ticks = ktime_to_ns(vsync_time);
+	spin_lock_irqsave(&mdp3_session->vsync_lock, flag);
+	vsync_ticks = ktime_to_ns(mdp3_session->vsync_time);
+	spin_unlock_irqrestore(&mdp3_session->vsync_lock, flag);
 
 	pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
 	rc = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
@@ -395,6 +466,148 @@
 	return 0;
 }
 
+static int mdp3_overlay_get(struct msm_fb_data_type *mfd,
+				struct mdp_overlay *req)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mdp3_session->overlay.id == req->id)
+		*req = mdp3_session->overlay;
+	else
+		rc = -EINVAL;
+
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_overlay_set(struct msm_fb_data_type *mfd,
+				struct mdp_overlay *req)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mdp3_session->overlay.id == req->id) {
+		mdp3_session->overlay = *req;
+		if (req->id == MSMFB_NEW_REQUEST) {
+			mdp3_session->overlay.id = 1;
+			req->id = 1;
+		}
+	} else {
+		rc = -EINVAL;
+	}
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
+{
+	int rc = 0;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+
+	mdp3_ctrl_pan_display(mfd);
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mdp3_session->overlay.id == ndx && ndx == 1) {
+		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+		mdp3_bufq_deinit(&mdp3_session->bufq_in);
+		mdp3_bufq_deinit(&mdp3_session->bufq_out);
+	} else {
+		rc = -EINVAL;
+	}
+
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_overlay_queue_buffer(struct msm_fb_data_type *mfd,
+					struct msmfb_overlay_data *req)
+{
+	int rc;
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+	struct msmfb_data *img = &req->data;
+	struct mdp3_img_data data;
+
+	rc = mdp3_get_img(img, &data);
+	if (rc) {
+		pr_err("fail to get overlay buffer\n");
+		return rc;
+	}
+
+	rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
+	if (rc) {
+		pr_err("fail to queue the overlay buffer, buffer drop\n");
+		mdp3_put_img(&data);
+		return rc;
+	}
+	return 0;
+}
+
+static int mdp3_overlay_play(struct msm_fb_data_type *mfd,
+				 struct msmfb_overlay_data *req)
+{
+	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
+	int rc = 0;
+
+	pr_debug("mdp3_overlay_play req id=%x mem_id=%d\n",
+		req->id, req->data.memory_id);
+
+	mutex_lock(&mdp3_session->lock);
+
+	if (mfd->panel_power_on)
+		rc = mdp3_overlay_queue_buffer(mfd, req);
+	else
+		rc = -EPERM;
+
+	mutex_unlock(&mdp3_session->lock);
+
+	return rc;
+}
+
+static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd)
+{
+	struct mdp3_session_data *mdp3_session;
+	struct mdp3_img_data *data;
+	int rc = 0;
+
+	if (!mfd || !mfd->mdp.private1)
+		return -EINVAL;
+
+	mdp3_session = mfd->mdp.private1;
+	if (!mdp3_session || !mdp3_session->dma)
+		return -EINVAL;
+
+	if (!mdp3_session->status) {
+		pr_err("%s, display off!\n", __func__);
+		return -EPERM;
+	}
+
+	mutex_lock(&mdp3_session->lock);
+
+	data = mdp3_bufq_pop(&mdp3_session->bufq_in);
+	if (data) {
+		mdp3_session->dma->update(mdp3_session->dma,
+			(void *)data->addr);
+		mdp3_bufq_push(&mdp3_session->bufq_out, data);
+	}
+
+	if (mdp3_bufq_count(&mdp3_session->bufq_out) > 1) {
+		data = mdp3_bufq_pop(&mdp3_session->bufq_out);
+		mdp3_put_img(data);
+	}
+
+	mutex_unlock(&mdp3_session->lock);
+	return rc;
+}
+
 static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
 {
 	struct fb_info *fbi;
@@ -445,6 +658,9 @@
 		break;
 	case metadata_op_get_caps:
 		metadata->data.caps.mdp_rev = 304;
+		metadata->data.caps.rgb_pipes = 0;
+		metadata->data.caps.vig_pipes = 0;
+		metadata->data.caps.dma_pipes = 1;
 		break;
 	default:
 		pr_warn("Unsupported request to MDP META IOCTL.\n");
@@ -460,6 +676,8 @@
 	int rc = -EINVAL;
 	struct mdp3_session_data *mdp3_session;
 	struct msmfb_metadata metadata;
+	struct mdp_overlay req;
+	struct msmfb_overlay_data ov_data;
 	int val;
 
 	pr_debug("mdp3_ctrl_ioctl_handler\n");
@@ -478,8 +696,6 @@
 	case MSMFB_OVERLAY_VSYNC_CTRL:
 		if (!copy_from_user(&val, argp, sizeof(val))) {
 			rc = mdp3_ctrl_vsync_enable(mfd, val);
-			if (!val)
-				init_completion(&mdp3_session->vsync_comp);
 		} else {
 			pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed\n");
 			rc = -EFAULT;
@@ -493,10 +709,42 @@
 		if (!rc)
 			rc = copy_to_user(argp, &metadata, sizeof(metadata));
 		break;
+	case MSMFB_OVERLAY_GET:
+		rc = copy_from_user(&req, argp, sizeof(req));
+		if (!rc) {
+			rc = mdp3_overlay_get(mfd, &req);
+
+		if (!IS_ERR_VALUE(rc))
+			rc = copy_to_user(argp, &req, sizeof(req));
+		}
+		if (rc)
+			pr_err("OVERLAY_GET failed (%d)\n", rc);
+		break;
+	case MSMFB_OVERLAY_SET:
+		rc = copy_from_user(&req, argp, sizeof(req));
+		if (!rc) {
+			rc = mdp3_overlay_set(mfd, &req);
+
+		if (!IS_ERR_VALUE(rc))
+			rc = copy_to_user(argp, &req, sizeof(req));
+		}
+		if (rc)
+			pr_err("OVERLAY_SET failed (%d)\n", rc);
+		break;
+	case MSMFB_OVERLAY_UNSET:
+		if (!IS_ERR_VALUE(copy_from_user(&val, argp, sizeof(val))))
+			rc = mdp3_overlay_unset(mfd, val);
+		break;
+	case MSMFB_OVERLAY_PLAY:
+		rc = copy_from_user(&ov_data, argp, sizeof(ov_data));
+		if (!rc)
+			rc = mdp3_overlay_play(mfd, &ov_data);
+		if (rc)
+			pr_err("OVERLAY_PLAY failed (%d)\n", rc);
+		break;
 	default:
 		break;
 	}
-
 	return rc;
 }
 
@@ -515,7 +763,7 @@
 	mdp3_interface->cursor_update = NULL;
 	mdp3_interface->dma_fnc = mdp3_ctrl_pan_display;
 	mdp3_interface->ioctl_handler = mdp3_ctrl_ioctl_handler;
-	mdp3_interface->kickoff_fnc = NULL;
+	mdp3_interface->kickoff_fnc = mdp3_ctrl_display_commit_kickoff;
 
 	mdp3_session = kmalloc(sizeof(struct mdp3_session_data), GFP_KERNEL);
 	if (!mdp3_session) {
@@ -525,6 +773,7 @@
 	memset(mdp3_session, 0, sizeof(struct mdp3_session_data));
 	mutex_init(&mdp3_session->lock);
 	init_completion(&mdp3_session->vsync_comp);
+	spin_lock_init(&mdp3_session->vsync_lock);
 	mdp3_session->dma = mdp3_get_dma_pipe(MDP3_DMA_CAP_ALL);
 	if (!mdp3_session->dma) {
 		rc = -ENODEV;
@@ -540,6 +789,9 @@
 
 	mdp3_session->panel = dev_get_platdata(&mfd->pdev->dev);
 	mdp3_session->status = 0;
+	mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+	mdp3_bufq_init(&mdp3_session->bufq_in);
+	mdp3_bufq_init(&mdp3_session->bufq_out);
 
 	mfd->mdp.private1 = mdp3_session;
 
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index d42ece7..fb3bd36 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -18,10 +18,20 @@
 #include <linux/mutex.h>
 #include <linux/completion.h>
 
+#include "mdp3.h"
 #include "mdp3_dma.h"
 #include "mdss_fb.h"
 #include "mdss_panel.h"
 
+#define MDP3_MAX_BUF_QUEUE 8
+
+struct mdp3_buffer_queue {
+	struct mdp3_img_data img_data[MDP3_MAX_BUF_QUEUE];
+	int count;
+	int push_idx;
+	int pop_idx;
+};
+
 struct mdp3_session_data {
 	struct mutex lock;
 	int status;
@@ -29,7 +39,12 @@
 	struct mdss_panel_data *panel;
 	struct mdp3_intf *intf;
 	struct msm_fb_data_type *mfd;
+	ktime_t vsync_time;
+	spinlock_t vsync_lock;
 	struct completion vsync_comp;
+	struct mdp_overlay overlay;
+	struct mdp3_buffer_queue bufq_in;
+	struct mdp3_buffer_queue bufq_out;
 };
 
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 69e3d7e..a09f503 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -20,17 +20,6 @@
 #define DMA_STOP_POLL_SLEEP_US 1000
 #define DMA_STOP_POLL_TIMEOUT_US 16000
 
-static ktime_t mdp3_get_vsync_time(struct mdp3_dma *dma)
-{
-	unsigned long flag;
-	ktime_t time;
-
-	spin_lock_irqsave(&dma->dma_lock, flag);
-	time = dma->vsync_time;
-	spin_unlock_irqrestore(&dma->dma_lock, flag);
-	return time;
-}
-
 static void mdp3_vsync_intr_handler(int type, void *arg)
 {
 	struct mdp3_dma *dma = (struct mdp3_dma *)arg;
@@ -41,13 +30,11 @@
 	vsync_client = dma->vsync_client;
 	if (!vsync_client.handler)
 		dma->cb_type &= ~MDP3_DMA_CALLBACK_TYPE_VSYNC;
-	dma->vsync_time = ktime_get();
 	complete(&dma->vsync_comp);
+	spin_unlock(&dma->dma_lock);
 	if (vsync_client.handler)
 		vsync_client.handler(vsync_client.arg);
-	spin_unlock(&dma->dma_lock);
-
-	if (!vsync_client.handler)
+	else
 		mdp3_irq_disable_nosync(type);
 }
 
@@ -186,7 +173,7 @@
 			updated = 1;
 		}
 	} else {
-		if (!dma->vsync_client.handler) {
+		if (dma->vsync_client.handler) {
 			dma->vsync_client.handler = NULL;
 			dma->vsync_client.arg = NULL;
 			updated = 1;
@@ -696,7 +683,6 @@
 		dma->histo_intr_enable = mdp3_dmap_histo_intr_enable;
 		dma->histo_intr_clear = mdp3_dmap_histo_intr_clear;
 		dma->vsync_enable = mdp3_dma_vsync_enable;
-		dma->get_vsync_time = mdp3_get_vsync_time;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
 		break;
@@ -717,7 +703,6 @@
 		dma->histo_intr_enable = NULL;
 		dma->histo_intr_clear = NULL;
 		dma->vsync_enable = mdp3_dma_vsync_enable;
-		dma->get_vsync_time = mdp3_get_vsync_time;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
 		break;
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 2fb8427..cef749b 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -231,7 +231,6 @@
 	spinlock_t dma_lock;
 	struct completion vsync_comp;
 	struct completion dma_comp;
-	ktime_t vsync_time;
 	struct mdp3_vsync_notification vsync_client;
 	u32 cb_type;
 
@@ -275,9 +274,6 @@
 
 	void (*vsync_enable)(struct mdp3_dma *dma,
 			struct mdp3_vsync_notification *vsync_client);
-
-	ktime_t (*get_vsync_time)(struct mdp3_dma *dma);
-
 };
 
 struct mdp3_video_intf_cfg {
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index e87f028..1876057 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -119,6 +119,12 @@
 	 89909, 119880, 148352, 119880, false},
 	{HDMI_VFRMT_1280x720p120_16_9, 1280, 720, false, 1650, 370, 750, 30,
 	 90000, 120000, 148500, 120000, false},
+	{HDMI_VFRMT_1280x1024p60_5_4, 1280, 1024, false, 1688, 408, 1066, 42,
+	 63981, 60020, 108000, 60000, false},
+
+	/* All 1024 H Active */
+	{HDMI_VFRMT_1024x768p60_4_3, 1024, 768, false, 1344, 320, 806, 38,
+	 48363, 60004, 65000, 60000, false},
 
 	/* All 1440 H Active */
 	{HDMI_VFRMT_1440x576i50_4_3, 1440, 576, true,  1728, 288, 625, 24,
@@ -1016,7 +1022,7 @@
 static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl,
 	const u8 *data_buf, u32 num_of_cea_blocks)
 {
-	u8 i = 0;
+	u8 i = 0, offset = 0, std_blk = 0;
 	u32 video_format = HDMI_VFRMT_640x480p60_4_3;
 	u32 has480p = false;
 	u8 len;
@@ -1175,6 +1181,72 @@
 		}
 	}
 
+	std_blk = 0;
+	offset  = 0;
+	while (std_blk < 8) {
+		if ((edid_blk0[0x26 + offset] == 0x81) &&
+		    (edid_blk0[0x26 + offset + 1] == 0x80)) {
+			pr_debug("%s: 108MHz: off=[%x] stdblk=[%x]\n",
+				 __func__, offset, std_blk);
+			hdmi_edid_add_sink_video_format(sink_data,
+				HDMI_VFRMT_1280x1024p60_5_4);
+		}
+		if ((edid_blk0[0x26 + offset] == 0x61) &&
+		    (edid_blk0[0x26 + offset + 1] == 0x40)) {
+			pr_debug("%s: 65MHz: off=[%x] stdblk=[%x]\n",
+				 __func__, offset, std_blk);
+			hdmi_edid_add_sink_video_format(sink_data,
+				HDMI_VFRMT_1024x768p60_4_3);
+			break;
+		} else {
+			offset += 2;
+		}
+		std_blk++;
+	}
+	/* check if the EDID revision is 4 (version 1.4) */
+	if (edid_blk0[0x13] == 4) {
+		u8  start = 0x36;
+		i = 0;
+		/* Check each of 4 - 18 bytes descriptors */
+		while (i < 4) {
+			u8  iter   = start;
+			u32 header_1 = 0;
+			u8  header_2 = 0;
+			header_1 = edid_blk0[iter++];
+			header_1 = header_1 << 8 | edid_blk0[iter++];
+			header_1 = header_1 << 8 | edid_blk0[iter++];
+			header_1 = header_1 << 8 | edid_blk0[iter++];
+			header_2 = edid_blk0[iter];
+			if (header_1 == 0x000000F7 &&
+			    header_2 == 0x00) {
+				iter++;
+				/* VESA DMT Standard Version (0x0A)*/
+				iter++;
+				/* First set of supported formats */
+				iter++;
+				/* Second set of supported formats */
+				if (edid_blk0[iter] & 0x02) {
+					pr_debug("%s: DMT 1280x1024@60\n",
+						 __func__);
+					hdmi_edid_add_sink_video_format(
+						sink_data,
+						HDMI_VFRMT_1280x1024p60_5_4);
+					break;
+				}
+			}
+			i++;
+			start += 0x12;
+		}
+	}
+
+	/* Established Timing I and II */
+	if (edid_blk0[0x24] & BIT(3)) {
+		pr_debug("%s: 65MHz: off=[%x] stdblk=[%x]\n",
+			 __func__, offset, std_blk);
+		hdmi_edid_add_sink_video_format(sink_data,
+				HDMI_VFRMT_1024x768p60_4_3);
+	}
+
 	hdmi_edid_get_extended_video_formats(edid_ctrl, data_buf+0x80);
 
 	/* mandaroty 3d format */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 42cc356..12552bc 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -190,6 +190,14 @@
 		{20480, 247500} } },
 };
 
+static bool is_cea_format(int mode)
+{
+	if ((mode > 0) && (mode < HDMI_EVFRMT_END))
+		return true;
+	else
+		return false;
+}
+
 const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
 {
 	switch (module) {
@@ -2100,7 +2108,8 @@
 		return rc;
 	}
 
-	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl) &&
+	    is_cea_format(hdmi_ctrl->video_resolution)) {
 		rc = hdmi_tx_audio_setup(hdmi_ctrl);
 		if (rc) {
 			DEV_ERR("%s: hdmi_msm_audio_setup failed. rc=%d\n",
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 0c8b0f8..53dfc71 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -109,8 +109,8 @@
 		hdmi_supported_video_mode_lut, MSM_HDMI_MODES_XTND);
 
 	/* Add any other specific DVI timings (DVI modes, etc.) */
-	MSM_HDMI_MODES_SET_TIMING(hdmi_supported_video_mode_lut,
-		HDMI_VFRMT_2560x1600p60_16_9);
+	MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+		hdmi_supported_video_mode_lut, MSM_HDMI_MODES_DVI);
 } /* hdmi_setup_video_mode_lut */
 
 const char *hdmi_get_single_video_3d_fmt_2string(u32 format)
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 26c6934..3cb23f3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -65,11 +65,19 @@
 {
 	u32 xres, yres;
 	u32 min_src_size, min_dst_size;
+	int content_secure;
 	struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
 
 	xres = mfd->fbi->var.xres;
 	yres = mfd->fbi->var.yres;
 
+	content_secure = (req->flags & MDP_SECURE_OVERLAY_SESSION);
+	if (!ctl->is_secure && content_secure &&
+				 (mfd->panel.type == WRITEBACK_PANEL)) {
+		pr_debug("return due to security concerns\n");
+		return -EPERM;
+	}
 	if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102) {
 		min_src_size = fmt->is_yuv ? 2 : 1;
 		min_dst_size = 1;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 4bce95c..323f1e7 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -700,7 +700,9 @@
 #define V4L2_QCOM_BUF_FLAG_CODECCONFIG  0x4000
 #define V4L2_QCOM_BUF_FLAG_EOSEQ  0x8000
 #define V4L2_QCOM_BUF_TIMESTAMP_INVALID 0x10000
+#define V4L2_QCOM_BUF_FLAG_IDRFRAME	0x20000	/* Image is a IDR-frame */
 #define V4L2_QCOM_BUF_FLAG_DECODEONLY 0x40000
+#define V4L2_QCOM_BUF_DATA_CORRUPT 0x80000
 
 /*
  *	O V E R L A Y   P R E V I E W
@@ -1838,6 +1840,7 @@
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP,
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM,
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+	V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP
 };
 #define V4L2_CID_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO \
 		(V4L2_CID_MPEG_MSM_VIDC_BASE + 23)
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 2319c48..da56df6 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. 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
@@ -33,6 +33,7 @@
 #define WCNSS_WLAN_IRQ_INVALID -1
 #define HAVE_WCNSS_SUSPEND_RESUME_NOTIFY 1
 #define HAVE_WCNSS_RESET_INTR 1
+#define HAVE_WCNSS_CAL_DOWNLOAD 1
 
 struct device *wcnss_wlan_get_device(void);
 struct resource *wcnss_wlan_get_memory_map(struct device *dev);
@@ -65,7 +66,7 @@
 void wcnss_resume_notify(void);
 void wcnss_riva_log_debug_regs(void);
 void wcnss_pronto_log_debug_regs(void);
-int wcnss_cold_boot_done(void);
+int wcnss_device_ready(void);
 
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index f632ad6..2164275 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -73,6 +73,16 @@
 	unsigned int aspect_height;
 };
 
+struct msm_vidc_mpeg2_seqdisp_payload {
+	unsigned int video_format;
+	bool color_descp;
+	unsigned int color_primaries;
+	unsigned int transfer_char;
+	unsigned int matrix_coeffs;
+	unsigned int disp_width;
+	unsigned int disp_height;
+};
+
 struct msm_vidc_panscan_window {
 	unsigned int panscan_height_offset;
 	unsigned int panscan_width_offset;
@@ -94,6 +104,7 @@
 	EXTRADATA_FRAME_RATE = 0x00000007,
 	EXTRADATA_PANSCAN_WINDOW = 0x00000008,
 	EXTRADATA_RECOVERY_POINT_SEI = 0x00000009,
+	EXTRADATA_MPEG2_SEQDISP = 0x0000000D,
 	EXTRADATA_MULTISLICE_INFO = 0x7F100000,
 	EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
 	EXTRADATA_INDEX = 0x7F100002,
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 0dd14e6..2d34d70 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -70,7 +70,6 @@
 #define COMPRESSED_IO	0x0040
 #define NT_MODE        0x0400
 
-
 #define NO_TIMESTAMP    0xFF00
 #define SET_TIMESTAMP   0x0000
 
@@ -79,6 +78,19 @@
 
 #define SESSION_MAX	0x08
 
+/* payload structure bytes */
+#define READDONE_IDX_STATUS 0
+#define READDONE_IDX_BUFADD_LSW 1
+#define READDONE_IDX_BUFADD_MSW 2
+#define READDONE_IDX_MEMMAP_HDL 3
+#define READDONE_IDX_SIZE 4
+#define READDONE_IDX_OFFSET 5
+#define READDONE_IDX_LSW_TS 6
+#define READDONE_IDX_MSW_TS 7
+#define READDONE_IDX_FLAGS 8
+#define READDONE_IDX_NUMFRAMES 9
+#define READDONE_IDX_SEQ_ID 10
+
 #define SOFT_PAUSE_PERIOD       30   /* ramp up/down for 30ms    */
 #define SOFT_PAUSE_STEP         2000 /* Step value 2ms or 2000us */
 enum {
diff --git a/include/video/msm_hdmi_modes.h b/include/video/msm_hdmi_modes.h
index a15272b..ced6acb 100644
--- a/include/video/msm_hdmi_modes.h
+++ b/include/video/msm_hdmi_modes.h
@@ -122,9 +122,10 @@
 #define HDMI_EVFRMT_END			HDMI_VFRMT_4096x2160p24_16_9
 
 /* VESA DMT TIMINGS */
-#define HDMI_VFRMT_2560x1600p60_16_9	(HDMI_EVFRMT_END + 1)
+#define HDMI_VFRMT_1024x768p60_4_3	(HDMI_EVFRMT_END + 1)
 #define HDMI_VFRMT_1280x1024p60_5_4	(HDMI_EVFRMT_END + 2)
-#define VESA_DMT_VFRMT_END		HDMI_VFRMT_1280x1024p60_5_4
+#define HDMI_VFRMT_2560x1600p60_16_9	(HDMI_EVFRMT_END + 3)
+#define VESA_DMT_VFRMT_END		HDMI_VFRMT_2560x1600p60_16_9
 #define HDMI_VFRMT_MAX			(VESA_DMT_VFRMT_END + 1)
 #define HDMI_VFRMT_FORCE_32BIT		0x7FFFFFFF
 
@@ -183,6 +184,9 @@
 #define HDMI_VFRMT_1920x1080p30_16_9_TIMING				\
 	{HDMI_VFRMT_1920x1080p30_16_9, 1920, 88, 44, 148, false,	\
 	 1080, 4, 5, 36, false, 74250, 30000, false, true}
+#define HDMI_VFRMT_1024x768p60_4_3_TIMING                               \
+	{HDMI_VFRMT_1024x768p60_4_3, 1024, 24, 136, 160, false,         \
+	768, 2, 6, 29, false, 65000, 60000, false, true}
 #define HDMI_VFRMT_1280x1024p60_5_4_TIMING				\
 	{HDMI_VFRMT_1280x1024p60_5_4, 1280, 48, 112, 248, false,	\
 	1024, 1, 3, 38, false, 108000, 60000, false, true}
@@ -249,6 +253,7 @@
 	}
 
 	if (type & MSM_HDMI_MODES_DVI) {
+		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1024x768p60_4_3);
 		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x1024p60_5_4);
 		MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_2560x1600p60_16_9);
 	}
@@ -326,8 +331,9 @@
 	case HDMI_VFRMT_3840x2160p25_16_9:	return "3840x2160 p25 16/9";
 	case HDMI_VFRMT_3840x2160p24_16_9:	return "3840x2160 p24 16/9";
 	case HDMI_VFRMT_4096x2160p24_16_9:	return "4096x2160 p24 16/9";
+	case HDMI_VFRMT_1024x768p60_4_3:	return "1024x768 p60 4/3";
+	case HDMI_VFRMT_1280x1024p60_5_4:	return "1280x1024 p60 5/4";
 	case HDMI_VFRMT_2560x1600p60_16_9:	return "2560x1600 p60 16/9";
-	case HDMI_VFRMT_1280x1024p60_5_4:	return "1280x1042 p60 5/4";
 	default:				return "???";
 	}
 }
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 59debb7..2356791 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -137,6 +137,8 @@
 static DEFINE_RWLOCK(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
+#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
+
 static ATOMIC_NOTIFIER_HEAD(netlink_chain);
 
 static inline u32 netlink_group_mask(u32 group)
@@ -330,6 +332,11 @@
 	struct hlist_node *node;
 	unsigned long mask;
 	unsigned int i;
+	struct listeners *listeners;
+
+	listeners = nl_deref_protected(tbl->listeners);
+	if (!listeners)
+		return;
 
 	for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
 		mask = 0;
@@ -337,7 +344,7 @@
 			if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
 				mask |= nlk_sk(sk)->groups[i];
 		}
-		tbl->listeners->masks[i] = mask;
+		listeners->masks[i] = mask;
 	}
 	/* this function is only called with the netlink table "grabbed", which
 	 * makes sure updates are visible before bind or setsockopt return. */
@@ -518,7 +525,11 @@
 	if (netlink_is_kernel(sk)) {
 		BUG_ON(nl_table[sk->sk_protocol].registered == 0);
 		if (--nl_table[sk->sk_protocol].registered == 0) {
-			kfree(nl_table[sk->sk_protocol].listeners);
+			struct listeners *old;
+
+			old = nl_deref_protected(nl_table[sk->sk_protocol].listeners);
+			RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL);
+			kfree_rcu(old, rcu);
 			nl_table[sk->sk_protocol].module = NULL;
 			nl_table[sk->sk_protocol].registered = 0;
 		}
@@ -948,7 +959,7 @@
 	rcu_read_lock();
 	listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
 
-	if (group - 1 < nl_table[sk->sk_protocol].groups)
+	if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)
 		res = test_bit(group - 1, listeners->masks);
 
 	rcu_read_unlock();
@@ -1579,7 +1590,7 @@
 		new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
 		if (!new)
 			return -ENOMEM;
-		old = rcu_dereference_protected(tbl->listeners, 1);
+		old = nl_deref_protected(tbl->listeners);
 		memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
 		rcu_assign_pointer(tbl->listeners, new);
 
diff --git a/sound/soc/msm/mdm9615.c b/sound/soc/msm/mdm9615.c
index b140b5b..c3967dc 100644
--- a/sound/soc/msm/mdm9615.c
+++ b/sound/soc/msm/mdm9615.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. 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
@@ -2336,6 +2336,9 @@
 {
 	int ret;
 
+	/* Set GPIO headset detection by default */
+	hs_detect_use_gpio = true;
+
 	if (!cpu_is_msm9615()) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return -ENODEV ;
@@ -2413,8 +2416,6 @@
 	sif_virt_addr = ioremap(LPASS_SIF_MUX_ADDR, 4);
 	secpcm_portslc_virt_addr = ioremap(SEC_PCM_PORT_SLC_ADDR, 4);
 
-	hs_detect_use_gpio = true;
-
 	return ret;
 }
 module_init(mdm9615_audio_init);
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 9359ed7..9dbbf20 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -39,7 +39,10 @@
 #define COMPRE_CAPTURE_NUM_PERIODS	16
 /* Allocate the worst case frame size for compressed audio */
 #define COMPRE_CAPTURE_HEADER_SIZE	(sizeof(struct snd_compr_audio_info))
-#define COMPRE_CAPTURE_MAX_FRAME_SIZE	(6144)
+/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE
+ * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1
+ */
+#define COMPRE_CAPTURE_MAX_FRAME_SIZE	(4032)
 #define COMPRE_CAPTURE_PERIOD_SIZE	((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
 					  COMPRE_CAPTURE_HEADER_SIZE) * \
 					  MAX_NUM_FRAMES_PER_BUFFER)
@@ -226,7 +229,7 @@
 				prtd->pcm_irq_pos);
 
 		memcpy(prtd->audio_client->port[OUT].buf->data +
-			   prtd->pcm_irq_pos, (ptrmem + 2),
+			   prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE),
 			   COMPRE_CAPTURE_HEADER_SIZE);
 		pr_debug("buf = %p, updated data = 0x%X, *data = %p\n",
 				prtd->audio_client->port[OUT].buf,
@@ -235,9 +238,10 @@
 				prtd->audio_client->port[OUT].buf->data);
 		if (!atomic_read(&prtd->start))
 			break;
-		pr_debug("frame size=%d, buffer = 0x%X\n", ptrmem[2],
-				ptrmem[1]);
-		if (ptrmem[2] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
+		pr_debug("frame size=%d, buffer = 0x%X\n",
+				ptrmem[READDONE_IDX_SIZE],
+				ptrmem[READDONE_IDX_BUFADD_LSW]);
+		if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
 			pr_err("Frame length exceeded the max length");
 			break;
 		}
@@ -546,7 +550,7 @@
 {
 	pr_debug("%s\n", __func__);
 	/* MP3 Block */
-	compr->info.compr_cap.num_codecs = 4;
+	compr->info.compr_cap.num_codecs = 5;
 	compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
 	compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
 	compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
@@ -555,6 +559,7 @@
 	compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
 	compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
 	compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
+	compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB;
 	/* Add new codecs here */
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 59d4de2..af8e873 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -45,17 +45,6 @@
 
 #define TRUE        0x01
 #define FALSE       0x00
-#define READDONE_IDX_STATUS 0
-#define READDONE_IDX_BUFADD_LSW 1
-#define READDONE_IDX_BUFADD_MSW 2
-#define READDONE_IDX_MEMMAP_HDL 3
-#define READDONE_IDX_SIZE 4
-#define READDONE_IDX_OFFSET 5
-#define READDONE_IDX_LSW_TS 6
-#define READDONE_IDX_MSW_TS 7
-#define READDONE_IDX_FLAGS 8
-#define READDONE_IDX_NUMFRAMES 9
-#define READDONE_IDX_SEQ_ID 10
 
 /* TODO, combine them together */
 static DEFINE_MUTEX(session_lock);
@@ -3371,6 +3360,7 @@
 	struct list_head *ptr, *next;
 	u32 lbuf_addr_lsw;
 	u32 liomode;
+	u32 io_compressed;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -3387,12 +3377,15 @@
 	read.buf_size = param->len;
 	read.seq_id = param->uid;
 	liomode = (NT_MODE | ASYNC_IO_MODE);
+	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
 	if (ac->io_mode == liomode)
 		lbuf_addr_lsw = (read.buf_addr_lsw - 32);
+	else if (ac->io_mode == io_compressed)
+		lbuf_addr_lsw = (read.buf_addr_lsw - 64);
 	else
 		lbuf_addr_lsw = read.buf_addr_lsw;
 
-	list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
+	list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
 		buf_node = list_entry(ptr, struct asm_buffer_node, list);
 			if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
 				read.mem_map_handle = buf_node->mmap_hdl;