Merge "mfd: pm8xxx-pwm: Add support for pwm size of 7 bit"
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
new file mode 100644
index 0000000..f57a7bd
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-cmd.dtsi
@@ -0,0 +1,124 @@
+/* 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.
+ */
+
+/ {
+	qcom,dsi_v2_truly_wvga_video {
+		compatible = "qcom,dsi-panel-v2";
+		label = "Truly WVGA command mode dsi panel";
+		qcom,dsi-ctrl-phandle = <&mdss_dsi0>;
+		qcom,rst-gpio = <&msmgpio 41 0>;
+		qcom,mode-selection-gpio = <&msmgpio 7 0>;
+		qcom,te-gpio = <&msmgpio 12 0>;
+		vdda-supply = <&pm8110_l19>;
+		vddio-supply=<&pm8110_l14>;
+		qcom,mdss-pan-res = <480 800>;
+		qcom,mdss-pan-bpp = <24>;
+		qcom,mdss-pan-dest = "display_1";
+		qcom,mdss-pan-porch-values = <40 8 160 10 2 12>;
+		qcom,mdss-pan-underflow-clr = <0xff>;
+		qcom,mdss-pan-bl-levels = <1 255>;
+		qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+		qcom,mdss-pan-dsi-mode = <1>;
+		qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+		qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+		qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+		qcom,mdss-pan-dsi-traffic-mode = <1>;
+		qcom,mdss-pan-dsi-dst-format = <8>;
+		qcom,mdss-pan-insert-dcs-cmd = <1>;
+		qcom,mdss-pan-wr-mem-continue = <0x3c>;
+		qcom,mdss-pan-wr-mem-start = <0x2c>;
+		qcom,mdss-pan-dsi-vc = <0>;
+		qcom,mdss-pan-dsi-rgb-swap = <0>;
+		qcom,mdss-pan-dsi-data-lanes = <1 1 0 0>;
+		qcom,mdss-pan-dsi-dlane-swap = <0>;
+		qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+		qcom,mdss-pan-dsi-stream = <0>;
+		qcom,mdss-pan-dsi-mdp-tr = <0x02>;
+		qcom,mdss-pan-dsi-dma-tr = <0x04>;
+		qcom,mdss-pan-dsi-frame-rate = <60>;
+		qcom,panel-phy-regulatorSettings =[02 08 05 00 20 03];
+		qcom,panel-phy-timingSettings = [5D 12 0C  00 33 38
+						 10 16 1E 03 04 00];
+		qcom,panel-phy-strengthCtrl = [ff 06];
+		qcom,panel-phy-bistCtrl = [03 03 00 00 0f 00];
+		qcom,panel-phy-laneConfig =
+					[80 45 00 00 01 66 /*lane0**/
+					80 45 00 00 01 66 /*lane1*/
+					80 45 00 00 01 66 /*lane2*/
+					80 45 00 00 01 66 /*lane3*/
+					40 67 00 00 01 88]; /*Clk*/
+
+		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
+		qcom,panel-on-cmds = [
+					05 01 00 00 00 02
+						01 00
+					23 01 00 00 00 02
+						b0 04
+					29 01 00 00 00 03
+						b3 02 00
+					23 01 00 00 00 02
+						bd 00
+					29 01 00 00 00 03
+						c0 18 66
+					29 01 00 00 00 10
+						c1 23 31 99 21 20 00 30 28 0c 0c
+						00 00 00 21 01
+					29 01 00 00 00 07
+						c2 00 06 06 01 03 00
+					29 01 00 00 00 19
+						c8 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 19
+						c9 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 19
+						ca 04 10 18 20 2e 46 3c 28 1f 18
+						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
+					29 01 00 00 00 11
+						d0 29 03 ce a6 00 43 20 10 01 00
+						01 01 00 03 01 00
+					29 01 00 00 00 08
+						d1 18 0C 23 03 75 02 50
+					23 01 00 00 00 02
+						d3 11
+					29 01 00 00 00 03
+						d5 2a 2a
+					29 01 00 00 00 03
+						de 01 51
+					23 01 00 00 00 02
+						e6 51
+					23 01 00 00 00 02
+						fa 03
+					23 01 00 00 64 02
+						d6 28
+					15 01 00 00 00 02
+						36 41
+					39 01 00 00 00 05
+						2a 00 00 01 df
+					39 01 00 00 00 05
+						2b 00 00 03 1f
+					15 01 00 00 00 02
+						35 00
+					39 01 00 00 00 03
+						44 00 50
+					15 01 00 00 00 02
+						3a 77
+					05 01 00 00 7D 02
+						11 00
+					05 01 00 00 14 02
+						29 00
+					];
+		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+					05 01 00 00 78 02 10 00];
+		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+	};
+};
diff --git a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
index 5693ccd..8be8d71 100644
--- a/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-v2-panel-truly-wvga-video.dtsi
@@ -69,7 +69,7 @@
 						c1 23 31 99 21 20 00 30 28 0c 0c
 						00 00 00 21 01
 					29 01 00 00 00 07
-						c2 10 06 06 01 03 00
+						c2 00 06 06 01 03 00
 					29 01 00 00 00 19
 						c8 04 10 18 20 2e 46 3c 28 1f 18
 						10 04 04 10 18 20 2e 46 3c 28 1f 18 10 04
@@ -89,7 +89,7 @@
 					29 01 00 00 00 03
 						d5 2a 2a
 					29 01 00 00 00 03
-						de 01 41
+						de 01 51
 					23 01 00 00 00 02
 						e6 51
 					23 01 00 00 00 02
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index e991552..3860bce 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -265,7 +265,7 @@
 			qcom,led_mpp_4 {
 				label = "mpp";
 				linux,name = "green";
-				linux,default-trigger = "none";
+				linux,default-trigger = "battery-full";
 				qcom,default-state = "off";
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
@@ -287,7 +287,7 @@
 			qcom,led_mpp_6 {
 				label = "mpp";
 				linux,name = "red";
-				linux,default-trigger = "none";
+				linux,default-trigger = "battery-charging";
 				qcom,default-state = "off";
 				qcom,max-current = <40>;
 				qcom,current-setting = <5>;
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dts b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
index c46e9d2..62ef933 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dts
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dts
@@ -13,6 +13,7 @@
 /dts-v1/;
 
 /include/ "msm8610-qrd.dtsi"
+/include/ "msm8612-qrd-camera-sensor.dtsi"
 
 / {
 	model = "Qualcomm MSM 8610 QRD";
@@ -37,4 +38,16 @@
 
         qcom,ext-spk-amp-gpio = <&msmgpio 92 0x0>;
     };
+    i2c@f9925000 {
+		fsl@1c {
+			compatible = "fsl,mma8x5x";
+			reg = <0x1c>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <81 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vio-supply = <&pm8110_l14>;
+			fsl,irq-gpio = <&msmgpio 81 0x00>;
+			fsl,sensors-position = <5>;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
new file mode 100644
index 0000000..25554eb
--- /dev/null
+++ b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+&i2c {
+
+	qcom,camera@20 {
+		compatible = "shinetech,s5k4e1";
+		reg = <0x20>;
+		qcom,slave-id = <0x20 0x0000 0x4e10>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "SKUAB_ST_s5k4e1";
+		cam_vdig-supply = <&pm8110_l2>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 0 0>;
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 8000 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 13 0>,
+			<&msmgpio 21 0>,
+			<&msmgpio 20 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET1",
+			"CAM_STANDBY";
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <1>;
+		qcom,sensor-type = <0>;
+		qcom,cci-master = <0>;
+	};
+	qcom,camera@78 {
+		compatible = "shinetech,gc0339";
+		reg = <0x78>;
+		qcom,slave-id = <0x42 0x00 0xc8>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		qcom,sensor-name = "skuab_shinetech_gc0339";
+		cam_vdig-supply = <&pm8110_l14>;
+		cam_vana-supply = <&pm8110_l19>;
+		cam_vio-supply = <&pm8110_l14>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-type = <0 1 0>;
+		qcom,cam-vreg-min-voltage = <1800000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		gpios = <&msmgpio 14 0>,
+				<&msmgpio 15 0>,
+				<&msmgpio 85 0>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+				"CAM_RESET",
+				"CAM_STANDBY";
+		qcom,gpio-set-tbl-num = <1 1>;
+		qcom,gpio-set-tbl-flags = <0 2>;
+		qcom,gpio-set-tbl-delay = <1000 4000>;
+		qcom,csi-lane-assign = <0xe4>;
+		qcom,csi-lane-mask = <0x3>;
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <0>;
+		status = "ok";
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
new file mode 100644
index 0000000..cb8895f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-cdp.dts
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-cdp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 CDP";
+	compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
+	qcom,msm-id = <126 1 0x20002>,
+		      <185 1 0x20002>,
+		      <186 1 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
new file mode 100644
index 0000000..8e04c18
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-fluid.dts
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-fluid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+	qcom,msm-id = <126 3 0x20002>,
+		      <185 3 0x20002>,
+		      <186 3 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
new file mode 100644
index 0000000..7128abe
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-liquid.dts
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-liquid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 LIQUID";
+	compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
+	qcom,msm-id = <126 9 0x20002>,
+		      <185 9 0x20002>,
+		      <186 9 0x20002>;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
new file mode 100644
index 0000000..b7e35cf
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2-mtp.dts
@@ -0,0 +1,28 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msm8974-v2-2.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974v2 MTP";
+	compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+	qcom,msm-id = <126 8 0x20002>,
+		      <185 8 0x20002>,
+		      <186 8 0x20002>;
+};
+
+&pm8941_chg {
+	qcom,bpd-detection = "bpd_thm";
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-2.dtsi b/arch/arm/boot/dts/msm8974-v2-2.dtsi
new file mode 100644
index 0000000..09455b1
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-v2-2.dtsi
@@ -0,0 +1,105 @@
+/* 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. However, device definitions should be placed inside the
+ * msm8974.dtsi file.
+ */
+
+/include/ "msm8974-v2.dtsi"
+
+/* GPU overrides */
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03030001>;
+
+	qcom,initial-pwrlevel = <4>;
+
+	/* Updated bus bandwidth requirements */
+	qcom,msm-bus,vectors-KBps =
+		/* Off */
+		<26 512 0 0>, <89 604 0 0>,
+		/* SVS */
+		<26 512 0 2400000>, <89 604 0 3000000>,
+		/* Nominal / SVS */
+		<26 512 0 4656000>, <89 604 0 3000000>,
+		/* Nominal */
+		<26 512 0 4656000>, <89 604 0 5120000>,
+		/* Turbo / Nominal */
+		<26 512 0 7464000>, <89 604 0 5120000>,
+		/* Turbo */
+		<26 512 0 7464000>, <89 604 0 6400000>;
+
+	qcom,gpu-pwrlevels {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "qcom,gpu-pwrlevels";
+
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <450000000>;
+			qcom,bus-freq = <5>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@2 {
+			reg = <2>;
+			qcom,gpu-freq = <389000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@3 {
+			reg = <3>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <4>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@4 {
+			reg = <4>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <66>;
+		};
+
+		qcom,gpu-pwrlevel@5 {
+			reg = <5>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <2>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@6 {
+			reg = <6>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <1>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@7 {
+			reg = <7>;
+			qcom,gpu-freq = <27000000>;
+			qcom,bus-freq = <0>;
+			qcom,io-fraction = <0>;
+		};
+	};
+};
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index fb2c12c..66f2cd3 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -180,6 +180,12 @@
 	.pull = GPIOMUX_PULL_DOWN,
 };
 
+static struct gpiomux_setting gpio_epm_marker_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv  = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
@@ -526,6 +532,18 @@
 			[GPIOMUX_SUSPENDED] = &gpio_epm_config,
 		},
 	},
+	{
+		.gpio      = 85,		/* EPM MARKER2 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+		},
+	},
+	{
+		.gpio      = 96,		/* EPM MARKER1 */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_epm_marker_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S
index 5d25134..f8a32b4 100644
--- a/arch/arm/mach-msm/idle-v7.S
+++ b/arch/arm/mach-msm/idle-v7.S
@@ -25,6 +25,7 @@
 #ifdef CONFIG_MSM_SCM
 #define SCM_SVC_BOOT 0x1
 #define SCM_CMD_TERMINATE_PC 0x2
+#define SCM_CMD_CORE_HOTPLUGGED 0x10
 #endif
 
 ENTRY(msm_arch_idle)
@@ -99,7 +100,7 @@
 #ifdef CONFIG_MSM_SCM
 	ldr	r0, =SCM_SVC_BOOT
 	ldr	r1, =SCM_CMD_TERMINATE_PC
-	mov	r2, #0
+	ldr	r2, =SCM_CMD_CORE_HOTPLUGGED
 	bl	scm_call_atomic1
 #else
 	mrc     p15, 0, r3, c1, c0, 0    /* read current CR    */
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
index 95f33d5..ff3da11 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio_codec.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
@@ -25,7 +25,8 @@
 
 struct msm_hdmi_audio_codec_ops {
 	int (*audio_info_setup)(struct platform_device *pdev,
-		u32 num_of_channels, u32 channel_allocation, u32 level_shift,
+		u32 sample_rate, u32 num_of_channels,
+		u32 channel_allocation, u32 level_shift,
 		bool down_mix);
 	int (*get_audio_edid_blk) (struct platform_device *pdev,
 		struct msm_hdmi_audio_edid_blk *blk);
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 0de37c9..58b0513 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -742,6 +742,16 @@
 
 	fd_install(ret, lock->file);
 
+	/*
+	 * Taking a reference for lock file.
+	 * This is required as now we have two file descriptor
+	 * pointing to same file. If one FD is closed, lock file
+	 * will be closed. Taking this reference will make sure
+	 * that file doesn't get close. This refrence will go
+	 * when client will call close on this FD.
+	 */
+	fget(ret);
+
 	return ret;
 }
 EXPORT_SYMBOL(genlock_get_fd_handle);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index e316742..32a667f 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -109,6 +109,10 @@
 	.pm4_fw = NULL,
 	.wait_timeout = 0, /* in milliseconds, 0 means disabled */
 	.ib_check_level = 0,
+	.ft_policy = KGSL_FT_DEFAULT_POLICY,
+	.ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY,
+	.fast_hang_detect = 1,
+	.long_ib_detect = 1,
 };
 
 /* This set of registers are used for Hang detection
@@ -211,6 +215,8 @@
 		512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
 };
 
+static unsigned int adreno_isidle(struct kgsl_device *device);
+
 /**
  * adreno_perfcounter_init: Reserve kernel performance counters
  * @device: device to configure
@@ -818,6 +824,27 @@
 	return cmds - cmds_orig;
 }
 
+/**
+ * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu?
+ * @adreno_dev: the device
+ *
+ * In many cases it is preferable to poke the iommu or gpummu directly rather
+ * than using the GPU command stream. If we are idle or trying to go to a low
+ * power state, using the command stream will be slower and asynchronous, which
+ * needlessly complicates the power state transitions. Additionally,
+ * the hardware simulators do not support command stream MMU operations so
+ * the command stream can never be used if we are capturing CFF data.
+ *
+ */
+static bool adreno_use_default_setstate(struct adreno_device *adreno_dev)
+{
+	return (adreno_isidle(&adreno_dev->dev) ||
+		adreno_dev->drawctxt_active == NULL ||
+		KGSL_STATE_ACTIVE != adreno_dev->dev.state ||
+		atomic_read(&adreno_dev->dev.active_cnt) == 0 ||
+		adreno_dev->dev.cff_dump_enable);
+}
+
 static void adreno_iommu_setstate(struct kgsl_device *device,
 					unsigned int context_id,
 					uint32_t flags)
@@ -832,10 +859,7 @@
 	struct adreno_context *adreno_ctx = NULL;
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	if (!adreno_dev->drawctxt_active ||
-		KGSL_STATE_ACTIVE != device->state ||
-		!atomic_read(&device->active_cnt) ||
-		device->cff_dump_enable) {
+	if (adreno_use_default_setstate(adreno_dev)) {
 		kgsl_mmu_device_setstate(&device->mmu, flags);
 		return;
 	}
@@ -845,7 +869,7 @@
 	if (context == NULL)
 		return;
 
-	adreno_ctx = context->devctxt;
+	adreno_ctx = ADRENO_CONTEXT(context);
 
 	if (kgsl_mmu_enable_clk(&device->mmu,
 				KGSL_IOMMU_CONTEXT_USER))
@@ -886,8 +910,7 @@
 	adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
 			&link[0], sizedwords);
 
-	kgsl_mmu_disable_clk_on_ts(&device->mmu,
-		rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
+	kgsl_mmu_disable_clk_on_ts(&device->mmu, rb->global_ts, true);
 	kgsl_context_put(context);
 }
 
@@ -915,11 +938,11 @@
 	 * writes For CFF dump we must idle and use the registers so that it is
 	 * easier to filter out the mmu accesses from the dump
 	 */
-	if (!device->cff_dump_enable && adreno_dev->drawctxt_active) {
+	if (!adreno_use_default_setstate(adreno_dev)) {
 		context = kgsl_context_get(device, context_id);
 		if (context == NULL)
 			return;
-		adreno_ctx = context->devctxt;
+		adreno_ctx = ADRENO_CONTEXT(context);
 
 		if (flags & KGSL_MMUFLAGS_PTUPDATE) {
 			/* wait for graphics pipe to be idle */
@@ -1663,6 +1686,8 @@
 
 	adreno_debugfs_init(device);
 
+	adreno_ft_init_sysfs(device);
+
 	kgsl_pwrscale_init(device);
 	kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY);
 
@@ -1703,7 +1728,6 @@
 static int adreno_init(struct kgsl_device *device)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int i;
 
 	if (KGSL_STATE_DUMP_AND_FT != device->state)
@@ -1744,8 +1768,6 @@
 		adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver))
 		device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC;
 
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
-
 	/* Initialize ft detection register offsets */
 	ft_detect_regs[0] = adreno_getreg(adreno_dev,
 						ADRENO_REG_RBBM_STATUS);
@@ -1860,6 +1882,9 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
+	if (adreno_dev->drawctxt_active)
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
 	adreno_dev->drawctxt_active = NULL;
 
 	adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
@@ -1892,7 +1917,7 @@
 {
 	unsigned int ft_status = *((unsigned int *) data);
 	struct kgsl_context *context = ptr;
-	struct adreno_context *adreno_context = context->devctxt;
+	struct adreno_context *adreno_context = ADRENO_CONTEXT(context);
 
 	if (ft_status) {
 		context->reset_status =
@@ -1930,20 +1955,16 @@
 static int _set_max_ts(int id, void *ptr, void *data)
 {
 	struct kgsl_device *device = data;
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	struct kgsl_context *context = ptr;
-	struct adreno_context *drawctxt = context->devctxt;
+	struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
 
-	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
+	if (drawctxt && drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
 		kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id,
-			soptimestamp),
-			rb->timestamp[context->id]);
+			soptimestamp), drawctxt->timestamp);
 		kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id,
-			eoptimestamp),
-			rb->timestamp[context->id]);
+			eoptimestamp), drawctxt->timestamp);
 	}
 
 	return 0;
@@ -2199,7 +2220,7 @@
 	}
 
 	if (context) {
-		adreno_context = context->devctxt;
+		adreno_context = ADRENO_CONTEXT(context);
 		if (adreno_context->flags & CTXT_FLAGS_PREAMBLE) {
 			if (ft_data->ib1) {
 				ret = _find_hanging_ib_sequence(rb,
@@ -2266,6 +2287,9 @@
 		return -EINVAL;
 	}
 
+	if (adreno_dev->drawctxt_active)
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+
 	adreno_dev->drawctxt_active = NULL;
 
 	/* Stop the ringbuffer */
@@ -2328,11 +2352,9 @@
 	}
 
 reset_done:
-	if (context) {
-		struct adreno_context *adreno_context = context->devctxt;
-		kgsl_mmu_setstate(&device->mmu, adreno_context->pagetable,
-			KGSL_MEMSTORE_GLOBAL);
-	}
+	if (context)
+		kgsl_mmu_setstate(&device->mmu, context->pagetable,
+				KGSL_MEMSTORE_GLOBAL);
 
 	/* If iommu is used then we need to make sure that the iommu clocks
 	 * are on since there could be commands in pipeline that touch iommu */
@@ -2451,7 +2473,7 @@
 		}
 	} else {
 		no_context_ft = 0;
-		adreno_context = context->devctxt;
+		adreno_context = ADRENO_CONTEXT(context);
 		adreno_context->flags |= CTXT_FLAGS_GPU_HANG;
 		/*
 		 * set the invalid ts flag to 0 for this context since we have
@@ -2507,16 +2529,16 @@
 		goto play_good_cmds;
 	}
 
-	/* Do not try the reply if hang is due to a pagefault */
-	if (adreno_context && adreno_context->pagefault) {
+	/* Do not try to replay if hang is due to a pagefault */
+	if (context && test_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv)) {
 		/* Resume MMU */
 		mmu->mmu_ops->mmu_pagefault_resume(mmu);
-		if ((ft_data->context_id == adreno_context->id) &&
-			(ft_data->global_eop == adreno_context->pagefault_ts)) {
+		if ((ft_data->context_id == context->id) &&
+			(ft_data->global_eop == context->pagefault_ts)) {
 			ft_data->ft_policy &= ~KGSL_FT_REPLAY;
 			KGSL_FT_ERR(device, "MMU fault skipping replay\n");
 		}
-		adreno_context->pagefault = 0;
+		clear_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
 	}
 
 	if (ft_data->ft_policy & KGSL_FT_REPLAY) {
@@ -2604,6 +2626,10 @@
 			adreno_context->flags = (adreno_context->flags &
 				~CTXT_FLAGS_GPU_HANG) | CTXT_FLAGS_GPU_HANG_FT;
 		}
+
+		if (last_active_ctx)
+			_kgsl_context_get(&last_active_ctx->base);
+
 		adreno_dev->drawctxt_active = last_active_ctx;
 	}
 
@@ -2631,10 +2657,7 @@
 		struct kgsl_context *last_ctx = kgsl_context_get(device,
 			ft_data->last_valid_ctx_id);
 
-		if (last_ctx)
-			adreno_dev->drawctxt_active = last_ctx->devctxt;
-
-		kgsl_context_put(last_ctx);
+		adreno_dev->drawctxt_active = ADRENO_CONTEXT(last_ctx);
 	}
 
 done:
