Merge "msm_fb: display: fix mdp crash during overlay unset" into msm-3.4
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 0624dd1..1fd96f9 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -10,38 +10,13 @@
  * GNU General Public License for more details.
  */
 
+
+/* QPNP controlled regulators: */
+
 &spmi_bus {
+
 	qcom,pm8941@1 {
 
-		pm8941_s1: regulator@1400 {
-			regulator-min-microvolt = <1300000>;
-			regulator-max-microvolt = <1300000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			regulator-always-on;
-			status = "okay";
-		};
-
-		regulator@1700 {
-			regulator-min-microvolt = <2150000>;
-			regulator-max-microvolt = <2150000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-			regulator-name = "8941_s2_local";
-			regulator-always-on;
-			qcom,system-load = <100000>;
-		};
-
-		pm8941_s3: regulator@1a00 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			regulator-always-on;
-			status = "okay";
-		};
-
 		pm8941_boost: regulator@a000 {
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -49,216 +24,6 @@
 			status = "okay";
 		};
 
-		pm8941_l1: regulator@4000 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1225000>;
-			regulator-max-microvolt = <1225000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			regulator-always-on;
-			status = "okay";
-		};
-
-		pm8941_l2: regulator@4100 {
-			parent-supply = <&pm8941_s3>;
-			regulator-min-microvolt = <1200000>;
-			regulator-max-microvolt = <1200000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l3: regulator@4200 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1225000>;
-			regulator-max-microvolt = <1225000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l4: regulator@4300 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1225000>;
-			regulator-max-microvolt = <1225000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l6: regulator@4500 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l8: regulator@4700 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l9: regulator@4800 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l10: regulator@4900 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l11: regulator@4a00 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1300000>;
-			regulator-max-microvolt = <1300000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		regulator@4b00 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-			regulator-name = "8941_l12_local";
-			regulator-always-on;
-			qcom,system-load = <100000>;
-		};
-
-		pm8941_l13: regulator@4c00 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l14: regulator@4d00 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l15: regulator@4e00 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <2050000>;
-			regulator-max-microvolt = <2050000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l16: regulator@4f00 {
-			regulator-min-microvolt = <2700000>;
-			regulator-max-microvolt = <2700000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l17: regulator@5000 {
-			regulator-min-microvolt = <2850000>;
-			regulator-max-microvolt = <2850000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l18: regulator@5100 {
-			regulator-min-microvolt = <2850000>;
-			regulator-max-microvolt = <2850000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l19: regulator@5200 {
-			regulator-min-microvolt = <2900000>;
-			regulator-max-microvolt = <2900000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l20: regulator@5300 {
-			regulator-min-microvolt = <2950000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l21: regulator@5400 {
-			regulator-min-microvolt = <2950000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l22: regulator@5500 {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l23: regulator@5600 {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_l24: regulator@5700 {
-			regulator-min-microvolt = <3075000>;
-			regulator-max-microvolt = <3075000>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_lvs1: regulator@8000 {
-			parent-supply = <&pm8941_s3>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_lvs2: regulator@8100 {
-			parent-supply = <&pm8941_s3>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8941_lvs3: regulator@8200 {
-			parent-supply = <&pm8941_s3>;
-			qcom,enable-time = <200>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
 		pm8941_mvs1: regulator@8300 {
 			parent-supply = <&pm8941_boost>;
 			qcom,enable-time = <200>;
@@ -273,48 +38,6 @@
 			status = "okay";
 		};
 	};
-
-	qcom,pm8841@5 {
-
-		regulator@1400 {
-			regulator-min-microvolt = <1050000>;
-			regulator-max-microvolt = <1050000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			regulator-always-on;
-			status = "okay";
-			regulator-name = "8841_s1_local";
-			qcom,system-load = <100000>;
-		};
-
-		regulator@1700 {
-			regulator-min-microvolt = <1050000>;
-			regulator-max-microvolt = <1050000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			regulator-always-on;
-			regulator-name = "8841_s2_local";
-			qcom,system-load = <100000>;
-			status = "okay";
-		};
-
-		pm8841_s3: regulator@1a00 {
-			regulator-min-microvolt = <1050000>;
-			regulator-max-microvolt = <1050000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			regulator-always-on;
-			status = "okay";
-		};
-
-		pm8841_s4: regulator@1d00 {
-			regulator-min-microvolt = <900000>;
-			regulator-max-microvolt = <900000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-	};
 };
 
 /* RPM controlled regulators: */
@@ -364,6 +87,39 @@
 		};
 	};
 
+	rpm-regulator-smpb3 {
+		status = "okay";
+		pm8841_s3: regulator-s3 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,init-voltage = <1050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpb4 {
+		status = "okay";
+		pm8841_s4: regulator-s4 {
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
+			qcom,init-voltage = <900000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pm8941_s1: regulator-s1 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1300000>;
+			qcom,init-current = <100>;
+			qcom,system-load = <100000>;
+			regulator-always-on;
+			status = "okay";
+		};
+	};
+
 	rpm-regulator-smpa2 {
 		status = "okay";
 		qcom,allow-atomic = <1>;
@@ -383,6 +139,140 @@
 		};
 	};
 
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pm8941_s3: regulator-s3 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			qcom,init-current = <100>;
+			qcom,system-load = <100000>;
+			regulator-always-on;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pm8941_l1: regulator-l1 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			qcom,init-current = <10>;
+			qcom,system-load = <10000>;
+			regulator-always-on;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pm8941_l2: regulator-l2 {
+			parent-supply = <&pm8941_s3>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pm8941_l3: regulator-l3 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		status = "okay";
+		pm8941_l4: regulator-l4 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pm8941_l5: regulator-l5 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pm8941_l6: regulator-l6 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pm8941_l7: regulator-l7 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pm8941_l8: regulator-l8 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pm8941_l9: regulator-l9 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8941_l10: regulator-l10 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		status = "okay";
+		pm8941_l11: regulator-l11 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1300000>;
+			status = "okay";
+		};
+	};
+
 	rpm-regulator-ldoa12 {
 		status = "okay";
 		qcom,allow-atomic = <1>;
@@ -402,6 +292,152 @@
 			compatible = "qcom,rpm-regulator-smd";
 		};
 	};
+
+	rpm-regulator-ldoa13 {
+		status = "okay";
+		pm8941_l13: regulator-l13 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		pm8941_l14: regulator-l14 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		status = "okay";
+		pm8941_l15: regulator-l15 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <2050000>;
+			regulator-max-microvolt = <2050000>;
+			qcom,init-voltage = <2050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pm8941_l16: regulator-l16 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,init-voltage = <2700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pm8941_l17: regulator-l17 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		status = "okay";
+		pm8941_l18: regulator-l18 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		status = "okay";
+		pm8941_l19: regulator-l19 {
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,init-voltage = <2900000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		status = "okay";
+		pm8941_l20: regulator-l20 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		status = "okay";
+		pm8941_l21: regulator-l21 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		status = "okay";
+		pm8941_l22: regulator-l22 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <3000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		status = "okay";
+		pm8941_l23: regulator-l23 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <3000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		status = "okay";
+		pm8941_l24: regulator-l24 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,init-voltage = <3075000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		status = "okay";
+		pm8941_lvs1: regulator-lvs1 {
+			parent-supply = <&pm8941_s3>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa2 {
+		status = "okay";
+		pm8941_lvs2: regulator-lvs2 {
+			parent-supply = <&pm8941_s3>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-vsa3 {
+		status = "okay";
+		pm8941_lvs3: regulator-lvs3 {
+			parent-supply = <&pm8941_s3>;
+			status = "okay";
+		};
+	};
 };
 
 / {
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f763d49..f27889b 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -289,7 +289,7 @@
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
 obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
-obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o
+obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o clock-mdss-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 6366376..1097907 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -142,6 +142,7 @@
 	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
 	.bus_scale = &bus_scale_data,
 	.qfprom_phys_base = 0x00700000,
+	.stby_khz = 384000,
 };
 
 static int __init acpuclk_8960ab_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 5780ca1..d7568ab 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -62,6 +62,7 @@
 #define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
 #define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
 #define HDMI_PANEL_NAME "hdmi_msm"
+#define MHL_PANEL_NAME "hdmi_msm,mhl_8334"
 #define TVOUT_PANEL_NAME "tvout_msm"
 
 #define LVDS_PIXEL_MAP_PATTERN_1	1
@@ -73,11 +74,18 @@
 static unsigned char hdmi_is_primary;
 #endif
 
+static unsigned char mhl_display_enabled;
+
 unsigned char apq8064_hdmi_as_primary_selected(void)
 {
 	return hdmi_is_primary;
 }
 
+unsigned char apq8064_mhl_display_enabled(void)
+{
+	return mhl_display_enabled;
+}
+
 static void set_mdp_clocks_for_wuxga(void);
 
 static int msm_fb_detect_panel(const char *name)
@@ -1067,7 +1075,15 @@
 			PANEL_NAME_MAX_LEN);
 		pr_debug("msm_fb_pdata.ext_panel_name %s\n",
 			msm_fb_pdata.ext_panel_name);
+
+		if (!strncmp((char *)msm_fb_pdata.ext_panel_name,
+			MHL_PANEL_NAME, strnlen(MHL_PANEL_NAME,
+				PANEL_NAME_MAX_LEN))) {
+			pr_debug("MHL is external display by boot parameter\n");
+			mhl_display_enabled = 1;
+		}
 	}
 
 	msm_fb_pdata.ext_resolution = resolution;
+	hdmi_msm_data.is_mhl_enabled = mhl_display_enabled;
 }
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 2258b8d..50885ad 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -84,6 +84,7 @@
 #define APQ_8064_GSBI5_QUP_I2C_BUS_ID 5
 
 unsigned char apq8064_hdmi_as_primary_selected(void);
+unsigned char apq8064_mhl_display_enabled(void);
 void apq8064_init_fb(void);
 void apq8064_allocate_fb_region(void);
 void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index e9a034e..6add371 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2761,21 +2761,17 @@
 		msm_kgsl_3d0.dev.platform_data;
 	uint32_t soc_platform_version = socinfo_get_version();
 
-	if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
-		kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
-		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
-	}
 	if (cpu_is_msm8960ab()) {
 		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
-	} else {
-
+	} else if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+		kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+		kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+	} else if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
 		/* 8960v3 GPU registers returns 5 for patch release
 		 * but it should be 6, so dummy up the chipid here
 		 * based the platform type
 		 */
-
-		if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3)
-			kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+		kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
 	}
 }
 
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index ac33494..41bc229 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -29,6 +29,7 @@
 #include "clock-pll.h"
 #include "clock-rpm.h"
 #include "clock-voter.h"
+#include "clock-mdss-8974.h"
 
 enum {
 	GCC_BASE,
@@ -518,7 +519,8 @@
 #define edppll_270_mm_source_val 4
 #define edppll_350_mm_source_val 4
 #define dsipll_750_mm_source_val 1
-#define dsipll_250_mm_source_val 2
+#define dsipll0_byte_mm_source_val 1
+#define dsipll0_pixel_mm_source_val 1
 #define hdmipll_297_mm_source_val 3
 
 #define F(f, s, div, m, n) \
@@ -2734,21 +2736,101 @@
 	},
 };
 
-static struct clk_freq_tbl ftbl_mdss_byte0_1_clk[] = {
-	F_MDSS( 93750000, dsipll_750,   8,   0,   0),
-	F_MDSS(187500000, dsipll_750,   4,   0,   0),
-	F_END
+static struct clk *dsi_pll_clk_get_parent(struct clk *c)
+{
+	return &cxo_clk_src.c;
+}
+
+static struct clk dsipll0_byte_clk_src = {
+	.dbg_name = "dsipll0_byte_clk_src",
+	.ops = &clk_ops_dsi_byte_pll,
+	CLK_INIT(dsipll0_byte_clk_src),
 };
 
+static struct clk dsipll0_pixel_clk_src = {
+	.dbg_name = "dsipll0_pixel_clk_src",
+	.ops = &clk_ops_dsi_pixel_pll,
+	CLK_INIT(dsipll0_pixel_clk_src),
+};
+
+static struct clk_freq_tbl byte_freq = {
+	.src_clk = &dsipll0_byte_clk_src,
+	.div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+};
+static struct clk_freq_tbl pixel_freq = {
+	.src_clk = &dsipll0_byte_clk_src,
+	.div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+};
+static struct clk_ops clk_ops_byte;
+static struct clk_ops clk_ops_pixel;
+
+#define CFG_RCGR_DIV_MASK		BM(4, 0)
+
+static int set_rate_byte(struct clk *clk, unsigned long rate)
+{
+	struct rcg_clk *rcg = to_rcg_clk(clk);
+	struct clk *pll = &dsipll0_byte_clk_src;
+	unsigned long source_rate, div;
+	int rc;
+
+	if (rate == 0)
+		return -EINVAL;
+
+	rc = clk_set_rate(pll, rate);
+	if (rc)
+		return rc;
+
+	source_rate = clk_round_rate(pll, rate);
+	if ((2 * source_rate) % rate)
+		return -EINVAL;
+
+	div = ((2 * source_rate)/rate) - 1;
+	if (div > CFG_RCGR_DIV_MASK)
+		return -EINVAL;
+
+	byte_freq.div_src_val &= ~CFG_RCGR_DIV_MASK;
+	byte_freq.div_src_val |= BVAL(4, 0, div);
+	set_rate_mnd(rcg, &byte_freq);
+
+	return 0;
+}
+
+static int set_rate_pixel(struct clk *clk, unsigned long rate)
+{
+	struct rcg_clk *rcg = to_rcg_clk(clk);
+	struct clk *pll = &dsipll0_pixel_clk_src;
+	unsigned long source_rate, div;
+	int rc;
+
+	if (rate == 0)
+		return -EINVAL;
+
+	rc = clk_set_rate(pll, rate);
+	if (rc)
+		return rc;
+
+	source_rate = clk_round_rate(pll, rate);
+	if ((2 * source_rate) % rate)
+		return -EINVAL;
+
+	div = ((2 * source_rate)/rate) - 1;
+	if (div > CFG_RCGR_DIV_MASK)
+		return -EINVAL;
+
+	pixel_freq.div_src_val &= ~CFG_RCGR_DIV_MASK;
+	pixel_freq.div_src_val |= BVAL(4, 0, div);
+	set_rate_hid(rcg, &pixel_freq);
+
+	return 0;
+}
+
 static struct rcg_clk byte0_clk_src = {
 	.cmd_rcgr_reg = BYTE0_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_mdss_byte0_1_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = &byte_freq,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "byte0_clk_src",
-		.ops = &clk_ops_rcg,
+		.ops = &clk_ops_byte,
 		VDD_DIG_FMAX_MAP3(LOW, 93800000, NOMINAL, 187500000,
 				  HIGH, 188000000),
 		CLK_INIT(byte0_clk_src.c),
@@ -2757,13 +2839,11 @@
 
 static struct rcg_clk byte1_clk_src = {
 	.cmd_rcgr_reg = BYTE1_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_mdss_byte0_1_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = &byte_freq,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "byte1_clk_src",
-		.ops = &clk_ops_rcg,
+		.ops = &clk_ops_byte,
 		VDD_DIG_FMAX_MAP3(LOW, 93800000, NOMINAL, 187500000,
 				  HIGH, 188000000),
 		CLK_INIT(byte1_clk_src.c),
@@ -2900,21 +2980,14 @@
 	},
 };
 
-static struct clk_freq_tbl ftbl_mdss_pclk0_1_clk[] = {
-	F_MDSS(125000000, dsipll_250,   2,   0,   0),
-	F_MDSS(250000000, dsipll_250,   1,   0,   0),
-	F_END
-};
 
 static struct rcg_clk pclk0_clk_src = {
 	.cmd_rcgr_reg = PCLK0_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_mdss_pclk0_1_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = &pixel_freq,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "pclk0_clk_src",
-		.ops = &clk_ops_rcg_mnd,
+		.ops = &clk_ops_pixel,
 		VDD_DIG_FMAX_MAP2(LOW, 125000000, NOMINAL, 250000000),
 		CLK_INIT(pclk0_clk_src.c),
 	},
@@ -2922,13 +2995,11 @@
 
 static struct rcg_clk pclk1_clk_src = {
 	.cmd_rcgr_reg = PCLK1_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_mdss_pclk0_1_clk,
-	.current_freq = &rcg_dummy_freq,
+	.current_freq = &pixel_freq,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "pclk1_clk_src",
-		.ops = &clk_ops_rcg_mnd,
+		.ops = &clk_ops_pixel,
 		VDD_DIG_FMAX_MAP2(LOW, 125000000, NOMINAL, 250000000),
 		CLK_INIT(pclk1_clk_src.c),
 	},
@@ -4932,6 +5003,8 @@
 	CLK_LOOKUP("byte_clk", mdss_byte1_clk.c, ""),
 	CLK_LOOKUP("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi"),
 	CLK_LOOKUP("core_clk", mdss_esc1_clk.c, ""),
+	CLK_LOOKUP("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi"),
+	CLK_LOOKUP("pixel_clk", mdss_pclk1_clk.c, ""),
 	CLK_LOOKUP("iface_clk", mdss_hdmi_ahb_clk.c, ""),
 	CLK_LOOKUP("core_clk", mdss_hdmi_clk.c, ""),
 	CLK_LOOKUP("core_clk", mdss_mdp_clk.c, "mdp.0"),
@@ -4997,6 +5070,7 @@
 	CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c, ""),
 	CLK_LOOKUP("bus_clk", camss_vfe_vfe_ocmemnoc_clk.c, ""),
 	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdp.0"),
+	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdss_dsi_clk_ctrl"),
 	CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd928000.qcom,iommu"),
 	CLK_LOOKUP("core_clk", mdss_axi_clk.c, "fd928000.qcom,iommu"),
 	CLK_LOOKUP("bus_clk", mdss_axi_clk.c, "mdp.0"),
@@ -5375,6 +5449,19 @@
 	WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
 }
 
+static void __init mdss_clock_setup(void)
+{
+	clk_ops_byte = clk_ops_rcg_mnd;
+	clk_ops_byte.set_rate = set_rate_byte;
+	clk_ops_dsi_byte_pll.get_parent = dsi_pll_clk_get_parent;
+
+	clk_ops_pixel = clk_ops_rcg;
+	clk_ops_pixel.set_rate = set_rate_pixel;
+	clk_ops_dsi_pixel_pll.get_parent = dsi_pll_clk_get_parent;
+
+	mdss_clk_ctrl_init();
+}
+
 static void __init msm8974_clock_post_init(void)
 {
 	clk_set_rate(&axi_clk_src.c, 282000000);
@@ -5405,6 +5492,8 @@
 	clk_prepare_enable(&gcc_mmss_noc_cfg_ahb_clk.c);
 	clk_prepare_enable(&gcc_ocmem_noc_cfg_ahb_clk.c);
 
+	mdss_clock_setup();
+
 	/* Set rates for single-rate clocks. */
 	clk_set_rate(&usb30_master_clk_src.c,
 			usb30_master_clk_src.freq_tbl[0].freq_hz);
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
index 572cec6f..46e9e0c 100644
--- a/arch/arm/mach-msm/clock-local2.h
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -36,7 +36,7 @@
 	const u32	m_val;
 	const u32	n_val;
 	const u32	d_val;
-	const u32	div_src_val;
+	u32	div_src_val;
 	const unsigned	sys_vdd;
 };
 
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
new file mode 100644
index 0000000..e8aa790
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -0,0 +1,225 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+
+#include "clock.h"
+#include "clock-mdss-8974.h"
+
+#define MDSS_DSI_PHY_BASE_ADR		0xFD922800
+#define DSI_REG_SIZE			2048
+
+#define VCO_CLK				424000000
+static unsigned char *mdss_dsi_base;
+static int pll_byte_clk_rate;
+static int pll_pclk_rate;
+static int pll_initialized;
+static struct clk *mdss_dsi_ahb_clk;
+
+void __init mdss_clk_ctrl_init(void)
+{
+	mdss_dsi_base = ioremap(MDSS_DSI_PHY_BASE_ADR,
+					DSI_REG_SIZE);
+	if (!mdss_dsi_base)
+		pr_err("%s:%d unable to remap dsi base",
+			       __func__, __LINE__);
+
+	mdss_dsi_ahb_clk = clk_get_sys("mdss_dsi_clk_ctrl", "iface_clk");
+	if (!IS_ERR(mdss_dsi_ahb_clk)) {
+		clk_prepare(mdss_dsi_ahb_clk);
+	} else {
+		mdss_dsi_ahb_clk = NULL;
+		pr_err("%s:%d unable to get iface clock\n",
+			       __func__, __LINE__);
+	}
+}
+
+static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized)
+		return pll_byte_clk_rate;
+	else {
+		pr_err("%s: DSI PLL not configured\n",
+				__func__);
+		return -EINVAL;
+	}
+}
+
+static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized)
+		return pll_pclk_rate;
+	else {
+		pr_err("%s: Configure Byte clk first\n",
+				__func__);
+		return -EINVAL;
+	}
+}
+
+static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized)
+		return 0;
+	else {
+		pr_err("%s: Configure Byte clk first\n",
+				__func__);
+		return -EINVAL;
+	}
+}
+
+static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+	int pll_divcfg1, pll_divcfg2;
+	int half_bitclk_rate;
+
+	if (pll_initialized)
+		return 0;
+
+	if (!mdss_dsi_ahb_clk) {
+		pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	clk_enable(mdss_dsi_ahb_clk);
+
+	half_bitclk_rate = rate * 4;
+
+	pll_divcfg1 = (VCO_CLK / half_bitclk_rate) - 2;
+
+	/* Configuring the VCO to 424 Mhz */
+	/* Configuring the half rate Bit clk to 212 Mhz */
+
+	pll_divcfg2 = 3; /* ByteClk is 1/4 the half-bitClk rate */
+
+	/* Configure the Loop filter */
+	/* Loop filter resistance value */
+	writel_relaxed(0x08, mdss_dsi_base + 0x022c);
+	/* Loop filter capacitance values : c1 and c2 */
+	writel_relaxed(0x70, mdss_dsi_base + 0x0230);
+	writel_relaxed(0x15, mdss_dsi_base + 0x0234);
+
+	writel_relaxed(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
+	writel_relaxed(pll_divcfg1, mdss_dsi_base + 0x0204); /* postDiv1 */
+	writel_relaxed(pll_divcfg2, mdss_dsi_base + 0x0224); /* postDiv2 */
+	writel_relaxed(0x03, mdss_dsi_base + 0x0228); /* postDiv3 */
+
+	writel_relaxed(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
+	writel_relaxed(0x06, mdss_dsi_base + 0x027c); /* Cal CFG4 */
+	writel_relaxed(0x05, mdss_dsi_base + 0x0264); /* Cal CFG4 */
+
+	writel_relaxed(0x0a, mdss_dsi_base + 0x023c); /* SDM CFG1 */
+	writel_relaxed(0xab, mdss_dsi_base + 0x0240); /* SDM CFG2 */
+	writel_relaxed(0x0a, mdss_dsi_base + 0x0244); /* SDM CFG3 */
+	writel_relaxed(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
+
+	udelay(10);
+
+	writel_relaxed(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
+	writel_relaxed(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
+	writel_relaxed(0x01, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
+	writel_relaxed(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
+	writel_relaxed(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
+
+	writel_relaxed(0x5f, mdss_dsi_base + 0x028c); /* CAL CFG8 */
+	writel_relaxed(0xa8, mdss_dsi_base + 0x0294); /* CAL CFG10 */
+	writel_relaxed(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
+	writel_relaxed(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
+	writel_relaxed(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
+	writel_relaxed(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
+	writel_relaxed(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
+	writel_relaxed(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
+
+	pll_byte_clk_rate = 53000000;
+	pll_pclk_rate = 105000000;
+
+	clk_disable(mdss_dsi_ahb_clk);
+	pll_initialized = 1;
+
+	return 0;
+}
+
+static int mdss_dsi_pll_enable(struct clk *c)
+{
+	u32 status;
+	u32 max_reads, timeout_us;
+	static int pll_enabled;
+
+	if (pll_enabled)
+		return 0;
+
+	if (!mdss_dsi_ahb_clk) {
+		pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	clk_enable(mdss_dsi_ahb_clk);
+	/* PLL power up */
+	writel_relaxed(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+	writel_relaxed(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(20);
+	writel_relaxed(0x07, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(20);
+	writel_relaxed(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+
+	/* poll for PLL ready status */
+	max_reads = 20;
+	timeout_us = 100;
+	if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+			   status,
+			   ((status & 0x01) == 1),
+				     max_reads, timeout_us)) {
+		pr_err("%s: DSI PLL status=%x failed to Lock\n",
+		       __func__, status);
+		clk_disable(mdss_dsi_ahb_clk);
+		return -EINVAL;
+	}
+	clk_disable(mdss_dsi_ahb_clk);
+	pll_enabled = 1;
+
+	return 0;
+}
+
+static void mdss_dsi_pll_disable(struct clk *c)
+{
+	if (!mdss_dsi_ahb_clk)
+		pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
+				__func__);
+
+	clk_enable(mdss_dsi_ahb_clk);
+	writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
+	clk_disable(mdss_dsi_ahb_clk);
+}
+
+struct clk_ops clk_ops_dsi_pixel_pll = {
+	.enable = mdss_dsi_pll_enable,
+	.disable = mdss_dsi_pll_disable,
+	.set_rate = mdss_dsi_pll_pixel_set_rate,
+	.round_rate = mdss_dsi_pll_pixel_round_rate,
+};
+
+struct clk_ops clk_ops_dsi_byte_pll = {
+	.enable = mdss_dsi_pll_enable,
+	.disable = mdss_dsi_pll_disable,
+	.set_rate = mdss_dsi_pll_byte_set_rate,
+	.round_rate = mdss_dsi_pll_byte_round_rate,
+};
diff --git a/arch/arm/mach-msm/clock-mdss-8974.h b/arch/arm/mach-msm/clock-mdss-8974.h
new file mode 100644
index 0000000..aaf72d2
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8974.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8974
+#define __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8974
+
+void mdss_clk_ctrl_init(void);
+extern struct clk_ops clk_ops_dsi_byte_pll;
+extern struct clk_ops clk_ops_dsi_pixel_pll;
+
+#endif
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index de97186..a3a1574 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -76,8 +76,6 @@
 	enum msm_pm_sleep_mode pm_mode;
 	struct cpuidle_state_usage *st_usage = NULL;
 
-	local_irq_disable();
-
 #ifdef CONFIG_CPU_PM
 	cpu_pm_enter();
 #endif
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index c6a0441..3b262bc 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2848,26 +2848,6 @@
 struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index eac2140..a257a9c 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -853,26 +853,6 @@
 struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 29edf1b..377ecae 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2314,20 +2314,20 @@
 	.mode_8k = {
 		.mode = AFE_PCM_CFG_MODE_PCM,
 		.sync = AFE_PCM_CFG_SYNC_INT,
-		.frame = AFE_PCM_CFG_FRM_256BPF,
+		.frame = AFE_PCM_CFG_FRM_32BPF,
 		.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD,
 		.slot = 0,
 		.data = AFE_PCM_CFG_CDATAOE_MASTER,
-		.pcm_clk_rate = 2048000,
+		.pcm_clk_rate = 256000,
 	},
 	.mode_16k = {
 		.mode = AFE_PCM_CFG_MODE_PCM,
 		.sync = AFE_PCM_CFG_SYNC_INT,
-		.frame = AFE_PCM_CFG_FRM_256BPF,
+		.frame = AFE_PCM_CFG_FRM_32BPF,
 		.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD,
 		.slot = 0,
 		.data = AFE_PCM_CFG_CDATAOE_MASTER,
-		.pcm_clk_rate = 4096000,
+		.pcm_clk_rate = 512000,
 	}
 };
 
@@ -4061,26 +4061,6 @@
 struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 9f31a18..57d7f08 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -3003,26 +3003,6 @@
 struct msm_iommu_domain_name msm8660_iommu_ctx_names[] = {
 	/* Camera */
 	{
-		.name = "vpe_src",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vpe_dst",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_imgwr",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
-		.name = "vfe_misc",
-		.domain = CAMERA_DOMAIN,
-	},
-	/* Camera */
-	{
 		.name = "ijpeg_src",
 		.domain = CAMERA_DOMAIN,
 	},
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 1458afe..7f04be8 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -40,6 +40,15 @@
 #define MSM8974_MPM2_PSHOLD_PHYS	0xFC4AB000
 #define MSM8974_MPM2_PSHOLD_SIZE	SZ_4K
 
+/*
+ * TODO: Revert IMEM_PHYS back to actual
+ * address 0xfe805000
+ * after IMEM issues resolved.
+ *
+ */
+#define MSM8974_IMEM_PHYS	0xFC42B000
+#define MSM8974_IMEM_SIZE	SZ_4K
+
 #ifdef CONFIG_DEBUG_MSM8974_UART
 #define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
 #define MSM_DEBUG_UART_PHYS	0xF991E000
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 89964de..2035d3f 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -301,6 +301,7 @@
 	MSM_CHIP_DEVICE(APCS_GCC, MSM8974),
 	MSM_CHIP_DEVICE(TLMM, MSM8974),
 	MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
+	MSM_CHIP_DEVICE(IMEM, MSM8974),
 	{
 		.virtual =  (unsigned long) MSM_SHARED_RAM_BASE,
 		.length =   MSM_SHARED_RAM_SIZE,
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
index 5f7a95e..ee3672e 100644
--- a/arch/arm/mach-msm/ipc_logging_debug.c
+++ b/arch/arm/mach-msm/ipc_logging_debug.c
@@ -186,6 +186,15 @@
 {
 	tsv_timestamp_read(ectxt, dctxt, " ");
 	tsv_byte_array_read(ectxt, dctxt, "");
+
+	/* add trailing \n if necessary */
+	if (*(dctxt->buff - 1) != '\n') {
+		if (dctxt->size) {
+			++dctxt->buff;
+			--dctxt->size;
+		}
+		*(dctxt->buff - 1) = '\n';
+	}
 }
 
 void check_and_create_debugfs(void)
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 2073856..43c85bb 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -108,6 +108,8 @@
 	int soft_reset_direction =
 		mdm_drv->pdata->soft_reset_inverted ? 1 : 0;
 
+	mdm_peripheral_disconnect(mdm_drv);
+
 	/* Wait for the modem to complete its power down actions. */
 	for (i = 20; i > 0; i--) {
 		if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
@@ -127,7 +129,6 @@
 		*/
 		msleep(4000);
 	}
-	mdm_peripheral_disconnect(mdm_drv);
 }
 
 static void mdm_do_first_power_on(struct mdm_modem_drv *mdm_drv)
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 9ba9f7b1..70bb406 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -21,7 +21,7 @@
 #include <mach/rpm.h>
 #include "msm_bus_core.h"
 
-#define NMASTERS 45
+#define NMASTERS 55
 #define NSLAVES 75
 #define NFAB_8960 5
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 9dcd51f..012bf5a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -26,6 +26,7 @@
 enum {
 	SLAVE_NODE,
 	MASTER_NODE,
+	CLK_NODE,
 };
 
 enum {
@@ -57,7 +58,7 @@
 static int msm_bus_fabric_add_node(struct msm_bus_fabric *fabric,
 	struct msm_bus_inode_info *info)
 {
-	int status = -ENOMEM;
+	int status = -ENOMEM, ctx;
 	MSM_BUS_DBG("msm_bus_fabric_add_node: ID %d Gw: %d\n",
 		info->node_info->priv_id, info->node_info->gateway);
 	status = radix_tree_preload(GFP_ATOMIC);
@@ -71,17 +72,15 @@
 		radix_tree_tag_set(&fabric->fab_tree, info->node_info->priv_id,
 			SLAVE_NODE);
 
-	if (info->node_info->slaveclk[DUAL_CTX]) {
-		info->nodeclk[DUAL_CTX].clk = clk_get_sys("msm_bus",
-			info->node_info->slaveclk[DUAL_CTX]);
-		if (IS_ERR(info->nodeclk[DUAL_CTX].clk)) {
-			MSM_BUS_ERR("Could not get clock for %s\n",
-				info->node_info->slaveclk[DUAL_CTX]);
-			status = -EINVAL;
-			goto out;
+	for (ctx = 0; ctx < NUM_CTX; ctx++) {
+		if (info->node_info->slaveclk[ctx]) {
+			radix_tree_tag_set(&fabric->fab_tree,
+				info->node_info->priv_id, CLK_NODE);
+			break;
 		}
-		info->nodeclk[DUAL_CTX].enable = false;
-		info->nodeclk[DUAL_CTX].dirty = false;
+
+		info->nodeclk[ctx].enable = false;
+		info->nodeclk[ctx].dirty = false;
 	}
 
 out:
@@ -435,11 +434,7 @@
 	unsigned int i, nfound = 0, status = 0;
 	struct msm_bus_inode_info *info[fabric->pdata->nslaves];
 
-	if (fabric->clk_dirty == false) {
-		MSM_BUS_DBG("No clocks have been touched for fabric: %d\n",
-			fabric->fabdev.id);
-		goto out;
-	} else
+	if (fabric->clk_dirty == true)
 		status = msm_bus_fabric_clk_set(enable, &fabric->info);
 
 	if (status)
@@ -447,9 +442,9 @@
 			fabric->fabdev.id);
 
 	nfound = radix_tree_gang_lookup_tag(&fabric->fab_tree, (void **)&info,
-		fabric->fabdev.id, fabric->pdata->nslaves, SLAVE_NODE);
+		fabric->fabdev.id, fabric->pdata->nslaves, CLK_NODE);
 	if (nfound == 0) {
-		MSM_BUS_DBG("No slaves found for fabric: %d\n",
+		MSM_BUS_DBG("No clock nodes found for fabric: %d\n",
 			fabric->fabdev.id);
 		goto out;
 	}
@@ -503,7 +498,7 @@
 	 */
 	status = msm_bus_fabric_clk_commit(DISABLE, fabric);
 	if (status)
-		MSM_BUS_DBG("Error disabling clocks on fabric: %d\n",
+		MSM_BUS_WARN("Error disabling clocks on fabric: %d\n",
 			fabric->fabdev.id);
 	fabric->clk_dirty = false;
 	return status;
diff --git a/arch/arm/mach-msm/msm_memory_dump.c b/arch/arm/mach-msm/msm_memory_dump.c
index 4f48a0d..17cb2da 100644
--- a/arch/arm/mach-msm/msm_memory_dump.c
+++ b/arch/arm/mach-msm/msm_memory_dump.c
@@ -20,7 +20,7 @@
 
 
 /*TODO: Needs to be set to correct value */
-#define DUMP_TABLE_OFFSET	0x20
+#define DUMP_TABLE_OFFSET	0x14
 #define MSM_DUMP_TABLE_VERSION	MK_TABLE(1, 0)
 
 static struct msm_memory_dump mem_dump_data;
@@ -67,7 +67,8 @@
 	table = mem_dump_data.dump_table_ptr;
 	table->version = MSM_DUMP_TABLE_VERSION;
 	mem_dump_data.dump_table_phys = virt_to_phys(table);
-	/* TODO: Need to write physical address of table to IMEM */
+	writel_relaxed(mem_dump_data.dump_table_phys,
+				MSM_IMEM_BASE + DUMP_TABLE_OFFSET);
 	atomic_notifier_chain_register(&panic_notifier_list,
 						&msm_memory_dump_blk);
 	printk(KERN_INFO "MSM Memory Dump table set up\n");
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index ea408f7..af903f8 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -19,6 +19,8 @@
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
 #include <linux/of.h>
 #include <linux/cpu.h>
 #include <linux/platform_device.h>
@@ -54,6 +56,8 @@
 	cpumask_t alive_mask;
 	struct work_struct init_dogwork_struct;
 	struct delayed_work dogwork_struct;
+	bool irq_ppi;
+	struct msm_watchdog_data __percpu **wdog_cpu_dd;
 	struct notifier_block panic_blk;
 };
 
@@ -199,7 +203,7 @@
 		ping_other_cpus(wdog_dd);
 	pet_watchdog(wdog_dd);
 	if (enable)
-		schedule_delayed_work(&wdog_dd->dogwork_struct,
+		schedule_delayed_work_on(0, &wdog_dd->dogwork_struct,
 							delay_time);
 }
 
@@ -218,6 +222,8 @@
 		/* In case we got suspended mid-exit */
 		__raw_writel(0, wdog_dd->base + WDT0_EN);
 	}
+	if (wdog_dd->irq_ppi)
+		free_percpu(wdog_dd->wdog_cpu_dd);
 	printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
 	kzfree(wdog_dd);
 	return 0;
@@ -242,6 +248,13 @@
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t wdog_ppi_bark(int irq, void *dev_id)
+{
+	struct msm_watchdog_data *wdog_dd =
+			*(struct msm_watchdog_data **)(dev_id);
+	return wdog_bark_handler(irq, wdog_dd);
+}
+
 static void configure_bark_dump(struct msm_watchdog_data *wdog_dd)
 {
 	int ret;
@@ -287,6 +300,32 @@
 							init_dogwork_struct);
 	unsigned long delay_time;
 	u64 timeout;
+	int ret;
+
+	if (wdog_dd->irq_ppi) {
+		wdog_dd->wdog_cpu_dd = alloc_percpu(struct msm_watchdog_data *);
+		if (!wdog_dd->wdog_cpu_dd) {
+			dev_err(wdog_dd->dev, "fail to allocate cpu data\n");
+			return;
+		}
+		*__this_cpu_ptr(wdog_dd->wdog_cpu_dd) = wdog_dd;
+		ret = request_percpu_irq(wdog_dd->bark_irq, wdog_ppi_bark,
+					"apps_wdog_bark",
+					wdog_dd->wdog_cpu_dd);
+		if (ret) {
+			dev_err(wdog_dd->dev, "failed to request bark irq\n");
+			free_percpu(wdog_dd->wdog_cpu_dd);
+			return;
+		}
+	} else {
+		ret = devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq,
+				wdog_bark_handler, IRQF_TRIGGER_RISING,
+						"apps_wdog_bark", wdog_dd);
+		if (ret) {
+			dev_err(wdog_dd->dev, "failed to request bark irq\n");
+			return;
+		}
+	}
 	delay_time = msecs_to_jiffies(wdog_dd->pet_time);
 	wdog_dd->min_slack_ticks = UINT_MAX;
 	wdog_dd->min_slack_ns = ULLONG_MAX;
@@ -298,12 +337,14 @@
 	wdog_dd->panic_blk.notifier_call = panic_wdog_handler;
 	atomic_notifier_chain_register(&panic_notifier_list,
 				       &wdog_dd->panic_blk);
-	schedule_delayed_work(&wdog_dd->dogwork_struct, delay_time);
+	schedule_delayed_work_on(0, &wdog_dd->dogwork_struct, delay_time);
 
 	__raw_writel(1, wdog_dd->base + WDT0_EN);
 	__raw_writel(1, wdog_dd->base + WDT0_RST);
 	wdog_dd->last_pet = sched_clock();
 	printk(KERN_INFO "MSM Watchdog Initialized\n");
+	if (wdog_dd->irq_ppi)
+		enable_percpu_irq(wdog_dd->bark_irq, 0);
 	return;
 }
 
@@ -377,6 +418,7 @@
 								__func__);
 		return -ENXIO;
 	}
+	pdata->irq_ppi = irq_is_per_cpu(pdata->bark_irq);
 	dump_pdata(pdata);
 	return 0;
 }
@@ -396,13 +438,6 @@
 		goto err;
 	wdog_dd->dev = &pdev->dev;
 	platform_set_drvdata(pdev, wdog_dd);
-	ret = devm_request_irq(&pdev->dev, wdog_dd->bark_irq, wdog_bark_handler,
-				IRQF_TRIGGER_RISING, "apps_wdog_bark", wdog_dd);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to request bark irq\n");
-		ret = -ENXIO;
-		goto err;
-	}
 	cpumask_clear(&wdog_dd->alive_mask);
 	INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work);
 	INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work);
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 63f7fd9..f1c31c1 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -2038,18 +2038,6 @@
 	podev->pdev = pdev;
 	platform_set_drvdata(pdev, podev);
 
-	if (podev->platform_support.bus_scale_table != NULL) {
-		podev->bus_scale_handle =
-			msm_bus_scale_register_client(
-				(struct msm_bus_scale_pdata *)
-				podev->platform_support.bus_scale_table);
-		if (!podev->bus_scale_handle) {
-			printk(KERN_ERR "%s not able to get bus scale\n",
-								__func__);
-			rc =  -ENOMEM;
-			goto err;
-		}
-	}
 	rc = misc_register(&podev->miscdevice);
 	qce_hw_support(podev->qce, &podev->ce_support);
 	if (podev->ce_support.bam) {
@@ -2070,6 +2058,18 @@
 				platform_support->bus_scale_table;
 		podev->platform_support.sha_hmac = platform_support->sha_hmac;
 	}
+	if (podev->platform_support.bus_scale_table != NULL) {
+		podev->bus_scale_handle =
+			msm_bus_scale_register_client(
+				(struct msm_bus_scale_pdata *)
+				podev->platform_support.bus_scale_table);
+		if (!podev->bus_scale_handle) {
+			pr_err("%s not able to get bus scale\n",
+				__func__);
+			rc =  -ENOMEM;
+			goto err;
+		}
+	}
 	if (rc >= 0)
 		return 0;
 	else
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 3d1fbc8..19dd6dc 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -179,7 +179,7 @@
 		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
 		512, 0, 2, SZ_256K },
 	/* A3XX doesn't use the pix_shader_start */
-	{ ADRENO_REV_A320, 3, 2, 0, ANY_ID,
+	{ ADRENO_REV_A320, 3, 2, ANY_ID, ANY_ID,
 		"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
 		512, 0, 2, SZ_512K },
 	{ ADRENO_REV_A330, 3, 3, 0, 0,
@@ -387,7 +387,7 @@
 
 	if (cpu_is_msm8960())
 		cmds += adreno_add_change_mh_phys_limit_cmds(cmds,
-			reg_map_desc[num_iommu_units - 1]->gpuaddr - PAGE_SIZE,
+			reg_map_desc[0]->gpuaddr,
 			device->mmu.setstate_memory.gpuaddr +
 			KGSL_IOMMU_SETSTATE_NOP_OFFSET);
 	else
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 1eb671f..6dc7dc5 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -121,6 +121,8 @@
 				continue;
 			iommu_drvdata = dev_get_drvdata(
 					iommu_unit->dev[j].dev->parent);
+			if (iommu_drvdata->aclk)
+				clk_disable_unprepare(iommu_drvdata->aclk);
 			if (iommu_drvdata->clk)
 				clk_disable_unprepare(iommu_drvdata->clk);
 			clk_disable_unprepare(iommu_drvdata->pclk);
@@ -247,6 +249,17 @@
 					goto done;
 				}
 			}
+			if (iommu_drvdata->aclk) {
+				ret = clk_prepare_enable(iommu_drvdata->aclk);
+				if (ret) {
+					if (iommu_drvdata->clk)
+						clk_disable_unprepare(
+							iommu_drvdata->clk);
+					clk_disable_unprepare(
+							iommu_drvdata->pclk);
+					goto done;
+				}
+			}
 			iommu_unit->dev[j].clk_enabled = true;
 		}
 	}
@@ -756,9 +769,7 @@
 		kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000001);
 		kgsl_regwrite(mmu->device, MH_MMU_MPU_END,
 			mh->mpu_base +
-			iommu->iommu_units
-				[iommu->unit_count - 1].reg_map.gpuaddr -
-				PAGE_SIZE);
+			iommu->iommu_units[0].reg_map.gpuaddr);
 	} else {
 		kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
 	}
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c6d568c..0d15f75 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -939,7 +939,6 @@
 		server_q_idx = msm_find_free_queue();
 		if (server_q_idx < 0)
 			return server_q_idx;
-
 		rc = msm_server_begin_session(pcam, server_q_idx);
 		if (rc < 0) {
 			pr_err("%s error starting server session ", __func__);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 5b618f8..577648f 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -31,6 +31,7 @@
 #include <media/videobuf2-msm-mem.h>
 #include <media/msm_isp.h>
 #include <mach/camera.h>
+#include <mach/iommu.h>
 #include <media/msm_isp.h>
 #include <linux/ion.h>
 #include <linux/iommu.h>
@@ -315,6 +316,10 @@
 	uint32_t ping_imem_cbcr;
 	uint32_t pong_imem_y;
 	uint32_t pong_imem_cbcr;
+
+	/*IOMMU domain for this session*/
+	int domain_num;
+	struct iommu_domain *domain;
 };
 
 struct msm_isp_buf_info {
@@ -417,6 +422,8 @@
 	struct msm_cam_media_controller *p_mctl;
 	struct msm_mem_map_info mem_map;
 	int dev_num;
+	int domain_num;
+	struct iommu_domain *domain;
 };
 
 struct msm_cam_subdev_info {
@@ -576,6 +583,10 @@
 	 * dispatch the irq to the corresponding subdev. */
 	struct v4l2_subdev *subdev_table[MSM_CAM_HW_MAX];
 	struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
+
+    /*IOMMU domain (Page table)*/
+	int domain_num;
+	struct iommu_domain *domain;
 };
 
 enum msm_cam_buf_lookup_type {
@@ -623,9 +634,9 @@
 	struct msm_free_buf *free_buf);
 /*Memory(PMEM) functions*/
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
-	struct ion_client *client);
+	struct ion_client *client, int domain_num);
 int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
-	struct ion_client *client);
+	struct ion_client *client, int domain_num);
 int msm_pmem_region_get_phy_addr(struct hlist_head *ptype,
 	struct msm_mem_map_info *mem_map, int32_t *phyaddr);
 uint8_t msm_pmem_region_lookup(struct hlist_head *ptype,
@@ -647,7 +658,7 @@
 	struct msm_vfe_cfg_cmd *cfgcmd, void *data);
 int msm_vpe_subdev_init(struct v4l2_subdev *sd);
 int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