@@ -2653,7 +2676,6 @@
 	int ret = 0;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	unsigned int timestamp;
 
 	/*
 	 * If GPU FT is turned off do not run FT.
@@ -2670,8 +2692,8 @@
 	"Bad context_id: %u, global_eop: 0x%x\n",
 	ft_data->ib1, ft_data->context_id, ft_data->global_eop);
 
-	timestamp = rb->timestamp[KGSL_MEMSTORE_GLOBAL];
-	KGSL_FT_INFO(device, "Last issued global timestamp: %x\n", timestamp);
+	KGSL_FT_INFO(device, "Last issued global timestamp: %x\n",
+			rb->global_ts);
 
 	/* We may need to replay commands multiple times based on whether
 	 * multiple contexts hang the GPU */
@@ -2700,14 +2722,12 @@
 	/* Restore correct states after fault tolerance */
 	if (adreno_dev->drawctxt_active)
 		device->mmu.hwpagetable =
-			adreno_dev->drawctxt_active->pagetable;
+			adreno_dev->drawctxt_active->base.pagetable;
 	else
 		device->mmu.hwpagetable = device->mmu.defaultpagetable;
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL] = timestamp;
 	kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
-			eoptimestamp),
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			eoptimestamp), rb->global_ts);
 
 	/* switch to NULL ctxt */
 	if (adreno_dev->drawctxt_active != NULL)
@@ -2798,6 +2818,264 @@
 }
 EXPORT_SYMBOL(adreno_dump_and_exec_ft);
 
+/**
+ * _ft_sysfs_store() -  Common routine to write to FT sysfs files
+ * @buf: value to write
+ * @count: size of the value to write
+ * @sysfs_cfg: KGSL FT sysfs config to write
+ *
+ * This is a common routine to write to FT sysfs files.
+ */
+static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr)
+{
+	char temp[20];
+	unsigned long val;
+	int rc;
+
+	snprintf(temp, sizeof(temp), "%.*s",
+			 (int)min(count, sizeof(temp) - 1), buf);
+	rc = kstrtoul(temp, 0, &val);
+	if (rc)
+		return rc;
+
+	*ptr = val;
+
+	return count;
+}
+
+/**
+ * _get_adreno_dev() -  Routine to get a pointer to adreno dev
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ */
+struct adreno_device *_get_adreno_dev(struct device *dev)
+{
+	struct kgsl_device *device = kgsl_device_from_dev(dev);
+	return device ? ADRENO_DEVICE(device) : NULL;
+}
+
+/**
+ * _ft_policy_store() -  Routine to configure FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT policy can be set to any of the options below.
+ * KGSL_FT_DISABLE -> BIT(0) Set to disable FT
+ * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
+ * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
+ * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
+ * by default set FT policy to KGSL_FT_DEFAULT_POLICY
+ */
+static int _ft_policy_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+}
+
+/**
+ * _ft_policy_show() -  Routine to read FT policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT policy
+ */
+static int _ft_policy_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy);
+}
+
+/**
+ * _ft_pagefault_policy_store() -  Routine to configure FT
+ * pagefault policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * FT pagefault policy can be set to any of the options below.
+ * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
+ * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE  -> BIT(1) Set to enable GPU HALT on
+ * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE  -> BIT(2) Set to log only one
+ * pagefault per page.
+ * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
+ * pagefault per INT.
+ */
+static int _ft_pagefault_policy_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+}
+
+/**
+ * _ft_pagefault_policy_show() -  Routine to read FT pagefault
+ * policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ *
+ * This is a routine to read current FT pagefault policy
+ */
+static int _ft_pagefault_policy_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy);
+}
+
+/**
+ * _ft_fast_hang_detect_store() -  Routine to configure FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x1 - Enable fast hang detection
+ * 0x0 - Disable fast hang detection
+ */
+static int _ft_fast_hang_detect_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+
+}
+
+/**
+ * _ft_fast_hang_detect_show() -  Routine to read FT fast
+ * hang detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_fast_hang_detect_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				(adreno_dev->fast_hang_detect ? 1 : 0));
+}
+
+/**
+ * _ft_long_ib_detect_store() -  Routine to configure FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ *
+ * 0x0 - Enable long IB detection
+ * 0x1 - Disable long IB detection
+ */
+static int _ft_long_ib_detect_store(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	int ret;
+	if (adreno_dev == NULL)
+		return 0;
+
+	mutex_lock(&adreno_dev->dev.mutex);
+	ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect);
+	mutex_unlock(&adreno_dev->dev.mutex);
+
+	return ret;
+
+}
+
+/**
+ * _ft_long_ib_detect_show() -  Routine to read FT long IB
+ * detect policy
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static int _ft_long_ib_detect_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+	if (adreno_dev == NULL)
+		return 0;
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+				(adreno_dev->long_ib_detect ? 1 : 0));
+}
+
+
+#define FT_DEVICE_ATTR(name) \
+	DEVICE_ATTR(name, 0644,	_ ## name ## _show, _ ## name ## _store);
+
+FT_DEVICE_ATTR(ft_policy);
+FT_DEVICE_ATTR(ft_pagefault_policy);
+FT_DEVICE_ATTR(ft_fast_hang_detect);
+FT_DEVICE_ATTR(ft_long_ib_detect);
+
+
+const struct device_attribute *ft_attr_list[] = {
+	&dev_attr_ft_policy,
+	&dev_attr_ft_pagefault_policy,
+	&dev_attr_ft_fast_hang_detect,
+	&dev_attr_ft_long_ib_detect,
+	NULL,
+};
+
+int adreno_ft_init_sysfs(struct kgsl_device *device)
+{
+	return kgsl_create_device_sysfs_files(device->dev, ft_attr_list);
+}
+
+void adreno_ft_uninit_sysfs(struct kgsl_device *device)
+{
+	kgsl_remove_device_sysfs_files(device->dev, ft_attr_list);
+}
+
 static int adreno_getproperty(struct kgsl_device *device,
 				enum kgsl_property_type type,
 				void *value,
@@ -2942,20 +3220,15 @@
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
-	unsigned long wait;
+	unsigned long wait = jiffies;
 	unsigned long timeout = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
 	unsigned int rptr;
 
-	/*
-	 * The first time into the loop, wait for 100 msecs and kick wptr again
-	 * to ensure that the hardware has updated correctly.  After that, kick
-	 * it periodically every KGSL_TIMEOUT_PART msecs until the timeout
-	 * expires
-	 */
-
-	wait = jiffies + msecs_to_jiffies(100);
-
 	do {
+		/*
+		 * Wait is "jiffies" first time in the loop to start
+		 * GPU stall detection immediately.
+		 */
 		if (time_after(jiffies, wait)) {
 			/* Check to see if the core is hung */
 			if (adreno_ft_detect(device, regs))
@@ -2977,11 +3250,10 @@
 /* Caller must hold the device mutex. */
 int adreno_idle(struct kgsl_device *device)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	unsigned int rbbm_status;
 	unsigned long wait_time;
 	unsigned long wait_time_part;
 	unsigned int prev_reg_val[FT_DETECT_REGS_COUNT];
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	memset(prev_reg_val, 0, sizeof(prev_reg_val));
 
@@ -2999,23 +3271,15 @@
 	wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
 
 	while (time_before(jiffies, wait_time)) {
-		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS,
-					&rbbm_status);
-		if (adreno_is_a2xx(adreno_dev)) {
-			if (rbbm_status == 0x110)
-				return 0;
-		} else {
-			if (!(rbbm_status & 0x80000000))
-				return 0;
-		}
+		if (adreno_isidle(device))
+			return 0;
 
-		/* Dont wait for timeout, detect hang faster.
-		 */
+		/* Dont wait for timeout, detect hang faster.  */
 		if (time_after(jiffies, wait_time_part)) {
-				wait_time_part = jiffies +
-					msecs_to_jiffies(KGSL_TIMEOUT_PART);
-				if ((adreno_ft_detect(device, prev_reg_val)))
-					goto err;
+			wait_time_part = jiffies +
+				msecs_to_jiffies(KGSL_TIMEOUT_PART);
+			if ((adreno_ft_detect(device, prev_reg_val)))
+				goto err;
 		}
 
 	}
@@ -3064,9 +3328,8 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	WARN_ON(device->state == KGSL_STATE_INIT);
 	/* If the device isn't active, don't force it on. */
-	if (device->state == KGSL_STATE_ACTIVE) {
+	if (kgsl_pwrctrl_isenabled(device)) {
 		/* Is the ring buffer is empty? */
 		unsigned int rptr = adreno_get_rptr(rb);
 		if (rptr == rb->wptr) {
@@ -3109,21 +3372,20 @@
 	phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size)
 {
 	struct kgsl_context *context;
-	struct adreno_context *adreno_context = NULL;
 	int next = 0;
 	struct kgsl_memdesc *desc = NULL;
 
-
 	read_lock(&device->context_lock);
 	while (1) {
 		context = idr_get_next(&device->context_idr, &next);
 		if (context == NULL)
 			break;
 
-		adreno_context = (struct adreno_context *)context->devctxt;
-
-		if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
+		if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable,
 					pt_base)) {
+			struct adreno_context *adreno_context;
+
+			adreno_context = ADRENO_CONTEXT(context);
 			desc = &adreno_context->gpustate;
 			if (kgsl_gpuaddr_in_memdesc(desc, gpuaddr, size))
 				break;
@@ -3257,9 +3519,10 @@
 static unsigned int _get_context_id(struct kgsl_context *k_ctxt)
 {
 	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
+
 	if (k_ctxt != NULL) {
-		struct adreno_context *a_ctxt = k_ctxt->devctxt;
-		if (k_ctxt->id == KGSL_CONTEXT_INVALID || a_ctxt == NULL)
+		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+		if (kgsl_context_detached(k_ctxt))
 			context_id = KGSL_CONTEXT_INVALID;
 		else if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
 			context_id = k_ctxt->id;
@@ -3330,7 +3593,8 @@
 		 */
 
 		if (context && device->state != KGSL_STATE_SLUMBER) {
-			adreno_ringbuffer_issuecmds(device, context->devctxt,
+			adreno_ringbuffer_issuecmds(device,
+					ADRENO_CONTEXT(context),
 					KGSL_CMD_FLAGS_GET_INT, NULL, 0);
 		}
 	}
@@ -3390,6 +3654,7 @@
 	unsigned int curr_context_id = 0;
 	static struct adreno_context *curr_context;
 	static struct kgsl_context *context;
+	static char pid_name[TASK_COMM_LEN] = "unknown";
 
 	if (!adreno_dev->fast_hang_detect)
 		fast_hang_detected = 0;
@@ -3402,7 +3667,7 @@
 
 	if (is_adreno_rbbm_status_idle(device) &&
 		(kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED)
-		== rb->timestamp[KGSL_MEMSTORE_GLOBAL])) {
+		 == rb->global_ts)) {
 
 		/*
 		 * On A2XX if the RPTR != WPTR and the device is idle, then
@@ -3453,8 +3718,13 @@
 
 	if (curr_global_ts == prev_global_ts) {
 
-		/* Get the current context here */
-		if (context == NULL) {
+		/* If we don't already have a good context, get it. */
+		if (kgsl_context_detached(context)) {
+			kgsl_context_put(context);
+			context = NULL;
+			curr_context = NULL;
+			strlcpy(pid_name, "unknown", sizeof(pid_name));
+
 			kgsl_sharedmem_readl(&device->memstore,
 				&curr_context_id,
 				KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
@@ -3464,8 +3734,12 @@
 
 			context = kgsl_context_get(device, curr_context_id);
 			if (context != NULL) {
-				curr_context = context->devctxt;
+				struct task_struct *task;
+				curr_context = ADRENO_CONTEXT(context);
 				curr_context->ib_gpu_time_used = 0;
+				task = find_task_by_vpid(context->pid);
+				if (task)
+					get_task_comm(pid_name, task);
 			} else {
 				KGSL_DRV_ERR(device,
 					"Fault tolerance no context found\n");
@@ -3489,8 +3763,7 @@
 			KGSL_FT_ERR(device,
 				"Proc %s, ctxt_id %d ts %d triggered fault tolerance"
 				" on global ts %d\n",
-				curr_context ? curr_context->pid_name : "",
-				curr_context ? curr_context->id : 0,
+				pid_name, context ? context->id : 0,
 				(kgsl_readtimestamp(device, context,
 				KGSL_TIMESTAMP_RETIRED) + 1),
 				curr_global_ts + 1);
@@ -3502,7 +3775,7 @@
 			curr_context->ib_gpu_time_used += KGSL_TIMEOUT_PART;
 			KGSL_FT_INFO(device,
 			"Proc %s used GPU Time %d ms on timestamp 0x%X\n",
-			curr_context->pid_name, curr_context->ib_gpu_time_used,
+			pid_name, curr_context->ib_gpu_time_used,
 			curr_global_ts+1);
 
 			if ((long_ib_detected) &&
@@ -3518,8 +3791,7 @@
 						"Proc %s, ctxt_id %d ts %d"
 						"used GPU for %d ms long ib "
 						"detected on global ts %d\n",
-						curr_context->pid_name,
-						curr_context->id,
+						pid_name, context->id,
 						(kgsl_readtimestamp(device,
 						context,
 						KGSL_TIMESTAMP_RETIRED)+1),
@@ -3541,6 +3813,7 @@
 		kgsl_context_put(context);
 		context = NULL;
 		curr_context = NULL;
+		strlcpy(pid_name, "unknown", sizeof(pid_name));
 		adreno_dev->long_ib = 0;
 		adreno_dev->long_ib_ts = 0;
 	}
@@ -3563,7 +3836,7 @@
 	if (context_id == KGSL_CONTEXT_INVALID)
 		return -EINVAL;
 
-	ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
+	ts_issued = adreno_context_timestamp(context, &adreno_dev->ringbuffer);
 
 	if (timestamp_cmp(timestamp, ts_issued) <= 0)
 		return 0;
@@ -3598,7 +3871,8 @@
 				unsigned int msecs)
 {
 	static unsigned int io_cnt;
-	struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
+	struct adreno_context *adreno_ctx = context ? ADRENO_CONTEXT(context) :
+		NULL;
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	unsigned int context_id = _get_context_id(context);
 	unsigned int time_elapsed = 0;
@@ -3606,8 +3880,6 @@
 	int ts_compare = 1;
 	int io, ret = -ETIMEDOUT;
 
-	/* Get out early if the context has already been destroyed */
-
 	if (context_id == KGSL_CONTEXT_INVALID) {
 		KGSL_DRV_WARN(device, "context was detached");
 		return -EINVAL;
@@ -3745,9 +4017,9 @@
 	switch (type) {
 	case KGSL_TIMESTAMP_QUEUED: {
 		struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-		timestamp = rb->timestamp[context_id];
+		timestamp = adreno_context_timestamp(context,
+				&adreno_dev->ringbuffer);
 		break;
 	}
 	case KGSL_TIMESTAMP_CONSUMED:
@@ -3919,6 +4191,7 @@
 	/* Optional functions */
 	.setstate = adreno_setstate,
 	.drawctxt_create = adreno_drawctxt_create,
+	.drawctxt_detach = adreno_drawctxt_detach,
 	.drawctxt_destroy = adreno_drawctxt_destroy,
 	.setproperty = adreno_setproperty,
 	.postmortem_dump = adreno_dump,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b53d16f..cb75b34 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -25,6 +25,9 @@
 #define ADRENO_DEVICE(device) \
 		KGSL_CONTAINER_OF(device, struct adreno_device, dev)
 
+#define ADRENO_CONTEXT(device) \
+		KGSL_CONTAINER_OF(device, struct adreno_context, base)
+
 #define ADRENO_CHIPID_CORE(_id) (((_id) >> 24) & 0xFF)
 #define ADRENO_CHIPID_MAJOR(_id) (((_id) >> 16) & 0xFF)
 #define ADRENO_CHIPID_MINOR(_id) (((_id) >> 8) & 0xFF)
@@ -337,10 +340,10 @@
 #define  KGSL_FT_DEFAULT_POLICY           (KGSL_FT_REPLAY + KGSL_FT_SKIPIB)
 
 /* Pagefault policy flags */
-#define KGSL_FT_PAGEFAULT_INT_ENABLE         0x00000001
-#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE     0x00000002
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE   0x00000004
-#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT    0x00000008
+#define KGSL_FT_PAGEFAULT_INT_ENABLE         BIT(0)
+#define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE     BIT(1)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE   BIT(2)
+#define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT    BIT(3)
 #define KGSL_FT_PAGEFAULT_DEFAULT_POLICY     (KGSL_FT_PAGEFAULT_INT_ENABLE + \
 					KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
 
@@ -407,6 +410,9 @@
 unsigned int adreno_ft_detect(struct kgsl_device *device,
 						unsigned int *prev_reg_val);
 
+int adreno_ft_init_sysfs(struct kgsl_device *device);
+void adreno_ft_uninit_sysfs(struct kgsl_device *device);
+
 int adreno_perfcounter_get(struct adreno_device *adreno_dev,
 	unsigned int groupid, unsigned int countable, unsigned int *offset,
 	unsigned int flags);
@@ -501,6 +507,26 @@
 }
 
 /**
+ * adreno_context_timestamp() - Return the last queued timestamp for the context
+ * @k_ctxt: Pointer to the KGSL context to query
+ * @rb: Pointer to the ringbuffer structure for the GPU
+ *
+ * Return the last queued context for the given context. This is used to verify
+ * that incoming requests are not using an invalid (unsubmitted) timestamp
+ */
+static inline int adreno_context_timestamp(struct kgsl_context *k_ctxt,
+		struct adreno_ringbuffer *rb)
+{
+	if (k_ctxt) {
+		struct adreno_context *a_ctxt = ADRENO_CONTEXT(k_ctxt);
+
+		if (a_ctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+			return a_ctxt->timestamp;
+	}
+	return rb->global_ts;
+}
+
+/**
  * adreno_encode_istore_size - encode istore size in CP format
  * @adreno_dev - The 3D device.
  *
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 42137fe..3d72c5c 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1355,7 +1355,7 @@
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+		drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
 
 	if (result)
 		return result;
@@ -1364,7 +1364,7 @@
 	drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
 
 	/* blank out gmem shadow. */
-	kgsl_sharedmem_set(drawctxt->dev_priv->device,
+	kgsl_sharedmem_set(drawctxt->base.device,
 			&drawctxt->context_gmem_shadow.gmemshadow, 0, 0,
 			drawctxt->context_gmem_shadow.size);
 
@@ -1389,7 +1389,7 @@
 	kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
 			    KGSL_CACHE_OP_FLUSH);
 
-	kgsl_cffdump_syncmem(drawctxt->dev_priv,
+	kgsl_cffdump_syncmem(drawctxt->base.device,
 			&drawctxt->context_gmem_shadow.gmemshadow,
 			drawctxt->context_gmem_shadow.gmemshadow.gpuaddr,
 			drawctxt->context_gmem_shadow.gmemshadow.size, false);
@@ -1410,13 +1410,13 @@
 	 */
 
 	ret = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, _context_size(adreno_dev));
+		drawctxt->base.pagetable, _context_size(adreno_dev));
 
 	if (ret)
 		return ret;
 
-	kgsl_sharedmem_set(drawctxt->dev_priv->device, &drawctxt->gpustate, 0,
-		0, _context_size(adreno_dev));
+	kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate,
+		0, 0, _context_size(adreno_dev));
 
 	tmp_ctx.cmd = tmp_ctx.start
 	    = (unsigned int *)((char *)drawctxt->gpustate.hostptr + CMD_OFFSET);
@@ -1440,8 +1440,8 @@
 	kgsl_cache_range_op(&drawctxt->gpustate,
 			    KGSL_CACHE_OP_FLUSH);
 
-	kgsl_cffdump_syncmem(drawctxt->dev_priv, &drawctxt->gpustate,
-			drawctxt->gpustate.gpuaddr,
+	kgsl_cffdump_syncmem(drawctxt->base.device,
+			&drawctxt->gpustate, drawctxt->gpustate.gpuaddr,
 			drawctxt->gpustate.size, false);
 
 done:
@@ -1516,7 +1516,7 @@
 			"Current active context has caused gpu hang\n");
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->reg_save[1],
 			context->reg_save[2] << 2, true);
 		/* save registers and constants. */
@@ -1525,7 +1525,7 @@
 			context->reg_save, 3);
 
 		if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_save[1],
 				context->shader_save[2] << 2, true);
@@ -1534,7 +1534,7 @@
 				KGSL_CMD_FLAGS_PMODE,
 				context->shader_save, 3);
 
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_fixup[1],
 				context->shader_fixup[2] << 2, true);
@@ -1552,7 +1552,7 @@
 
 	if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
 	    (context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->context_gmem_shadow.gmem_save[1],
 			context->context_gmem_shadow.gmem_save[2] << 2, true);
 		/* save gmem.
@@ -1562,7 +1562,7 @@
 			KGSL_CMD_FLAGS_PMODE,
 			context->context_gmem_shadow.gmem_save, 3);
 
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->chicken_restore[1],
 			context->chicken_restore[2] << 2, true);
 
@@ -1586,9 +1586,18 @@
 	unsigned int cmds[5];
 
 	if (context == NULL) {
-		/* No context - set the default apgetable and thats it */
+		/* No context - set the default pagetable and thats it */
+		unsigned int id;
+		/*
+		 * If there isn't a current context, the kgsl_mmu_setstate
+		 * will use the CPU path so we don't need to give
+		 * it a valid context id.
+		 */
+		id = (adreno_dev->drawctxt_active != NULL)
+			? adreno_dev->drawctxt_active->base.id
+			: KGSL_CONTEXT_INVALID;
 		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
-				adreno_dev->drawctxt_active->id);
+				  id);
 		return;
 	}
 
@@ -1597,16 +1606,17 @@
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
-	cmds[4] = context->id;
+	cmds[4] = context->base.id;
 	adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
 					cmds, 5);
-	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+	kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+			context->base.id);
 
 	/* restore gmem.
 	 *  (note: changes shader. shader must not already be restored.)
 	 */
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->context_gmem_shadow.gmem_restore[1],
 			context->context_gmem_shadow.gmem_restore[2] << 2,
 			true);
@@ -1616,7 +1626,7 @@
 			context->context_gmem_shadow.gmem_restore, 3);
 
 		if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->chicken_restore[1],
 				context->chicken_restore[2] << 2, true);
@@ -1631,7 +1641,7 @@
 	}
 
 	if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-		kgsl_cffdump_syncmem(context->dev_priv, &context->gpustate,
+		kgsl_cffdump_syncmem(context->base.device, &context->gpustate,
 			context->reg_restore[1],
 			context->reg_restore[2] << 2, true);
 
@@ -1641,7 +1651,7 @@
 
 		/* restore shader instructions & partitioning. */
 		if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
-			kgsl_cffdump_syncmem(context->dev_priv,
+			kgsl_cffdump_syncmem(context->base.device,
 				&context->gpustate,
 				context->shader_restore[1],
 				context->shader_restore[2] << 2, true);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7e5638c..670f0cf 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2321,7 +2321,7 @@
 	tmp_ctx.gmem_base = adreno_dev->gmem_base;
 
 	result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
-		drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
+		drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size);
 
 	if (result)
 		return result;
@@ -2355,7 +2355,7 @@
 	 */
 
 	ret = kgsl_allocate(&drawctxt->gpustate,
-		drawctxt->pagetable, CONTEXT_SIZE);
+		drawctxt->base.pagetable, CONTEXT_SIZE);
 
 	if (ret)
 		return ret;
@@ -2420,7 +2420,7 @@
 		 * already be saved.)
 		 */
 