-void msm_vpe_subdev_release(void);
+void msm_vpe_subdev_release(struct v4l2_subdev *sd);
 void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
 int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
 	int msg_type);
@@ -695,9 +706,9 @@
 int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
 	int image_mode, struct msm_frame_buffer *buf);
 int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client);
+	struct ion_client *client, int domain_num);
 int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client);
+	struct ion_client *client, int domain_num);
 int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
 	void __user *arg);
 void msm_release_ion_client(struct kref *ref);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index a0cbed5..953f042 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -130,7 +130,8 @@
 			rc = videobuf2_pmem_contig_user_get(mem, &offset,
 				buf_type,
 				pcam_inst->buf_offset[buf_idx][i].addr_offset,
-				pcam_inst->path, pmctl->client);
+				pcam_inst->path, pmctl->client,
+				pmctl->domain_num);
 		else
 			rc = videobuf2_pmem_contig_mmap_get(mem, &offset,
 				buf_type, pcam_inst->path);
@@ -265,7 +266,8 @@
 	}
 	for (i = 0; i < vb->num_planes; i++) {
 		mem = vb2_plane_cookie(vb, i);
-		videobuf2_pmem_contig_user_put(mem, pmctl->client);
+		videobuf2_pmem_contig_user_put(mem, pmctl->client,
+			pmctl->domain_num);
 	}
 	buf->state = MSM_BUFFER_STATE_UNUSED;
 }