-		kgsl_cffdump_syncmem(context->dev_priv,
+		kgsl_cffdump_syncmem(context->base.device,
 			&context->gpustate,
 			context->context_gmem_shadow.gmem_save[1],
 			context->context_gmem_shadow.gmem_save[2] << 2, true);
@@ -2441,8 +2441,17 @@
 
 	if (context == NULL) {
 		/* No context - set the default pagetable and thats it */
+		unsigned int id;
+		/*
+		 * If there isn't a current context, the kgsl_mmu_setstate
+		 * will use the CPU path so we don't need to give
+		 * it a valid context id.
+		 */
+		id = (adreno_dev->drawctxt_active != NULL)
+			? adreno_dev->drawctxt_active->base.id
+			: KGSL_CONTEXT_INVALID;
 		kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable,
-				adreno_dev->drawctxt_active->id);
+				  id);
 		return;
 	}
 
@@ -2451,10 +2460,11 @@
 	cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2);
 	cmds[3] = device->memstore.gpuaddr +
 		KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
-	cmds[4] = context->id;
+	cmds[4] = context->base.id;
 	adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE,
 					cmds, 5);
-	kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
+	kgsl_mmu_setstate(&device->mmu, context->base.pagetable,
+			context->base.id);
 
 	/*
 	 * Restore GMEM.  (note: changes shader.
@@ -2462,7 +2472,7 @@
 	 */
 
 	if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
-		kgsl_cffdump_syncmem(context->dev_priv,
+		kgsl_cffdump_syncmem(context->base.device,
 			&context->gpustate,
 			context->context_gmem_shadow.gmem_restore[1],
 			context->context_gmem_shadow.gmem_restore[2] << 2,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 90bd017..fc98d86 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -56,41 +56,6 @@
 		&adreno_dev->wait_timeout);
 	debugfs_create_u32("ib_check", 0644, device->d_debugfs,
 			   &adreno_dev->ib_check_level);
-	/* By Default enable fast hang detection */
-	adreno_dev->fast_hang_detect = 1;
-	debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
-			   &adreno_dev->fast_hang_detect);
-	/*
-	 * FT policy can be set to any of the options below.
-	 * KGSL_FT_OFF -> BIT(0) Set to turn off FT
-	 * KGSL_FT_REPLAY  -> BIT(1) Set to enable replay
-	 * KGSL_FT_SKIPIB  -> BIT(2) Set to skip IB
-	 * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame
-	 * KGSL_FT_DISABLE -> BIT(4) Set to disable FT for faulting context
-	 * by default set FT policy to KGSL_FT_DEFAULT_POLICY
-	 */
-	adreno_dev->ft_policy = KGSL_FT_DEFAULT_POLICY;
-	debugfs_create_u32("ft_policy", 0644, device->d_debugfs,
-			   &adreno_dev->ft_policy);
-	/* By default enable long IB detection */
-	adreno_dev->long_ib_detect = 1;
-	debugfs_create_u32("long_ib_detect", 0644, device->d_debugfs,
-			   &adreno_dev->long_ib_detect);
-
-	/*
-	 * FT pagefault policy can be set to any of the options below.
-	 * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT
-	 * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE  -> BIT(1) Set to enable GPU HALT on
-	 * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW.
-	 * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE  -> BIT(2) Set to log only one
-	 * pagefault per page.
-	 * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one
-	 * pagefault per INT.
-	 */
-	 adreno_dev->ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY;
-	 debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs,
-			&adreno_dev->ft_pf_policy);
-
 	debugfs_create_file("active_cnt", 0444, device->d_debugfs, device,
 			    &_active_count_fops);
 }
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index b32cdae..bf173a7 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -134,34 +134,32 @@
 
 /**
  * adreno_drawctxt_create - create a new adreno draw context
- * @device - KGSL device to create the context on
- * @pagetable - Pagetable for the context
- * @context- Generic KGSL context structure
- * @flags - flags for the context (passed from user space)
+ * @dev_priv: the owner of the context
+ * @flags: flags for the context (passed from user space)
  *
- * Create a new draw context for the 3D core.  Return 0 on success,
- * or error code on failure.
+ * Create and return a new draw context for the 3D core.
  */
-int adreno_drawctxt_create(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context, uint32_t *flags)
+struct kgsl_context *
+adreno_drawctxt_create(struct kgsl_device_private *dev_priv,
+			uint32_t *flags)
 {
 	struct adreno_context *drawctxt;
+	struct kgsl_device *device = dev_priv->device;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
-	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 	int ret;
 
 	drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
-
 	if (drawctxt == NULL)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 
-	drawctxt->pid = task_pid_nr(current);
-	strlcpy(drawctxt->pid_name, current->comm, TASK_COMM_LEN);
-	drawctxt->pagetable = pagetable;
+	ret = kgsl_context_init(dev_priv, &drawctxt->base);
+	if (ret != 0) {
+		kfree(drawctxt);
+		return ERR_PTR(ret);
+	}
+
 	drawctxt->bin_base_offset = 0;
-	drawctxt->id = context->id;
-	rb->timestamp[context->id] = 0;
+	drawctxt->timestamp = 0;
 
 	*flags &= (KGSL_CONTEXT_PREAMBLE |
 		KGSL_CONTEXT_NO_GMEM_ALLOC |
@@ -192,50 +190,47 @@
 
 	drawctxt->type =
 		(*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT;
-	drawctxt->dev_priv = context->dev_priv;
 
 	ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt);
 	if (ret)
 		goto err;
 
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ref_wait_ts),
 			KGSL_INIT_REFTIMESTAMP);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, ts_cmp_enable),
+			0);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp),
+			0);
 	kgsl_sharedmem_writel(device, &device->memstore,
-			KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
+			KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp),
+			0);
 
-	context->devctxt = drawctxt;
-	return 0;
+	return &drawctxt->base;
 err:
-	kfree(drawctxt);
-	return ret;
+	kgsl_context_put(&drawctxt->base);
+	return ERR_PTR(ret);
 }
 
 /**
- * adreno_drawctxt_destroy - destroy a draw context
- * @device - KGSL device that owns the context
- * @context- Generic KGSL context container for the context
+ * adreno_drawctxt_detach(): detach a context from the GPU
+ * @context: Generic KGSL context container for the context
  *
- * Destroy an existing context.  Return 0 on success or error
- * code on failure.
  */
-
-/* destroy a drawing context */
-
-void adreno_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context)
+void adreno_drawctxt_detach(struct kgsl_context *context)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct kgsl_device *device;
+	struct adreno_device *adreno_dev;
 	struct adreno_context *drawctxt;
 
-	if (context == NULL || context->devctxt == NULL)
+	if (context == NULL)
 		return;
 
-	drawctxt = context->devctxt;
+	device = context->device;
+	adreno_dev = ADRENO_DEVICE(device);
+	drawctxt = ADRENO_CONTEXT(context);
 	/* deactivate context */
 	if (adreno_dev->drawctxt_active == drawctxt) {
 		/* no need to save GMEM or shader, the context is
@@ -256,9 +251,17 @@
 
 	kgsl_sharedmem_free(&drawctxt->gpustate);
 	kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
+}
 
+
+void adreno_drawctxt_destroy(struct kgsl_context *context)
+{
+	struct adreno_context *drawctxt;
+	if (context == NULL)
+		return;
+
+	drawctxt = ADRENO_CONTEXT(context);
 	kfree(drawctxt);
-	context->devctxt = NULL;
 }
 
 /**
@@ -274,10 +277,12 @@
 				      struct kgsl_context *context,
 				      unsigned int offset)
 {
-	struct adreno_context *drawctxt = context->devctxt;
+	struct adreno_context *drawctxt;
 
-	if (drawctxt)
-		drawctxt->bin_base_offset = offset;
+	if (context == NULL)
+		return;
+	drawctxt = ADRENO_CONTEXT(context);
+	drawctxt->bin_base_offset = offset;
 }
 
 /**
@@ -316,12 +321,22 @@
 
 	KGSL_CTXT_INFO(device, "from %d to %d flags %d\n",
 		adreno_dev->drawctxt_active ?
-		adreno_dev->drawctxt_active->id : 0,
-		drawctxt ? drawctxt->id : 0, flags);
+		adreno_dev->drawctxt_active->base.id : 0,
+		drawctxt ? drawctxt->base.id : 0, flags);
 
 	/* Save the old context */
 	adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active);
 
+	/* Put the old instance of the active drawctxt */
+	if (adreno_dev->drawctxt_active) {
+		kgsl_context_put(&adreno_dev->drawctxt_active->base);
+		adreno_dev->drawctxt_active = NULL;
+	}
+
+	/* Get a refcount to the new instance */
+	if (drawctxt)
+		_kgsl_context_get(&drawctxt->base);
+
 	/* Set the new context */
 	adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt);
 	adreno_dev->drawctxt_active = drawctxt;
diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h
index 2b8e600..88d1b8c 100644
--- a/drivers/gpu/msm/adreno_drawctxt.h
+++ b/drivers/gpu/msm/adreno_drawctxt.h
@@ -13,8 +13,6 @@
 #ifndef __ADRENO_DRAWCTXT_H
 #define __ADRENO_DRAWCTXT_H
 
-#include <linux/sched.h>
-
 #include "adreno_pm4types.h"
 #include "a2xx_reg.h"
 
@@ -96,15 +94,11 @@
 };
 
 struct adreno_context {
-	pid_t pid;
-	char pid_name[TASK_COMM_LEN];
-	unsigned int id;
+	struct kgsl_context base;
 	unsigned int ib_gpu_time_used;
+	unsigned int timestamp;
 	uint32_t flags;
-	uint32_t pagefault;
-	unsigned long pagefault_ts;
 	unsigned int type;
-	struct kgsl_pagetable *pagetable;
 	struct kgsl_memdesc gpustate;
 	unsigned int reg_restore[3];
 	unsigned int shader_save[3];
@@ -131,16 +125,15 @@
 	struct kgsl_memdesc constant_load_commands[3];
 	struct kgsl_memdesc cond_execs[4];
 	struct kgsl_memdesc hlsqcontrol_restore_commands[1];
-	struct kgsl_device_private *dev_priv;
 };
 
-int adreno_drawctxt_create(struct kgsl_device *device,
-			struct kgsl_pagetable *pagetable,
-			struct kgsl_context *context,
+
+struct kgsl_context *adreno_drawctxt_create(struct kgsl_device_private *,
 			uint32_t *flags);
 
-void adreno_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context);
+void adreno_drawctxt_detach(struct kgsl_context *context);
+
+void adreno_drawctxt_destroy(struct kgsl_context *context);
 
 void adreno_drawctxt_switch(struct adreno_device *adreno_dev,
 				struct adreno_context *drawctxt,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index f6c05b5..999b782 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -138,7 +138,7 @@
 			if (context && context->flags & CTXT_FLAGS_GPU_HANG) {
 				KGSL_CTXT_WARN(rb->device,
 				"Context %p caused a gpu hang. Will not accept commands for context %d\n",
-				context, context->id);
+				context, context->base.id);
 				return -EDEADLK;
 			}
 			wait_time = jiffies + wait_timeout;
@@ -575,6 +575,8 @@
 	/* overlay structure on memptrs memory */
 	rb->memptrs = (struct kgsl_rbmemptrs *) rb->memptrs_desc.hostptr;
 
+	rb->global_ts = 0;
+
 	return 0;
 }
 
@@ -594,11 +596,11 @@
 	memset(rb, 0, sizeof(struct adreno_ringbuffer));
 }
 
-static uint32_t
+static int
 adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb,
 				struct adreno_context *context,
 				unsigned int flags, unsigned int *cmds,
-				int sizedwords, uint32_t timestamp)
+				int sizedwords)
 {
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
 	unsigned int *ringcmds;
@@ -607,6 +609,7 @@
 	unsigned int rcmd_gpu;
 	unsigned int context_id = KGSL_MEMSTORE_GLOBAL;
 	unsigned int gpuaddr = rb->device->memstore.gpuaddr;
+	unsigned int timestamp;
 
 	/*
 	 * if the context was not created with per context timestamp
@@ -616,20 +619,7 @@
 	 */
 	if ((context && (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)) &&
 		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE))
-		context_id = context->id;
-
-	if ((context && (context->flags & CTXT_FLAGS_USER_GENERATED_TS)) &&
-		!(flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) {
-		if (timestamp_cmp(rb->timestamp[context_id],
-						timestamp) >= 0) {
-			KGSL_DRV_ERR(rb->device,
-				"Invalid user generated ts <%d:0x%x>, "
-				"less than last issued ts <%d:0x%x>\n",
-				context_id, timestamp, context_id,
-				rb->timestamp[context_id]);
-			return -ERANGE;
-		}
-	}
+		context_id = context->base.id;
 
 	/* reserve space to temporarily turn off protected mode
 	*  error checking if needed
@@ -669,13 +659,8 @@
 		total_sizedwords += 2;
 
 	ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
-	if (!ringcmds) {
-		/*
-		 * We could not allocate space in ringbuffer, just return the
-		 * last timestamp
-		 */
-		return rb->timestamp[context_id];
-	}
+	if (!ringcmds)
+		return -ENOSPC;
 
 	rcmd_gpu = rb->buffer_desc.gpuaddr
 		+ sizeof(uint)*(rb->wptr-total_sizedwords);
@@ -690,26 +675,19 @@
 	}
 
 	/* always increment the global timestamp. once. */
-	rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
+	rb->global_ts++;
 
-	/*
-	 * If global timestamp then we are not using per context ts for
-	 * this submission
-	 */
-	if (context_id != KGSL_MEMSTORE_GLOBAL) {
-		if (context->flags & CTXT_FLAGS_USER_GENERATED_TS)
-			rb->timestamp[context_id] = timestamp;
-		else
-			rb->timestamp[context_id]++;
-	}
-	timestamp = rb->timestamp[context_id];
+	if (KGSL_MEMSTORE_GLOBAL != context_id)
+		timestamp = context->timestamp;
+	else
+		timestamp = rb->global_ts;
 
 	/* scratchpad ts for fault tolerance */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
 		cp_type0_packet(adreno_getreg(adreno_dev,
 			ADRENO_REG_CP_TIMESTAMP), 1));
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			rb->global_ts);
 
 	/* start-of-pipeline timestamp */
 	GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
@@ -781,7 +759,7 @@
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 				eoptimestamp)));
 		GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu,
-			rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+			rb->global_ts);
 	}
 
 	if (adreno_is_a20x(adreno_dev)) {
@@ -857,7 +835,7 @@
 
 	adreno_ringbuffer_submit(rb);
 
-	return timestamp;
+	return 0;
 }
 
 unsigned int
@@ -877,7 +855,7 @@
 	flags |= KGSL_CMD_FLAGS_INTERNAL_ISSUE;
 
 	return adreno_ringbuffer_addcmds(rb, drawctxt, flags, cmds,
-							sizedwords, 0);
+							sizedwords);
 }
 
 static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
@@ -1097,12 +1075,9 @@
 		ret = -EINVAL;
 		goto done;
 	}
-	drawctxt = context->devctxt;
+	drawctxt = ADRENO_CONTEXT(context);
 
 	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG) {
-		KGSL_CTXT_ERR(device, "proc %s failed fault tolerance"
-			" will not accept commands for context %d\n",
-			drawctxt->pid_name, drawctxt->id);
 		ret = -EDEADLK;
 		goto done;
 	}
@@ -1116,10 +1091,6 @@
 		start_index = 1;
 
 	if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) {
-		KGSL_CTXT_ERR(device,
-			"proc %s triggered fault tolerance"
-			" skipping commands for context till EOF %d\n",
-			drawctxt->pid_name, drawctxt->id);
 		if (flags & KGSL_CMD_FLAGS_EOF)
 			drawctxt->flags &= ~CTXT_FLAGS_SKIP_EOF;
 		if (start_index)
@@ -1172,10 +1143,30 @@
 
 	adreno_drawctxt_switch(adreno_dev, drawctxt, flags);
 
-	*timestamp = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
+	if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
+		if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
+			KGSL_DRV_ERR(device,
+				"Invalid user generated ts <%d:0x%x>, "
+				"less than last issued ts <%d:0x%x>\n",
+				context->id, *timestamp, context->id,
+				drawctxt->timestamp);
+			return -ERANGE;
+		}
+		drawctxt->timestamp = *timestamp;
+	} else
+		drawctxt->timestamp++;
+
+	ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
 					drawctxt,
 					(flags & KGSL_CMD_FLAGS_EOF),
-					&link[0], (cmds - link), *timestamp);
+					&link[0], (cmds - link));
+	if (ret)
+		goto done;
+
+	if (drawctxt->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+		*timestamp = drawctxt->timestamp;
+	else
+		*timestamp = adreno_dev->ringbuffer.global_ts;
 
 #ifdef CONFIG_MSM_KGSL_CFF_DUMP
 	/*
@@ -1282,7 +1273,7 @@
 	k_ctxt = kgsl_context_get(device, ft_data->context_id);
 
 	if (k_ctxt) {
-		a_ctxt = k_ctxt->devctxt;
+		a_ctxt = ADRENO_CONTEXT(k_ctxt);
 		if (a_ctxt->flags & CTXT_FLAGS_PREAMBLE)
 			_turn_preamble_on_for_ib_seq(rb, rb_rptr);
 		kgsl_context_put(k_ctxt);
@@ -1319,7 +1310,7 @@
 			k_ctxt = kgsl_context_get(rb->device, val2);
 
 			if (k_ctxt) {
-				a_ctxt = k_ctxt->devctxt;
+				a_ctxt = ADRENO_CONTEXT(k_ctxt);
 
 			/* If we are changing to a good context and were not
 			 * copying commands then copy over commands to the good
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index e9fb050..9634e32 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -55,7 +55,7 @@
 
 	unsigned int wptr; /* write pointer offset in dwords from baseaddr */
 
-	unsigned int timestamp[KGSL_MEMSTORE_MAX];
+	unsigned int global_ts;
 };
 
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4c1ef54..966e035 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -448,20 +448,24 @@
 	entry->priv = NULL;
 }
 
-/* Allocate a new context id */
-
-static struct kgsl_context *
-kgsl_create_context(struct kgsl_device_private *dev_priv)
+/**
+ * kgsl_context_init() - helper to initialize kgsl_context members
+ * @dev_priv: the owner of the context
+ * @context: the newly created context struct, should be allocated by
+ * the device specific drawctxt_create function.
+ *
+ * This is a helper function for the device specific drawctxt_create
+ * function to initialize the common members of its context struct.
+ * If this function succeeds, reference counting is active in the context
+ * struct and the caller should kgsl_context_put() it on error.
+ * If it fails, the caller should just free the context structure
+ * it passed in.
+ */
+int kgsl_context_init(struct kgsl_device_private *dev_priv,
+			struct kgsl_context *context)
 {
+	int ret = 0, id;
 	struct kgsl_device *device = dev_priv->device;
-	struct kgsl_context *context;
-	int ret, id = 0;
-
-	context = kzalloc(sizeof(*context), GFP_KERNEL);
-
-	if (context == NULL)
-		return ERR_PTR(-ENOMEM);
-
 
 	while (1) {
 		if (idr_pre_get(&device->context_idr, GFP_KERNEL) == 0) {
@@ -480,30 +484,26 @@
 	}
 
 	if (ret)
-		goto func_end;
+		goto fail;
 
 	/* MAX - 1, there is one memdesc in memstore for device info */
 	if (id >= KGSL_MEMSTORE_MAX) {
 		KGSL_DRV_INFO(device, "cannot have more than %d "
 				"ctxts due to memstore limitation\n",
 				KGSL_MEMSTORE_MAX);
-		write_lock(&device->context_lock);
-		idr_remove(&device->context_idr, id);
-		write_unlock(&device->context_lock);
 		ret = -ENOSPC;
-		goto func_end;
+		goto fail_free_id;
 	}
 
 	kref_init(&context->refcount);
-	context->dev_priv = dev_priv;
+	context->device = dev_priv->device;
+	context->pagetable = dev_priv->process_priv->pagetable;
+
+	context->pid = dev_priv->process_priv->pid;
 
 	ret = kgsl_sync_timeline_create(context);
-	if (ret) {
-		write_lock(&device->context_lock);
-		idr_remove(&dev_priv->device->context_idr, id);
-		write_unlock(&device->context_lock);
-		goto func_end;
-	}
+	if (ret)
+		goto fail_free_id;
 
 	/* Initialize the pending event list */
 	INIT_LIST_HEAD(&context->events);
@@ -518,15 +518,15 @@
 	 */
 
 	INIT_LIST_HEAD(&context->events_list);
-
-func_end:
-	if (ret) {
-		kfree(context);
-		return ERR_PTR(ret);
-	}
-
-	return context;
+	return 0;
+fail_free_id:
+	write_lock(&device->context_lock);
+	idr_remove(&dev_priv->device->context_idr, id);
+	write_unlock(&device->context_lock);
+fail:
+	return ret;
 }
+EXPORT_SYMBOL(kgsl_context_init);
 
 /**
  * kgsl_context_detach - Release the "master" context reference
@@ -536,37 +536,36 @@
  * has requested for it to be destroyed. The context itself may
  * exist a bit longer until its reference count goes to zero.
  * Other code referencing the context can detect that it has been
- * detached because the context id will be set to KGSL_CONTEXT_INVALID.
+ * detached by checking the KGSL_CONTEXT_DETACHED bit in
+ * context->priv.
  */
 void
 kgsl_context_detach(struct kgsl_context *context)
 {
-	int id;
 	struct kgsl_device *device;
 	if (context == NULL)
 		return;
-	device = context->dev_priv->device;
-	trace_kgsl_context_detach(device, context);
-	id = context->id;
 
-	if (device->ftbl->drawctxt_destroy)
-		device->ftbl->drawctxt_destroy(device, context);
-	/*device specific drawctxt_destroy MUST clean up devctxt */
-	BUG_ON(context->devctxt);
+	device = context->device;
+
+	/*
+	 * Mark the context as detached to keep others from using
+	 * the context before it gets fully removed, and to make sure
+	 * we don't try to detach twice.
+	 */
+	if (test_and_set_bit(KGSL_CONTEXT_DETACHED, &context->priv))
+		return;
+
+	trace_kgsl_context_detach(device, context);
+
+	device->ftbl->drawctxt_detach(context);
 	/*
 	 * Cancel events after the device-specific context is
-	 * destroyed, to avoid possibly freeing memory while
+	 * detached, to avoid possibly freeing memory while
 	 * it is still in use by the GPU.
 	 */
 	kgsl_cancel_events_ctxt(device, context);
 
-	write_lock(&device->context_lock);
-	context->id = KGSL_CONTEXT_INVALID;
-	idr_remove(&device->context_idr, id);
-	write_unlock(&device->context_lock);
-
-	context->dev_priv = NULL;
-
 	kgsl_context_put(context);
 }
 
@@ -575,8 +574,19 @@
 {
 	struct kgsl_context *context = container_of(kref, struct kgsl_context,
 						    refcount);
+	struct kgsl_device *device = context->device;
+
+	trace_kgsl_context_destroy(device, context);
+
+	write_lock(&device->context_lock);
+	if (context->id != KGSL_CONTEXT_INVALID) {
+		idr_remove(&device->context_idr, context->id);
+		context->id = KGSL_CONTEXT_INVALID;
+	}
+	write_unlock(&device->context_lock);
 	kgsl_sync_timeline_destroy(context);
-	kfree(context);
+
+	device->ftbl->drawctxt_destroy(context);
 }
 
 struct kgsl_device *kgsl_get_device(int dev_idx)
@@ -975,7 +985,7 @@
 		if (context == NULL)
 			break;
 
-		if (context->dev_priv == dev_priv)
+		if (context->pid == private->pid)
 			kgsl_context_detach(context);
 
 		next = next + 1;
@@ -1623,27 +1633,16 @@
 	int result = 0;
 	struct kgsl_drawctxt_create *param = data;
 	struct kgsl_context *context = NULL;
+	struct kgsl_device *device = dev_priv->device;
 
-	context = kgsl_create_context(dev_priv);
-
+	context = device->ftbl->drawctxt_create(dev_priv, &param->flags);
 	if (IS_ERR(context)) {
 		result = PTR_ERR(context);
 		goto done;
 	}
-
-	if (dev_priv->device->ftbl->drawctxt_create) {
-		result = dev_priv->device->ftbl->drawctxt_create(
-			dev_priv->device, dev_priv->process_priv->pagetable,
-			context, &param->flags);
-		if (result)
-			goto done;
-	}
 	trace_kgsl_context_create(dev_priv->device, context, param->flags);
 	param->drawctxt_id = context->id;
 done:
-	if (result && !IS_ERR(context))
-		kgsl_context_detach(context);
-
 	return result;
 }
 
@@ -2600,7 +2599,7 @@
 	if (!entry)
 		return -EINVAL;
 
-	kgsl_cffdump_syncmem(dev_priv, &entry->memdesc, param->gpuaddr,
+	kgsl_cffdump_syncmem(dev_priv->device, &entry->memdesc, param->gpuaddr,
 			     param->len, true);
 
 	kgsl_mem_entry_put(entry);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index b07a1cad..43bcc30 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -410,29 +410,19 @@
 	cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5);
 }
 
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
-	struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
-	bool clean_cache)
+void kgsl_cffdump_syncmem(struct kgsl_device *device,
+			  struct kgsl_memdesc *memdesc, uint gpuaddr,
+			  uint sizebytes, bool clean_cache)
 {
-	struct kgsl_device *device = dev_priv->device;
 	const void *src;
 
 	if (!device->cff_dump_enable)
 		return;
 
+	BUG_ON(memdesc == NULL);
+
 	total_syncmem += sizebytes;
 
-	if (memdesc == NULL) {
-		struct kgsl_mem_entry *entry;
-		entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
-			gpuaddr, sizebytes);
-		if (entry == NULL) {
-			KGSL_CORE_ERR("did not find mapping "
-				"for gpuaddr: 0x%08x\n", gpuaddr);
-			return;
-		}
-		memdesc = &entry->memdesc;
-	}
 	src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
 	if (memdesc->hostptr == NULL) {
 		KGSL_CORE_ERR(
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index ab5a345..2852e0f 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -28,7 +28,7 @@
 void kgsl_cffdump_destroy(void);
 void kgsl_cffdump_open(struct kgsl_device *device);
 void kgsl_cffdump_close(struct kgsl_device *device);
-void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+void kgsl_cffdump_syncmem(struct kgsl_device *,
 	struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 	bool clean_cache);
 void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr,
@@ -74,7 +74,7 @@
 	return;
 }
 
-static inline void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
+static inline void kgsl_cffdump_syncmem(struct kgsl_device *device,
 		struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
 		bool clean_cache)
 {
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index d0e40db..1f8bcbe 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -15,6 +15,7 @@
 
 #include <linux/idr.h>
 #include <linux/pm_qos.h>
+#include <linux/sched.h>
 
 #include "kgsl.h"
 #include "kgsl_mmu.h"
@@ -103,11 +104,10 @@
 	   calling the hook */
 	void (*setstate) (struct kgsl_device *device, unsigned int context_id,
 			uint32_t flags);
-	int (*drawctxt_create) (struct kgsl_device *device,
-		struct kgsl_pagetable *pagetable, struct kgsl_context *context,
-		uint32_t *flags);
-	void (*drawctxt_destroy) (struct kgsl_device *device,
-		struct kgsl_context *context);
+	struct kgsl_context *(*drawctxt_create) (struct kgsl_device_private *,
+						uint32_t *flags);
+	void (*drawctxt_detach) (struct kgsl_context *context);
+	void (*drawctxt_destroy) (struct kgsl_context *context);
 	long (*ioctl) (struct kgsl_device_private *dev_priv,
 		unsigned int cmd, void *data);
 	int (*setproperty) (struct kgsl_device *device,
@@ -254,31 +254,44 @@
 	.ver_minor = DRIVER_VERSION_MINOR
 
 
+/* bits for struct kgsl_context.priv */
+/* the context has been destroyed by userspace and is no longer using the gpu */
+#define KGSL_CONTEXT_DETACHED 0
+/* the context has caused a pagefault */
+#define KGSL_CONTEXT_PAGEFAULT 1
+
 /**
  * struct kgsl_context - Master structure for a KGSL context object
- * @refcount - kref object for reference counting the context
- * @id - integer identifier for the context
- * @dev_priv - pointer to the owning device instance
- * @devctxt - pointer to the device specific context information
- * @reset_status - status indication whether a gpu reset occured and whether
+ * @refcount: kref object for reference counting the context
+ * @id: integer identifier for the context
+ * @priv: in-kernel context flags, use KGSL_CONTEXT_* values
+ * @dev_priv: pointer to the owning device instance
+ * @reset_status: status indication whether a gpu reset occured and whether
  * this context was responsible for causing it
- * @wait_on_invalid_ts - flag indicating if this context has tried to wait on a
+ * @wait_on_invalid_ts: flag indicating if this context has tried to wait on a
  * bad timestamp
- * @timeline - sync timeline used to create fences that can be signaled when a
+ * @timeline: sync timeline used to create fences that can be signaled when a
  * sync_pt timestamp expires
- * @events - list head of pending events for this context
- * @events_list - list node for the list of all contexts that have pending events
+ * @events: list head of pending events for this context
+ * @events_list: list node for the list of all contexts that have pending events
+ * @pid: process that owns this context.
+ * @pagefault: flag set if this context caused a pagefault.
+ * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
+ * is set.
  */
 struct kgsl_context {
 	struct kref refcount;
 	uint32_t id;
-	struct kgsl_device_private *dev_priv;
-	void *devctxt;
+	pid_t pid;
+	unsigned long priv;
+	struct kgsl_device *device;
+	struct kgsl_pagetable *pagetable;
 	unsigned int reset_status;
 	bool wait_on_invalid_ts;
 	struct sync_timeline *timeline;
 	struct list_head events;
 	struct list_head events_list;
+	unsigned int pagefault_ts;
 };
 
 struct kgsl_process_private {
@@ -429,6 +442,9 @@
 
 void kgsl_context_destroy(struct kref *kref);
 
+int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context
+		*context);
+
 /**
  * kgsl_context_put() - Release context reference count
  * @context: Pointer to the KGSL context to be released
@@ -442,6 +458,22 @@
 	if (context)
 		kref_put(&context->refcount, kgsl_context_destroy);
 }
+
+/**
+ * kgsl_context_detached() - check if a context is detached
+ * @context: the context
+ *
+ * Check if a context has been destroyed by userspace and is only waiting
+ * for reference counts to go away. This check is used to weed out
+ * contexts that shouldn't use the gpu so NULL is considered detached.
+ */
+static inline bool kgsl_context_detached(struct kgsl_context *context)
+{
+	return (context == NULL || test_bit(KGSL_CONTEXT_DETACHED,
+						&context->priv));
+}
+
+
 /**
  * kgsl_context_get() - get a pointer to a KGSL context
  * @device: Pointer to the KGSL device that owns the context
@@ -462,7 +494,10 @@
 
 	context = idr_find(&device->context_idr, id);
 
-	if (context)
+	/* Don't return a context that has been detached */
+	if (kgsl_context_detached(context))
+		context = NULL;
+	else
 		kref_get(&context->refcount);
 
 	read_unlock(&device->context_lock);
@@ -471,6 +506,20 @@
 }
 
 /**
+* _kgsl_context_get() - lightweight function to just increment the ref count
+* @context: Pointer to the KGSL context
+*
+* Get a reference to the specified KGSL context structure. This is a
+* lightweight way to just increase the refcount on a known context rather than
+* walking through kgsl_context_get and searching the iterator
+*/
+static inline void _kgsl_context_get(struct kgsl_context *context)
+{
+	if (context)
+		kref_get(&context->refcount);
+}
+
+/**
  * kgsl_context_get_owner() - get a pointer to a KGSL context in a specific
  * process
  * @dev_priv: Pointer to the process struct
@@ -489,8 +538,8 @@
 
 	context = kgsl_context_get(dev_priv->device, id);
 
-	/* Verify that the context belongs to the dev_priv instance */
-	if (context && context->dev_priv != dev_priv) {
+	/* Verify that the context belongs to current calling process. */
+	if (context != NULL && context->pid != dev_priv->process_priv->pid) {
 		kgsl_context_put(context);
 		return NULL;
 	}
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 0b75175..40974b0 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -147,7 +147,7 @@
 	 * Increment the refcount to avoid freeing the context while
 	 * cancelling its events
 	 */
-	kref_get(&context->refcount);
+	_kgsl_context_get(context);
 
 	/* Remove ourselves from the master pending list */
 	list_del_init(&context->events_list);
@@ -324,7 +324,7 @@
 		 * Increment the refcount to make sure that the list_del_init
 		 * is called with a valid context's list
 		 */
-		kref_get(&context->refcount);
+		_kgsl_context_get(context);
 		/*
 		 * If kgsl_timestamp_expired_context returns 0 then it no longer
 		 * has any pending events and can be removed from the list
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 7af4575..14aae9f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -327,7 +327,7 @@
 	unsigned int no_page_fault_log = 0;
 	unsigned int curr_context_id = 0;
 	unsigned int curr_global_ts = 0;
-	static struct kgsl_context *context;
+	struct kgsl_context *context;
 
 	ret = get_iommu_unit(dev, &mmu, &iommu_unit);
 	if (ret)
@@ -401,23 +401,16 @@
 	context = kgsl_context_get(device, curr_context_id);
 
 	if (context != NULL) {
-		struct adreno_context *drawctxt = context->devctxt;
-
 		kgsl_sharedmem_readl(&device->memstore, &curr_global_ts,
 			KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
 			eoptimestamp));
 
-		/*
-		 * Store pagefault's timestamp in adreno context,
-		 * this information will be used in GFT
-		 */
-
-		if (drawctxt != NULL) {
-			drawctxt->pagefault = 1;
-			drawctxt->pagefault_ts = curr_global_ts;
-		}
+		/* save pagefault timestamp for GFT */
+		set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv);
+		context->pagefault_ts = curr_global_ts;
 
 		kgsl_context_put(context);
+		context = NULL;
 	}
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 5e6d24b..20391be 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1214,6 +1214,11 @@
 	}
 }
 
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device)
+{
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0);
+}
 
 /**
  * kgsl_pre_hwaccess - Enforce preconditions for touching registers
@@ -1230,7 +1235,7 @@
 	/* In order to touch a register you must hold the device mutex...*/
 	BUG_ON(!mutex_is_locked(&device->mutex));
 	/* and have the clock on! */