@@ -856,21 +858,21 @@
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 /* Unmap using ION APIs */
 static void __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	int i = 0;
 	for (i = 0; i < meta_frame->frame.num_planes; i++) {
 		D("%s Plane %d handle %p", __func__, i,
 			meta_frame->map[i].handle);
 		ion_unmap_iommu(client, meta_frame->map[i].handle,
-					CAMERA_DOMAIN, GEN_POOL);
+					domain_num, 0);
 		ion_free(client, meta_frame->map[i].handle);
 	}
 }
 
 /* Map using ION APIs */
 static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	unsigned long paddr = 0;
 	unsigned long len = 0;
@@ -886,7 +888,7 @@
 			for (j = i-1; j >= 0; j--) {
 				ion_unmap_iommu(client,
 					meta_frame->map[j].handle,
-					CAMERA_DOMAIN, GEN_POOL);
+					domain_num, 0);
 				ion_free(client, meta_frame->map[j].handle);
 			}
 			return -EACCES;
@@ -895,7 +897,7 @@
 			meta_frame->frame.mp[i].fd, i,
 			meta_frame->map[i].handle);
 		if (ion_map_iommu(client, meta_frame->map[i].handle,
-				CAMERA_DOMAIN, GEN_POOL, SZ_4K,
+				domain_num, 0, SZ_4K,
 				0, &paddr, &len, UNCACHED, 0) < 0) {
 			pr_err("%s: cannot map address plane %d", __func__, i);
 			ion_free(client, meta_frame->map[i].handle);
@@ -904,7 +906,7 @@
 				if (meta_frame->map[j].handle) {
 					ion_unmap_iommu(client,
 						meta_frame->map[j].handle,
-						CAMERA_DOMAIN, GEN_POOL);
+						domain_num, 0);
 					ion_free(client,
 						meta_frame->map[j].handle);
 				}