-	BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags));
+	BUG_ON(!kgsl_pwrctrl_isenabled(device));
 }
 EXPORT_SYMBOL(kgsl_pre_hwaccess);
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 3bf65ee..b7d9226 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -110,6 +110,8 @@
 void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device);
 void kgsl_pwrctrl_enable(struct kgsl_device *device);
 void kgsl_pwrctrl_disable(struct kgsl_device *device);
+bool kgsl_pwrctrl_isenabled(struct kgsl_device *device);
+
 static inline unsigned long kgsl_get_clkrate(struct clk *clk)
 {
 	return (clk != NULL) ? clk_get_rate(clk) : 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 35f24d9..6094e04 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -109,7 +109,7 @@
 	struct kgsl_device *device;
 
 	if (context)
-		device = context->dev_priv->device;
+		device = context->device;
 	else
 		device = (struct kgsl_device *)data;
 
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 1853996c..62ecdeb 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -239,7 +239,7 @@
 	char ktimeline_name[sizeof(context->timeline->name)] = {};
 	snprintf(ktimeline_name, sizeof(ktimeline_name),
 		"%s_%.15s(%d)-%.15s(%d)-%d",
-		context->dev_priv->device->name,
+		context->device->name,
 		current->group_leader->comm, current->group_leader->pid,
 		current->comm, current->pid, context->id);
 
@@ -250,7 +250,7 @@
 
 	ktimeline = (struct kgsl_sync_timeline *) context->timeline;
 	ktimeline->last_timestamp = 0;
-	ktimeline->device = context->dev_priv->device;
+	ktimeline->device = context->device;
 	ktimeline->context_id = context->id;
 
 	return 0;
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index abb7c35..5981163 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -678,6 +678,28 @@
 	)
 );
 
+TRACE_EVENT(kgsl_context_destroy,
+
+	TP_PROTO(struct kgsl_device *device, struct kgsl_context *context),
+
+	TP_ARGS(device, context),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, id)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->id = context->id;
+	),
+
+	TP_printk(
+		"d_name=%s ctx=%u",
+		__get_str(device_name), __entry->id
+	)
+);
+
 TRACE_EVENT(kgsl_mmu_pagefault,
 
 	TP_PROTO(struct kgsl_device *device, unsigned int page,
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index cc1819d..883417f 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -859,11 +859,30 @@
 	return status;
 }
 
-static void
-z180_drawctxt_destroy(struct kgsl_device *device,
-			  struct kgsl_context *context)
+struct kgsl_context *
+z180_drawctxt_create(struct kgsl_device_private *dev_priv,
+			uint32_t *flags)
 {
-	struct z180_device *z180_dev = Z180_DEVICE(device);
+	int ret;
+	struct kgsl_context *context = kzalloc(sizeof(*context), GFP_KERNEL);
+	if (context == NULL)
+		return ERR_PTR(-ENOMEM);
+	ret = kgsl_context_init(dev_priv, context);
+	if (ret != 0) {
+		kfree(context);
+		return ERR_PTR(ret);
+	}
+	return context;
+}
+
+static void
+z180_drawctxt_detach(struct kgsl_context *context)
+{
+	struct kgsl_device *device;
+	struct z180_device *z180_dev;
+
+	device = context->device;
+	z180_dev = Z180_DEVICE(device);
 
 	z180_idle(device);
 
@@ -875,6 +894,12 @@
 	}
 }
 
+static void
+z180_drawctxt_destroy(struct kgsl_context *context)
+{
+	kfree(context);
+}
+
 static void z180_power_stats(struct kgsl_device *device,
 			    struct kgsl_power_stats *stats)
 {
@@ -941,7 +966,8 @@
 	.gpuid = z180_gpuid,
 	.irq_handler = z180_irq_handler,
 	/* Optional functions */
-	.drawctxt_create = NULL,
+	.drawctxt_create = z180_drawctxt_create,
+	.drawctxt_detach = z180_drawctxt_detach,
 	.drawctxt_destroy = z180_drawctxt_destroy,
 	.ioctl = NULL,
 	.postmortem_dump = z180_dump,
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index a587ed2..a309ceb 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -65,6 +65,8 @@
 #define EPM_ADC_MILLI_VOLTS_SOURCE	4750
 #define EPM_ADC_SCALE_FACTOR		64
 #define GPIO_EPM_GLOBAL_ENABLE		86
+#define GPIO_EPM_MARKER1		85
+#define GPIO_EPM_MARKER2		96
 #define EPM_ADC_CONVERSION_TIME_MIN	50000
 #define EPM_ADC_CONVERSION_TIME_MAX	51000
 /* PSoc Commands */
@@ -715,6 +717,56 @@
 	return 0;
 }
 
+static int epm_set_marker1(struct epm_marker_level *marker_init)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_EPM_MARKER1, "EPM_MARKER1");
+	if (!rc) {
+		gpio_direction_output(GPIO_EPM_MARKER1, 1);
+	} else {
+		pr_err("%s: Configure MARKER1 GPIO Failed\n",
+							__func__);
+		return rc;
+	}
+
+	gpio_set_value(GPIO_EPM_MARKER1, marker_init->level);
+
+	return 0;
+}
+
+static int epm_set_marker2(struct epm_marker_level *marker_init)
+{
+	int rc = 0;
+
+	rc = gpio_request(GPIO_EPM_MARKER2, "EPM_MARKER2");
+	if (!rc) {
+		gpio_direction_output(GPIO_EPM_MARKER2, 1);
+	} else {
+		pr_err("%s: Configure MARKER2 GPIO Failed\n",
+							__func__);
+		return rc;
+	}
+
+	gpio_set_value(GPIO_EPM_MARKER2, marker_init->level);
+
+	return 0;
+}
+
+static int epm_marker1_release(void)
+{
+	gpio_free(GPIO_EPM_MARKER1);
+
+	return 0;
+}
+
+static int epm_marker2_release(void)
+{
+	gpio_free(GPIO_EPM_MARKER2);
+
+	return 0;
+}
+
 static int epm_psoc_init(struct epm_adc_drv *epm_adc,
 					struct epm_psoc_init_resp *init_resp)
 {
@@ -1296,6 +1348,58 @@
 				return -EFAULT;
 			break;
 		}
+	case EPM_MARKER1_REQUEST:
+		{
+			struct epm_marker_level marker_init;
+			uint32_t result;
+
+			if (copy_from_user(&marker_init, (void __user *)arg,
+					sizeof(struct epm_marker_level)))
+				return -EFAULT;
+
+			result = epm_set_marker1(&marker_init);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER2_REQUEST:
+		{
+			struct epm_marker_level marker_init;
+			uint32_t result;
+
+			if (copy_from_user(&marker_init, (void __user *)arg,
+					sizeof(struct epm_marker_level)))
+				return -EFAULT;
+
+			result = epm_set_marker2(&marker_init);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER1_RELEASE:
+		{
+			uint32_t result;
+			result = epm_marker1_release();
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
+	case EPM_MARKER2_RELEASE:
+		{
+			uint32_t result;
+			result = epm_marker2_release();
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_INIT:
 		{
 			struct epm_psoc_init_resp psoc_init;
@@ -1312,11 +1416,29 @@
 				return -EINVAL;
 			}
 
+			if (!rc) {
+				rc = epm_adc_psoc_gpio_init(true);
+				if (rc) {
+					pr_err("GPIO init failed\n");
+					return -EINVAL;
+				}
+			}
+
 			if (copy_to_user((void __user *)arg, &psoc_init,
 				sizeof(struct epm_psoc_init_resp)))
 				return -EFAULT;
 			break;
 		}
+	case EPM_PSOC_ADC_DEINIT:
+		{
+			uint32_t result;
+			result = epm_adc_psoc_gpio_init(false);
+
+			if (copy_to_user((void __user *)arg, &result,
+						sizeof(uint32_t)))
+				return -EFAULT;
+			break;
+		}
 	case EPM_PSOC_ADC_CHANNEL_ENABLE:
 	case EPM_PSOC_ADC_CHANNEL_DISABLE:
 		{
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 6e8c809..982e4d4 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1343,3 +1343,17 @@
 	pkt->trigger_type = get_hfi_ssr_type(type);
 	return 0;
 }
+
+int create_pkt_cmd_sys_image_version(
+		struct hfi_cmd_sys_get_property_packet *pkt)
+{
+	if (!pkt) {
+		dprintk(VIDC_ERR, "%s invalid param :%p\n", __func__, pkt);
+		return -EINVAL;
+	}
+	pkt->size = sizeof(struct hfi_cmd_sys_get_property_packet);
+	pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
+	pkt->num_properties = 1;
+	pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
+	return 0;
+}
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.h b/drivers/media/platform/msm/vidc/hfi_packetization.h
index df93906..20619c0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.h
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.h
@@ -89,4 +89,7 @@
 
 int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
 		struct hfi_cmd_sys_test_ssr_packet *pkt);
+
+int create_pkt_cmd_sys_image_version(
+		struct hfi_cmd_sys_get_property_packet *pkt);
 #endif
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 859345f..44105ad 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -14,6 +14,7 @@
 #include <linux/slab.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
+#include <mach/msm_smem.h>
 #include "vidc_hfi_helper.h"
 #include "vidc_hfi_io.h"
 #include "msm_vidc_debug.h"
@@ -1089,6 +1090,44 @@
 	callback(SESSION_GET_SEQ_HDR_DONE, &data_done);
 }
 
+void hfi_process_sys_property_info(
+		struct hfi_property_sys_image_version_info_type *pkt)
+{
+	int i = 0;
+	u32 smem_block_size = 0;
+	u8 *smem_table_ptr;
+	char version[256];
+	const u32 smem_image_index_venus = 14 * 128;
+
+	if (!pkt || !pkt->string_size) {
+		dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
+		return;
+	}
+
+	if (pkt->string_size < sizeof(version)) {
+		/*
+		 * The version string returned by firmware includes null
+		 * characters at the start and in between. Replace the null
+		 * characters with space, to print the version info.
+		 */
+		for (i = 0; i < pkt->string_size; i++) {
+			if (pkt->str_image_version[i] != '\0')
+				version[i] = pkt->str_image_version[i];
+			else
+				version[i] = ' ';
+		}
+		version[i] = '\0';
+		dprintk(VIDC_INFO, "F/W version: %s\n", version);
+	}
+
+	smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+						&smem_block_size);
+	if (smem_table_ptr &&
+		((smem_image_index_venus + 128) <= smem_block_size))
+		memcpy(smem_table_ptr + smem_image_index_venus,
+			   (u8 *)pkt->str_image_version, 128);
+}
+
 u32 hfi_process_msg_packet(
 		msm_vidc_callback callback, u32 device_id,
 		struct vidc_hal_msg_pkt_hdr *msg_hdr)
@@ -1121,6 +1160,11 @@
 			(struct hfi_msg_sys_session_init_done_packet *)
 					msg_hdr);
 		break;
+	case HFI_MSG_SYS_PROPERTY_INFO:
+		hfi_process_sys_property_info(
+		   (struct hfi_property_sys_image_version_info_type *)
+			msg_hdr);
+		break;
 	case HFI_MSG_SYS_SESSION_END_DONE:
 		hfi_process_session_end_done(callback, device_id,
 			(struct hfi_msg_sys_session_end_done_packet *)
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 7547464..7039929 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -934,6 +934,8 @@
 	struct hal_buffer_requirements *bufreq;
 	int extra_idx = 0;
 	struct hfi_device *hdev;
+	struct hal_buffer_count_actual new_buf_count;
+	enum hal_property property_id;
 	if (!q || !num_buffers || !num_planes
 		|| !sizes || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p, %p, %p\n",
@@ -960,6 +962,16 @@
 					i, inst->capability.height.max,
 					inst->capability.width.max);
 		}
+		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
+		new_buf_count.buffer_type = HAL_BUFFER_INPUT;
+		new_buf_count.buffer_count_actual = *num_buffers;
+		rc = call_hfi_op(hdev, session_set_property,
+				inst->session, property_id, &new_buf_count);
+		if (rc) {
+			dprintk(VIDC_WARN,
+				"Failed to set new buffer count(%d) on FW, err: %d\n",
+				new_buf_count.buffer_count_actual, rc);
+		}
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		dprintk(VIDC_DBG, "Getting bufreqs on capture plane\n");
@@ -987,15 +999,11 @@
 		}
 		if (*num_buffers && *num_buffers >
 			bufreq->buffer_count_actual) {
-			struct hal_buffer_count_actual new_buf_count;
-			enum hal_property property_id =
-				HAL_PARAM_BUFFER_COUNT_ACTUAL;
-
+			property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 			new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 			new_buf_count.buffer_count_actual = *num_buffers;
 			rc = call_hfi_op(hdev, session_set_property,
 				inst->session, property_id, &new_buf_count);
-
 		}
 		if (bufreq->buffer_count_actual > *num_buffers)
 			*num_buffers =  bufreq->buffer_count_actual;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 28ea41a..8ee9c32 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1030,6 +1030,7 @@
 static int venus_hfi_core_init(void *device)
 {
 	struct hfi_cmd_sys_init_packet pkt;
+	struct hfi_cmd_sys_get_property_packet version_pkt;
 	int rc = 0;
 	struct venus_hfi_device *dev;
 
@@ -1088,6 +1089,10 @@
 		rc = -ENOTEMPTY;
 		goto err_core_init;
 	}
+	rc = create_pkt_cmd_sys_image_version(&version_pkt);
+	if (rc || venus_hfi_iface_cmdq_write(dev, &version_pkt))
+		dprintk(VIDC_WARN, "Failed to send image version pkt to f/w");
+
 	return rc;
 err_core_init:
 	disable_irq_nosync(dev->hal_data->irq);
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index bb72da7..ac6cb02 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -335,7 +335,6 @@
 #define HFI_MSG_SYS_OX_START			\
 (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
 #define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
-#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
 #define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
 
 #define HFI_MSG_SESSION_OX_START		\
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 2b6d6bb..0f1e896 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -197,6 +197,10 @@
 	(HFI_PROPERTY_SYS_COMMON_START + 0x003)
 #define HFI_PROPERTY_SYS_IDLE_INDICATOR         \
 	(HFI_PROPERTY_SYS_COMMON_START + 0x004)
+#define  HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL     \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x005)
+#define  HFI_PROPERTY_SYS_IMAGE_VERSION    \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x006)
 
 #define HFI_PROPERTY_PARAM_COMMON_START	\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -615,6 +619,11 @@
 	struct hfi_resource_ocmem_requirement rg_requirements[1];
 };
 
+struct hfi_property_sys_image_version_info_type {
+	u32 string_size;
+	u8  str_image_version[1];
+};
+
 struct hfi_venc_config_advanced {
 	u8 pipe2d;
 	u8 hw_mode;
@@ -703,6 +712,7 @@
 #define HFI_MSG_SYS_SESSION_INIT_DONE	(HFI_MSG_SYS_COMMON_START + 0x6)
 #define HFI_MSG_SYS_SESSION_END_DONE	(HFI_MSG_SYS_COMMON_START + 0x7)
 #define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_COMMON_START + 0x8)
+#define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_COMMON_START + 0xA)
 
 #define HFI_MSG_SESSION_COMMON_START		\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET +	\
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 16012bd..7f02187 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -2229,7 +2229,8 @@
 	return err;
 }
 
-#define BAM_APPS_PIPE_LOCK_GRP 0
+#define BAM_APPS_PIPE_LOCK_GRP0 0
+#define BAM_APPS_PIPE_LOCK_GRP1 1
 /*
  * This function allocates, configures, connects an end point and
  * also registers event notification for an end point. It also allocates
@@ -2273,7 +2274,13 @@
 	}
 
 	sps_config->options = SPS_O_AUTO_ENABLE | SPS_O_DESC_DONE;
-	sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP;
+
+	if (pipe_index == SPS_DATA_PROD_PIPE_INDEX ||
+			pipe_index == SPS_DATA_CONS_PIPE_INDEX)
+		sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP0;
+	else if (pipe_index == SPS_CMD_CONS_PIPE_INDEX)
+		sps_config->lock_group = BAM_APPS_PIPE_LOCK_GRP1;
+
 	/*
 	 * Descriptor FIFO is a cyclic FIFO. If SPS_MAX_DESC_NUM descriptors
 	 * are allowed to be submitted before we get any ack for any of them,
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 2a007ca..23941a9 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -2352,7 +2352,8 @@
 			}
 			rc = devm_request_irq(chip->dev, chip->batt_pres.irq,
 				qpnp_chg_bat_if_batt_pres_irq_handler,
-				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+				| IRQF_SHARED | IRQF_ONESHOT,
 				"batt-pres", chip);
 			if (rc < 0) {
 				pr_err("Can't request %d batt-pres irq: %d\n",
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 823229b..8b1f3a8 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -48,7 +48,7 @@
 		return retval;
 
 	/* bursts of unspecified length. */
-	writel(0, USB_AHBBURST);
+	writel_relaxed(0, USB_AHBBURST);
 	/* Use the AHB transactor */
 	writel_relaxed(0x08, USB_AHBMODE);
 	/* Disable streaming mode and select host mode */
@@ -60,6 +60,10 @@
 							USB_PHY_CTRL2);
 	}
 
+	/* Disable ULPI_TX_PKT_EN_CLR_FIX which is valid only for HSIC */
+	writel_relaxed(readl_relaxed(USB_GENCONFIG2) & ~(1<<19),
+					USB_GENCONFIG2);
+
 	ehci_port_power(ehci, 1);
 	return 0;
 }
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index eb65509..2a98e49 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -2207,6 +2207,8 @@
 		/* Clear alt interrupt latch and enable bits */
 		ulpi_write(phy, 0x1F, 0x92);
 		ulpi_write(phy, 0x1F, 0x95);
+		/* re-enable DP and DM pull down resistors */
+		ulpi_write(phy, 0x6, 0xB);
 		break;
 	default:
 		break;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index fb0e8ba..44a5e62 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -360,13 +360,13 @@
 				__func__, rc);
 			goto error;
 		}
-		mp->vreg_config[i].peak_current = val_array[i];
+		mp->vreg_config[i].enable_load = val_array[i];
 
 		pr_debug("%s: %s min=%d, max=%d, pc=%d\n", __func__,
 			mp->vreg_config[i].vreg_name,
 			mp->vreg_config[i].min_voltage,
 			mp->vreg_config[i].max_voltage,
-			mp->vreg_config[i].peak_current);
+			mp->vreg_config[i].enable_load);
 	}
 
 	devm_kfree(dev, val_array);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 91e5660..e4a6b86 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -87,6 +87,9 @@
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
 static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
 	enum hdmi_tx_power_module_type module, int enable);
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+				bool wait_audio_tx);
+static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -1676,10 +1679,11 @@
 } /* hdmi_tx_powerdown_phy */
 
 static int hdmi_tx_audio_acr_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
-	bool enabled, int num_of_channels)
+	bool enabled)
 {
 	/* Read first before writing */
 	u32 acr_pck_ctrl_reg;
+	u32 sample_rate;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -1687,6 +1691,8 @@
 		return -EINVAL;
 	}
 
+	sample_rate = hdmi_ctrl->audio_data.sample_rate;
+
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
 		DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1721,18 +1727,19 @@
 			return -EPERM;
 		}
 
-		n = audio_acr->lut[hdmi_ctrl->audio_sample_rate].n;
-		cts = audio_acr->lut[hdmi_ctrl->audio_sample_rate].cts;
-		layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+		n = audio_acr->lut[sample_rate].n;
+		cts = audio_acr->lut[sample_rate].cts;
+		layout = (MSM_HDMI_AUDIO_CHANNEL_2 ==
+			hdmi_ctrl->audio_data.channel_num) ? 0 : 1;
 
 		if (
-		(AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
 			multiplier = 4;
 			n >>= 2; /* divide N by 4 and use multiplier */
 		} else if (
-		(AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate)) {
 			multiplier = 2;
 			n >>= 1; /* divide N by 2 and use multiplier */
 		} else {
@@ -1743,12 +1750,16 @@
 
 		/* AUDIO_PRIORITY | SOURCE */
 		acr_pck_ctrl_reg |= 0x80000100;
+
+		/* Reset multiplier bits */
+		acr_pck_ctrl_reg &= ~(7 << 16);
+
 		/* N_MULTIPLE(multiplier) */
 		acr_pck_ctrl_reg |= (multiplier & 7) << 16;
 
-		if ((AUDIO_SAMPLE_RATE_48KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_96KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_192KHZ == hdmi_ctrl->audio_sample_rate)) {
+		if ((AUDIO_SAMPLE_RATE_48KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_96KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_192KHZ == sample_rate)) {
 			/* SELECT(3) */
 			acr_pck_ctrl_reg |= 3 << 4;
 			/* CTS_48 */
@@ -1759,9 +1770,9 @@
 			/* N */
 			DSS_REG_W(io, HDMI_ACR_48_1, n);
 		} else if (
-		(AUDIO_SAMPLE_RATE_44_1KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_88_2KHZ == hdmi_ctrl->audio_sample_rate) ||
-		(AUDIO_SAMPLE_RATE_176_4KHZ == hdmi_ctrl->audio_sample_rate)) {
+		(AUDIO_SAMPLE_RATE_44_1KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_88_2KHZ == sample_rate) ||
+		(AUDIO_SAMPLE_RATE_176_4KHZ == sample_rate)) {
 			/* SELECT(2) */
 			acr_pck_ctrl_reg |= 2 << 4;
 			/* CTS_44 */
@@ -1800,12 +1811,15 @@
 } /* hdmi_tx_audio_acr_setup */
 
 static int hdmi_tx_audio_iframe_setup(struct hdmi_tx_ctrl *hdmi_ctrl,
-	bool enabled, u32 num_of_channels, u32 channel_allocation,
-	u32 level_shift, bool down_mix)
+	bool enabled)
 {
 	struct dss_io_data *io = NULL;
 
 	u32 channel_count = 1; /* Def to 2 channels -> Table 17 in CEA-D */
+	u32 num_of_channels;
+	u32 channel_allocation;
+	u32 level_shift;
+	u32 down_mix;
 	u32 check_sum, audio_info_0_reg, audio_info_1_reg;
 	u32 audio_info_ctrl_reg;
 	u32 aud_pck_ctrl_2_reg;
@@ -1816,6 +1830,11 @@
 		return -EINVAL;
 	}
 
+	num_of_channels    = hdmi_ctrl->audio_data.channel_num;
+	channel_allocation = hdmi_ctrl->audio_data.spkr_alloc;
+	level_shift        = hdmi_ctrl->audio_data.level_shift;
+	down_mix           = hdmi_ctrl->audio_data.down_mix;
+
 	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
 	if (!io->base) {
 		DEV_ERR("%s: core io not inititalized\n", __func__);
@@ -1926,8 +1945,8 @@
 } /* hdmi_tx_audio_iframe_setup */
 
 static int hdmi_tx_audio_info_setup(struct platform_device *pdev,
-	u32 num_of_channels, u32 channel_allocation, u32 level_shift,
-	bool down_mix)
+	u32 sample_rate, u32 num_of_channels, u32 channel_allocation,
+	u32 level_shift, bool down_mix)
 {
 	int rc = 0;
 	struct hdmi_tx_ctrl *hdmi_ctrl = platform_get_drvdata(pdev);
@@ -1937,10 +1956,31 @@
 		return -ENODEV;
 	}
 
-	if (hdmi_ctrl->panel_power_on) {
-		rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true,
-			num_of_channels, channel_allocation, level_shift,
-			down_mix);
+	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl) && hdmi_ctrl->panel_power_on) {
+
+		/* Map given sample rate to Enum */
+		if (sample_rate == 32000)
+			sample_rate = AUDIO_SAMPLE_RATE_32KHZ;
+		else if (sample_rate == 44100)
+			sample_rate = AUDIO_SAMPLE_RATE_44_1KHZ;
+		else if (sample_rate == 48000)
+			sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+		else if (sample_rate == 88200)
+			sample_rate = AUDIO_SAMPLE_RATE_88_2KHZ;
+		else if (sample_rate == 96000)
+			sample_rate = AUDIO_SAMPLE_RATE_96KHZ;
+		else if (sample_rate == 176400)
+			sample_rate = AUDIO_SAMPLE_RATE_176_4KHZ;
+		else if (sample_rate == 192000)
+			sample_rate = AUDIO_SAMPLE_RATE_192KHZ;
+
+		hdmi_ctrl->audio_data.sample_rate = sample_rate;
+		hdmi_ctrl->audio_data.channel_num = num_of_channels;
+		hdmi_ctrl->audio_data.spkr_alloc  = channel_allocation;
+		hdmi_ctrl->audio_data.level_shift = level_shift;
+		hdmi_ctrl->audio_data.down_mix    = down_mix;
+
+		rc = hdmi_tx_audio_setup(hdmi_ctrl);
 		if (rc)
 			DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.rc=%d\n",
 				__func__, rc);
@@ -2047,7 +2087,6 @@
 static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
-	const int channels = MSM_HDMI_AUDIO_CHANNEL_2;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -2061,14 +2100,14 @@
 		return -EINVAL;
 	}
 
-	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true, channels);
+	rc = hdmi_tx_audio_acr_setup(hdmi_ctrl, true);
 	if (rc) {
 		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed. rc=%d\n",
 			__func__, rc);
 		return rc;
 	}
 
-	rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true, channels, 0, 0, false);
+	rc = hdmi_tx_audio_iframe_setup(hdmi_ctrl, true);
 	if (rc) {
 		DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed. rc=%d\n",
 			__func__, rc);
@@ -2080,9 +2119,10 @@
 	return 0;
 } /* hdmi_tx_audio_setup */
 
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
+				bool wait_audio_tx)
 {
-	u32 i, status, sleep_us, timeout_us, timeout_sec = 15;
+	u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
 	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
@@ -2096,33 +2136,43 @@
 		return;
 	}
 
-	/* Check if audio engine is turned off by QDSP or not */
-	/* send off notification after every 1 sec for 15 seconds */
-	for (i = 0; i < timeout_sec; i++) {
-		sleep_us = 5000; /* Maximum time to sleep between two reads */
-		timeout_us = 1000 * 1000; /* Total time for condition to meet */
+	if (wait_audio_tx) {
+		/* Check if audio engine is turned off by QDSP or not */
+		/* send off notification after every 1 sec for 15 seconds */
+		for (i = 0; i < timeout_sec; i++) {
+			/* Maximum time to sleep between two reads */
+			sleep_us = 5000;
+			/* Total time for condition to meet */
+			timeout_us = 1000 * 1000;
 
-		if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
-			status, ((status & BIT(0)) == 0),
-			sleep_us, timeout_us)) {
+			if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
+				status, ((status & BIT(0)) == 0),
+				sleep_us, timeout_us)) {
 
-			DEV_ERR("%s: audio still on after %d sec. try again\n",
+				DEV_ERR(
+				"%s: audio still on after %d sec. try again\n",
 				__func__, i+1);
 
-			hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, true);
-			continue;
+				hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
+					true);
+				continue;
+			}
+			break;
 		}