@@ -925,7 +927,7 @@
 				if (meta_frame->map[j].handle) {
 					ion_unmap_iommu(client,
 						meta_frame->map[j].handle,
-						CAMERA_DOMAIN, GEN_POOL);
+						domain_num, 0);
 					ion_free(client,
 						meta_frame->map[j].handle);
 				}
@@ -952,7 +954,7 @@
 #else
 /* Unmap using PMEM APIs */
 static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	int i = 0, rc = 0;
 
@@ -965,7 +967,7 @@
 
 /* Map using PMEM APIs */
 static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	unsigned long kvstart = 0;
 	unsigned long paddr = 0;
@@ -1024,7 +1026,7 @@
 #endif
 
 int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 
 	if ((NULL == meta_frame) || (NULL == client)) {
@@ -1035,16 +1037,16 @@
 	memset(&meta_frame->map[0], 0,
 		sizeof(struct msm_cam_buf_map_info) * VIDEO_MAX_PLANES);
 
-	return __msm_mctl_map_user_frame(meta_frame, client);
+	return __msm_mctl_map_user_frame(meta_frame, client, domain_num);
 }
 
 int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	if ((NULL == meta_frame) || (NULL == client)) {
 		pr_err("%s Invalid input ", __func__);
 		return -EINVAL;
 	}
-	__msm_mctl_unmap_user_frame(meta_frame, client);
+	__msm_mctl_unmap_user_frame(meta_frame, client, domain_num);
 	return 0;
 }
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index e2e9d1b..5136d9d 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -116,7 +116,7 @@
 }
 
 static int msm_pmem_table_add(struct hlist_head *ptype,
-	struct msm_pmem_info *info, struct ion_client *client)
+	struct msm_pmem_info *info, struct ion_client *client, int domain_num)
 {
 	unsigned long paddr;
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -135,7 +135,7 @@
 	region->handle = ion_import_dma_buf(client, info->fd);
 	if (IS_ERR_OR_NULL(region->handle))
 		goto out1;
-	if (ion_map_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL,
+	if (ion_map_iommu(client, region->handle, domain_num, 0,
 				  SZ_4K, 0, &paddr, &len, UNCACHED, 0) < 0)
 		goto out2;
 #elif CONFIG_ANDROID_PMEM
@@ -180,7 +180,7 @@
 	return 0;
 out3:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_unmap_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL);
+	ion_unmap_iommu(client, region->handle, domain_num, 0);
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
@@ -195,7 +195,8 @@
 }
 
 static int __msm_register_pmem(struct hlist_head *ptype,
-			struct msm_pmem_info *pinfo, struct ion_client *client)
+			struct msm_pmem_info *pinfo, struct ion_client *client,
+			int domain_num)
 {
 	int rc = 0;
 
@@ -211,7 +212,7 @@
 	case MSM_PMEM_BAYER_GRID:
 	case MSM_PMEM_BAYER_FOCUS:
 	case MSM_PMEM_BAYER_HIST:
-		rc = msm_pmem_table_add(ptype, pinfo, client);
+		rc = msm_pmem_table_add(ptype, pinfo, client, domain_num);
 		break;
 
 	default:
@@ -223,7 +224,8 @@
 }
 
 static int __msm_pmem_table_del(struct hlist_head *ptype,
-			struct msm_pmem_info *pinfo, struct ion_client *client)
+			struct msm_pmem_info *pinfo, struct ion_client *client,
+			int domain_num)
 {
 	int rc = 0;
 	struct msm_pmem_region *region;
@@ -250,7 +252,7 @@
 				hlist_del(node);
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 				ion_unmap_iommu(client, region->handle,
-					CAMERA_DOMAIN, GEN_POOL);
+					domain_num, 0);
 				ion_free(client, region->handle);
 #else
 				put_pmem_file(region->file);
@@ -394,7 +396,8 @@
 }
 
 int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
-					  struct ion_client *client)
+					struct ion_client *client,
+					int domain_num)
 {
 	struct msm_pmem_info info;
 
@@ -403,12 +406,12 @@
 			return -EFAULT;
 	}
 
-	return __msm_register_pmem(ptype, &info, client);
+	return __msm_register_pmem(ptype, &info, client, domain_num);
 }
 //EXPORT_SYMBOL(msm_register_pmem);
 
 int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
-					   struct ion_client *client)
+			struct ion_client *client, int domain_num)
 {
 	struct msm_pmem_info info;
 
@@ -417,6 +420,6 @@
 		return -EFAULT;
 	}
 
-	return __msm_pmem_table_del(ptype, &info, client);
+	return __msm_pmem_table_del(ptype, &info, client, domain_num);
 }
 //EXPORT_SYMBOL(msm_pmem_table_del);
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 9fa9734..ede0f7a 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -36,8 +36,8 @@
 #define D(fmt, args...) do {} while (0)
 #endif
 
-static int vpe_enable(uint32_t);
-static int vpe_disable(void);
+static int vpe_enable(uint32_t, struct msm_cam_media_controller *);
+static int vpe_disable(struct msm_cam_media_controller *);
 static int vpe_update_scaler(struct msm_pp_crop *pcrop);
 struct vpe_ctrl_type *vpe_ctrl;
 static atomic_t vpe_init_done = ATOMIC_INIT(0);
@@ -520,7 +520,7 @@
 	{"vpe_pclk", -1},
 };
 
-int vpe_enable(uint32_t clk_rate)
+int vpe_enable(uint32_t clk_rate, struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 	unsigned long flags = 0;
@@ -549,8 +549,27 @@
 	if (rc < 0)
 		goto vpe_clk_failed;
 
+#ifdef CONFIG_MSM_IOMMU
+	rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+	if (rc < 0) {
+		pr_err("%s: Device attach failed\n", __func__);
+		goto src_attach_failed;
+	}
+	rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+	if (rc < 0) {
+		pr_err("%s: Device attach failed\n", __func__);
+		goto dst_attach_failed;
+	}
+#endif
 	return rc;
 
+#ifdef CONFIG_MSM_IOMMU
+dst_attach_failed:
+	iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+src_attach_failed:
+#endif
+	msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+		vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
 vpe_clk_failed:
 	if (vpe_ctrl->fs_vpe)
 		regulator_disable(vpe_ctrl->fs_vpe);
@@ -560,7 +579,7 @@
 	return rc;
 }
 
-int vpe_disable(void)
+int vpe_disable(struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 	unsigned long flags = 0;
@@ -572,7 +591,10 @@
 		return rc;
 	}
 	spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-
+#ifdef CONFIG_MSM_IOMMU
+	iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+	iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+#endif
 	disable_irq(vpe_ctrl->vpeirq->start);
 	tasklet_kill(&vpe_tasklet);
 	msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
@@ -655,23 +677,25 @@
 	return rc;  /* this rc should have error code. */
 }
 
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
 {
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	if (!atomic_read(&vpe_init_done)) {
 		/* no VPE object created */
 		pr_err("%s: no VPE object to release", __func__);
 		return;
 	}
-
 	vpe_reset();
-	vpe_disable();
+	vpe_disable(mctl);
 	iounmap(vpe_ctrl->vpebase);
 	vpe_ctrl->vpebase = NULL;
 	atomic_set(&vpe_init_done, 0);
 }
 EXPORT_SYMBOL(msm_vpe_subdev_release);
 
-static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
+static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd,
+				struct msm_cam_media_controller *mctl)
 {
 	int rc = 0;
 
@@ -802,7 +826,7 @@
 		D("%s Mapping Source frame ", __func__);
 		zoom->src_frame.frame = zoom->pp_frame_cmd.src_frame;
 		rc = msm_mctl_map_user_frame(&zoom->src_frame,
-			zoom->p_mctl->client);
+			zoom->p_mctl->client, mctl->domain_num);
 		if (rc < 0) {
 			pr_err("%s Error mapping source buffer rc = %d",
 				__func__, rc);
@@ -813,12 +837,12 @@
 		D("%s Mapping Destination frame ", __func__);
 		zoom->dest_frame.frame = zoom->pp_frame_cmd.dest_frame;
 		rc = msm_mctl_map_user_frame(&zoom->dest_frame,
-			zoom->p_mctl->client);
+			zoom->p_mctl->client, mctl->domain_num);
 		if (rc < 0) {
 			pr_err("%s Error mapping dest buffer rc = %d",
 				__func__, rc);
 			msm_mctl_unmap_user_frame(&zoom->src_frame,
-				zoom->p_mctl->client);
+				zoom->p_mctl->client, mctl->domain_num);
 			kfree(zoom);
 			break;
 		}
@@ -843,13 +867,13 @@
 			return -EFAULT;
 		}
 		turbo_mode = (int)clk_rate.rate;
-		rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
-				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
+		rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE, mctl) :
+				vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE, mctl);
 		break;
 		}
 
 	case VPE_CMD_DISABLE:
-		rc = vpe_disable();
+		rc = vpe_disable(mctl);
 		break;
 
 	default:
@@ -864,7 +888,8 @@
 {
 	struct msm_vpe_cfg_cmd *vpe_cmd;
 	int rc = 0;
-
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	switch (cmd) {
 	case VIDIOC_MSM_VPE_INIT: {
 		msm_vpe_subdev_init(sd);
@@ -872,12 +897,12 @@
 		}
 
 	case VIDIOC_MSM_VPE_RELEASE:
-		msm_vpe_subdev_release();
+		msm_vpe_subdev_release(sd);
 		break;
 
 	case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
 		vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
-		rc = msm_vpe_process_vpe_cmd(vpe_cmd);
+		rc = msm_vpe_process_vpe_cmd(vpe_cmd, mctl);
 		if (rc < 0) {
 			pr_err("%s Error processing VPE cmd %d ",
 				__func__, vpe_cmd->cmd_type);
@@ -903,9 +928,9 @@
 		D("%s Unmapping source and destination buffers ",
 			__func__);
 		msm_mctl_unmap_user_frame(&pp_frame_info->src_frame,
-			pp_frame_info->p_mctl->client);
+			pp_frame_info->p_mctl->client, mctl->domain_num);
 		msm_mctl_unmap_user_frame(&pp_frame_info->dest_frame,
-			pp_frame_info->p_mctl->client);
+			pp_frame_info->p_mctl->client, mctl->domain_num);
 
 		pp_event_info.event = MCTL_PP_EVENT_CMD_ACK;
 		pp_event_info.ack.cmd = pp_frame_info->user_cmd;
@@ -973,7 +998,8 @@
 {
 	struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
 	struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
-
+	struct msm_cam_media_controller *mctl;
+	mctl = v4l2_get_subdev_hostdata(sd);
 	if (atomic_read(&vpe_ctrl->active) == 0) {
 		pr_err("%s already closed\n", __func__);
 		return -EINVAL;
@@ -983,9 +1009,9 @@
 	if (frame_info) {
 		D("%s Unmap the pending item from the queue ", __func__);
 		msm_mctl_unmap_user_frame(&frame_info->src_frame,
-			frame_info->p_mctl->client);
+			frame_info->p_mctl->client, mctl->domain_num);
 		msm_mctl_unmap_user_frame(&frame_info->dest_frame,
-			frame_info->p_mctl->client);
+			frame_info->p_mctl->client, mctl->domain_num);
 	}
 	/* Drain the payload queue. */
 	msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
@@ -1066,6 +1092,19 @@
 
 	disable_irq(vpe_ctrl->vpeirq->start);
 
+#ifdef CONFIG_MSM_IOMMU
+	/*get device context for IOMMU*/
+	vpe_ctrl->iommu_ctx_src = msm_iommu_get_ctx("vpe_src"); /*re-confirm*/
+	vpe_ctrl->iommu_ctx_dst = msm_iommu_get_ctx("vpe_dst"); /*re-confirm*/
+	if (!vpe_ctrl->iommu_ctx_src || !vpe_ctrl->iommu_ctx_dst) {
+		release_mem_region(vpe_ctrl->vpemem->start,
+			resource_size(vpe_ctrl->vpemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vpe_no_resource;
+	}
+#endif
+
 	atomic_set(&vpe_ctrl->active, 0);
 	vpe_ctrl->pdev = pdev;
 	sd_info.sdev_type = VPE_DEV;
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 6516ea1..aad2380 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -121,6 +121,8 @@
 	struct msm_mctl_pp_frame_info *pp_frame_info;
 	atomic_t active;
 	struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
+	struct device *iommu_ctx_src;
+	struct device *iommu_ctx_dst;
 };
 
 /*
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index f8c102f..b8a6217 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -160,6 +160,16 @@
 			g_server_dev.interface_map_table[i].mctl_handle = 0;
 }
 
+struct iommu_domain *msm_cam_server_get_domain()
+{
+	return g_server_dev.domain;
+}
+
+int msm_cam_server_get_domain_num()
+{
+	return g_server_dev.domain_num;
+}
+
 uint32_t msm_cam_server_get_mctl_handle(void)
 {
 	uint32_t i;
@@ -1056,7 +1066,7 @@
 {
 	int rc = 0;
 	rc = msm_iommu_map_contig_buffer(
-		(unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		(unsigned long)IMEM_Y_PING_OFFSET, mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
 		SZ_4K, IOMMU_WRITE | IOMMU_READ,
 		(unsigned long *)&mctl->ping_imem_y);
@@ -1068,7 +1078,7 @@
 		mctl->ping_imem_cbcr = 0;
 	}
 	msm_iommu_map_contig_buffer(
-		(unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+		(unsigned long)IMEM_Y_PONG_OFFSET, mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
 		SZ_4K, IOMMU_WRITE | IOMMU_READ,
 		(unsigned long *)&mctl->pong_imem_y);
@@ -1085,10 +1095,10 @@
 static void unmap_imem_addresses(struct msm_cam_media_controller *mctl)
 {
 	msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
-		CAMERA_DOMAIN, GEN_POOL,
+		mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
 	msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
-		CAMERA_DOMAIN, GEN_POOL,
+		mctl->domain_num, 0,
 		((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
 	mctl->ping_imem_y = 0;
 	mctl->ping_imem_cbcr = 0;
@@ -1471,6 +1481,10 @@
 		pr_err("%s: invalid mctl controller", __func__);
 		goto error;
 	}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		pmctl->domain = msm_cam_server_get_domain();
+		pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
 	rc = map_imem_addresses(pmctl);
 	if (rc < 0) {
 		pr_err("%sFailed to map imem addresses %d\n", __func__, rc);
@@ -2215,6 +2229,23 @@
 	return err;
 }
 
+#ifdef CONFIG_MSM_IOMMU
+static int camera_register_domain(void)
+{
+	struct msm_iova_partition camera_fw_partition = {
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	};
+	struct msm_iova_layout camera_fw_layout = {
+		.partitions = &camera_fw_partition,
+		.npartitions = 1,
+		.client_name = "camera_isp",
+		.domain_flags = 0,
+	};
+
+	return msm_register_domain(&camera_fw_layout);
+}
+#endif
 
 static int msm_setup_server_dev(struct platform_device *pdev)
 {
@@ -2291,6 +2322,21 @@
 		g_server_dev.interface_map_table[i].interface = 0x01 << i;
 		g_server_dev.interface_map_table[i].mctl_handle = 0;
 	}
+#ifdef CONFIG_MSM_IOMMU
+	g_server_dev.domain_num = camera_register_domain();
+	if (g_server_dev.domain_num < 0) {
+		pr_err("%s: could not register domain\n", __func__);
+		rc = -ENODEV;
+		return rc;
+	}
+	g_server_dev.domain =
+		msm_get_iommu_domain(g_server_dev.domain_num);
+	if (!g_server_dev.domain) {
+		pr_err("%s: cannot find domain\n", __func__);
+		rc = -ENODEV;
+		return rc;
+	}
+#endif
 	return rc;
 }
 
@@ -2348,6 +2394,11 @@
 		return rc;
 	}
 
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+		pmctl->domain = msm_cam_server_get_domain();
+		pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
+
 	D("%s: call mctl_open\n", __func__);
 	rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
 
@@ -2620,6 +2671,7 @@
 		pr_err("%s: cannot find mctl\n", __func__);
 		return -ENODEV;
 	}
+
 	INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
 	spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
 
@@ -2733,13 +2785,15 @@
 	case MSM_CAM_IOCTL_REGISTER_PMEM:
 		return msm_register_pmem(
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
-			(void __user *)arg, config_cam->p_mctl->client);
+			(void __user *)arg, config_cam->p_mctl->client,
+			config_cam->p_mctl->domain_num);
 		break;
 
 	case MSM_CAM_IOCTL_UNREGISTER_PMEM:
 		return msm_pmem_table_del(
 			&config_cam->p_mctl->stats_info.pmem_stats_list,
-			(void __user *)arg, config_cam->p_mctl->client);
+			(void __user *)arg, config_cam->p_mctl->client,
+			config_cam->p_mctl->domain_num);
 		break;
 
 	case VIDIOC_SUBSCRIBE_EVENT:
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 42900f3..d38bb98 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -20,6 +20,8 @@
 #include "msm.h"
 
 uint32_t msm_cam_server_get_mctl_handle(void);
+struct iommu_domain *msm_cam_server_get_domain(void);
+int msm_cam_server_get_domain_num(void);
 struct msm_cam_media_controller *msm_cam_server_get_mctl(uint32_t handle);
 void msm_cam_server_free_mctl(uint32_t handle);
 /* Server session control APIs */
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
index 0bd7b94..2179282 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
@@ -401,7 +401,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe31_ctrl->stats_ops.enqueue_buf(
 				vfe31_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 		if (rc < 0) {
 			pr_err("%s: dq stats buf (type = %d) err = %d",
 				__func__, stats_type, rc);
@@ -412,7 +412,7 @@
 }
 
 static unsigned long vfe31_stats_unregbuf(
-	struct msm_stats_reqbuf *req_buf)
+	struct msm_stats_reqbuf *req_buf, int domain_num)
 {
 	int i = 0, rc = 0;
 
@@ -420,7 +420,7 @@
 		rc = vfe31_ctrl->stats_ops.buf_unprepare(
 			vfe31_ctrl->stats_ops.stats_ctrl,
 			req_buf->stats_type, i,
-			vfe31_ctrl->stats_ops.client);
+			vfe31_ctrl->stats_ops.client, domain_num);
 		if (rc < 0) {
 			pr_err("%s: unreg stats buf (type = %d) err = %d",
 				__func__, req_buf->stats_type, rc);
@@ -3296,7 +3296,7 @@
 }
 
 static long vfe_stats_bufq_sub_ioctl(struct msm_vfe_cfg_cmd *cmd,
-	void *ion_client)
+	void *ion_client, int domain_num)
 {
 	long rc = 0;
 	switch (cmd->cmd_type) {
@@ -3344,7 +3344,7 @@
 		}
 		rc = vfe31_ctrl->stats_ops.enqueue_buf(&vfe31_ctrl->stats_ctrl,
 				(struct msm_stats_buf_info *)cmd->value,
-				vfe31_ctrl->stats_ops.client);
+				vfe31_ctrl->stats_ops.client, domain_num);
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ: {
 		struct msm_stats_flush_bufq *flush_req = NULL;
@@ -3376,7 +3376,7 @@
 			rc = -EINVAL ;
 			goto end;
 		}
-		rc = vfe31_stats_unregbuf(req_buf);
+		rc = vfe31_stats_unregbuf(req_buf, domain_num);
 	}
 	break;
 	default:
@@ -3630,7 +3630,8 @@
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 	case VFE_CMD_STATS_UNREGBUF:
 		/* for easy porting put in one envelope */
-		rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data);
+		rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data,
+			pmctl->domain_num);
 		return rc;
 	default:
 		if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -4003,10 +4004,25 @@
 			vfe31_ctrl->vfe_camif_clk,
 			ARRAY_SIZE(vfe_camif_clk_info), 1);
 		if (rc < 0)
-			goto vfe_clk_enable_failed;
+			goto vfe_camif_clk_enable_failed;
 		msm_vfe_camif_pad_reg_reset();
 	}
 
+#ifdef CONFIG_MSM_IOMMU
+	rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+	if (rc < 0) {
+		rc = -ENODEV;
+		pr_err("%s: Device attach failed\n", __func__);
+		goto device_imgwr_attach_failed;
+	}
+	rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_misc);
+	if (rc < 0) {
+		rc = -ENODEV;
+		pr_err("%s: Device attach failed\n", __func__);
+		goto device_misc_attach_failed;
+	}
+#endif
+
 	msm_camio_bus_scale_cfg(
 		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
 	msm_camio_bus_scale_cfg(
@@ -4017,6 +4033,19 @@
 
 	return rc;
 
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+	iommu_detach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+	if (!mctl->sdata->csi_if)
+		msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
+			vfe_camif_clk_info,
+			vfe31_ctrl->vfe_camif_clk,
+			ARRAY_SIZE(vfe_camif_clk_info), 0);
+vfe_camif_clk_enable_failed:
+	msm_cam_clk_enable(&vfe31_ctrl->pdev->dev, vfe_clk_info,
+		vfe31_ctrl->vfe_clk, ARRAY_SIZE(vfe_clk_info), 0);
 vfe_clk_enable_failed:
 	regulator_disable(vfe31_ctrl->fs_vfe);
 vfe_fs_failed:
@@ -4025,7 +4054,6 @@
 camif_remap_failed:
 	iounmap(vfe31_ctrl->vfebase);
 vfe_remap_failed:
-	disable_irq(vfe31_ctrl->vfeirq->start);
 mctl_failed:
 	return rc;
 }
@@ -4037,6 +4065,11 @@
 	disable_irq(vfe31_ctrl->vfeirq->start);
 	tasklet_kill(&vfe31_tasklet);
 
+#ifdef CONFIG_MSM_IOMMU
+	iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_misc);
+	iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+#endif
+
 	if (!pmctl->sdata->csi_if)
 		msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
 			vfe_camif_clk_info,
@@ -4140,6 +4173,25 @@
 
 	disable_irq(vfe31_ctrl->vfeirq->start);
 
+#ifdef CONFIG_MSM_IOMMU
+	/*get device context for IOMMU*/
+	vfe31_ctrl->iommu_ctx_imgwr =
+		msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+	vfe31_ctrl->iommu_ctx_misc =
+		msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+	if (!vfe31_ctrl->iommu_ctx_imgwr || !vfe31_ctrl->iommu_ctx_misc) {
+		if (vfe31_ctrl->camifmem) {
+			release_mem_region(vfe31_ctrl->camifmem->start,
+				resource_size(vfe31_ctrl->camifmem));
+		}
+		release_mem_region(vfe31_ctrl->vfemem->start,
+			resource_size(vfe31_ctrl->vfemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vfe31_no_resource;
+	}
+#endif
+
 	vfe31_ctrl->pdev = pdev;
 	vfe31_ctrl->fs_vfe = regulator_get(&vfe31_ctrl->pdev->dev, "vdd");
 	if (IS_ERR(vfe31_ctrl->fs_vfe)) {
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
index 60db8e5..97ecd6e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
@@ -928,6 +928,8 @@
 	uint32_t snapshot_frame_cnt;
 	struct msm_stats_bufq_ctrl stats_ctrl;
 	struct msm_stats_ops stats_ops;
+	struct device *iommu_ctx_imgwr;
+	struct device *iommu_ctx_misc;
 };
 
 enum VFE31_STATS_NUM {
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 84a36b9..908f3fb 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -995,7 +995,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe32_ctrl->stats_ops.enqueue_buf(
 				vfe32_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 		if (rc < 0) {
 			pr_err("%s: dq stats buf (type = %d) err = %d",
 				 __func__, stats_type, rc);
@@ -1008,7 +1008,7 @@
 
 static unsigned long vfe32_stats_unregbuf(
 	struct vfe32_ctrl_type *vfe32_ctrl,
-	struct msm_stats_reqbuf *req_buf)
+	struct msm_stats_reqbuf *req_buf, int domain_num)
 {
 	int i = 0, rc = 0;
 
@@ -1016,7 +1016,7 @@
 		rc = vfe32_ctrl->stats_ops.buf_unprepare(
 			vfe32_ctrl->stats_ops.stats_ctrl,
 			req_buf->stats_type, i,
-			vfe32_ctrl->stats_ops.client);
+			vfe32_ctrl->stats_ops.client, domain_num);
 		if (rc < 0) {
 			pr_err("%s: unreg stats buf (type = %d) err = %d",
 				__func__, req_buf->stats_type, rc);
@@ -4910,7 +4910,7 @@
 
 static long vfe_stats_bufq_sub_ioctl(
 	struct vfe32_ctrl_type *vfe_ctrl,
-	struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+	struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
 {
 	long rc = 0;
 	switch (cmd->cmd_type) {
@@ -4959,7 +4959,7 @@
 	rc = vfe_ctrl->stats_ops.enqueue_buf(
 			&vfe_ctrl->stats_ctrl,
 			(struct msm_stats_buf_info *)cmd->value,
-			vfe_ctrl->stats_ops.client);
+			vfe_ctrl->stats_ops.client, domain_num);
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 	{
@@ -4993,7 +4993,7 @@
 			rc = -EINVAL ;
 			goto end;
 		}
-		rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf);
+		rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf, domain_num);
 	}
 	break;
 	default:
@@ -5048,7 +5048,7 @@
 	case VFE_CMD_STATS_UNREGBUF:
 		/* for easy porting put in one envelope */
 		rc = vfe_stats_bufq_sub_ioctl(vfe32_ctrl,
-				cmd, vfe_params->data);
+				cmd, vfe_params->data, pmctl->domain_num);
 		return rc;
 	default:
 		if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -5273,6 +5273,21 @@
 	if (rc < 0)
 		goto clk_enable_failed;
 
+#ifdef CONFIG_MSM_IOMMU
+	rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+	if (rc < 0) {
+		pr_err("%s: imgwr attach failed rc = %d\n", __func__, rc);
+		rc = -ENODEV;
+		goto device_imgwr_attach_failed;
+	}
+	rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_misc);
+	if (rc < 0) {
+		pr_err("%s: misc attach failed rc = %d\n", __func__, rc);
+		rc = -ENODEV;
+		goto device_misc_attach_failed;
+	}
+#endif
+
 	msm_camio_bus_scale_cfg(
 		mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
 	msm_camio_bus_scale_cfg(
@@ -5293,6 +5308,13 @@
 
 	return rc;
 
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+	iommu_detach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
+			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
 clk_enable_failed:
 	if (axi_ctrl->fs_vfe)
 		regulator_disable(axi_ctrl->fs_vfe);
@@ -5300,7 +5322,6 @@
 	iounmap(axi_ctrl->share_ctrl->vfebase);
 	axi_ctrl->share_ctrl->vfebase = NULL;
 remap_failed:
-	disable_irq(axi_ctrl->vfeirq->start);
 mctl_failed:
 	return rc;
 }
@@ -5344,6 +5365,10 @@
 		return;
 	disable_irq(axi_ctrl->vfeirq->start);
 	tasklet_kill(&axi_ctrl->vfe32_tasklet);
+#ifdef CONFIG_MSM_IOMMU
+	iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_misc);
+	iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_imgwr);
+#endif
 	msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
 			axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
 	if (axi_ctrl->fs_vfe)
@@ -6396,6 +6421,21 @@
 		goto vfe32_no_resource;
 	}
 
+#ifdef CONFIG_MSM_IOMMU
+	/*get device context for IOMMU*/
+	axi_ctrl->iommu_ctx_imgwr =
+		msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+	axi_ctrl->iommu_ctx_misc =
+		msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+	if (!axi_ctrl->iommu_ctx_imgwr || !axi_ctrl->iommu_ctx_misc) {
+		release_mem_region(axi_ctrl->vfemem->start,
+			resource_size(axi_ctrl->vfemem));
+		pr_err("%s: No iommu fw context found\n", __func__);
+		rc = -ENODEV;
+		goto vfe32_no_resource;
+	}
+#endif
+
 	tasklet_init(&axi_ctrl->vfe32_tasklet,
 		axi32_do_tasklet, (unsigned long)axi_ctrl);
 
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index 81df0d5..985493e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -1006,6 +1006,8 @@
 	struct clk *vfe_clk[3];
 	struct tasklet_struct vfe32_tasklet;
 	struct vfe_share_ctrl_t *share_ctrl;