-		break;
 	}
+
 	if (i == timeout_sec)
 		DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
 
-	if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false, 0, 0, 0, false))
+	if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
 		DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
 
-	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false, 0))
+	if (hdmi_tx_audio_acr_setup(hdmi_ctrl, false))
 		DEV_ERR("%s: hdmi_tx_audio_acr_setup failed.\n", __func__);
 
+	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
+
 	DEV_INFO("HDMI Audio: Disabled\n");
 } /* hdmi_tx_audio_off */
 
@@ -2239,7 +2289,7 @@
 
 	if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
 		hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
-		hdmi_tx_audio_off(hdmi_ctrl);
+		hdmi_tx_audio_off(hdmi_ctrl, true);
 	}
 
 	hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2656,7 +2706,8 @@
 
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
 
-	hdmi_ctrl->audio_sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.sample_rate = AUDIO_SAMPLE_RATE_48KHZ;
+	hdmi_ctrl->audio_data.channel_num = MSM_HDMI_AUDIO_CHANNEL_2;
 
 	hdmi_ctrl->sdev.name = "hdmi";
 	if (switch_dev_register(&hdmi_ctrl->sdev) < 0) {
@@ -3216,13 +3267,13 @@
 				__func__, hdmi_tx_pm_name(module_type), rc);
 			goto error;
 		}
-		mp->vreg_config[j].peak_current = val_array[i];
+		mp->vreg_config[j].enable_load = val_array[i];
 
 		DEV_DBG("%s: %s min=%d, max=%d, pc=%d\n", __func__,
 			mp->vreg_config[j].vreg_name,
 			mp->vreg_config[j].min_voltage,
 			mp->vreg_config[j].max_voltage,
-			mp->vreg_config[j].peak_current);
+			mp->vreg_config[j].enable_load);
 
 		ndx_mask >>= 1;
 		j++;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index d4f8e67..18ee782 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -38,12 +38,20 @@
 	struct dss_module_power power_data[HDMI_TX_MAX_PM];
 };
 
+struct hdmi_audio {
+	int sample_rate;
+	int channel_num;
+	int spkr_alloc;
+	int level_shift;
+	int down_mix;
+};
+
 struct hdmi_tx_ctrl {
 	struct platform_device *pdev;
 	struct hdmi_tx_platform_data pdata;
 	struct mdss_panel_data panel_data;
 
-	int audio_sample_rate;
+	struct hdmi_audio audio_data;
 
 	struct mutex mutex;
 	struct kobject *kobj;
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 31058f8..c862e78 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -213,7 +213,7 @@
 			}
 			msleep(in_vreg[i].pre_on_sleep);
 			rc = regulator_set_optimum_mode(in_vreg[i].vreg,
-				in_vreg[i].peak_current);
+				in_vreg[i].enable_load);
 			if (rc < 0) {
 				DEV_ERR("%pS->%s: %s set opt m fail\n",
 					__builtin_return_address(0), __func__,
@@ -233,7 +233,8 @@
 		for (i = num_vreg-1; i >= 0; i--)
 			if (regulator_is_enabled(in_vreg[i].vreg)) {
 				msleep(in_vreg[i].pre_off_sleep);
-				regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+				regulator_set_optimum_mode(in_vreg[i].vreg,
+					in_vreg[i].disable_load);
 				regulator_disable(in_vreg[i].vreg);
 				msleep(in_vreg[i].post_off_sleep);
 			}
@@ -241,12 +242,13 @@
 	return rc;
 
 disable_vreg:
-	regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+	regulator_set_optimum_mode(in_vreg[i].vreg, in_vreg[i].disable_load);
 
 vreg_set_opt_mode_fail:
 	for (i--; i >= 0; i--) {
 		msleep(in_vreg[i].pre_off_sleep);
-		regulator_set_optimum_mode(in_vreg[i].vreg, 0);
+		regulator_set_optimum_mode(in_vreg[i].vreg,
+			in_vreg[i].disable_load);
 		regulator_disable(in_vreg[i].vreg);
 		msleep(in_vreg[i].post_off_sleep);
 	}
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index cb0fb70..6ad21e8 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -52,7 +52,8 @@
 	char vreg_name[32];
 	int min_voltage;
 	int max_voltage;
-	int peak_current;
+	int enable_load;
+	int disable_load;
 	int pre_on_sleep;
 	int post_on_sleep;
 	int pre_off_sleep;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index d1e5e64..eaef12b 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -30,6 +30,7 @@
 static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
 
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
 
 static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
 				       u32 reg, u32 val)
@@ -94,6 +95,11 @@
 	}
 }
 
+static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
+{
+	return bitmap_weight(smp, SMP_MB_CNT) == 0;
+}
+
 static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
 {
 	u32 fetch_size, val, wm[3];
@@ -227,6 +233,8 @@
 
 	mutex_lock(&mdss_mdp_smp_lock);
 	for (i = 0; i < MAX_PLANES; i++) {
+		if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+			continue;
 		mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
 			pipe->smp_map[i].reserved);
 		cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
@@ -708,10 +716,9 @@
 		if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)
 			mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_VIG_OP_MODE,
 			opmode);
-
-		mdss_mdp_smp_alloc(pipe);
 	}
 
+	mdss_mdp_smp_alloc(pipe);
 	ret = mdss_mdp_src_addr_setup(pipe, src_data);
 	if (ret) {
 		pr_err("addr setup error for pnum=%d\n", pipe->num);
diff --git a/include/linux/epm_adc.h b/include/linux/epm_adc.h
index 4fa41b5..6f00df7 100644
--- a/include/linux/epm_adc.h
+++ b/include/linux/epm_adc.h
@@ -97,6 +97,23 @@
 	uint32_t gain;
 };
 
+struct epm_marker_level {
+	uint8_t		level;
+};
+
+struct epm_gpio_buffer_request {
+	uint8_t		cmd;
+	uint8_t		bitmask_monitor_pin;
+	uint8_t		status;
+};
+
+struct epm_get_gpio_buffer_resp {
+	uint8_t		cmd;
+	uint8_t		status;
+	uint8_t		bitmask_monitor_pin;
+	uint32_t	timestamp;
+};
+
 #ifdef __KERNEL__
 struct epm_adc_platform_data {
 	struct epm_chan_properties *channel;
@@ -121,7 +138,19 @@
 #define EPM_ADC_DEINIT		_IOR(EPM_ADC_IOCTL_CODE, 3,	\
 					     uint32_t)
 
-#define EPM_PSOC_ADC_INIT		_IOR(EPM_ADC_IOCTL_CODE, 4, \
+#define EPM_MARKER1_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 90,	\
+						uint32_t)
+
+#define EPM_MARKER1_RELEASE	_IOWR(EPM_ADC_IOCTL_CODE, 91,	\
+						uint32_t)
+
+#define EPM_MARKER2_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 95,	\
+						uint32_t)
+
+#define EPM_MARKER2_RELEASE	_IOWR(EPM_ADC_IOCTL_CODE, 92,	\
+						uint32_t)
+
+#define EPM_PSOC_ADC_INIT		_IOWR(EPM_ADC_IOCTL_CODE, 4, \
 					struct epm_psoc_init_resp)
 
 #define EPM_PSOC_ADC_CHANNEL_ENABLE	_IOWR(EPM_ADC_IOCTL_CODE, 5, \
@@ -157,4 +186,13 @@
 #define EPM_PSOC_ADC_SET_VADC_REFERENCE		_IOWR(EPM_ADC_IOCTL_CODE, 15, \
 						struct epm_psoc_set_vadc)
 
+#define EPM_PSOC_ADC_DEINIT		_IOWR(EPM_ADC_IOCTL_CODE, 16,	\
+							     uint32_t)
+
+#define EPM_PSOC_GPIO_BUFFER_REQUEST	_IOWR(EPM_ADC_IOCTL_CODE, 17,	\
+								uint32_t)
+
+#define EPM_PSOC_GET_GPIO_BUFFER_DATA	_IOWR(EPM_ADC_IOCTL_CODE, 18,	\
+								uint32_t)
+
 #endif /* __EPM_ADC_H */
diff --git a/include/linux/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index a741107..e8ca1cd 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -54,12 +54,16 @@
 #define AUDIO_SET_ASM_CUSTOM_TOPOLOGY	_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
 #define AUDIO_SET_SPEAKER_PROT _IOW(AUDIO_IOCTL_MAGIC, 25, \
-		struct msm_spk_prot_cfg)
+			struct msm_spk_prot_cfg)
 #define AUDIO_GET_SPEAKER_PROT _IOR(AUDIO_IOCTL_MAGIC, 26, \
-		struct msm_spk_prot_status)
+			struct msm_spk_prot_status)
 #define AUDIO_SET_AANC_CAL		_IOW(AUDIO_IOCTL_MAGIC, \
 			(AUDIO_MAX_COMMON_IOCTL_NUM+27), unsigned)
-#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+30)
+#define AUDIO_REGISTER_VOCPROC_VOL_TABLE	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+28), unsigned)
+#define AUDIO_DEREGISTER_VOCPROC_VOL_TABLE	_IOW(AUDIO_IOCTL_MAGIC, \
+			(AUDIO_MAX_COMMON_IOCTL_NUM+29), unsigned)
+#define	AUDIO_MAX_ACDB_IOCTL	(AUDIO_MAX_COMMON_IOCTL_NUM+40)
 
 /* ACDB structures */
 struct cal_block {
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 46bce9e..e5d5c32 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -113,7 +113,7 @@
 		channel_allocation);
 
 	codec_data->hdmi_ops.audio_info_setup(codec_data->hdmi_core_pdev,
-			num_channels, channel_allocation,
+			params_rate(params), num_channels, channel_allocation,
 			level_shift, down_mix);
 
 	return 0;
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index d6090cf..2836b87 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/msm_audio_ion.h>
 #include "audio_acdb.h"
+#include "q6voice.h"
 
 
 #define MAX_NETWORKS			15
@@ -949,6 +950,36 @@
 	return result;
 }
 
+static int register_vocvol_table(void)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	result = voc_register_vocproc_vol_table();
+	if (result < 0) {
+		pr_err("%s: Register vocproc vol failed!\n", __func__);
+		goto done;
+	}
+
+done:
+	return result;
+}
+
+static int deregister_vocvol_table(void)
+{
+	int result = 0;
+	pr_debug("%s\n", __func__);
+
+	result = voc_deregister_vocproc_vol_table();
+	if (result < 0) {
+		pr_err("%s: Deregister vocproc vol failed!\n", __func__);
+		goto done;
+	}
+
+done:
+	return result;
+}
+
 static int acdb_open(struct inode *inode, struct file *f)
 {
 	s32 result = 0;
@@ -1139,10 +1170,16 @@
 		}
 		if (copy_to_user((void *)arg, &prot_status,
 			sizeof(prot_status))) {
-			pr_err("%s Failed to update prot_status\n", __func__);
+			pr_err("%s: Failed to update prot_status\n", __func__);
 		}
 		mutex_unlock(&acdb_data.acdb_mutex);
 		goto done;
+	case AUDIO_REGISTER_VOCPROC_VOL_TABLE:
+		result = register_vocvol_table();
+		goto done;
+	case AUDIO_DEREGISTER_VOCPROC_VOL_TABLE:
+		result = deregister_vocvol_table();
+		goto done;
 	}
 
 	if (copy_from_user(&size, (void *) arg, sizeof(size))) {
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index f268171..2e5ff35 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -300,6 +300,16 @@
 	return (session_id == common.voice[VOC_PATH_VOICE2_PASSIVE].session_id);
 }
 
+static bool is_voc_state_active(int voc_state)
+{
+	if ((voc_state == VOC_RUN) ||
+		(voc_state == VOC_CHANGE) ||
+		(voc_state == VOC_STANDBY))
+		return true;
+
+	return false;
+}
+
 static bool is_other_session_active(u32 session_id)
 {
 	int i;
@@ -310,9 +320,7 @@
 		if (common.voice[i].session_id == session_id)
 			continue;
 
-		if ((common.voice[i].voc_state == VOC_RUN) ||
-		    (common.voice[i].voc_state == VOC_CHANGE) ||
-		    (common.voice[i].voc_state == VOC_STANDBY)) {
+		if (is_voc_state_active(common.voice[i].voc_state)) {
 			ret = true;
 			break;
 		}
@@ -1213,9 +1221,8 @@
 	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
 		v = &common.voice[i];
 		if ((v->dtmf_rx_detect_en) &&
-			((v->voc_state == VOC_RUN) ||
-			 (v->voc_state == VOC_CHANGE) ||
-			 (v->voc_state == VOC_STANDBY))) {
+			is_voc_state_active(v->voc_state)) {
+
 			pr_debug("disable dtmf det on ses_id=%d\n",
 				 v->session_id);
 			voice_send_dtmf_rx_detection_cmd(v, 0);
@@ -1236,9 +1243,7 @@
 	mutex_lock(&v->lock);
 	v->dtmf_rx_detect_en = enable;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_dtmf_rx_detection_cmd(v,
 						       v->dtmf_rx_detect_en);
 
@@ -2327,6 +2332,62 @@
 	return ret;
 }
 
+int voc_register_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_register_vol_cal_cmd(v);
+			if (result) {
+				pr_err("%s: Failed to register vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+				mutex_unlock(&v->lock);
+				goto done;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
+int voc_deregister_vocproc_vol_table(void)
+{
+	int			result = 0;
+	int			i;
+	struct voice_data	*v = NULL;
+	pr_debug("%s\n", __func__);
+
+	mutex_lock(&common.common_lock);
+	for (i = 0; i < MAX_VOC_SESSIONS; i++) {
+		v = &common.voice[i];
+
+		mutex_lock(&v->lock);
+		if (is_voc_state_active(v->voc_state)) {
+			result = voice_send_cvp_deregister_vol_cal_cmd(v);
+			if (result) {
+				pr_err("%s: Failed to deregister vocvol table for session 0x%x!\n",
+					__func__, v->session_id);
+				mutex_unlock(&v->lock);
+				goto done;
+			}
+		}
+		mutex_unlock(&v->lock);
+	}
+done:
+	mutex_unlock(&common.common_lock);
+	return result;
+}
+
 static int voice_map_memory_physical_cmd(struct voice_data *v,
 					 struct mem_map_table *table_info,
 					 dma_addr_t phys,
@@ -3870,9 +3931,7 @@
 
 	v->stream_tx.stream_mute = mute;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_stream_mute_cmd(v);
 
 	mutex_unlock(&v->lock);
@@ -4026,9 +4085,7 @@
 
 	v->dev_rx.volume = vol_idx;
 
-	if ((v->voc_state == VOC_RUN) ||
-	    (v->voc_state == VOC_CHANGE) ||
-	    (v->voc_state == VOC_STANDBY))
+	if (is_voc_state_active(v->voc_state))
 		ret = voice_send_vol_index_cmd(v);
 
 	mutex_unlock(&v->lock);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index b8f7008..4a3ff2a 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1377,6 +1377,8 @@
 int voc_alloc_cal_shared_memory(void);
 int voc_alloc_voip_shared_memory(void);
 int is_voc_initialized(void);
+int voc_register_vocproc_vol_table(void);
+int voc_deregister_vocproc_vol_table(void);
 
 uint32_t voc_get_session_id(char *name);