+	struct device *iommu_ctx_imgwr;
+	struct device *iommu_ctx_misc;
 };
 
 struct vfe32_ctrl_type {
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.c b/drivers/media/video/msm/vfe/msm_vfe40.c
index 1aee087..875e034 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40.c
@@ -415,7 +415,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe40_ctrl->stats_ops.enqueue_buf(
 				vfe40_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 		if (rc < 0) {
 			pr_err("%s: dq stats buf (type = %d) err = %d",
 				 __func__, stats_type, rc);
@@ -3308,7 +3308,7 @@
 
 static long vfe_stats_bufq_sub_ioctl(
 	struct vfe40_ctrl_type *vfe_ctrl,
-	struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+	struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
 {
 	long rc = 0;
 	switch (cmd->cmd_type) {
@@ -3357,7 +3357,7 @@
 	rc = vfe_ctrl->stats_ops.enqueue_buf(
 			&vfe_ctrl->stats_ctrl,
 			(struct msm_stats_buf_info *)cmd->value,
-			vfe_ctrl->stats_ops.client);
+			vfe_ctrl->stats_ops.client, domain_num);
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 	{
@@ -3419,7 +3419,7 @@
 	case VFE_CMD_STATS_FLUSH_BUFQ:
 		/* for easy porting put in one envelope */
 		rc = vfe_stats_bufq_sub_ioctl(vfe40_ctrl,
-				cmd, vfe_params->data);
+				cmd, vfe_params->data, pmctl->domain_num);
 		return rc;
 	default:
 		if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 460eb07..75d9293 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -395,7 +395,7 @@
 		stats_buf = &bufq->bufs[i];
 		rc = vfe2x_ctrl->stats_ops.enqueue_buf(
 				vfe2x_ctrl->stats_ops.stats_ctrl,
-				&(stats_buf->info), NULL);
+				&(stats_buf->info), NULL, -1);
 			if (rc < 0) {
 				pr_err("%s: dq stats buf (type = %d) err = %d",
 					 __func__, stats_type, rc);
@@ -414,7 +414,7 @@
 		rc = vfe2x_ctrl->stats_ops.buf_unprepare(
 			vfe2x_ctrl->stats_ops.stats_ctrl,
 			req_buf->stats_type, i,
-			vfe2x_ctrl->stats_ops.client);
+			vfe2x_ctrl->stats_ops.client, -1);
 		if (rc < 0) {
 			pr_err("%s: unreg stats buf (type = %d) err = %d",
 				__func__, req_buf->stats_type, rc);
@@ -473,7 +473,7 @@
 		stats_buf->state == MSM_STATS_BUFFER_STATE_PREPARED) {
 		rc = vfe2x_ctrl->stats_ops.enqueue_buf(
 				&vfe2x_ctrl->stats_ctrl,
-				info, vfe2x_ctrl->stats_ops.client);
+				info, vfe2x_ctrl->stats_ops.client, -1);
 		if (rc < 0) {
 			pr_err("%s: enqueue_buf (type = %d), index : %d, err = %d",
 				 __func__, info->type, info->buf_idx, rc);
@@ -555,7 +555,7 @@
 		rc = vfe2x_ctrl->stats_ops.enqueue_buf(
 				&vfe2x_ctrl->stats_ctrl,
 				(struct msm_stats_buf_info *)cmd->value,
-				vfe2x_ctrl->stats_ops.client);
+				vfe2x_ctrl->stats_ops.client, -1);
 	}
 	break;
 	case VFE_CMD_STATS_FLUSH_BUFQ: {
@@ -2352,7 +2352,7 @@
 	return 0;
 }
 
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
 {
 	return;
 }
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
index 5fbcdb1..5820d76 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
@@ -182,7 +182,8 @@
 #endif
 
 static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl,
-	struct msm_stats_buf_info *info, struct ion_client *client)
+	struct msm_stats_buf_info *info, struct ion_client *client,
+	int domain_num)
 {
 	unsigned long paddr;
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -219,7 +220,7 @@
 		goto out1;
 	}
 	if (ion_map_iommu(client, stats_buf->handle,
-			CAMERA_DOMAIN, GEN_POOL, SZ_4K,
+			domain_num, 0, SZ_4K,
 			0, &paddr, &len, UNCACHED, 0) < 0) {
 		rc = -EINVAL;
 		pr_err("%s: cannot map address", __func__);
@@ -257,7 +258,7 @@
 	return 0;
 out3:
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_unmap_iommu(client, stats_buf->handle, CAMERA_DOMAIN, GEN_POOL);
+	ion_unmap_iommu(client, stats_buf->handle, domain_num, 0);
 #endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 out2:
@@ -270,7 +271,7 @@
 }
 static int msm_stats_buf_unprepare(struct msm_stats_bufq_ctrl *stats_ctrl,
 	enum msm_stats_enum_type stats_type, int buf_idx,
-	struct ion_client *client)
+	struct ion_client *client, int domain_num)
 {
 	int rc = 0;
 	struct msm_stats_bufq *bufq = NULL;
@@ -292,7 +293,7 @@
 	}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	ion_unmap_iommu(client, stats_buf->handle,
-					CAMERA_DOMAIN, GEN_POOL);
+					domain_num, 0);
 	ion_free(client, stats_buf->handle);
 #else
 	put_pmem_file(stats_buf->file);
@@ -472,12 +473,13 @@
 	return rc;
 }
 static int msm_stats_enqueue_buf(struct msm_stats_bufq_ctrl *stats_ctrl,
-	struct msm_stats_buf_info *info, struct ion_client *client)
+	struct msm_stats_buf_info *info, struct ion_client *client,
+	int domain_num)
 {
 	int rc = 0;
 	D("%s: stats type : %d, idx : %d\n", __func__,
 		info->type, info->buf_idx);
-	rc = msm_stats_buf_prepare(stats_ctrl, info, client);
+	rc = msm_stats_buf_prepare(stats_ctrl, info, client, domain_num);
 	if (rc < 0) {
 		pr_err("%s: buf_prepare failed, rc = %d", __func__, rc);
 		return -EINVAL;
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
index 18fd425..bf3e70e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
@@ -55,8 +55,8 @@
 	struct msm_stats_bufq_ctrl *stats_ctrl;
 	struct ion_client *client;
 	int (*enqueue_buf) (struct msm_stats_bufq_ctrl *stats_ctrl,
-						struct msm_stats_buf_info *info,
-						struct ion_client *client);
+				struct msm_stats_buf_info *info,
+				struct ion_client *client, int domain_num);
 	int (*qbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
 				 enum msm_stats_enum_type stats_type,
 				 int buf_idx);
@@ -69,10 +69,10 @@
 	int (*buf_unprepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
 		enum msm_stats_enum_type stats_type,
 		int buf_idx,
-		struct ion_client *client);
+		struct ion_client *client, int domain_num);
 	int (*buf_prepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
-						struct msm_stats_buf_info *info,
-						struct ion_client *client);
+				struct msm_stats_buf_info *info,
+				struct ion_client *client, int domain_num);
 	int (*reqbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
 				   struct msm_stats_reqbuf *reqbuf,
 				   struct ion_client *client);
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index d48240a..16fb14d 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -81,12 +81,11 @@
 		goto fail_device_address;
 	}
 
-	mem->kvaddr += offset;
 	mem->mem_type = client->mem_type;
 	mem->smem_priv = hndl;
-	mem->device_addr = iova + offset;
+	mem->device_addr = iova;
 	mem->size = buffer_size;
-	pr_debug("Buffer device address: 0x%lx, size: %d\n",
+	pr_err("NOTE: Buffer device address: 0x%lx, size: %d\n",
 		mem->device_addr, mem->size);
 	return rc;
 fail_device_address:
@@ -145,8 +144,8 @@
 		goto fail_device_address;
 	}
 	mem->device_addr = iova;
-	pr_debug("device_address = 0x%lx, kvaddr = 0x%p\n",
-		mem->device_addr, mem->kvaddr);
+	pr_err("NOTE: device_address = 0x%lx, kvaddr = 0x%p, size = %d\n",
+		mem->device_addr, mem->kvaddr, size);
 	mem->size = size;
 	return rc;
 fail_device_address:
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index bab7642..4e810dc 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -165,6 +165,7 @@
 	int buff_off;
 	int size;
 	u32 uvaddr;
+	u32 device_addr;
 	struct msm_smem *handle;
 };
 
@@ -230,6 +231,28 @@
 	return ret;
 }
 
+struct buffer_info *get_same_fd_buffer(struct list_head *list,
+		int fd)
+{
+	struct buffer_info *temp;
+	struct buffer_info *ret = NULL;
+	if (!list || fd < 0) {
+		pr_err("%s Invalid input\n", __func__);
+		goto err_invalid_input;
+	}
+	if (!list_empty(list)) {
+		list_for_each_entry(temp, list, list) {
+			if (temp && temp->fd == fd)  {
+				pr_err("Found same fd buffer\n");
+				ret = temp;
+				break;
+			}
+		}
+	}
+err_invalid_input:
+	return ret;
+}
+
 static int msm_v4l2_open(struct file *filp)
 {
 	int rc = 0;
@@ -362,8 +385,9 @@
 				rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
 					&buffer_info);
 				list_del(&bi->list);
-				msm_smem_free(v4l2_inst->mem_client,
-					bi->handle);
+				if (bi->handle)
+					msm_smem_free(v4l2_inst->mem_client,
+							bi->handle);
 				kfree(bi);
 			}
 		}
@@ -374,8 +398,9 @@
 int msm_v4l2_prepare_buf(struct file *file, void *fh,
 				struct v4l2_buffer *b)
 {
-	struct msm_smem *handle;
+	struct msm_smem *handle = NULL;
 	struct buffer_info *binfo;
+	struct buffer_info *temp;
 	struct msm_vidc_inst *vidc_inst;
 	struct msm_v4l2_vid_inst *v4l2_inst;
 	int i, rc = 0;
@@ -402,28 +427,43 @@
 			rc = -ENOMEM;
 			goto exit;
 		}
-		handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
+		temp = get_same_fd_buffer(&v4l2_inst->registered_bufs,
+				b->m.planes[i].reserved[0]);
+		if (temp) {
+			binfo->type = b->type;
+			binfo->fd = b->m.planes[i].reserved[0];
+			binfo->buff_off = b->m.planes[i].reserved[1];
+			binfo->size = b->m.planes[i].length;
+			binfo->uvaddr = b->m.planes[i].m.userptr;
+			binfo->device_addr =
+				temp->handle->device_addr + binfo->buff_off;
+			binfo->handle = NULL;
+		} else {
+			handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
 			b->m.planes[i].reserved[0],
 			b->m.planes[i].reserved[1],
 			vidc_inst->core->resources.io_map[NS_MAP].domain,
 			0);
-		if (!handle) {
-			pr_err("Failed to get device buffer address\n");
-			kfree(binfo);
-			goto exit;
+			if (!handle) {
+				pr_err("Failed to get device buffer address\n");
+				kfree(binfo);
+				goto exit;
+			}
+			binfo->type = b->type;
+			binfo->fd = b->m.planes[i].reserved[0];
+			binfo->buff_off = b->m.planes[i].reserved[1];
+			binfo->size = b->m.planes[i].length;
+			binfo->uvaddr = b->m.planes[i].m.userptr;
+			binfo->device_addr =
+				handle->device_addr + binfo->buff_off;
+			binfo->handle = handle;
+			pr_debug("Registering buffer: %d, %d, %d\n",
+					b->m.planes[i].reserved[0],
+					b->m.planes[i].reserved[1],
+					b->m.planes[i].length);
 		}
-		binfo->type = b->type;
-		binfo->fd = b->m.planes[i].reserved[0];
-		binfo->buff_off = b->m.planes[i].reserved[1];
-		binfo->size = b->m.planes[i].length;
-		binfo->uvaddr = b->m.planes[i].m.userptr;
-		binfo->handle = handle;
-		pr_debug("Registering buffer: %d, %d, %d\n",
-				b->m.planes[i].reserved[0],
-				b->m.planes[i].reserved[1],
-				b->m.planes[i].length);
 		list_add_tail(&binfo->list, &v4l2_inst->registered_bufs);
-		b->m.planes[i].m.userptr = handle->device_addr;
+		b->m.planes[i].m.userptr = binfo->device_addr;
 	}
 	rc = msm_vidc_prepare_buf(&v4l2_inst->vidc_inst, b);
 exit:
@@ -453,14 +493,16 @@
 			rc = -EINVAL;
 			goto err_invalid_buff;
 		}
-		b->m.planes[i].m.userptr = binfo->handle->device_addr;
-		pr_debug("Queueing device address = %ld\n",
-				binfo->handle->device_addr);
-		rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
-				binfo->handle);
-		if (rc) {
-			pr_err("Failed to clean caches: %d\n", rc);
-			goto err_invalid_buff;
+		b->m.planes[i].m.userptr = binfo->device_addr;
+		pr_debug("Queueing device address = 0x%x\n",
+				binfo->device_addr);
+		if (binfo->handle) {
+			rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
+					binfo->handle);
+			if (rc) {
+				pr_err("Failed to clean caches: %d\n", rc);
+				goto err_invalid_buff;
+			}
 		}
 	}
 	rc = msm_vidc_qbuf(&v4l2_inst->vidc_inst, b);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index d69ed53..0d62ccc 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -430,6 +430,7 @@
 	struct msm_vidc_cb_cmd_done *response = data;
 	struct msm_vidc_inst *inst;
 	unsigned long flags;
+	int i;
 	if (!response || !response->data) {
 		pr_err("Failed to get valid response for prop info\n");
 		return;
@@ -439,6 +440,12 @@
 	memcpy(&inst->buff_req, response->data,
 			sizeof(struct buffer_requirements));
 	spin_unlock_irqrestore(&inst->lock, flags);
+	for (i = 0; i < 8; i++) {
+		pr_err("NOTE: buffer type: %d, count : %d, size: %d\n",
+			inst->buff_req.buffer[i].buffer_type,
+			inst->buff_req.buffer[i].buffer_count_actual,
+			inst->buff_req.buffer[i].buffer_size);
+	}
 	signal_session_msg_receipt(cmd, inst);
 }
 
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index 740d183..c1a392e2 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -62,7 +62,7 @@
 		goto alloc_failed;
 	}
 	rc = ion_map_iommu(mem->client, mem->ion_handle,
-			CAMERA_DOMAIN, GEN_POOL, SZ_4K, 0,
+			-1, 0, SZ_4K, 0,
 			(unsigned long *)&phyaddr,
 			(unsigned long *)&len, UNCACHED, 0);
 	if (rc < 0) {
@@ -87,7 +87,7 @@
 {
 	int32_t rc = 0;
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-	ion_unmap_iommu(mem->client, mem->ion_handle, CAMERA_DOMAIN, GEN_POOL);
+	ion_unmap_iommu(mem->client, mem->ion_handle, -1, 0);
 	ion_free(mem->client, mem->ion_handle);
 	ion_client_destroy(mem->client);
 #else
@@ -174,7 +174,8 @@
 					struct videobuf2_msm_offset *offset,
 					enum videobuf2_buffer_type buffer_type,
 					uint32_t addr_offset, int path,
-					struct ion_client *client)
+					struct ion_client *client,
+					int domain_num)
 {
 	unsigned long len;
 	int rc = 0;
@@ -190,7 +191,7 @@
 		pr_err("%s ION import failed\n", __func__);
 		return PTR_ERR(mem->ion_handle);
 	}
-	rc = ion_map_iommu(client, mem->ion_handle, CAMERA_DOMAIN, GEN_POOL,
+	rc = ion_map_iommu(client, mem->ion_handle, domain_num, 0,
 		SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, UNCACHED, 0);
 	if (rc < 0)
 		ion_free(client, mem->ion_handle);
@@ -220,12 +221,12 @@
 EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get);
 
 void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
-					struct ion_client *client)
+				struct ion_client *client, int domain_num)
 {
 	if (mem->is_userptr) {
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		ion_unmap_iommu(client, mem->ion_handle,
-				CAMERA_DOMAIN, GEN_POOL);
+				domain_num, 0);
 		ion_free(client, mem->ion_handle);
 #elif CONFIG_ANDROID_PMEM
 		put_pmem_file(mem->file);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index a033693..b8db530 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -2172,6 +2172,18 @@
 	return rc;
 }
 
+static inline int msmsdcc_vreg_get_voltage(struct msm_mmc_reg_data *vreg)
+{
+	int rc = 0;
+
+	rc = regulator_get_voltage(vreg->reg);
+	if (rc < 0)
+		pr_err("%s: regulator_get_voltage(%s) failed. rc=%d\n",
+			__func__, vreg->name, rc);
+
+	return rc;
+}
+
 static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
 						int uA_load)
 {
@@ -2416,6 +2428,82 @@
 	VDD_IO_SET_LEVEL,
 };
 
+/*
+ * This function returns the current VDD IO voltage level.
+ * Returns negative value if it fails to read the voltage level
+ * Returns 0 if regulator was disabled or if VDD_IO (and VDD)
+ * regulator were not defined for host.
+ */
+static int msmsdcc_get_vdd_io_vol(struct msmsdcc_host *host)
+{
+	int rc = 0;
+
+	if (host->plat->vreg_data) {
+		struct msm_mmc_reg_data *io_reg =
+			host->plat->vreg_data->vdd_io_data;
+
+		/*
+		 * If vdd_io is not defined, then we can consider that
+		 * IO voltage is same as VDD.
+		 */
+		if (!io_reg)
+			io_reg = host->plat->vreg_data->vdd_data;
+
+		if (io_reg && io_reg->is_enabled)
+			rc = msmsdcc_vreg_get_voltage(io_reg);
+	}
+
+	return rc;
+}
+
+/*
+ * This function updates the IO pad power switch bit in MCI_CLK register
+ * based on currrent IO pad voltage level.
+ * NOTE: This function assumes that host lock was not taken by caller.
+ */
+static void msmsdcc_update_io_pad_pwr_switch(struct msmsdcc_host *host)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	if (!is_io_pad_pwr_switch(host))
+		return;
+
+	rc = msmsdcc_get_vdd_io_vol(host);
+
+	spin_lock_irqsave(&host->lock, flags);
+	/*
+	 * Dual voltage pad is the SDCC's (chipset) functionality and not all
+	 * the SDCC instances support the dual voltage pads.
+	 * For dual-voltage pad (1.8v/3.3v), SW should set IO_PAD_PWR_SWITCH
+	 * bit before using the pads in 1.8V mode.
+	 * For regular, not dual-voltage pads (including eMMC 1.2v/1.8v pads),
+	 * IO_PAD_PWR_SWITCH bit is a don't care.
+	 * But we don't have an option to know (by reading some SDCC register)
+	 * that a particular SDCC instance supports dual voltage pads or not,
+	 * so we simply set the IO_PAD_PWR_SWITCH bit for low voltage IO
+	 * (1.8v/1.2v). For regular (not dual-voltage pads), this bit value
+	 * is anyway ignored.
+	 */
+	if (rc > 0 && rc < 2700000)
+		host->io_pad_pwr_switch = 1;
+	else
+		host->io_pad_pwr_switch = 0;
+
+	if (atomic_read(&host->clks_on)) {
+		if (host->io_pad_pwr_switch)
+			writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
+					IO_PAD_PWR_SWITCH),
+					host->base + MMCICLOCK);
+		else
+			writel_relaxed((readl_relaxed(host->base + MMCICLOCK) &
+					~IO_PAD_PWR_SWITCH),
+					host->base + MMCICLOCK);
+		msmsdcc_sync_reg_wr(host);
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
 static int msmsdcc_set_vdd_io_vol(struct msmsdcc_host *host,
 				  enum vdd_io_level level,
 				  unsigned int voltage_level)
@@ -2717,6 +2805,7 @@
 		 * present or during system suspend).
 		 */
 		msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
+		msmsdcc_update_io_pad_pwr_switch(host);
 		msmsdcc_setup_pins(host, false);
 		break;
 	case MMC_POWER_UP:
@@ -2725,6 +2814,7 @@
 		msmsdcc_cfg_mpm_sdiowakeup(host, SDC_DAT1_ENABLE);
 
 		msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
+		msmsdcc_update_io_pad_pwr_switch(host);
 		msmsdcc_setup_pins(host, true);
 		break;
 	case MMC_POWER_ON:
@@ -3137,10 +3227,6 @@
 	/* Select free running MCLK as input clock of cm_dll_sdc4 */
 	clk |= (2 << 23);
 
-	/* Clear IO_PAD_PWR_SWITCH while powering off the card */
-	if (!ios->vdd)
-		host->io_pad_pwr_switch = 0;
-
 	if (host->io_pad_pwr_switch)
 		clk |= IO_PAD_PWR_SWITCH;
 
@@ -3429,14 +3515,12 @@
 	unsigned long flags;
 	int rc = 0;
 
-	spin_lock_irqsave(&host->lock, flags);
-	host->io_pad_pwr_switch = 0;
-	spin_unlock_irqrestore(&host->lock, flags);
-
 	switch (ios->signal_voltage) {
 	case MMC_SIGNAL_VOLTAGE_330:
 		/* Set VDD IO to high voltage range (2.7v - 3.6v) */
 		rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
+		if (!rc)
+			msmsdcc_update_io_pad_pwr_switch(host);
 		goto out;
 	case MMC_SIGNAL_VOLTAGE_180:
 		break;
@@ -3447,6 +3531,8 @@
 		 * DDR 1.2V mode.
 		 */
 		rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_SET_LEVEL, 1200000);
+		if (!rc)
+			msmsdcc_update_io_pad_pwr_switch(host);
 		goto out;
 	default:
 		/* invalid selection. don't do anything */
@@ -3485,12 +3571,7 @@
 	if (rc)
 		goto out;
 
-	spin_lock_irqsave(&host->lock, flags);
-	writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
-			IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
-	msmsdcc_sync_reg_wr(host);
-	host->io_pad_pwr_switch = 1;
-	spin_unlock_irqrestore(&host->lock, flags);
+	msmsdcc_update_io_pad_pwr_switch(host);
 
 	/* Wait 5 ms for the voltage regulater in the card to become stable. */
 	usleep_range(5000, 5500);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 3b1dbc7..236785d 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -428,6 +428,7 @@
 #define MSMSDCC_SW_RST		(1 << 5)
 #define MSMSDCC_SW_RST_CFG	(1 << 6)
 #define MSMSDCC_WAIT_FOR_TX_RX	(1 << 7)
+#define MSMSDCC_IO_PAD_PWR_SWITCH	(1 << 8)
 
 #define set_hw_caps(h, val)		((h)->hw_caps |= val)
 #define is_sps_mode(h)			((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -438,6 +439,7 @@
 #define is_sw_hard_reset(h)		((h)->hw_caps & MSMSDCC_SW_RST)
 #define is_sw_reset_save_config(h)	((h)->hw_caps & MSMSDCC_SW_RST_CFG)
 #define is_wait_for_tx_rx_active(h)	((h)->hw_caps & MSMSDCC_WAIT_FOR_TX_RX)
+#define is_io_pad_pwr_switch(h)	((h)->hw_caps & MSMSDCC_IO_PAD_PWR_SWITCH)
 
 /* Set controller capabilities based on version */
 static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -457,7 +459,7 @@
 	if (version) /* SDCC v4 and greater */
 		host->hw_caps |= MSMSDCC_AUTO_PROG_DONE |
 			MSMSDCC_SOFT_RESET | MSMSDCC_REG_WR_ACTIVE
-			| MSMSDCC_WAIT_FOR_TX_RX;
+			| MSMSDCC_WAIT_FOR_TX_RX | MSMSDCC_IO_PAD_PWR_SWITCH;
 
 	if (version >= 0x2D) /* SDCC v4 2.1.0 and greater */
 		host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG;
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 186d07d..f6e4b00 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -271,7 +271,7 @@
 			__func__, status);
 }
 
-static int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *dev)
+int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *dev)
 {
 	int	retval = 0;
 
@@ -298,18 +298,6 @@
 	return 0;
 }
 
-int rmnet_usb_ctrl_start(struct rmnet_ctrl_dev *dev)
-{
-	int	status = 0;
-
-	mutex_lock(&dev->dev_lock);
-	if (dev->is_opened)
-		status = rmnet_usb_ctrl_start_rx(dev);
-	mutex_unlock(&dev->dev_lock);
-
-	return status;
-}
-
 static int rmnet_usb_ctrl_alloc_rx(struct rmnet_ctrl_dev *dev)
 {
 	int	retval = -ENOMEM;
diff --git a/drivers/net/usb/rmnet_usb_ctrl.h b/drivers/net/usb/rmnet_usb_ctrl.h
index 3259940..7a84817 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.h
+++ b/drivers/net/usb/rmnet_usb_ctrl.h
@@ -73,7 +73,7 @@
 
 extern struct rmnet_ctrl_dev *ctrl_dev[];
 
-extern int rmnet_usb_ctrl_start(struct rmnet_ctrl_dev *);
+extern int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *);
 extern int rmnet_usb_ctrl_stop_rx(struct rmnet_ctrl_dev *);
 extern int rmnet_usb_ctrl_init(void);
 extern void rmnet_usb_ctrl_exit(void);
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 4f8039e..b8c6140 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -151,7 +151,7 @@
 	retval = usbnet_resume(iface);
 	if (!retval) {
 		if (oldstate & PM_EVENT_SUSPEND)
-			retval = rmnet_usb_ctrl_start(dev);
+			retval = rmnet_usb_ctrl_start_rx(dev);
 	}
 fail:
 	return retval;
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index d26c845..1867fe2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -89,6 +89,8 @@
 
 static struct workqueue_struct	*usbnet_wq;
 
+static DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
+
 /* use ethtool to change the level for any given device */
 static int msg_level = -1;
 module_param (msg_level, int, 0);
@@ -664,7 +666,6 @@
 // precondition: never called in_interrupt
 static void usbnet_terminate_urbs(struct usbnet *dev)
 {
-	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
 	DECLARE_WAITQUEUE(wait, current);
 	int temp;
 
@@ -1240,7 +1241,7 @@
 	// waiting for all pending urbs to complete?
 	if (dev->wait) {
 		if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
-			wake_up (dev->wait);
+			wake_up(&unlink_wakeup);
 		}
 
 	// or are we maybe short a few urbs?
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 5e1b77a..2868d61 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1999,11 +1999,6 @@
 	if (soc > 100)
 		soc = 100;
 
-	if (bms_fake_battery != -EINVAL) {
-		pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
-		return bms_fake_battery;
-	}
-
 	if (soc < 0) {
 		pr_err("bad rem_usb_chg = %d rem_chg %d,"
 				"cc_uah %d, unusb_chg %d\n",
@@ -2111,6 +2106,11 @@
 	int batt_temp;
 	int rc;
 
+	if (bms_fake_battery != -EINVAL) {
+		pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
+		return bms_fake_battery;
+	}
+
 	rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
 	if (rc) {
 		pr_err("error reading adc channel = %d, rc = %d\n",
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index eebda9e..7af0afd 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -354,21 +354,33 @@
 static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
 {
 	struct usb_hcd *hcd = hsic_to_hcd(mehci);
-	unsigned long timeout;
+	int cnt = 0;
 
 	/* initiate read operation */
 	writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
 	       USB_ULPI_VIEWPORT);
 
 	/* wait for completion */
-	timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USEC);
-	while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
-		if (time_after(jiffies, timeout)) {
-			dev_err(mehci->dev, "ulpi_read: timeout %08x\n",
-				readl_relaxed(USB_ULPI_VIEWPORT));
-			return -ETIMEDOUT;
-		}
+	while (cnt < ULPI_IO_TIMEOUT_USEC) {
+		if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
+			break;
 		udelay(1);
+		cnt++;
+	}
+
+	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+		dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
+				readl_relaxed(USB_ULPI_VIEWPORT));
+		dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
+				readl_relaxed(USB_PORTSC),
+				readl_relaxed(USB_USBCMD),
+				readl_relaxed(USB_FRINDEX));
+
+		/*frame counter increments afte 125us*/
+		udelay(130);
+		dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
+				readl_relaxed(USB_FRINDEX));
+		return -ETIMEDOUT;
 	}
 
 	return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
@@ -393,7 +405,17 @@
 	}
 
 	if (cnt >= ULPI_IO_TIMEOUT_USEC) {
-		dev_err(mehci->dev, "ulpi_write: timeout\n");
+		dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
+				readl_relaxed(USB_ULPI_VIEWPORT));
+		dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
+				readl_relaxed(USB_PORTSC),
+				readl_relaxed(USB_USBCMD),
+				readl_relaxed(USB_FRINDEX));
+
+		/*frame counter increments afte 125us*/
+		udelay(130);
+		dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
+				readl_relaxed(USB_FRINDEX));
 		return -ETIMEDOUT;
 	}
 
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 0976fc6..c6ffaf2 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1418,7 +1418,7 @@
 		video_format, video_format_2string(video_format),
 		supported ? "Supported" : "Not-Supported");
 	if (supported) {
-		if (mhl_is_connected()) {
+		if (mhl_is_enabled()) {
 			const struct hdmi_disp_mode_timing_type *mhl_timing =
 				hdmi_mhl_get_supported_mode(video_format);
 			boolean mhl_supported = mhl_timing != NULL;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 26e5687..a5e72fe 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -4448,6 +4448,11 @@
 	return 0;
 }
 
+bool mhl_is_enabled(void)
+{
+	return hdmi_msm_state->is_mhl_enabled;
+}
+
 static int __devinit hdmi_msm_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -4620,6 +4625,12 @@
 	if (switch_dev_register(&external_common_state->sdev) < 0)
 		DEV_ERR("Hdmi switch registration failed\n");
 
+	/* Set the default video resolution for MHL-enabled display */
+	if (hdmi_msm_state->is_mhl_enabled) {
+		DEV_DBG("MHL Enabled. Restricting default video resolution\n");
+		external_common_state->video_resolution =
+			HDMI_VFRMT_1920x1080p30_16_9;
+	}
 	return 0;
 
 error:
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index d051828..f012e2e 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -17,14 +17,149 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/of_device.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
 
 #include "mdss.h"
 #include "mdss_panel.h"
 #include "mdss_dsi.h"
 
-static struct mdss_panel_common_pdata *panel_pdata;
+static struct mdss_dsi_drv_pdata dsi_drv;
 
 static unsigned char *mdss_dsi_base;
+static unsigned char *mmss_cc_base;
+
+static int mdss_dsi_regulator_init(struct platform_device *pdev)
+{
+	int ret;
+	dsi_drv.vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
+	if (IS_ERR(dsi_drv.vdd_vreg)) {
+		pr_err("could not get 8941_l22, rc = %ld\n",
+				PTR_ERR(dsi_drv.vdd_vreg));
+		return -ENODEV;
+	}
+
+	ret = regulator_set_voltage(dsi_drv.vdd_vreg, 3000000, 3000000);
+	if (ret) {
+		pr_err("vdd_vreg->set_voltage failed, rc=%d\n", ret);
+		return -EINVAL;
+	}
+
+	dsi_drv.vdd_io_vreg = devm_regulator_get(&pdev->dev, "vdd_io");
+	if (IS_ERR(dsi_drv.vdd_io_vreg)) {
+		pr_err("could not get 8941_l12, rc = %ld\n",
+				PTR_ERR(dsi_drv.vdd_io_vreg));
+		return -ENODEV;
+	}
+
+	ret = regulator_set_voltage(dsi_drv.vdd_io_vreg, 1800000, 1800000);
+	if (ret) {
+		pr_err("vdd_io_vreg->set_voltage failed, rc=%d\n", ret);
+		return -EINVAL;
+	}
+
+	dsi_drv.dsi_vreg = devm_regulator_get(&pdev->dev, "vreg");
+	if (IS_ERR(dsi_drv.dsi_vreg)) {
+		pr_err("could not get 8941_l2, rc = %ld\n",
+				PTR_ERR(dsi_drv.dsi_vreg));
+		return -ENODEV;
+	}
+
+	ret = regulator_set_voltage(dsi_drv.dsi_vreg, 1200000, 1200000);
+	if (ret) {
+		pr_err("dsi_vreg->set_voltage failed, rc=%d\n", ret);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mdss_dsi_panel_power_on(int enable)
+{
+	int ret;
+	pr_debug("%s: enable=%d\n", __func__, enable);
+
+	if (enable) {
+		ret = regulator_set_optimum_mode(dsi_drv.vdd_vreg, 100000);
+		if (ret < 0) {
+			pr_err("%s: vdd_vreg set regulator mode failed.\n",
+						       __func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(dsi_drv.vdd_io_vreg, 100000);
+		if (ret < 0) {
+			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
+						       __func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(dsi_drv.dsi_vreg, 100000);
+		if (ret < 0) {
+			pr_err("%s: dsi_vreg set regulator mode failed.\n",
+						       __func__);
+			return ret;
+		}
+
+		ret = regulator_enable(dsi_drv.vdd_vreg);
+		if (ret) {
+			pr_err("%s: Failed to enable regulator.\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_enable(dsi_drv.vdd_io_vreg);
+		if (ret) {
+			pr_err("%s: Failed to enable regulator.\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_enable(dsi_drv.dsi_vreg);
+		if (ret) {
+			pr_err("%s: Failed to enable regulator.\n", __func__);
+			return ret;
+		}
+
+	} else {
+		ret = regulator_disable(dsi_drv.vdd_vreg);
+		if (ret) {
+			pr_err("%s: Failed to disable regulator.\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_disable(dsi_drv.vdd_io_vreg);
+		if (ret) {
+			pr_err("%s: Failed to disable regulator.\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_disable(dsi_drv.dsi_vreg);
+		if (ret) {
+			pr_err("%s: Failed to disable regulator.\n", __func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(dsi_drv.vdd_vreg, 100);
+		if (ret < 0) {
+			pr_err("%s: vdd_vreg set regulator mode failed.\n",
+						       __func__);
+			return ret;
+		}
+
+		ret = regulator_set_optimum_mode(dsi_drv.vdd_io_vreg, 100);
+		if (ret < 0) {
+			pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
+						       __func__);
+			return ret;
+		}
+		ret = regulator_set_optimum_mode(dsi_drv.dsi_vreg, 100);
+		if (ret < 0) {
+			pr_err("%s: dsi_vreg set regulator mode failed.\n",
+						       __func__);
+			return ret;
+		}
+	}
+	return 0;
+}
 
 static int mdss_dsi_off(struct mdss_panel_data *pdata)
 {
@@ -38,7 +173,7 @@
 
 	mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
 
-	ret = panel_pdata->off(pdata);
+	ret = dsi_drv.off(pdata);
 	if (ret) {
 		pr_err("%s: Panel OFF failed\n", __func__);
 		return ret;
@@ -54,6 +189,12 @@
 
 	mdss_dsi_unprepare_clocks();
 
+	ret = mdss_dsi_panel_power_on(0);
+	if (ret) {
+		pr_err("%s: Panel power off failed\n", __func__);
+		return ret;
+	}
+
 	pr_debug("%s-:\n", __func__);
 
 	return ret;
@@ -148,7 +289,13 @@
 		wmb();
 	}
 
-	ret = panel_pdata->on(pdata);
+	ret = mdss_dsi_panel_power_on(1);
+	if (ret) {
+		pr_err("%s: Panel power on failed\n", __func__);
+		return ret;
+	}
+
+	ret = dsi_drv.on(pdata);
 	if (ret) {
 		pr_err("%s: unable to initialize the panel\n", __func__);
 		return ret;
@@ -167,7 +314,7 @@
 
 unsigned char *mdss_dsi_get_clk_base(void)
 {
-	return mdss_dsi_base;
+	return mmss_cc_base;
 }
 
 static int mdss_dsi_resource_initialized;
@@ -196,8 +343,35 @@
 			}
 		}
 
+		mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		if (!mdss_dsi_mres) {
+			pr_err("%s:%d unable to get the MDSS resources",
+				       __func__, __LINE__);
+			return -ENOMEM;
+		}
+		if (mdss_dsi_mres) {
+			mmss_cc_base = ioremap(mdss_dsi_mres->start,
+				resource_size(mdss_dsi_mres));
+			if (!mmss_cc_base) {
+				pr_err("%s:%d unable to remap dsi resources",
+					       __func__, __LINE__);
+				return -ENOMEM;
+			}
+		}
+
+		rc = mdss_dsi_regulator_init(pdev);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"%s: failed to init regulator, rc=%d\n",
+							__func__, rc);
+			iounmap(mdss_dsi_base);
+			iounmap(mmss_cc_base);
+			return rc;
+		}
+
 		if (mdss_dsi_clk_init(pdev)) {
 			iounmap(mdss_dsi_base);
+			iounmap(mmss_cc_base);
 			return -EPERM;
 		}
 
@@ -208,6 +382,7 @@
 				"%s: failed to add child nodes, rc=%d\n",
 							__func__, rc);
 			iounmap(mdss_dsi_base);
+			iounmap(mmss_cc_base);
 			return rc;
 		}
 
@@ -240,21 +415,19 @@
 	u32 h_period, v_period, dsi_pclk_rate;
 	struct mdss_panel_data *pdata = NULL;
 
-	panel_pdata = panel_data;
+	h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
+			+ (panel_data->panel_info.lcdc.h_back_porch)
+			+ (panel_data->panel_info.xres)
+			+ (panel_data->panel_info.lcdc.h_front_porch));
 
-	h_period = ((panel_pdata->panel_info.lcdc.h_pulse_width)
-			+ (panel_pdata->panel_info.lcdc.h_back_porch)
-			+ (panel_pdata->panel_info.xres)
-			+ (panel_pdata->panel_info.lcdc.h_front_porch));
+	v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
+			+ (panel_data->panel_info.lcdc.v_back_porch)
+			+ (panel_data->panel_info.yres)
+			+ (panel_data->panel_info.lcdc.v_front_porch));
 
-	v_period = ((panel_pdata->panel_info.lcdc.v_pulse_width)
-			+ (panel_pdata->panel_info.lcdc.v_back_porch)
-			+ (panel_pdata->panel_info.yres)
-			+ (panel_pdata->panel_info.lcdc.v_front_porch));
+	mipi  = &panel_data->panel_info.mipi;
 
-	mipi  = &panel_pdata->panel_info.mipi;
-
-	panel_pdata->panel_info.type =
+	panel_data->panel_info.type =
 		((mipi->mode == DSI_VIDEO_MODE)
 			? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
 
@@ -278,23 +451,23 @@
 	else
 		bpp = 3;		/* Default format set to RGB888 */
 
-	if (panel_pdata->panel_info.type == MIPI_VIDEO_PANEL &&
-		!panel_pdata->panel_info.clk_rate) {
-		h_period += panel_pdata->panel_info.lcdc.xres_pad;
-		v_period += panel_pdata->panel_info.lcdc.yres_pad;
+	if (panel_data->panel_info.type == MIPI_VIDEO_PANEL &&
+		!panel_data->panel_info.clk_rate) {
+		h_period += panel_data->panel_info.lcdc.xres_pad;
+		v_period += panel_data->panel_info.lcdc.yres_pad;
 
 		if (lanes > 0) {
-			panel_pdata->panel_info.clk_rate =
+			panel_data->panel_info.clk_rate =
 			((h_period * v_period * (mipi->frame_rate) * bpp * 8)
 			   / lanes);
 		} else {
 			pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
-			panel_pdata->panel_info.clk_rate =
+			panel_data->panel_info.clk_rate =
 				(h_period * v_period
 					 * (mipi->frame_rate) * bpp * 8);
 		}
 	}
-	pll_divider_config.clk_rate = panel_pdata->panel_info.clk_rate;
+	pll_divider_config.clk_rate = panel_data->panel_info.clk_rate;
 
 	rc = mdss_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
 	if (rc) {
@@ -306,6 +479,9 @@
 		dsi_pclk_rate = 35000000;
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
+	dsi_drv.on = panel_data->on;
+	dsi_drv.off = panel_data->off;
+
 	/*
 	 * data chain
 	 */
@@ -315,10 +491,11 @@
 
 	pdata->on = mdss_dsi_on;
 	pdata->off = mdss_dsi_off;
-	memcpy(&(pdata->panel_info), &(panel_pdata->panel_info),
+	memcpy(&(pdata->panel_info), &(panel_data->panel_info),
 	       sizeof(struct mdss_panel_info));
 
 	pdata->dsi_base = mdss_dsi_base;
+	pdata->mmss_cc_base = mmss_cc_base;
 
 	/*
 	 * register in mdp driver
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 57fce1a..0af4371 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -19,7 +19,6 @@
 
 #include "mdss_panel.h"
 
-#define MMSS_MDSS_CC_BASE_PHY 0xFD8C2300	/* mmss clcok control */
 #define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
 
 #define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
@@ -244,6 +243,13 @@
 	int (*off) (struct mdss_panel_data *pdata);
 };
 
+struct mdss_dsi_drv_pdata {
+	struct regulator *vdd_vreg;
+	struct regulator *vdd_io_vreg;
+	struct regulator *dsi_vreg;
+	int (*on) (struct mdss_panel_data *pdata);
+	int (*off) (struct mdss_panel_data *pdata);
+};
 int dsi_panel_device_register(struct platform_device *pdev,
 			      struct mdss_panel_common_pdata *panel_data);
 
@@ -290,5 +296,4 @@
 void mdss_dsi_unprepare_clocks(void);
 void cont_splash_clk_ctrl(int enable);
 unsigned char *mdss_dsi_get_base_adr(void);
-
 #endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 7efca07..1a1bb07 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -810,15 +810,6 @@
 
 	mfd->op_enable = true;
 
-	/* cursor memory allocation */
-	if (mfd->cursor_update) {
-		mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
-					(dma_addr_t *) &mfd->cursor_buf_phys,
-					GFP_KERNEL);
-		if (!mfd->cursor_buf)
-			mfd->cursor_update = 0;
-	}
-
 	if (mfd->lut_update) {
 		ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
 		if (ret)
@@ -829,11 +820,6 @@
 		if (mfd->lut_update)
 			fb_dealloc_cmap(&fbi->cmap);
 
-		if (mfd->cursor_buf)
-			dma_free_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
-					  mfd->cursor_buf,
-					  (dma_addr_t) mfd->cursor_buf_phys);
-
 		mfd->op_enable = false;
 		return -EPERM;
 	}
@@ -1104,7 +1090,7 @@
 	if (ret)
 		return ret;
 
-	return mfd->cursor_update(info, &cursor);
+	return mfd->cursor_update(mfd, &cursor);
 }
 
 static int mdss_fb_set_lut(struct fb_info *info, void __user *p)
@@ -1120,7 +1106,7 @@
 	if (ret)
 		return ret;
 
-	mfd->lut_update(info, &cmap);
+	mfd->lut_update(mfd, &cmap);
 	return 0;
 }
 
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 3ea0ab3..ab140fe 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -69,11 +69,10 @@
 	int (*kickoff_fnc) (struct mdss_mdp_ctl *ctl);
 	int (*ioctl_handler) (struct msm_fb_data_type *mfd, u32 cmd, void *arg);
 	void (*dma_fnc) (struct msm_fb_data_type *mfd);
-	int (*cursor_update) (struct fb_info *info,
+	int (*cursor_update) (struct msm_fb_data_type *mfd,
 			      struct fb_cursor *cursor);
-	int (*lut_update) (struct fb_info *info,
-			   struct fb_cmap *cmap);
-	int (*do_histogram) (struct fb_info *info,
+	int (*lut_update) (struct msm_fb_data_type *mfd, struct fb_cmap *cmap);
+	int (*do_histogram) (struct msm_fb_data_type *mfd,
 			     struct mdp_histogram *hist);
 
 	struct ion_handle *ihdl;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 3c7afed..63df8ed 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt)	"%s: " fmt, __func__
 
+#include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
@@ -602,15 +603,24 @@
 		mfd->kickoff_fnc(mfd->ctl);
 }
 
-static int mdss_mdp_hw_cursor_update(struct fb_info *info,
+static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
 				     struct fb_cursor *cursor)
 {
-	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
 	struct mdss_mdp_mixer *mixer;
 	struct fb_image *img = &cursor->image;
-	int calpha_en, transp_en, blendcfg, alpha;
+	u32 blendcfg;
 	int off, ret = 0;
 
+	if (!mfd->cursor_buf) {
+		mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
+					(dma_addr_t *) &mfd->cursor_buf_phys,
+					GFP_KERNEL);
+		if (!mfd->cursor_buf) {
+			pr_err("can't allocate cursor buffer\n");
+			return -ENOMEM;
+		}
+	}
+
 	mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
 	off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
 
@@ -630,6 +640,7 @@
 				   (img->dy << 16) | img->dx);
 
 	if (cursor->set & FB_CUR_SETIMAGE) {
+		int calpha_en, transp_en, alpha, size;
 		ret = copy_from_user(mfd->cursor_buf, img->data,
 				     img->width * img->height * 4);
 		if (ret)
@@ -647,8 +658,9 @@
 		else
 			calpha_en = 0x2; /* argb */
 
-		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_SIZE,
-				   (img->height << 16) | img->width);
+		size = (img->height << 16) | img->width;
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_IMG_SIZE, size);
+		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_SIZE, size);
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_STRIDE,
 				   img->width * 4);
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BASE_ADDR,
@@ -684,10 +696,13 @@
 	}
 
 	if (!cursor->enable != !(blendcfg & 0x1)) {
-		if (cursor->enable)
+		if (cursor->enable) {
+			pr_debug("enable hw cursor on mixer=%d\n", mixer->num);
 			blendcfg |= 0x1;
-		else
+		} else {
+			pr_debug("disable hw cursor on mixer=%d\n", mixer->num);
 			blendcfg &= ~0x1;
+		}
 
 		MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
 				   blendcfg);
@@ -809,7 +824,6 @@
 	mfd->on_fnc = mdss_mdp_ctl_on;
 	mfd->off_fnc = mdss_mdp_ctl_off;
 	mfd->hw_refresh = true;
-	mfd->lut_update = NULL;
 	mfd->do_histogram = NULL;
 	mfd->overlay_play_enable = true;
 	mfd->cursor_update = mdss_mdp_hw_cursor_update;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 3ec3a5d..91010f4 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -168,6 +168,7 @@
 	struct mdss_panel_info panel_info;
 	void (*set_backlight) (u32 bl_level);
 	unsigned char *dsi_base;
+	unsigned char *mmss_cc_base;
 
 	/* function entry chain */
 	int (*on) (struct mdss_panel_data *pdata);
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index 646dd29..4347dc7 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -224,12 +224,6 @@
 	return 0;
 }
 
-bool mhl_is_connected(void)
-{
-	return true;
-}
-
-
 /*  USB_HANDSHAKING FUNCTIONS */
 
 int mhl_device_discovery(const char *name, int *result)
@@ -547,6 +541,11 @@
 	pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
 		mhl_msm_state->mhl_data->irq);
 
+	if (!mhl_msm_state->mhl_data->mhl_enabled) {
+		pr_info("MHL Display not enabled\n");
+		return -ENODEV;
+	}
+
 	/* Init GPIO stuff here */
 	ret = mhl_sii_gpio_setup(1);
 	if (ret == -1) {
diff --git a/drivers/video/msm/mhl_api.h b/drivers/video/msm/mhl_api.h
index a4364ea..7fdbaa9 100644
--- a/drivers/video/msm/mhl_api.h
+++ b/drivers/video/msm/mhl_api.h
@@ -15,9 +15,9 @@
 #define __MHL_API_H__
 
 #ifdef CONFIG_FB_MSM_HDMI_MHL_8334
-bool mhl_is_connected(void);
+bool mhl_is_enabled(void);
 #else
-static bool mhl_is_connected(void)
+static bool mhl_is_enabled(void)
 {
 	return false;
 }
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index 7169870..f28053c 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -49,6 +49,28 @@
 })
 
 /**
+ * readl_poll_timeout_noirq - Periodically poll an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @max_reads: Maximum number of reads before giving up
+ * @time_between_us: Time to udelay() between successive reads
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout.
+ */
+#define readl_poll_timeout_noirq(addr, val, cond, max_reads, time_between_us) \
+({ \
+	int count; \
+	for (count = (max_reads); count > 0; count--) { \
+		(val) = readl(addr); \
+		if (cond) \
+			break; \
+		udelay(time_between_us); \
+	} \
+	(cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
  * readl_poll - Periodically poll an address until a condition is met
  * @addr: Address to poll
  * @val: Variable to read the value into
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 516f764..a040d49 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -29,6 +29,7 @@
 
 #define USBCMD_RESET   2
 #define USB_USBINTR          (MSM_USB_BASE + 0x0148)
+#define USB_FRINDEX          (MSM_USB_BASE + 0x014C)
 
 #define PORTSC_PHCD            (1 << 23) /* phy suspend mode */
 #define PORTSC_PTS_MASK         (3 << 30)
diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h
index 84e2bea..5285997 100644
--- a/include/media/videobuf2-msm-mem.h
+++ b/include/media/videobuf2-msm-mem.h
@@ -72,9 +72,10 @@
 					struct videobuf2_msm_offset *offset,
 					enum videobuf2_buffer_type,
 					uint32_t addr_offset, int path,
-					struct ion_client *client);
+					struct ion_client *client,
+					int domain_num);
 void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
-					struct ion_client *client);
+				struct ion_client *client, int domain_num);
 unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *buf,
 					unsigned int plane_no);
 
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 040bbe0..a1be978 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1754,11 +1754,18 @@
 		return ret;
 	}
 
-	if (msm8960_configure_headset_mic_gpios()) {
-		pr_err("%s Fail to configure headset mic gpios\n", __func__);
+	if (cpu_is_msm8960()) {
+		if (msm8960_configure_headset_mic_gpios()) {
+			pr_err("%s Fail to configure headset mic gpios\n",
+								__func__);
+			msm8960_headset_gpios_configured = 0;
+		} else
+			msm8960_headset_gpios_configured = 1;
+	} else {
 		msm8960_headset_gpios_configured = 0;
-	} else
-		msm8960_headset_gpios_configured = 1;
+		pr_debug("%s headset GPIO 23 and 35 not configured msm960ab",
+								__func__);
+	}
 
 	mutex_init(&cdc_mclk_mutex);