Merge "msm: mdss: unstage pipe only if it was ever staged"
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index 6aed1ce..b4ae5e6 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -198,57 +198,74 @@
 
 The CPUfreq governor "interactive" is designed for latency-sensitive,
 interactive workloads. This governor sets the CPU speed depending on
-usage, similar to "ondemand" and "conservative" governors.  However,
-the governor is more aggressive about scaling the CPU speed up in
-response to CPU-intensive activity.
-
-Sampling the CPU load every X ms can lead to under-powering the CPU
-for X ms, leading to dropped frames, stuttering UI, etc.  Instead of
-sampling the cpu at a specified rate, the interactive governor will
-check whether to scale the cpu frequency up soon after coming out of
-idle.  When the cpu comes out of idle, a timer is configured to fire
-within 1-2 ticks.  If the cpu is very busy between exiting idle and
-when the timer fires then we assume the cpu is underpowered and ramp
-to MAX speed.
-
-If the cpu was not sufficiently busy to immediately ramp to MAX speed,
-then governor evaluates the cpu load since the last speed adjustment,
-choosing the highest value between that longer-term load or the
-short-term load since idle exit to determine the cpu speed to ramp to.
+usage, similar to "ondemand" and "conservative" governors, but with a
+different set of configurable behaviors.
 
 The tuneable values for this governor are:
 
+target_loads: CPU load values used to adjust speed to influence the
+current CPU load toward that value.  In general, the lower the target
+load, the more often the governor will raise CPU speeds to bring load
+below the target.  The format is a single target load, optionally
+followed by pairs of CPU speeds and CPU loads to target at or above
+those speeds.  Colons can be used between the speeds and associated
+target loads for readability.  For example:
+
+   85 1000000:90 1700000:99
+
+targets CPU load 85% below speed 1GHz, 90% at or above 1GHz, until
+1.7GHz and above, at which load 99% is targeted.  If speeds are
+specified these must appear in ascending order.  Higher target load
+values are typically specified for higher speeds, that is, target load
+values also usually appear in an ascending order. The default is
+target load 90% for all speeds.
+
 min_sample_time: The minimum amount of time to spend at the current
-frequency before ramping down. This is to ensure that the governor has
-seen enough historic cpu load data to determine the appropriate
-workload.  Default is 80000 uS.
+frequency before ramping down. Default is 80000 uS.
 
 hispeed_freq: An intermediate "hi speed" at which to initially ramp
 when CPU load hits the value specified in go_hispeed_load.  If load
 stays high for the amount of time specified in above_hispeed_delay,
-then speed may be bumped higher.  Default is maximum speed.
+then speed may be bumped higher.  Default is the maximum speed
+allowed by the policy at governor initialization time.
 
-go_hispeed_load: The CPU load at which to ramp to the intermediate "hi
-speed".  Default is 85%.
+go_hispeed_load: The CPU load at which to ramp to hispeed_freq.
+Default is 99%.
 
-above_hispeed_delay: Once speed is set to hispeed_freq, wait for this
-long before bumping speed higher in response to continued high load.
+above_hispeed_delay: When speed is at or above hispeed_freq, wait for
+this long before raising speed in response to continued high load.
 Default is 20000 uS.
 
-timer_rate: Sample rate for reevaluating cpu load when the system is
-not idle.  Default is 20000 uS.
+timer_rate: Sample rate for reevaluating CPU load when the CPU is not
+idle.  A deferrable timer is used, such that the CPU will not be woken
+from idle to service this timer until something else needs to run.
+(The maximum time to allow deferring this timer when not running at
+minimum speed is configurable via timer_slack.)  Default is 20000 uS.
 
-input_boost: If non-zero, boost speed of all CPUs to hispeed_freq on
-touchscreen activity.  Default is 0.
+timer_slack: Maximum additional time to defer handling the governor
+sampling timer beyond timer_rate when running at speeds above the
+minimum.  For platforms that consume additional power at idle when
+CPUs are running at speeds greater than minimum, this places an upper
+bound on how long the timer will be deferred prior to re-evaluating
+load and dropping speed.  For example, if timer_rate is 20000uS and
+timer_slack is 10000uS then timers will be deferred for up to 30msec
+when not at lowest speed.  A value of -1 means defer timers
+indefinitely at all speeds.  Default is 80000 uS.
 
 boost: If non-zero, immediately boost speed of all CPUs to at least
 hispeed_freq until zero is written to this attribute.  If zero, allow
 CPU speeds to drop below hispeed_freq according to load as usual.
+Default is zero.
 
-boostpulse: Immediately boost speed of all CPUs to hispeed_freq for
-min_sample_time, after which speeds are allowed to drop below
+boostpulse: On each write, immediately boost speed of all CPUs to
+hispeed_freq for at least the period of time specified by
+boostpulse_duration, after which speeds are allowed to drop below
 hispeed_freq according to load as usual.
 
+boostpulse_duration: Length of time to hold CPU speed at hispeed_freq
+on a write to boostpulse, before allowing speed to drop according to
+load as usual.  Default is 80000 uS.
+
 
 3. The Governor Interface in the CPUfreq Core
 =============================================
diff --git a/Documentation/devicetree/bindings/cache/msm_cache_erp.txt b/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
index 400b299..8d00cc2 100644
--- a/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
+++ b/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
@@ -7,6 +7,17 @@
 - interrupt-names: Should contain the interrupt names "l1_irq" and
   "l2_irq"
 
+Optional properties:
+- reg: A set of I/O regions to be dumped in the event of a hardware fault being
+  detected. If this property is present, the "reg-names" property is must be
+  present as well.
+- reg-names: Human-readable names assigned to the I/O regions defined by the
+  "reg" property. The names can be completely arbitrary, since they are
+  intended to be human-read during failure analysis, and because the set of I/O
+  regions of interest may vary with the overall system design. This property
+  shall only be present if the "reg" property is present, and must contain as
+  many elements as the "reg" property.
+
 Example:
 	qcom,cache_erp {
 		compatible = "qcom,cache_erp";
@@ -14,3 +25,17 @@
 		interrupt-names = "l1_irq", "l2_irq";
 	};
 
+Example with "reg" property defined:
+	qcom,cache_erp@f9012000 {
+		reg = <0xf9012000 0x80>,
+		      <0xf9089000 0x80>,
+		      <0xf9099000 0x80>;
+
+		reg-names = "l2_saw",
+			    "krait0_saw",
+			    "krait1_saw";
+
+		compatible = "qcom,cache_erp";
+		interrupts = <1 9 0>, <0 2 0>;
+		interrupt-names = "l1_irq", "l2_irq";
+	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index bb19768..a3f3a06 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -118,6 +118,9 @@
 Subnode properties:
 - compatible :		Must be "qcom,mdss-fb"
 - cell-index :		Index representing frame buffer
+- qcom,mdss-mixer-swap: A boolean property that indicates if the mixer muxes
+			 need to be swapped based on the target panel.
+			 By default the property is not defined.
 
 
 
@@ -162,6 +165,7 @@
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
+			qcom,mdss-mixer-swap;
 		};
 	};
 
diff --git a/Documentation/devicetree/bindings/regulator/krait-regulator.txt b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
index aaa731e..6a02e86 100644
--- a/Documentation/devicetree/bindings/regulator/krait-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/krait-regulator.txt
@@ -13,6 +13,8 @@
 				register base
 - reg-names:			"apcs_gcc" -string to identify the area where
 				the APCS GCC registers reside.
+- qcom,pfm-threshold		The power coeff threshold in abstract power units below which
+				pmic will be made to operate in PFM mode.
 
 Optional properties:
 - qcom,use-phase-switching	indicates whether the driver should add/shed phases on the PMIC
@@ -51,6 +53,7 @@
 		reg-names = "apcs_gcc";
 		compatible = "qcom,krait-pdn";
 		qcom,use-phase-switching;
+		qcom,pfm-threshold = <376975>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 65de56f..383e50d 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -449,6 +449,10 @@
 - qcom,prim-auxpcm-gpio-sync : GPIO on which Primary AUXPCM SYNC signal is coming.
 - qcom,prim-auxpcm-gpio-din  : GPIO on which Primary AUXPCM DIN signal is coming.
 - qcom,prim-auxpcm-gpio-dout : GPIO on which Primary AUXPCM DOUT signal is coming.
+- qcom,prim-auxpcm-gpio-set : set of GPIO lines used for Primary AUXPCM port
+		 Possible Values:
+		 prim-gpio-prim : Primary AUXPCM shares GPIOs with Primary MI2S
+		 prim-gpio-tert : Primary AUXPCM shares GPIOs with Tertiary MI2S
 - qcom,sec-auxpcm-gpio-clk  : GPIO on which Secondary AUXPCM clk signal is coming.
 - qcom,sec-auxpcm-gpio-sync : GPIO on which Secondary AUXPCM SYNC signal is coming.
 - qcom,sec-auxpcm-gpio-din  : GPIO on which Secondary AUXPCM DIN signal is coming.
@@ -503,6 +507,7 @@
 	qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
 	qcom,prim-auxpcm-gpio-din  = <&msmgpio 67 0>;
 	qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+	qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
 	qcom,sec-auxpcm-gpio-clk  = <&msmgpio 79 0>;
 	qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
 	qcom,sec-auxpcm-gpio-din  = <&msmgpio 81 0>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 6d06e99..1613856 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -121,6 +121,8 @@
 - qcom,pool-64-bit-align: If present then the pool's memory will be aligned
   to 64 bits
 - qcom,enable_hbm: if present host bus manager is enabled.
+- qcom,disable-park-mode: if present park mode is enabled. Park mode enables executing
+  up to 3 usb packets from each QH.
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
diff --git a/arch/arm/boot/dts/apq8074-v2-liquid.dts b/arch/arm/boot/dts/apq8074-v2-liquid.dts
new file mode 100644
index 0000000..4ec1cdd
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v2-liquid.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+/include/ "apq8074-v2.dtsi"
+/include/ "msm8974-liquid.dtsi"
+
+/ {
+	model = "Qualcomm APQ 8074v2 LIQUID";
+	compatible = "qcom,apq8074-liquid", "qcom,apq8074", "qcom,liquid";
+	qcom,msm-id = <184 9 0x20000>;
+};
+
+&usb3 {
+	interrupt-parent = <&usb3>;
+	interrupts = <0 1>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0x0 0xffffffff>;
+	interrupt-map = <0x0 0 &intc 0 133 0
+			0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+	interrupt-names = "hs_phy_irq", "pmic_id_irq";
+
+	qcom,misc-ref = <&pm8941_misc>;
+};
diff --git a/arch/arm/boot/dts/apq8074-v2.dtsi b/arch/arm/boot/dts/apq8074-v2.dtsi
index 0f867e0..3b65236 100644
--- a/arch/arm/boot/dts/apq8074-v2.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.dtsi
@@ -19,9 +19,9 @@
 /include/ "msm8974-v2.dtsi"
 
 / {
-	qcom,qseecom@7f00000 {
+	qcom,qseecom@a700000 {
 		compatible = "qcom,qseecom";
-		reg = <0x07f00000 0x500000>;
+		reg = <0x0a700000 0x500000>;
 		reg-names = "secapp-region";
 		qcom,disk-encrypt-pipe-pair = <2>;
 		qcom,hlos-ce-hw-instance = <1>;
@@ -39,10 +39,10 @@
 };
 
 &memory_hole {
-	qcom,memblock-remove = <0x07f00000 0x8000000>; /* Address and size of the hole */
+	qcom,memblock-remove = <0x0a700000 0x5800000>; /* Address and size of the hole */
 };
 
 &qseecom {
-	status = "enabled";
+	status = "disabled";
 };
 
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 99410b3..41920d5 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -686,6 +686,54 @@
 			label = "wled";
 		};
 
+		pwm@b100 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb100 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <0>;
+		};
+
+		pwm@b200 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb200 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <1>;
+		};
+
+		pwm@b300 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb300 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <2>;
+		};
+
+		pwm@b400 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb400 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <3>;
+		};
+
+		pwm@b500 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb500 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <4>;
+		};
+
+		pwm@b600 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xb600 0x100>,
+			      <0xb042 0x7e>;
+			reg-names = "qpnp-lpg-channel-base", "qpnp-lpg-lut-base";
+			qcom,channel-id = <5>;
+		};
+
 		regulator@8000 {
 			regulator-name = "8226_lvs1";
 			reg = <0x8000 0x100>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 9ee78a4..aa03951 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -229,6 +229,8 @@
 		HSUSB_3p3-supply = <&pm8226_l20>;
 		qcom,vdd-voltage-level = <1 5 7>;
 
+		qcom,hsusb-otg-phy-init-seq =
+			<0x44 0x80 0x68 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
 		qcom,hsusb-otg-phy-type = <2>;
 		qcom,hsusb-otg-mode = <1>;
 		qcom,hsusb-otg-otg-control = <2>;
@@ -915,6 +917,42 @@
 				<55 512 3936000 393600>,
 				<55 512 3936000 393600>;
 	};
+
+	qcom,qcrypto@fd404000 {
+		compatible = "qcom,qcrypto";
+                reg  =  <0xfd400000 0x20000>,
+                        <0xfd404000 0x8000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <2>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcrypto-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<56 512 0 0>,
+				<56 512 3936000 393600>;
+	};
+
+        qcom,qcedev@fd400000 {
+		compatible = "qcom,qcedev";
+		reg  =  <0xfd400000 0x20000>,
+			<0xfd404000 0x8000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <1>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcedev-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,active-only = <0>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<56 512 0 0>,
+				<56 512 3936000 393600>;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index a458869..d9acb81 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -347,6 +347,12 @@
 		qcom,ext-spk-amp-gpio = <&pm8841_mpps 1 0>;
 		qcom,dock-plug-det-irq = <&pm8841_mpps 2 0>;
 		qcom,hdmi-audio-rx;
+
+		qcom,prim-auxpcm-gpio-clk  = <&msmgpio 74 0>;
+		qcom,prim-auxpcm-gpio-sync = <&msmgpio 75 0>;
+		qcom,prim-auxpcm-gpio-din  = <&msmgpio 76 0>;
+		qcom,prim-auxpcm-gpio-dout = <&msmgpio 77 0>;
+		qcom,prim-auxpcm-gpio-set = "prim-gpio-tert";
 	};
 
 	hsic_hub {
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 0be3756..d1b3334 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -466,6 +466,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges;
+		qcom,pfm-threshold = <73>;
 
 		krait0_vreg: regulator@f9088000 {
 			compatible = "qcom,krait-regulator";
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 3227370..f787cf5 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -38,7 +38,7 @@
 
 		secure_mem: secure_region {
 			linux,contiguous-region;
-			reg = <0 0x7800000>;
+			reg = <0 0xFC00000>;
 			label = "secure_mem";
 		};
 
@@ -691,6 +691,7 @@
 		qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
 		qcom,prim-auxpcm-gpio-din  = <&msmgpio 67 0>;
 		qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+		qcom,prim-auxpcm-gpio-set = "prim-gpio-prim";
 		qcom,sec-auxpcm-gpio-clk  = <&msmgpio 79 0>;
 		qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
 		qcom,sec-auxpcm-gpio-din  = <&msmgpio 81 0>;
@@ -1239,7 +1240,27 @@
 		qcom,firmware-name = "venus";
 	};
 
-	qcom,cache_erp {
+	qcom,cache_erp@f9012000 {
+		reg = <0xf9012000 0x80>,
+		      <0xf9089000 0x80>,
+		      <0xf9099000 0x80>,
+		      <0xf90a9000 0x80>,
+		      <0xf90b9000 0x80>,
+		      <0xf9088000 0x40>,
+		      <0xf9098000 0x40>,
+		      <0xf90a8000 0x40>,
+		      <0xf90b8000 0x40>;
+
+		reg-names = "l2_saw",
+			    "krait0_saw",
+			    "krait1_saw",
+			    "krait2_saw",
+			    "krait3_saw",
+			    "krait0_acs",
+			    "krait1_acs",
+			    "krait2_acs",
+			    "krait3_acs";
+
 		compatible = "qcom,cache_erp";
 		interrupts = <1 9 0>, <0 2 0>;
 		interrupt-names = "l1_irq", "l2_irq";
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index ad95601..de88ff1 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -37,6 +37,10 @@
 	};
 };
 
+&hsic_host {
+	qcom,disable-park-mode;
+};
+
 &ipa_hw {
 	qcom,ipa-hw-ver = <1>; /* IPA h-w revision */
 };
diff --git a/arch/arm/boot/dts/msm9625-v2.dtsi b/arch/arm/boot/dts/msm9625-v2.dtsi
index 3ce6844..81d8e00 100644
--- a/arch/arm/boot/dts/msm9625-v2.dtsi
+++ b/arch/arm/boot/dts/msm9625-v2.dtsi
@@ -35,6 +35,10 @@
 	qcom,ipa-hw-ver = <2>; /* IPA h-w revision */
 };
 
+&hsic_host {
+	qcom,disable-park-mode;
+};
+
 &sfpb_spinlock {
 	status = "disable";
 };
diff --git a/arch/arm/boot/dts/msmkrypton.dtsi b/arch/arm/boot/dts/msmkrypton.dtsi
index db61dab..3f51659 100644
--- a/arch/arm/boot/dts/msmkrypton.dtsi
+++ b/arch/arm/boot/dts/msmkrypton.dtsi
@@ -37,12 +37,70 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
-	timer: msm-qtimer@f9021000 {
-		compatible = "arm,armv7-timer";
-		reg = <0xf9021000 0x1000>;
-		interrupts = <0 7 0>;
-		irq-is-not-percpu;
+	timer@f9020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xf9020000 0x1000>;
 		clock-frequency = <19200000>;
+
+		frame@f9021000 {
+			frame-number = <0>;
+			interrupts = <0 7 0x4>,
+				     <0 6 0x4>;
+			reg = <0xf9021000 0x1000>,
+			      <0xf9022000 0x1000>;
+		};
+
+		frame@f9023000 {
+			frame-number = <1>;
+			interrupts = <0 8 0x4>;
+			reg = <0xf9023000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9024000 {
+			frame-number = <2>;
+			interrupts = <0 9 0x4>;
+			reg = <0xf9024000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9025000 {
+			frame-number = <3>;
+			interrupts = <0 10 0x4>;
+			reg = <0xf9025000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9026000 {
+			frame-number = <4>;
+			interrupts = <0 11 0x4>;
+			reg = <0xf9026000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9027000 {
+			frame-number = <5>;
+			interrupts = <0 12 0x4>;
+			reg = <0xf9027000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9028000 {
+			frame-number = <6>;
+			interrupts = <0 13 0x4>;
+			reg = <0xf9028000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@f9029000 {
+			frame-number = <7>;
+			interrupts = <0 14 0x4>;
+			reg = <0xf9029000 0x1000>;
+			status = "disabled";
+		};
 	};
 
 	uartdm3: serial@f991f000 {
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index c47117e..f595188 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -313,6 +313,19 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_STORAGE_ENE_UB6250=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_BLOCK_MINORS=32
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+CONFIG_MMC_TEST=m
+CONFIG_MMC_BLOCK_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_MSM=y
+CONFIG_MMC_SDHCI_MSM=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_BACKLIGHT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 23244dc..59cafd1 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -350,6 +350,7 @@
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index df1837f..fd8a639 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -356,6 +356,7 @@
 CONFIG_ION=y
 CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
+CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
 # CONFIG_FB_MSM_BACKLIGHT is not set
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index cc85d70..a70e6c6 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -437,6 +437,7 @@
 	select CPU_FREQ
 	select CPU_FREQ_GOV_USERSPACE
 	select CPU_FREQ_GOV_ONDEMAND
+	select CPU_FREQ_GOV_POWERSAVE
 	select MSM_PIL
 	select MSM_RUN_QUEUE_STATS
 	select ARM_HAS_SG_CHAIN
@@ -1092,7 +1093,7 @@
 	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
 	default "0x00200000" if ARCH_MSM9625
-	default "0x00200000" if ARCH_MSMKRYPTON
+	default "0x00000000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
 	default "0x00000000" if ARCH_QSD8X50 && MSM_SOC_REV_A
 	default "0x20000000" if ARCH_QSD8X50
@@ -1246,6 +1247,14 @@
                 help
                   Say Y here if you want the debug print routines to direct
                   their output to the serial port on APQ8084 devices.
+
+	config DEBUG_MSM9625_UART
+                bool "Kernel low-level debugging messages via MSM9625 UART"
+                depends on ARCH_MSM9625
+                select MSM_HAS_DEBUG_UART_HS_V14
+                help
+                  Say Y here if you want the debug print routines to direct
+                  their output to the serial port on MSM9625 devices.
 endchoice
 
 choice
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 75191d6..d57709d 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -57,13 +57,14 @@
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-fluid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-liquid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2-mtp.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= apq8074-v2-liquid.dtb
 
 # APQ8084
    zreladdr-$(CONFIG_ARCH_APQ8084)	:= 0x00008000
         dtb-$(CONFIG_ARCH_APQ8084)	+= apq8084-sim.dtb
 
 # MSMKRYPTON
-   zreladdr-$(CONFIG_ARCH_MSMKRYPTON)	:= 0x00208000
+   zreladdr-$(CONFIG_ARCH_MSMKRYPTON)	:= 0x00008000
 	dtb-$(CONFIG_ARCH_MSMKRYPTON)	+= msmkrypton-sim.dtb
 
 # MSM9615
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index c60e89a..a61f5ca 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -128,122 +128,122 @@
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  835000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  845000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  880000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  905000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  920000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  940000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  980000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  995000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1015000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1030000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1050000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  915000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  930000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  945000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  960000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  975000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  990000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1000000, 506 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_v1_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 3200000 },
-	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 3200000 },
-	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 3200000 },
-	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 3200000 },
-	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 3200000 },
-	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 3200000 },
-	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 3200000 },
-	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),  825000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),  825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),  825000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),  825000, 124 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),  825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),  825000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),  825000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10), 825000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10), 825000, 229 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10), 825000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10), 825000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12), 835000, 298 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12), 855000, 321 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12), 870000, 346 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12), 885000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16), 900000, 397 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16), 910000, 423 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 925000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 940000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 950000, 506 },
 	{ 0, { 0 } }
 };
 
@@ -284,618 +284,618 @@
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  815000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  825000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  835000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  845000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  855000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  865000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  875000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  890000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  900000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  915000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  925000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  940000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  950000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  965000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  980000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  995000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16), 1010000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1025000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1040000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1055000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1070000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1085000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  810000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  820000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  830000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  840000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  850000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  860000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  875000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  885000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  895000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  920000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  930000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  945000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  960000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  975000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17), 1005000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17), 1020000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1030000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1045000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1060000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  785000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  795000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  910000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  955000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1005000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1020000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1035000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  780000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  790000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  935000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  970000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  985000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  995000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1010000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  780000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  790000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  870000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  880000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  950000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  960000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  975000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  985000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  760000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  770000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  780000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  790000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  800000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  810000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  820000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  830000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  840000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  860000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  870000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  880000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  920000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  930000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  940000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  955000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  965000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  73 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  85 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  760000, 104 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  770000, 124 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 144 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 165 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 186 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 208 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 229 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 252 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 275 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 298 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 321 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  870000, 346 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 371 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 397 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 423 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  905000, 450 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  915000, 477 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 506 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 536 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 567 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 598 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  805000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  815000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  825000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  835000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  845000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  855000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  865000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  875000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  900000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  915000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  925000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  940000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  950000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  965000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  980000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  995000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18), 1010000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1025000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1040000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  810000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  820000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  830000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  840000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  850000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  860000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  885000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  895000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  910000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  920000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  930000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  945000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  960000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  975000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  990000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1005000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1020000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  785000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  795000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  805000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  815000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  825000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  835000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  845000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  855000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  865000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  875000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  890000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  900000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  910000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  925000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  940000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  955000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  970000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  980000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  995000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  780000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  790000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  800000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  810000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  820000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  830000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  850000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  860000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  885000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  895000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  935000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  950000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  960000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  970000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  985000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  995000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  870000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  880000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  920000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  930000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  940000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  950000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  960000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  975000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  985000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  760000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  770000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  890000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  900000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  910000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  920000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  930000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  940000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  955000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  965000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  975000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 3200000 },
-	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 102 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 121 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 141 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 161 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 181 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 202 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 223 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 245 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 267 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 289 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 313 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 336 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 360 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 383 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 409 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  875000, 435 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  885000, 461 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  895000, 488 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  905000, 516 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  915000, 543 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  920000, 573 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  930000, 604 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  940000, 636 },
+	{ 1, { 2150400, HFPLL, 1, 112 }, L2(19),  950000, 656 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  805000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  815000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  825000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  835000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  845000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  855000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  865000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  890000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  900000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  915000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  925000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  940000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  965000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  980000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  995000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18), 1010000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1025000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  800000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  800000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  800000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  800000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  800000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  810000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  820000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  830000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  840000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  850000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  875000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  885000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  895000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  910000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  920000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  945000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  960000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  975000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  990000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18), 1005000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  785000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  795000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  805000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  815000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  825000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  835000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  855000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  865000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  875000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  890000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  900000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  925000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  940000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  955000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  970000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  980000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  780000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  790000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  800000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  810000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  820000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  840000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  850000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  860000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  875000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  885000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  910000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  925000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  935000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  950000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  960000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  775000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  775000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  775000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  775000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  775000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  775000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  780000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  790000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  800000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  810000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  830000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  840000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  850000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  860000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  870000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  895000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  910000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  920000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  930000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  940000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  760000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  770000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  780000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  790000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  800000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  820000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  830000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  840000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  850000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  860000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  880000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  890000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  900000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  910000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  920000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 691 },
 	{ 0, { 0 } }
 };
 
 static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
-	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  400000 },
-	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000, 3200000 },
-	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 3200000 },
-	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 3200000 },
-	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 3200000 },
-	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 3200000 },
-	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 3200000 },
-	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 3200000 },
-	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 3200000 },
-	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 3200000 },
-	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 3200000 },
-	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 3200000 },
-	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 3200000 },
-	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 3200000 },
-	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 3200000 },
-	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 3200000 },
-	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
-	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 3200000 },
-	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 3200000 },
-	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 3200000 },
-	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 3200000 },
-	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 3200000 },
-	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
-	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 3200000 },
-	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 3200000 },
-	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 3200000 },
-	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 3200000 },
+	{ 1, {  300000, PLL_0, 0,   0 },  L2(0),  750000,  72 },
+	{ 0, {  345600, HFPLL, 2,  36 },  L2(1),  750000,  83 },
+	{ 1, {  422400, HFPLL, 2,  44 },  L2(2),  750000, 101 },
+	{ 0, {  499200, HFPLL, 2,  52 },  L2(2),  750000, 120 },
+	{ 0, {  576000, HFPLL, 1,  30 },  L2(3),  750000, 139 },
+	{ 1, {  652800, HFPLL, 1,  34 },  L2(3),  750000, 159 },
+	{ 1, {  729600, HFPLL, 1,  38 },  L2(4),  760000, 180 },
+	{ 0, {  806400, HFPLL, 1,  42 },  L2(4),  770000, 200 },
+	{ 1, {  883200, HFPLL, 1,  46 },  L2(4),  780000, 221 },
+	{ 1, {  960000, HFPLL, 1,  50 },  L2(9),  790000, 242 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 264 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(10),  810000, 287 },
+	{ 1, { 1190400, HFPLL, 1,  62 }, L2(10),  820000, 308 },
+	{ 1, { 1267200, HFPLL, 1,  66 }, L2(13),  830000, 333 },
+	{ 0, { 1344000, HFPLL, 1,  70 }, L2(14),  840000, 356 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(15),  850000, 380 },
+	{ 1, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 404 },
+	{ 1, { 1574400, HFPLL, 1,  82 }, L2(17),  870000, 430 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(17),  875000, 456 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(18),  885000, 482 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(18),  895000, 510 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(18),  905000, 538 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 565 },
+	{ 0, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 596 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 627 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 659 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 691 },
 	{ 0, { 0 } }
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 74ca145..47bf27a 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -129,12 +129,26 @@
 		pr_warn("acpu rcg didn't update its configuration\n");
 }
 
-/*
- * This function can be called in both atomic and nonatomic context.
- * Since regulator APIS can sleep, we cannot always use the clk prepare
- * unprepare API.
- */
-static int set_speed(struct clkctl_acpu_speed *tgt_s, bool atomic)
+static int set_speed_atomic(struct clkctl_acpu_speed *tgt_s)
+{
+	struct clkctl_acpu_speed *strt_s = priv->current_speed;
+	struct clk *strt = priv->src_clocks[strt_s->src].clk;
+	struct clk *tgt = priv->src_clocks[tgt_s->src].clk;
+	int rc = 0;
+
+	WARN(strt_s->src == ACPUPLL && tgt_s->src == ACPUPLL,
+		"can't reprogram ACPUPLL during atomic context\n");
+	rc = clk_enable(tgt);
+	if (rc)
+		return rc;
+
+	select_clk_source_div(priv, tgt_s);
+	clk_disable(strt);
+
+	return rc;
+}
+
+static int set_speed(struct clkctl_acpu_speed *tgt_s)
 {
 	int rc = 0;
 	unsigned int tgt_freq_hz = tgt_s->khz * 1000;
@@ -148,19 +162,13 @@
 		select_clk_source_div(priv, cxo_s);
 
 		/* Re-program acpu pll */
-		if (atomic)
-			clk_disable(tgt);
-		else
-			clk_disable_unprepare(tgt);
+		clk_disable_unprepare(tgt);
 
 		rc = clk_set_rate(tgt, tgt_freq_hz);
 		if (rc)
 			pr_err("Failed to set ACPU PLL to %u\n", tgt_freq_hz);
 
-		if (atomic)
-			BUG_ON(clk_enable(tgt));
-		else
-			BUG_ON(clk_prepare_enable(tgt));
+		BUG_ON(clk_prepare_enable(tgt));
 
 		/* Switch back to acpu pll */
 		select_clk_source_div(priv, tgt_s);
@@ -172,10 +180,7 @@
 			return rc;
 		}
 
-		if (atomic)
-			rc = clk_enable(tgt);
-		else
-			rc = clk_prepare_enable(tgt);
+		rc = clk_prepare_enable(tgt);
 
 		if (rc) {
 			pr_err("ACPU PLL enable failed\n");
@@ -184,16 +189,10 @@
 
 		select_clk_source_div(priv, tgt_s);
 
-		if (atomic)
-			clk_disable(strt);
-		else
-			clk_disable_unprepare(strt);
+		clk_disable_unprepare(strt);
 
 	} else {
-		if (atomic)
-			rc = clk_enable(tgt);
-		else
-			rc = clk_prepare_enable(tgt);
+		rc = clk_prepare_enable(tgt);
 
 		if (rc) {
 			pr_err("%s enable failed\n",
@@ -203,10 +202,7 @@
 
 		select_clk_source_div(priv, tgt_s);
 
-		if (atomic)
-			clk_disable(strt);
-		else
-			clk_disable_unprepare(strt);
+		clk_disable_unprepare(strt);
 
 	}
 
@@ -250,9 +246,9 @@
 
 	/* Switch CPU speed. Flag indicates atomic context */
 	if (reason == SETRATE_CPUFREQ || reason == SETRATE_INIT)
-		rc = set_speed(tgt_s, false);
+		rc = set_speed(tgt_s);
 	else
-		rc = set_speed(tgt_s, true);
+		rc = set_speed_atomic(tgt_s);
 
 	if (rc)
 		goto out;
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index ddea91c..f52bc28 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -123,11 +123,18 @@
 	unsigned int mplxrexnok;
 };
 
+struct msm_erp_dump_region {
+	struct resource *res;
+	void __iomem *va;
+};
+
 static DEFINE_PER_CPU(struct msm_l1_err_stats, msm_l1_erp_stats);
 static struct msm_l2_err_stats msm_l2_erp_stats;
 
 static int l1_erp_irq, l2_erp_irq;
 static struct proc_dir_entry *procfs_entry;
+static int num_dump_regions;
+static struct msm_erp_dump_region *dump_regions;
 
 #ifdef CONFIG_MSM_L1_ERR_LOG
 static struct proc_dir_entry *procfs_log_entry;
@@ -211,6 +218,22 @@
 	return len;
 }
 
+static int msm_erp_dump_regions(void)
+{
+	int i = 0;
+	struct msm_erp_dump_region *r;
+
+	for (i = 0; i < num_dump_regions; i++) {
+		r = &dump_regions[i];
+
+		pr_alert("%s %pR:\n", r->res->name, r->res);
+		print_hex_dump(KERN_ALERT, "", DUMP_PREFIX_OFFSET, 32, 4, r->va,
+			       resource_size(r->res), 0);
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_MSM_L1_ERR_LOG
 static int proc_read_log(char *page, char **start, off_t off, int count,
 	int *eof, void *data)
@@ -267,6 +290,7 @@
 		pr_alert("\tCESR      = 0x%08x\n", cesr);
 		pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
 		pr_alert("\tMIDR      = 0x%08x\n", read_cpuid_id());
+		msm_erp_dump_regions();
 	}
 
 	if (cesr & CESR_DCTPE) {
@@ -425,6 +449,9 @@
 	if (port_error && print_alert)
 		ERP_PORT_ERR("L2 master port error detected");
 
+	if (soft_error && print_alert)
+		msm_erp_dump_regions();
+
 	if (soft_error && !unrecoverable)
 		ERP_1BIT_ERR("L2 single-bit error detected");
 
@@ -464,6 +491,37 @@
 	.notifier_call = cache_erp_cpu_callback,
 };
 
+static int msm_erp_read_dump_regions(struct platform_device *pdev)
+{
+	int i;
+	struct device_node *np = pdev->dev.of_node;
+	struct resource *res;
+
+	num_dump_regions = of_property_count_strings(np, "reg-names");
+
+	if (num_dump_regions <= 0) {
+		num_dump_regions = 0;
+		return 0; /* Not an error - this is an optional property */
+	}
+
+	dump_regions = devm_kzalloc(&pdev->dev,
+				    sizeof(*dump_regions) * num_dump_regions,
+				    GFP_KERNEL);
+	if (!dump_regions)
+		return -ENOMEM;
+
+	for (i = 0; i < num_dump_regions; i++) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+		dump_regions[i].res = res;
+		dump_regions[i].va = devm_ioremap(&pdev->dev, res->start,
+						  resource_size(res));
+		if (!dump_regions[i].va)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+
 static int msm_cache_erp_probe(struct platform_device *pdev)
 {
 	struct resource *r;
@@ -511,6 +569,11 @@
 		goto fail_l2;
 	}
 
+	ret = msm_erp_read_dump_regions(pdev);
+
+	if (ret)
+		goto fail_l2;
+
 	get_online_cpus();
 	register_hotcpu_notifier(&cache_erp_cpu_notifier);
 	for_each_cpu(cpu, cpu_online_mask)
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 6d76c41..af027f0 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -1709,13 +1709,19 @@
 	F_MMSS( 100000000,      gpll0,   6,    0,    0),
 	F_MMSS( 109090000,      gpll0, 5.5,    0,    0),
 	F_MMSS( 133330000,      gpll0, 4.5,    0,    0),
+	F_MMSS( 150000000,      gpll0,   4,    0,    0),
 	F_MMSS( 200000000,      gpll0,   3,    0,    0),
 	F_MMSS( 228570000, mmpll0_pll, 3.5,    0,    0),
 	F_MMSS( 266670000, mmpll0_pll,   3,    0,    0),
 	F_MMSS( 320000000, mmpll0_pll, 2.5,    0,    0),
+	F_MMSS( 400000000, mmpll0_pll,   2,    0,    0),
 	F_END
 };
 
+static unsigned long camss_vfe_vfe0_fmax_v2[VDD_DIG_NUM] = {
+	150000000, 320000000, 400000000,
+};
+
 static struct rcg_clk vfe0_clk_src = {
 	.cmd_rcgr_reg = VFE0_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -1972,11 +1978,17 @@
 
 static struct clk_freq_tbl ftbl_camss_vfe_cpp_clk[] = {
 	F_MMSS( 133330000,      gpll0, 4.5,    0,    0),
+	F_MMSS( 150000000,      gpll0,   4,    0,    0),
 	F_MMSS( 266670000, mmpll0_pll,   3,    0,    0),
 	F_MMSS( 320000000, mmpll0_pll, 2.5,    0,    0),
+	F_MMSS( 400000000, mmpll0_pll,   2,    0,    0),
 	F_END
 };
 
+static unsigned long camss_vfe_cpp_fmax_v2[VDD_DIG_NUM] = {
+	150000000, 320000000, 400000000,
+};
+
 static struct rcg_clk cpp_clk_src = {
 	.cmd_rcgr_reg = CPP_CMD_RCGR,
 	.set_rate = set_rate_hid,
@@ -2810,8 +2822,8 @@
 
 static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
 
-static DEFINE_CLK_VOTER(qseecom_ce1_clk_src, &ce1_clk_src.c, LONG_MAX);
-static DEFINE_CLK_VOTER(scm_ce1_clk_src, &ce1_clk_src.c, LONG_MAX);
+static DEFINE_CLK_VOTER(qseecom_ce1_clk_src, &ce1_clk_src.c, 100000000);
+static DEFINE_CLK_VOTER(scm_ce1_clk_src, &ce1_clk_src.c, 100000000);
 
 static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &xo.c);
 static DEFINE_CLK_BRANCH_VOTER(cxo_pil_lpass_clk, &xo.c);
@@ -3416,6 +3428,18 @@
 	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16390"),
 	CLK_LOOKUP("osr_clk", div_clk1.c, "msm-dai-q6-dev.16391"),
 
+	/* Add QCEDEV clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,      "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,  "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,  "fd400000.qcom,qcedev"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,      "fd400000.qcom,qcedev"),
+
+	/* Add QCRYPTO clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,     "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c, "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c, "fd404000.qcom,qcrypto"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,     "fd404000.qcom,qcrypto"),
+
 };
 
 static struct clk_lookup msm_clocks_8226_rumi[] = {
@@ -3545,6 +3569,12 @@
 
 	reg_init();
 
+	/* v2 specific changes */
+	if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		cpp_clk_src.c.fmax = camss_vfe_cpp_fmax_v2;
+		vfe0_clk_src.c.fmax = camss_vfe_vfe0_fmax_v2;
+	}
+
 	/*
 	 * MDSS needs the ahb clock and needs to init before we register the
 	 * lookup table.
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index a07b13d..6665d66 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -38,7 +38,7 @@
 #define EN_FEW_WAIT_VAL		(0x8 << 16)
 #define CLK_DIS_WAIT_VAL	(0x2 << 12)
 
-#define TIMEOUT_US		1000
+#define TIMEOUT_US		100
 
 struct gdsc {
 	struct regulator_dev	*rdev;
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 9a8bfc1..31b19b3 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -38,8 +38,8 @@
 #define MSM9625_MPM2_PSHOLD_SIZE	SZ_4K
 
 #ifdef CONFIG_DEBUG_MSM9625_UART
-#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71E000)
-#define MSM_DEBUG_UART_PHYS	0xF991E000
+#define MSM_DEBUG_UART_BASE	IOMEM(0xFA71F000)
+#define MSM_DEBUG_UART_PHYS	0xF991F000
 #endif
 
 #endif
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 20dc851..e889242 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -18,6 +18,14 @@
 
 #define QSEECOM_KEY_ID_SIZE   32
 
+#define	QSEOS_RESULT_FAIL_LOAD_KS         -48
+#define	QSEOS_RESULT_FAIL_SAVE_KS         -49
+#define	QSEOS_RESULT_FAIL_MAX_KEYS        -50
+#define	QSEOS_RESULT_FAIL_KEY_ID_EXISTS   -51
+#define	QSEOS_RESULT_FAIL_KEY_ID_DNE      -52
+#define	QSEOS_RESULT_FAIL_KS_OP           -53
+#define	QSEOS_RESULT_FAIL_CE_PIPE_INVALID -54
+
 enum qseecom_command_scm_resp_type {
 	QSEOS_APP_ID = 0xEE01,
 	QSEOS_LISTENER_ID
@@ -49,6 +57,22 @@
 	QSEOS_RESULT_FAILURE  = 0xFFFFFFFF
 };
 
+/* Key Management requests */
+enum qseecom_qceos_key_gen_cmd_id {
+	QSEOS_GENERATE_KEY  = 0x11,
+	QSEOS_DELETE_KEY,
+	QSEOS_MAX_KEY_COUNT,
+	QSEOS_SET_KEY,
+	QSEOS_KEY_CMD_MAX   = 0xEFFFFFFF
+};
+
+enum qseecom_pipe_type {
+	QSEOS_PIPE_ENC = 0,
+	QSEOS_PIPE_ENC_XTS,
+	QSEOS_PIPE_AUTH,
+	QSEOS_PIPE_ENUM_FILL = 0x7FFFFFFF
+};
+
 __packed  struct qsee_apps_region_info_ireq {
 	uint32_t qsee_cmd_id;
 	uint32_t addr;
@@ -143,29 +167,24 @@
 	unsigned int rsp_len; /* in/out */
 };
 
-/* Key Management requests */
-enum qseecom_qceos_key_gen_cmd_id {
-	QSEOS_GENERATE_KEY      = 0x02,
-	QSEOS_SET_KEY,
-	QSEOS_DELETE_KEY,
-	QSEOS_MAX_KEY_COUNT,
-	QSEOS_KEY_CMD_MAX     = 0xEFFFFFFF
-};
-
 __packed struct qseecom_key_generate_ireq {
+	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
 };
 
 __packed struct qseecom_key_select_ireq {
+	uint32_t qsee_command_id;
 	uint32_t ce;
 	uint32_t pipe;
+	uint32_t pipe_type;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
 	unsigned char hash[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_delete_ireq {
+	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
 };
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 42e04dd..4186603 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -22,7 +22,6 @@
 #define SCM_SVC_FUSE			0x8
 #define SCM_SVC_PWR			0x9
 #define SCM_SVC_MP			0xC
-#define SCM_SVC_CRYPTO			0xA
 #define SCM_SVC_DCVS			0xD
 #define SCM_SVC_ES			0x10
 #define SCM_SVC_TZSCHEDULER		0xFC
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 953f941d..52d20e3 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -61,9 +61,7 @@
 #define PMIC_VOLTAGE_MAX		1355000
 #define LV_RANGE_STEP			5000
 
-#define LOAD_PER_PHASE			3200000
-
-#define CORE_VOLTAGE_MIN		900000
+#define CORE_VOLTAGE_BOOTUP		900000
 
 #define KRAIT_LDO_VOLTAGE_MIN		465000
 #define KRAIT_LDO_VOLTAGE_OFFSET	465000
@@ -146,7 +144,10 @@
  *				regulator's callback functions to prevent
  *				simultaneous updates to the pmic's phase
  *				voltage.
- * @apcs_gcc_base		virtual address of the APCS GCC registers
+ * @apcs_gcc_base:		virtual address of the APCS GCC registers
+ * @manage_phases:		begin phase control
+ * @pfm_threshold:		the sum of coefficients below which PFM can be
+ *				enabled
  */
 struct pmic_gang_vreg {
 	const char		*name;
@@ -159,6 +160,8 @@
 	bool			retention_enabled;
 	bool			use_phase_switching;
 	void __iomem		*apcs_gcc_base;
+	bool			manage_phases;
+	int			pfm_threshold;
 };
 
 static struct pmic_gang_vreg *the_gang;
@@ -168,6 +171,9 @@
 	LDO_MODE = REGULATOR_MODE_IDLE,
 };
 
+#define WAIT_FOR_LOAD		0x2
+#define WAIT_FOR_VOLTAGE	0x1
+
 struct krait_power_vreg {
 	struct list_head		link;
 	struct regulator_desc		desc;
@@ -175,7 +181,7 @@
 	const char			*name;
 	struct pmic_gang_vreg		*pvreg;
 	int				uV;
-	int				load_uA;
+	int				load;
 	enum krait_supply_mode		mode;
 	void __iomem			*reg_base;
 	void __iomem			*mdd_base;
@@ -185,7 +191,10 @@
 	int				ldo_threshold_uV;
 	int				ldo_delta_uV;
 	int				cpu_num;
+	int				coeff1;
+	int				coeff2;
 	bool				online;
+	int				online_at_probe;
 };
 
 DEFINE_PER_CPU(struct krait_power_vreg *, krait_vregs);
@@ -293,6 +302,249 @@
 	return 0;
 }
 
+#define COEFF2_UV_THRESHOLD 850000
+static int get_coeff2(int krait_uV)
+{
+	int coeff2 = 0;
+	int krait_mV = krait_uV / 1000;
+
+	if (krait_uV <= COEFF2_UV_THRESHOLD)
+		coeff2 = (612229 * krait_mV) / 1000 - 211258;
+	else
+		coeff2 = (892564 * krait_mV) / 1000 - 449543;
+
+	return  coeff2;
+}
+
+static int get_coeff1(int actual_uV, int requested_uV, int load)
+{
+	int ratio = actual_uV * 1000 / requested_uV;
+	int coeff1 = 330 * load + (load * 673 * ratio / 1000);
+
+	return coeff1;
+}
+
+static int get_coeff_total(struct krait_power_vreg *from)
+{
+	int coeff_total = 0;
+	struct krait_power_vreg *kvreg;
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (!kvreg->online)
+			continue;
+
+		if (kvreg->mode == LDO_MODE) {
+			kvreg->coeff1 =
+				get_coeff1(kvreg->uV - kvreg->ldo_delta_uV,
+							kvreg->uV, kvreg->load);
+			kvreg->coeff2 =
+				get_coeff2(kvreg->uV - kvreg->ldo_delta_uV);
+		} else {
+			kvreg->coeff1 =
+				get_coeff1(pvreg->pmic_vmax_uV,
+							kvreg->uV, kvreg->load);
+			kvreg->coeff2 = get_coeff2(pvreg->pmic_vmax_uV);
+		}
+		coeff_total += kvreg->coeff1 + kvreg->coeff2;
+	}
+
+	return coeff_total;
+}
+
+static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
+{
+	pr_debug("programming phase_count = %d\n", phase_count);
+	if (pvreg->use_phase_switching)
+		/*
+		 * note the PMIC sets the phase count to one more than
+		 * the value in the register - hence subtract 1 from it
+		 */
+		return msm_spm_apcs_set_phase(phase_count - 1);
+	else
+		return 0;
+}
+
+static int num_online(struct pmic_gang_vreg *pvreg)
+{
+	int online_total = 0;
+	struct krait_power_vreg *kvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (kvreg->online)
+			online_total++;
+	}
+	return online_total;
+}
+
+static int get_total_load(struct krait_power_vreg *from)
+{
+	int load_total = 0;
+	struct krait_power_vreg *kvreg;
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		if (!kvreg->online)
+			continue;
+		load_total += kvreg->load;
+	}
+
+	return load_total;
+}
+
+static bool enable_phase_management(struct pmic_gang_vreg *pvreg)
+{
+	struct krait_power_vreg *kvreg;
+
+	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
+		pr_debug("%s online_at_probe:0x%x\n", kvreg->name,
+							kvreg->online_at_probe);
+		if (kvreg->online_at_probe)
+			return false;
+	}
+	return true;
+}
+
+#define PMIC_FTS_MODE_PFM	0x00
+#define PMIC_FTS_MODE_PWM	0x80
+#define ONE_PHASE_COEFF		1000000
+#define TWO_PHASE_COEFF		2000000
+
+#define PWM_SETTLING_TIME_US		50
+#define PHASE_SETTLING_TIME_US		50
+static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
+				int coeff_total)
+{
+	struct pmic_gang_vreg *pvreg = from->pvreg;
+	int phase_count;
+	int rc = 0;
+	int n_online = num_online(pvreg);
+	int load_total;
+
+	load_total = get_total_load(from);
+
+	if (pvreg->manage_phases == false) {
+		if (enable_phase_management(pvreg))
+			pvreg->manage_phases = true;
+		else
+			return 0;
+	}
+
+	/* First check if the coeff is low for PFM mode */
+	if (load_total <= pvreg->pfm_threshold && n_online == 1) {
+		if (!pvreg->pfm_mode) {
+			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
+			if (rc) {
+				pr_err("%s PFM en failed load_t %d rc = %d\n",
+					from->name, load_total, rc);
+				return rc;
+			} else {
+				pvreg->pfm_mode = true;
+			}
+		}
+		return rc;
+	}
+
+	/* coeff is high switch to PWM mode before changing phases */
+	if (pvreg->pfm_mode) {
+		rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
+		if (rc) {
+			pr_err("%s PFM exit failed load %d rc = %d\n",
+				from->name, coeff_total, rc);
+			return rc;
+		} else {
+			pvreg->pfm_mode = false;
+			udelay(PWM_SETTLING_TIME_US);
+		}
+	}
+
+	/* calculate phases */
+	if (coeff_total < ONE_PHASE_COEFF)
+		phase_count = 1;
+	else if (coeff_total < TWO_PHASE_COEFF)
+		phase_count = 2;
+	else
+		phase_count = 4;
+
+	/* don't increase the phase count higher than number of online cpus */
+	if (phase_count > n_online)
+		phase_count = n_online;
+
+	if (phase_count != pvreg->pmic_phase_count) {
+		rc = set_pmic_gang_phases(pvreg, phase_count);
+		if (rc < 0) {
+			pr_err("%s failed set phase %d rc = %d\n",
+				from->name, phase_count, rc);
+			return rc;
+		}
+
+		/* complete the writes before the delay */
+		mb();
+
+		/*
+		 * delay until the phases are settled when
+		 * the count is raised
+		 */
+		if (phase_count > pvreg->pmic_phase_count)
+			udelay(PHASE_SETTLING_TIME_US);
+
+		pvreg->pmic_phase_count = phase_count;
+	}
+
+	return rc;
+}
+
+static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
+			int input_uV, int output_uV, int load)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+	int coeff_total;
+	int rc;
+
+	kvreg->online_at_probe &= ~WAIT_FOR_LOAD;
+	coeff_total = get_coeff_total(kvreg);
+
+	rc = pmic_gang_set_phases(kvreg, coeff_total);
+	if (rc < 0) {
+		dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
+				kvreg->name, coeff_total, rc);
+	}
+
+	return kvreg->mode;
+}
+
+static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
+			int input_uV, int output_uV, int load_uA)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
+	int rc;
+
+	mutex_lock(&pvreg->krait_power_vregs_lock);
+	kvreg->load = load_uA;
+	if (!kvreg->online) {
+		mutex_unlock(&pvreg->krait_power_vregs_lock);
+		return kvreg->mode;
+	}
+
+	rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
+	mutex_unlock(&pvreg->krait_power_vregs_lock);
+
+	return rc;
+}
+
+static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	return 0;
+}
+
+static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
+{
+	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
+
+	return kvreg->mode;
+}
+
 static int switch_to_using_hs(struct krait_power_vreg *kvreg)
 {
 	if (kvreg->mode == HS_MODE)
@@ -368,19 +620,6 @@
 	return 0;
 }
 
-static int set_pmic_gang_phases(struct pmic_gang_vreg *pvreg, int phase_count)
-{
-	pr_debug("programming phase_count = %d\n", phase_count);
-	if (pvreg->use_phase_switching)
-		/*
-		 * note the PMIC sets the phase count to one more than
-		 * the value in the register - hence subtract 1 from it
-		 */
-		return msm_spm_apcs_set_phase(phase_count - 1);
-	else
-		return 0;
-}
-
 static int set_pmic_gang_voltage(struct pmic_gang_vreg *pvreg, int uV)
 {
 	int setpoint;
@@ -524,46 +763,6 @@
 	return rc;
 }
 
-#define PHASE_SETTLING_TIME_US		10
-static unsigned int pmic_gang_set_phases(struct krait_power_vreg *from,
-				int load_uA)
-{
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-	int phase_count = DIV_ROUND_UP(load_uA, LOAD_PER_PHASE);
-	int rc = 0;
-
-	if (phase_count <= 0)
-		phase_count = 1;
-
-	 /* Increase phases if it is less than the number of cpus online */
-	if (phase_count < num_online_cpus()) {
-		phase_count = num_online_cpus();
-	}
-
-	if (phase_count != pvreg->pmic_phase_count) {
-		rc = set_pmic_gang_phases(pvreg, phase_count);
-		if (rc < 0) {
-			dev_err(&from->rdev->dev,
-				"%s failed set phase %d rc = %d\n",
-				pvreg->name, phase_count, rc);
-			return rc;
-		}
-
-		/* complete the writes before the delay */
-		mb();
-
-		/*
-		 * delay until the phases are settled when
-		 * the count is raised
-		 */
-		if (phase_count > pvreg->pmic_phase_count)
-			udelay(PHASE_SETTLING_TIME_US);
-
-		pvreg->pmic_phase_count = phase_count;
-	}
-	return rc;
-}
-
 static int krait_power_get_voltage(struct regulator_dev *rdev)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -590,21 +789,6 @@
 	return vmax;
 }
 
-static int get_total_load(struct krait_power_vreg *from)
-{
-	int load_total = 0;
-	struct krait_power_vreg *kvreg;
-	struct pmic_gang_vreg *pvreg = from->pvreg;
-
-	list_for_each_entry(kvreg, &pvreg->krait_power_vregs, link) {
-		if (!kvreg->online)
-			continue;
-		load_total += kvreg->load_uA;
-	}
-
-	return load_total;
-}
-
 #define ROUND_UP_VOLTAGE(v, res) (DIV_ROUND_UP(v, res) * res)
 static int _set_voltage(struct regulator_dev *rdev,
 			int orig_krait_uV, int requested_uV)
@@ -613,6 +797,7 @@
 	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
 	int rc;
 	int vmax;
+	int coeff_total;
 
 	pr_debug("%s: %d to %d\n", kvreg->name, orig_krait_uV, requested_uV);
 	/*
@@ -636,6 +821,11 @@
 				kvreg->name, requested_uV, orig_krait_uV, rc);
 	}
 
+	kvreg->online_at_probe &= ~WAIT_FOR_VOLTAGE;
+	coeff_total = get_coeff_total(kvreg);
+	/* adjust the phases since coeff2 would have changed */
+	rc = pmic_gang_set_phases(kvreg, coeff_total);
+
 	return rc;
 }
 
@@ -670,89 +860,6 @@
 	return rc;
 }
 
-#define PMIC_FTS_MODE_PFM	0x00
-#define PMIC_FTS_MODE_PWM	0x80
-#define PFM_LOAD_UA		500000
-static unsigned int _get_optimum_mode(struct regulator_dev *rdev,
-			int input_uV, int output_uV, int load_uA)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
-	int rc;
-	int load_total_uA;
-
-	load_total_uA = get_total_load(kvreg);
-
-	if (load_total_uA < PFM_LOAD_UA) {
-		if (!pvreg->pfm_mode) {
-			rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PFM);
-			if (rc) {
-				dev_err(&rdev->dev,
-					"%s enter PFM failed load %d rc = %d\n",
-					kvreg->name, load_total_uA, rc);
-				goto out;
-			} else {
-				pvreg->pfm_mode = true;
-			}
-		}
-		return kvreg->mode;
-	}
-
-	if (pvreg->pfm_mode) {
-		rc = msm_spm_enable_fts_lpm(PMIC_FTS_MODE_PWM);
-		if (rc) {
-			dev_err(&rdev->dev,
-				"%s exit PFM failed load %d rc = %d\n",
-				kvreg->name, load_total_uA, rc);
-			goto out;
-		} else {
-			pvreg->pfm_mode = false;
-		}
-	}
-
-	rc = pmic_gang_set_phases(kvreg, load_total_uA);
-	if (rc < 0) {
-		dev_err(&rdev->dev, "%s failed set mode %d rc = %d\n",
-				kvreg->name, load_total_uA, rc);
-		goto out;
-	}
-
-out:
-	return kvreg->mode;
-}
-
-static unsigned int krait_power_get_optimum_mode(struct regulator_dev *rdev,
-			int input_uV, int output_uV, int load_uA)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-	struct pmic_gang_vreg *pvreg = kvreg->pvreg;
-	int rc;
-
-	mutex_lock(&pvreg->krait_power_vregs_lock);
-	kvreg->load_uA = load_uA;
-	if (!kvreg->online) {
-		mutex_unlock(&pvreg->krait_power_vregs_lock);
-		return kvreg->mode;
-	}
-
-	rc = _get_optimum_mode(rdev, input_uV, output_uV, load_uA);
-	mutex_unlock(&pvreg->krait_power_vregs_lock);
-
-	return rc;
-}
-
-static int krait_power_set_mode(struct regulator_dev *rdev, unsigned int mode)
-{
-	return 0;
-}
-
-static unsigned int krait_power_get_mode(struct regulator_dev *rdev)
-{
-	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
-
-	return kvreg->mode;
-}
-
 static int krait_power_is_enabled(struct regulator_dev *rdev)
 {
 	struct krait_power_vreg *kvreg = rdev_get_drvdata(rdev);
@@ -769,7 +876,7 @@
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	__krait_power_mdd_enable(kvreg, true);
 	kvreg->online = true;
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto en_err;
 	/*
@@ -791,8 +898,7 @@
 	mutex_lock(&pvreg->krait_power_vregs_lock);
 	kvreg->online = false;
 
-	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV,
-							kvreg->load_uA);
+	rc = _get_optimum_mode(rdev, kvreg->uV, kvreg->uV, kvreg->load);
 	if (rc < 0)
 		goto dis_err;
 
@@ -851,8 +957,10 @@
 DEFINE_SIMPLE_ATTRIBUTE(retention_fops,
 			get_retention_dbg_uV, set_retention_dbg_uV, "%llu\n");
 
+#define CPU_PWR_CTL_ONLINE_MASK 0x80
 static void kvreg_hw_init(struct krait_power_vreg *kvreg)
 {
+	int online;
 	/*
 	 * bhs_cnt value sets the ramp-up time from power collapse,
 	 * initialize the ramp up time
@@ -865,6 +973,10 @@
 	/* Enable MDD */
 	writel_relaxed(0x00000002, kvreg->mdd_base + MDD_MODE);
 	mb();
+	online = CPU_PWR_CTL_ONLINE_MASK
+			& readl_relaxed(kvreg->reg_base + CPU_PWR_CTL);
+	kvreg->online_at_probe
+		= online ? (WAIT_FOR_LOAD | WAIT_FOR_VOLTAGE) : 0x0;
 }
 
 static void glb_init(void __iomem *apcs_gcc_base)
@@ -1012,7 +1124,7 @@
 	kvreg->desc.ops		= &krait_power_ops;
 	kvreg->desc.type	= REGULATOR_VOLTAGE;
 	kvreg->desc.owner	= THIS_MODULE;
-	kvreg->uV		= CORE_VOLTAGE_MIN;
+	kvreg->uV		= CORE_VOLTAGE_BOOTUP;
 	kvreg->mode		= HS_MODE;
 	kvreg->desc.ops		= &krait_power_ops;
 	kvreg->headroom_uV	= headroom_uV;
@@ -1111,6 +1223,7 @@
 {
 	int rc;
 	bool use_phase_switching = false;
+	int pfm_threshold;
 	struct device *dev = &pdev->dev;
 	struct device_node *node = dev->of_node;
 	struct pmic_gang_vreg *pvreg;
@@ -1123,6 +1236,13 @@
 
 	use_phase_switching = of_property_read_bool(node,
 						"qcom,use-phase-switching");
+
+	rc = of_property_read_u32(node, "qcom,pfm-threshold", &pfm_threshold);
+	if (rc < 0) {
+		dev_err(dev, "pfm-threshold missing rc=%d, pfm disabled\n", rc);
+		return -EINVAL;
+	}
+
 	pvreg = devm_kzalloc(&pdev->dev,
 			sizeof(struct pmic_gang_vreg), GFP_KERNEL);
 	if (!pvreg) {
@@ -1148,6 +1268,7 @@
 	pvreg->retention_enabled = true;
 	pvreg->pmic_min_uV_for_retention = INT_MAX;
 	pvreg->use_phase_switching = use_phase_switching;
+	pvreg->pfm_threshold = pfm_threshold;
 
 	mutex_init(&pvreg->krait_power_vregs_lock);
 	INIT_LIST_HEAD(&pvreg->krait_power_vregs);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
index fd2dbb5..98419a4 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h
@@ -36,7 +36,7 @@
 	(((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0)
 
 #define INTERLEAVED_BW(fab_pdata, bw, ports) \
-	((fab_pdata->il_flag) ? msm_bus_div64((bw), (ports)) : (bw))
+	((fab_pdata->il_flag) ? msm_bus_div64((ports), (bw)) : (bw))
 #define INTERLEAVED_VAL(fab_pdata, n) \
 	((fab_pdata->il_flag) ? (n) : 1)
 
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 056da7d..475e8a1 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -290,10 +290,12 @@
 static void pil_dump_segs(const struct pil_priv *priv)
 {
 	struct pil_seg *seg;
+	phys_addr_t seg_h_paddr;
 
 	list_for_each_entry(seg, &priv->segs, list) {
-		pil_info(priv->desc, "%d: %#08zx %#08lx\n", seg->num,
-				seg->paddr, seg->paddr + seg->sz);
+		seg_h_paddr = seg->paddr + seg->sz;
+		pil_info(priv->desc, "%d: %pa %pa\n", seg->num,
+				&seg->paddr, &seg_h_paddr);
 	}
 }
 
@@ -322,7 +324,7 @@
 				return 0;
 		}
 	}
-	pil_err(priv->desc, "entry address %08zx not within range\n", entry);
+	pil_err(priv->desc, "entry address %pa not within range\n", &entry);
 	pil_dump_segs(priv);
 	return -EADDRNOTAVAIL;
 }
@@ -489,7 +491,8 @@
 
 static int pil_load_seg(struct pil_desc *desc, struct pil_seg *seg)
 {
-	int ret = 0, count, paddr;
+	int ret = 0, count;
+	phys_addr_t paddr;
 	char fw_name[30];
 	const struct firmware *fw = NULL;
 	const u8 *data;
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index ff10fe5..5aeeaf3 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -55,7 +55,8 @@
 	int (*init_image)(struct pil_desc *pil, const u8 *metadata,
 			  size_t size);
 	int (*mem_setup)(struct pil_desc *pil, phys_addr_t addr, size_t size);
-	int (*verify_blob)(struct pil_desc *pil, u32 phy_addr, size_t size);
+	int (*verify_blob)(struct pil_desc *pil, phys_addr_t phy_addr,
+			   size_t size);
 	int (*proxy_vote)(struct pil_desc *pil);
 	int (*auth_and_reset)(struct pil_desc *pil);
 	void (*proxy_unvote)(struct pil_desc *pil);
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index d44add6..65f86bc 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -203,7 +203,7 @@
 {
 	struct gss_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	void __iomem *cbase = drv->cbase;
 	int ret;
 
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 30f480a..8398206 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -93,7 +93,7 @@
 {
 	u32 reg;
 	const struct modem_data *drv = dev_get_drvdata(pil->dev);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Put modem AHB0,1,2 clocks into reset */
 	writel_relaxed(BIT(0) | BIT(1), drv->cbase + MAHB0_SFAB_PORT_RESET);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 0df8739..cf29cf1 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -123,7 +123,7 @@
 	int rc;
 	struct pronto_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Deassert reset to subsystem and wait for propagation */
 	reg = readl_relaxed(drv->reset_base);
diff --git a/arch/arm/mach-msm/pil-q6v3.c b/arch/arm/mach-msm/pil-q6v3.c
index 0575a3d..a369878 100644
--- a/arch/arm/mach-msm/pil-q6v3.c
+++ b/arch/arm/mach-msm/pil-q6v3.c
@@ -116,7 +116,7 @@
 {
 	u32 reg;
 	struct q6v3_data *drv = dev_get_drvdata(pil->dev);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Put Q6 into reset */
 	reg = readl_relaxed(drv->cbase + LCC_Q6_FUNC);
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 29d14dd..51f7aa2 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -130,7 +130,7 @@
 {
 	u32 reg, err;
 	const struct q6v4_data *drv = pil_to_q6v4_data(pil);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 
 	/* Enable Q6 ACLK */
 	writel_relaxed(0x10, drv->aclk_reg);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 277addc..04c1be3 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -127,7 +127,7 @@
 static int pil_lpass_reset(struct pil_desc *pil)
 {
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	int ret;
 
 	/* Deassert reset to subsystem and wait for propagation */
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index c3a0d32..c1c3100 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -243,7 +243,7 @@
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
 	struct platform_device *pdev = to_platform_device(pil->dev);
 	struct mba_data *mba = platform_get_drvdata(pdev);
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	int ret;
 
 	/*
@@ -402,7 +402,7 @@
 	return ret;
 }
 
-static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
+static int pil_mba_verify_blob(struct pil_desc *pil, phys_addr_t phy_addr,
 			       size_t size)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index a2665b4..d72b848 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -134,7 +134,7 @@
 	u32 reg, sel;
 	struct riva_data *drv = dev_get_drvdata(pil->dev);
 	void __iomem *base = drv->base;
-	unsigned long start_addr = pil_get_entry_addr(pil);
+	phys_addr_t start_addr = pil_get_entry_addr(pil);
 	void __iomem *cbase = drv->cbase;
 	bool use_cxo = cxo_is_needed(drv);
 
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 5a6e66a..a39e38b 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -64,7 +64,6 @@
 	(container_of(attr, struct msm_pm_kobj_attribute, ka)->cpu)
 
 #define SCLK_HZ (32768)
-#define MSM_PM_SLEEP_TICK_LIMIT (0x6DDD000)
 
 #define NUM_OF_COUNTERS 3
 #define MAX_BUF_SIZE  512
@@ -127,7 +126,6 @@
 static bool msm_pm_use_sync_timer;
 static struct msm_pm_cp15_save_data cp15_data;
 static bool msm_pm_retention_calls_tz;
-static uint32_t msm_pm_max_sleep_time;
 static bool msm_no_ramp_down_pc;
 static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
 static bool msm_pm_pc_reset_timer;
@@ -405,39 +403,6 @@
 	return;
 }
 
-/*
- * Convert time from nanoseconds to slow clock ticks, then cap it to the
- * specified limit
- */
-static int64_t msm_pm_convert_and_cap_time(int64_t time_ns, int64_t limit)
-{
-	do_div(time_ns, NSEC_PER_SEC / SCLK_HZ);
-	return (time_ns > limit) ? limit : time_ns;
-}
-
-/*
- * Set the sleep time for suspend.  0 means infinite sleep time.
- */
-void msm_pm_set_max_sleep_time(int64_t max_sleep_time_ns)
-{
-	if (max_sleep_time_ns == 0) {
-		msm_pm_max_sleep_time = 0;
-	} else {
-		msm_pm_max_sleep_time =
-			(uint32_t)msm_pm_convert_and_cap_time(
-			max_sleep_time_ns, MSM_PM_SLEEP_TICK_LIMIT);
-
-		if (msm_pm_max_sleep_time == 0)
-			msm_pm_max_sleep_time = 1;
-	}
-
-	if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
-		pr_info("%s: Requested %lld ns Giving %u sclk ticks\n",
-			__func__, max_sleep_time_ns,
-			msm_pm_max_sleep_time);
-}
-EXPORT_SYMBOL(msm_pm_set_max_sleep_time);
-
 static void msm_pm_save_cpu_reg(void)
 {
 	int i;
@@ -869,9 +834,8 @@
 	int exit_stat = -1;
 	enum msm_pm_sleep_mode sleep_mode;
 	void *msm_pm_idle_rs_limits = NULL;
-	int sleep_delay = 1;
+	uint32_t sleep_delay = 1;
 	int ret = -ENODEV;
-	int64_t timer_expiration = 0;
 	int notify_rpm = false;
 	bool timer_halted = false;
 
@@ -891,10 +855,8 @@
 
 	if (sleep_mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) {
 		notify_rpm = true;
-		timer_expiration = msm_pm_timer_enter_idle();
+		sleep_delay = (uint32_t)msm_pm_timer_enter_idle();
 
-		sleep_delay = (uint32_t) msm_pm_convert_and_cap_time(
-			timer_expiration, MSM_PM_SLEEP_TICK_LIMIT);
 		if (sleep_delay == 0) /* 0 would mean infinite time */
 			sleep_delay = 1;
 	}
@@ -1081,6 +1043,7 @@
 		void *rs_limits = NULL;
 		int ret = -ENODEV;
 		uint32_t power;
+		uint32_t msm_pm_max_sleep_time = 0;
 
 		if (MSM_PM_DEBUG_SUSPEND & msm_pm_debug_mask)
 			pr_info("%s: power collapse\n", __func__);
@@ -1090,8 +1053,8 @@
 		if (msm_pm_sleep_time_override > 0) {
 			int64_t ns = NSEC_PER_SEC *
 				(int64_t) msm_pm_sleep_time_override;
-			msm_pm_set_max_sleep_time(ns);
-			msm_pm_sleep_time_override = 0;
+			do_div(ns, NSEC_PER_SEC / SCLK_HZ);
+			msm_pm_max_sleep_time = (uint32_t) ns;
 		}
 
 		if (pm_sleep_ops.lowest_limits)
diff --git a/arch/arm/mach-msm/remote_spinlock.c b/arch/arm/mach-msm/remote_spinlock.c
index 94923a0..62e3e05 100644
--- a/arch/arm/mach-msm/remote_spinlock.c
+++ b/arch/arm/mach-msm/remote_spinlock.c
@@ -143,6 +143,7 @@
 }
 /* end dekkers implementation ----------------------------------------------- */
 
+#ifndef CONFIG_THUMB2_KERNEL
 /* swp implementation ------------------------------------------------------- */
 static void __raw_remote_swp_spin_lock(raw_remote_spinlock_t *lock)
 {
@@ -194,6 +195,7 @@
 	: "cc");
 }
 /* end swp implementation --------------------------------------------------- */
+#endif
 
 /* ldrex implementation ----------------------------------------------------- */
 static char *ldrex_compatible_string = "qcom,ipc-spinlock-ldrex";
@@ -431,6 +433,7 @@
 		current_ops.owner = __raw_remote_dek_spin_owner;
 		is_hw_lock_type = 0;
 		break;
+#ifndef CONFIG_THUMB2_KERNEL
 	case SWP_MODE:
 		current_ops.lock = __raw_remote_swp_spin_lock;
 		current_ops.unlock = __raw_remote_swp_spin_unlock;
@@ -439,6 +442,7 @@
 		current_ops.owner = __raw_remote_gen_spin_owner;
 		is_hw_lock_type = 0;
 		break;
+#endif
 	case LDREX_MODE:
 		current_ops.lock = __raw_remote_ex_spin_lock;
 		current_ops.unlock = __raw_remote_ex_spin_unlock;
diff --git a/drivers/coresight/coresight-csr.c b/drivers/coresight/coresight-csr.c
index 988d1c9..1c2ab25 100644
--- a/drivers/coresight/coresight-csr.c
+++ b/drivers/coresight/coresight-csr.c
@@ -102,7 +102,7 @@
 
 	CSR_LOCK(drvdata);
 }
-EXPORT_SYMBOL_GPL(msm_qdss_csr_enable_bam_to_usb);
+EXPORT_SYMBOL(msm_qdss_csr_enable_bam_to_usb);
 
 void msm_qdss_csr_disable_bam_to_usb(void)
 {
@@ -117,7 +117,7 @@
 
 	CSR_LOCK(drvdata);
 }
-EXPORT_SYMBOL_GPL(msm_qdss_csr_disable_bam_to_usb);
+EXPORT_SYMBOL(msm_qdss_csr_disable_bam_to_usb);
 
 void msm_qdss_csr_disable_flush(void)
 {
@@ -132,7 +132,7 @@
 
 	CSR_LOCK(drvdata);
 }
-EXPORT_SYMBOL_GPL(msm_qdss_csr_disable_flush);
+EXPORT_SYMBOL(msm_qdss_csr_disable_flush);
 
 static int __devinit csr_probe(struct platform_device *pdev)
 {
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 87cf63a..7d4dabe 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -595,7 +595,7 @@
 
 	return __stm_trace(options, entity_id, proto_id, data, size);
 }
-EXPORT_SYMBOL_GPL(stm_trace);
+EXPORT_SYMBOL(stm_trace);
 
 static ssize_t stm_write(struct file *file, const char __user *data,
 			 size_t size, loff_t *ppos)
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
index aef3d26..e237fb7 100644
--- a/drivers/coresight/coresight.c
+++ b/drivers/coresight/coresight.c
@@ -368,7 +368,7 @@
 	pr_err("coresight: enable failed\n");
 	return ret;
 }
-EXPORT_SYMBOL_GPL(coresight_enable);
+EXPORT_SYMBOL(coresight_enable);
 
 void coresight_disable(struct coresight_device *csdev)
 {
@@ -391,7 +391,7 @@
 out:
 	up(&coresight_mutex);
 }
-EXPORT_SYMBOL_GPL(coresight_disable);
+EXPORT_SYMBOL(coresight_disable);
 
 void coresight_abort(void)
 {
@@ -415,7 +415,7 @@
 out:
 	up(&coresight_mutex);
 }
-EXPORT_SYMBOL_GPL(coresight_abort);
+EXPORT_SYMBOL(coresight_abort);
 
 static ssize_t coresight_show_type(struct device *dev,
 				   struct device_attribute *attr, char *buf)
@@ -681,7 +681,7 @@
 err_kzalloc_csdev:
 	return ERR_PTR(ret);
 }
-EXPORT_SYMBOL_GPL(coresight_register);
+EXPORT_SYMBOL(coresight_register);
 
 void coresight_unregister(struct coresight_device *csdev)
 {
@@ -693,7 +693,7 @@
 		put_device(&csdev->dev);
 	}
 }
-EXPORT_SYMBOL_GPL(coresight_unregister);
+EXPORT_SYMBOL(coresight_unregister);
 
 static int __init coresight_init(void)
 {
diff --git a/drivers/coresight/of_coresight.c b/drivers/coresight/of_coresight.c
index 1eccd09..8b8c0d62 100644
--- a/drivers/coresight/of_coresight.c
+++ b/drivers/coresight/of_coresight.c
@@ -97,7 +97,7 @@
 						    "coresight-default-sink");
 	return pdata;
 }
-EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
+EXPORT_SYMBOL(of_get_coresight_platform_data);
 
 struct coresight_cti_data *of_get_coresight_cti_data(
 				struct device *dev, struct device_node *node)
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 63cdc68..7d1952c 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -20,97 +20,94 @@
 #include <linux/cpumask.h>
 #include <linux/cpufreq.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
+#include <linux/moduleparam.h>
+#include <linux/rwsem.h>
 #include <linux/sched.h>
 #include <linux/tick.h>
 #include <linux/time.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
-#include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/input.h>
 #include <asm/cputime.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/cpufreq_interactive.h>
 
-static atomic_t active_count = ATOMIC_INIT(0);
+static int active_count;
 
 struct cpufreq_interactive_cpuinfo {
 	struct timer_list cpu_timer;
-	int timer_idlecancel;
+	struct timer_list cpu_slack_timer;
+	spinlock_t load_lock; /* protects the next 4 fields */
 	u64 time_in_idle;
-	u64 idle_exit_time;
-	u64 timer_run_time;
-	int idling;
-	u64 target_set_time;
-	u64 target_set_time_in_idle;
+	u64 time_in_idle_timestamp;
+	u64 cputime_speedadj;
+	u64 cputime_speedadj_timestamp;
 	struct cpufreq_policy *policy;
 	struct cpufreq_frequency_table *freq_table;
 	unsigned int target_freq;
 	unsigned int floor_freq;
 	u64 floor_validate_time;
 	u64 hispeed_validate_time;
+	struct rw_semaphore enable_sem;
 	int governor_enabled;
 };
 
 static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo);
 
-/* Workqueues handle frequency scaling */
-static struct task_struct *up_task;
-static struct workqueue_struct *down_wq;
-static struct work_struct freq_scale_down_work;
-static cpumask_t up_cpumask;
-static spinlock_t up_cpumask_lock;
-static cpumask_t down_cpumask;
-static spinlock_t down_cpumask_lock;
-static struct mutex set_speed_lock;
+/* realtime thread handles frequency scaling */
+static struct task_struct *speedchange_task;
+static cpumask_t speedchange_cpumask;
+static spinlock_t speedchange_cpumask_lock;
+static struct mutex gov_lock;
 
 /* Hi speed to bump to from lo speed when load burst (default max) */
-static u64 hispeed_freq;
+static unsigned int hispeed_freq;
 
 /* Go to hi speed when CPU load at or above this value. */
-#define DEFAULT_GO_HISPEED_LOAD 85
-static unsigned long go_hispeed_load;
+#define DEFAULT_GO_HISPEED_LOAD 99
+static unsigned long go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;
+
+/* Target load.  Lower values result in higher CPU speeds. */
+#define DEFAULT_TARGET_LOAD 90
+static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD};
+static spinlock_t target_loads_lock;
+static unsigned int *target_loads = default_target_loads;
+static int ntarget_loads = ARRAY_SIZE(default_target_loads);
 
 /*
  * The minimum amount of time to spend at a frequency before we can ramp down.
  */
 #define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC)
-static unsigned long min_sample_time;
+static unsigned long min_sample_time = DEFAULT_MIN_SAMPLE_TIME;
 
 /*
  * The sample rate of the timer used to increase frequency
  */
 #define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC)
-static unsigned long timer_rate;
+static unsigned long timer_rate = DEFAULT_TIMER_RATE;
 
 /*
  * Wait this long before raising speed above hispeed, by default a single
  * timer interval.
  */
 #define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE
-static unsigned long above_hispeed_delay_val;
+static unsigned long above_hispeed_delay_val = DEFAULT_ABOVE_HISPEED_DELAY;
 
-/*
- * Boost pulse to hispeed on touchscreen input.
- */
-
-static int input_boost_val;
-
-struct cpufreq_interactive_inputopen {
-	struct input_handle *handle;
-	struct work_struct inputopen_work;
-};
-
-static struct cpufreq_interactive_inputopen inputopen;
-
-/*
- * Non-zero means longer-term speed boost active.
- */
-
+/* Non-zero means indefinite speed boost active */
 static int boost_val;
+/* Duration of a boot pulse in usecs */
+static int boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME;
+/* End time of boost pulse in ktime converted to usecs */
+static u64 boostpulse_endtime;
+
+/*
+ * Max additional time to wait in idle, beyond timer_rate, at speeds above
+ * minimum before wakeup to reduce speed, or -1 if unnecessary.
+ */
+#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE)
+static int timer_slack_val = DEFAULT_TIMER_SLACK;
 
 static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
 		unsigned int event);
@@ -125,104 +122,210 @@
 	.owner = THIS_MODULE,
 };
 
-static void cpufreq_interactive_timer(unsigned long data)
+static void cpufreq_interactive_timer_resched(
+	struct cpufreq_interactive_cpuinfo *pcpu)
 {
-	unsigned int delta_idle;
-	unsigned int delta_time;
-	int cpu_load;
-	int load_since_change;
-	u64 time_in_idle;
-	u64 idle_exit_time;
-	struct cpufreq_interactive_cpuinfo *pcpu =
-		&per_cpu(cpuinfo, data);
-	u64 now_idle;
-	unsigned int new_freq;
-	unsigned int index;
+	unsigned long expires = jiffies + usecs_to_jiffies(timer_rate);
 	unsigned long flags;
 
-	smp_rmb();
+	mod_timer_pinned(&pcpu->cpu_timer, expires);
+	if (timer_slack_val >= 0 && pcpu->target_freq > pcpu->policy->min) {
+		expires += usecs_to_jiffies(timer_slack_val);
+		mod_timer_pinned(&pcpu->cpu_slack_timer, expires);
+	}
 
+	spin_lock_irqsave(&pcpu->load_lock, flags);
+	pcpu->time_in_idle =
+		get_cpu_idle_time_us(smp_processor_id(),
+				     &pcpu->time_in_idle_timestamp);
+	pcpu->cputime_speedadj = 0;
+	pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp;
+	spin_unlock_irqrestore(&pcpu->load_lock, flags);
+}
+
+static unsigned int freq_to_targetload(unsigned int freq)
+{
+	int i;
+	unsigned int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&target_loads_lock, flags);
+
+	for (i = 0; i < ntarget_loads - 1 && freq >= target_loads[i+1]; i += 2)
+		;
+
+	ret = target_loads[i];
+	spin_unlock_irqrestore(&target_loads_lock, flags);
+	return ret;
+}
+
+/*
+ * If increasing frequencies never map to a lower target load then
+ * choose_freq() will find the minimum frequency that does not exceed its
+ * target load given the current load.
+ */
+
+static unsigned int choose_freq(
+	struct cpufreq_interactive_cpuinfo *pcpu, unsigned int loadadjfreq)
+{
+	unsigned int freq = pcpu->policy->cur;
+	unsigned int prevfreq, freqmin, freqmax;
+	unsigned int tl;
+	int index;
+
+	freqmin = 0;
+	freqmax = UINT_MAX;
+
+	do {
+		prevfreq = freq;
+		tl = freq_to_targetload(freq);
+
+		/*
+		 * Find the lowest frequency where the computed load is less
+		 * than or equal to the target load.
+		 */
+
+		cpufreq_frequency_table_target(
+			pcpu->policy, pcpu->freq_table, loadadjfreq / tl,
+			CPUFREQ_RELATION_L, &index);
+		freq = pcpu->freq_table[index].frequency;
+
+		if (freq > prevfreq) {
+			/* The previous frequency is too low. */
+			freqmin = prevfreq;
+
+			if (freq >= freqmax) {
+				/*
+				 * Find the highest frequency that is less
+				 * than freqmax.
+				 */
+				cpufreq_frequency_table_target(
+					pcpu->policy, pcpu->freq_table,
+					freqmax - 1, CPUFREQ_RELATION_H,
+					&index);
+				freq = pcpu->freq_table[index].frequency;
+
+				if (freq == freqmin) {
+					/*
+					 * The first frequency below freqmax
+					 * has already been found to be too
+					 * low.  freqmax is the lowest speed
+					 * we found that is fast enough.
+					 */
+					freq = freqmax;
+					break;
+				}
+			}
+		} else if (freq < prevfreq) {
+			/* The previous frequency is high enough. */
+			freqmax = prevfreq;
+
+			if (freq <= freqmin) {
+				/*
+				 * Find the lowest frequency that is higher
+				 * than freqmin.
+				 */
+				cpufreq_frequency_table_target(
+					pcpu->policy, pcpu->freq_table,
+					freqmin + 1, CPUFREQ_RELATION_L,
+					&index);
+				freq = pcpu->freq_table[index].frequency;
+
+				/*
+				 * If freqmax is the first frequency above
+				 * freqmin then we have already found that
+				 * this speed is fast enough.
+				 */
+				if (freq == freqmax)
+					break;
+			}
+		}
+
+		/* If same frequency chosen as previous then done. */
+	} while (freq != prevfreq);
+
+	return freq;
+}
+
+static u64 update_load(int cpu)
+{
+	struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu);
+	u64 now;
+	u64 now_idle;
+	unsigned int delta_idle;
+	unsigned int delta_time;
+	u64 active_time;
+
+	now_idle = get_cpu_idle_time_us(cpu, &now);
+	delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle);
+	delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp);
+	active_time = delta_time - delta_idle;
+	pcpu->cputime_speedadj += active_time * pcpu->policy->cur;
+
+	pcpu->time_in_idle = now_idle;
+	pcpu->time_in_idle_timestamp = now;
+	return now;
+}
+
+static void cpufreq_interactive_timer(unsigned long data)
+{
+	u64 now;
+	unsigned int delta_time;
+	u64 cputime_speedadj;
+	int cpu_load;
+	struct cpufreq_interactive_cpuinfo *pcpu =
+		&per_cpu(cpuinfo, data);
+	unsigned int new_freq;
+	unsigned int loadadjfreq;
+	unsigned int index;
+	unsigned long flags;
+	bool boosted;
+
+	if (!down_read_trylock(&pcpu->enable_sem))
+		return;
 	if (!pcpu->governor_enabled)
 		goto exit;
 
-	/*
-	 * Once pcpu->timer_run_time is updated to >= pcpu->idle_exit_time,
-	 * this lets idle exit know the current idle time sample has
-	 * been processed, and idle exit can generate a new sample and
-	 * re-arm the timer.  This prevents a concurrent idle
-	 * exit on that CPU from writing a new set of info at the same time
-	 * the timer function runs (the timer function can't use that info
-	 * until more time passes).
-	 */
-	time_in_idle = pcpu->time_in_idle;
-	idle_exit_time = pcpu->idle_exit_time;
-	now_idle = get_cpu_idle_time_us(data, &pcpu->timer_run_time);
-	smp_wmb();
+	spin_lock_irqsave(&pcpu->load_lock, flags);
+	now = update_load(data);
+	delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp);
+	cputime_speedadj = pcpu->cputime_speedadj;
+	spin_unlock_irqrestore(&pcpu->load_lock, flags);
 
-	/* If we raced with cancelling a timer, skip. */
-	if (!idle_exit_time)
-		goto exit;
-
-	delta_idle = (unsigned int)(now_idle - time_in_idle);
-	delta_time = (unsigned int)(pcpu->timer_run_time - idle_exit_time);
-
-	/*
-	 * If timer ran less than 1ms after short-term sample started, retry.
-	 */
-	if (delta_time < 1000)
+	if (WARN_ON_ONCE(!delta_time))
 		goto rearm;
 
-	if (delta_idle > delta_time)
-		cpu_load = 0;
-	else
-		cpu_load = 100 * (delta_time - delta_idle) / delta_time;
+	do_div(cputime_speedadj, delta_time);
+	loadadjfreq = (unsigned int)cputime_speedadj * 100;
+	cpu_load = loadadjfreq / pcpu->target_freq;
+	boosted = boost_val || now < boostpulse_endtime;
 
-	delta_idle = (unsigned int)(now_idle - pcpu->target_set_time_in_idle);
-	delta_time = (unsigned int)(pcpu->timer_run_time -
-				    pcpu->target_set_time);
-
-	if ((delta_time == 0) || (delta_idle > delta_time))
-		load_since_change = 0;
-	else
-		load_since_change =
-			100 * (delta_time - delta_idle) / delta_time;
-
-	/*
-	 * Choose greater of short-term load (since last idle timer
-	 * started or timer function re-armed itself) or long-term load
-	 * (since last frequency change).
-	 */
-	if (load_since_change > cpu_load)
-		cpu_load = load_since_change;
-
-	if (cpu_load >= go_hispeed_load || boost_val) {
-		if (pcpu->target_freq <= pcpu->policy->min) {
+	if (cpu_load >= go_hispeed_load || boosted) {
+		if (pcpu->target_freq < hispeed_freq) {
 			new_freq = hispeed_freq;
 		} else {
-			new_freq = pcpu->policy->max * cpu_load / 100;
+			new_freq = choose_freq(pcpu, loadadjfreq);
 
 			if (new_freq < hispeed_freq)
 				new_freq = hispeed_freq;
-
-			if (pcpu->target_freq == hispeed_freq &&
-			    new_freq > hispeed_freq &&
-			    pcpu->timer_run_time - pcpu->hispeed_validate_time
-			    < above_hispeed_delay_val) {
-				trace_cpufreq_interactive_notyet(data, cpu_load,
-								 pcpu->target_freq,
-								 new_freq);
-				goto rearm;
-			}
 		}
 	} else {
-		new_freq = pcpu->policy->max * cpu_load / 100;
+		new_freq = choose_freq(pcpu, loadadjfreq);
 	}
 
-	if (new_freq <= hispeed_freq)
-		pcpu->hispeed_validate_time = pcpu->timer_run_time;
+	if (pcpu->target_freq >= hispeed_freq &&
+	    new_freq > pcpu->target_freq &&
+	    now - pcpu->hispeed_validate_time < above_hispeed_delay_val) {
+		trace_cpufreq_interactive_notyet(
+			data, cpu_load, pcpu->target_freq,
+			pcpu->policy->cur, new_freq);
+		goto rearm;
+	}
+
+	pcpu->hispeed_validate_time = now;
 
 	if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table,
-					   new_freq, CPUFREQ_RELATION_H,
+					   new_freq, CPUFREQ_RELATION_L,
 					   &index)) {
 		pr_warn_once("timer %d: cpufreq_frequency_table_target error\n",
 			     (int) data);
@@ -236,41 +339,42 @@
 	 * floor frequency for the minimum sample time since last validated.
 	 */
 	if (new_freq < pcpu->floor_freq) {
-		if (pcpu->timer_run_time - pcpu->floor_validate_time
-		    < min_sample_time) {
-			trace_cpufreq_interactive_notyet(data, cpu_load,
-					 pcpu->target_freq, new_freq);
+		if (now - pcpu->floor_validate_time < min_sample_time) {
+			trace_cpufreq_interactive_notyet(
+				data, cpu_load, pcpu->target_freq,
+				pcpu->policy->cur, new_freq);
 			goto rearm;
 		}
 	}
 
-	pcpu->floor_freq = new_freq;
-	pcpu->floor_validate_time = pcpu->timer_run_time;
+	/*
+	 * Update the timestamp for checking whether speed has been held at
+	 * or above the selected frequency for a minimum of min_sample_time,
+	 * if not boosted to hispeed_freq.  If boosted to hispeed_freq then we
+	 * allow the speed to drop as soon as the boostpulse duration expires
+	 * (or the indefinite boost is turned off).
+	 */
+
+	if (!boosted || new_freq > hispeed_freq) {
+		pcpu->floor_freq = new_freq;
+		pcpu->floor_validate_time = now;
+	}
 
 	if (pcpu->target_freq == new_freq) {
-		trace_cpufreq_interactive_already(data, cpu_load,
-						  pcpu->target_freq, new_freq);
+		trace_cpufreq_interactive_already(
+			data, cpu_load, pcpu->target_freq,
+			pcpu->policy->cur, new_freq);
 		goto rearm_if_notmax;
 	}
 
 	trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq,
-					 new_freq);
-	pcpu->target_set_time_in_idle = now_idle;
-	pcpu->target_set_time = pcpu->timer_run_time;
+					 pcpu->policy->cur, new_freq);
 
-	if (new_freq < pcpu->target_freq) {
-		pcpu->target_freq = new_freq;
-		spin_lock_irqsave(&down_cpumask_lock, flags);
-		cpumask_set_cpu(data, &down_cpumask);
-		spin_unlock_irqrestore(&down_cpumask_lock, flags);
-		queue_work(down_wq, &freq_scale_down_work);
-	} else {
-		pcpu->target_freq = new_freq;
-		spin_lock_irqsave(&up_cpumask_lock, flags);
-		cpumask_set_cpu(data, &up_cpumask);
-		spin_unlock_irqrestore(&up_cpumask_lock, flags);
-		wake_up_process(up_task);
-	}
+	pcpu->target_freq = new_freq;
+	spin_lock_irqsave(&speedchange_cpumask_lock, flags);
+	cpumask_set_cpu(data, &speedchange_cpumask);
+	spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
+	wake_up_process(speedchange_task);
 
 rearm_if_notmax:
 	/*
@@ -281,28 +385,11 @@
 		goto exit;
 
 rearm:
-	if (!timer_pending(&pcpu->cpu_timer)) {
-		/*
-		 * If already at min: if that CPU is idle, don't set timer.
-		 * Else cancel the timer if that CPU goes idle.  We don't
-		 * need to re-evaluate speed until the next idle exit.
-		 */
-		if (pcpu->target_freq == pcpu->policy->min) {
-			smp_rmb();
-
-			if (pcpu->idling)
-				goto exit;
-
-			pcpu->timer_idlecancel = 1;
-		}
-
-		pcpu->time_in_idle = get_cpu_idle_time_us(
-			data, &pcpu->idle_exit_time);
-		mod_timer(&pcpu->cpu_timer,
-			  jiffies + usecs_to_jiffies(timer_rate));
-	}
+	if (!timer_pending(&pcpu->cpu_timer))
+		cpufreq_interactive_timer_resched(pcpu);
 
 exit:
+	up_read(&pcpu->enable_sem);
 	return;
 }
 
@@ -312,15 +399,16 @@
 		&per_cpu(cpuinfo, smp_processor_id());
 	int pending;
 
-	if (!pcpu->governor_enabled)
+	if (!down_read_trylock(&pcpu->enable_sem))
 		return;
+	if (!pcpu->governor_enabled) {
+		up_read(&pcpu->enable_sem);
+		return;
+	}
 
-	pcpu->idling = 1;
-	smp_wmb();
 	pending = timer_pending(&pcpu->cpu_timer);
 
 	if (pcpu->target_freq != pcpu->policy->min) {
-#ifdef CONFIG_SMP
 		/*
 		 * Entering idle while not at lowest speed.  On some
 		 * platforms this can hold the other CPU(s) at that speed
@@ -329,33 +417,11 @@
 		 * min indefinitely.  This should probably be a quirk of
 		 * the CPUFreq driver.
 		 */
-		if (!pending) {
-			pcpu->time_in_idle = get_cpu_idle_time_us(
-				smp_processor_id(), &pcpu->idle_exit_time);
-			pcpu->timer_idlecancel = 0;
-			mod_timer(&pcpu->cpu_timer,
-				  jiffies + usecs_to_jiffies(timer_rate));
-		}
-#endif
-	} else {
-		/*
-		 * If at min speed and entering idle after load has
-		 * already been evaluated, and a timer has been set just in
-		 * case the CPU suddenly goes busy, cancel that timer.  The
-		 * CPU didn't go busy; we'll recheck things upon idle exit.
-		 */
-		if (pending && pcpu->timer_idlecancel) {
-			del_timer(&pcpu->cpu_timer);
-			/*
-			 * Ensure last timer run time is after current idle
-			 * sample start time, so next idle exit will always
-			 * start a new idle sampling period.
-			 */
-			pcpu->idle_exit_time = 0;
-			pcpu->timer_idlecancel = 0;
-		}
+		if (!pending)
+			cpufreq_interactive_timer_resched(pcpu);
 	}
 
+	up_read(&pcpu->enable_sem);
 }
 
 static void cpufreq_interactive_idle_end(void)
@@ -363,34 +429,26 @@
 	struct cpufreq_interactive_cpuinfo *pcpu =
 		&per_cpu(cpuinfo, smp_processor_id());
 
-	pcpu->idling = 0;
-	smp_wmb();
-
-	/*
-	 * Arm the timer for 1-2 ticks later if not already, and if the timer
-	 * function has already processed the previous load sampling
-	 * interval.  (If the timer is not pending but has not processed
-	 * the previous interval, it is probably racing with us on another
-	 * CPU.  Let it compute load based on the previous sample and then
-	 * re-arm the timer for another interval when it's done, rather
-	 * than updating the interval start time to be "now", which doesn't
-	 * give the timer function enough time to make a decision on this
-	 * run.)
-	 */
-	if (timer_pending(&pcpu->cpu_timer) == 0 &&
-	    pcpu->timer_run_time >= pcpu->idle_exit_time &&
-	    pcpu->governor_enabled) {
-		pcpu->time_in_idle =
-			get_cpu_idle_time_us(smp_processor_id(),
-					     &pcpu->idle_exit_time);
-		pcpu->timer_idlecancel = 0;
-		mod_timer(&pcpu->cpu_timer,
-			  jiffies + usecs_to_jiffies(timer_rate));
+	if (!down_read_trylock(&pcpu->enable_sem))
+		return;
+	if (!pcpu->governor_enabled) {
+		up_read(&pcpu->enable_sem);
+		return;
 	}
 
+	/* Arm the timer for 1-2 ticks later if not already. */
+	if (!timer_pending(&pcpu->cpu_timer)) {
+		cpufreq_interactive_timer_resched(pcpu);
+	} else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) {
+		del_timer(&pcpu->cpu_timer);
+		del_timer(&pcpu->cpu_slack_timer);
+		cpufreq_interactive_timer(smp_processor_id());
+	}
+
+	up_read(&pcpu->enable_sem);
 }
 
-static int cpufreq_interactive_up_task(void *data)
+static int cpufreq_interactive_speedchange_task(void *data)
 {
 	unsigned int cpu;
 	cpumask_t tmp_mask;
@@ -399,34 +457,35 @@
 
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&up_cpumask_lock, flags);
+		spin_lock_irqsave(&speedchange_cpumask_lock, flags);
 
-		if (cpumask_empty(&up_cpumask)) {
-			spin_unlock_irqrestore(&up_cpumask_lock, flags);
+		if (cpumask_empty(&speedchange_cpumask)) {
+			spin_unlock_irqrestore(&speedchange_cpumask_lock,
+					       flags);
 			schedule();
 
 			if (kthread_should_stop())
 				break;
 
-			spin_lock_irqsave(&up_cpumask_lock, flags);
+			spin_lock_irqsave(&speedchange_cpumask_lock, flags);
 		}
 
 		set_current_state(TASK_RUNNING);
-		tmp_mask = up_cpumask;
-		cpumask_clear(&up_cpumask);
-		spin_unlock_irqrestore(&up_cpumask_lock, flags);
+		tmp_mask = speedchange_cpumask;
+		cpumask_clear(&speedchange_cpumask);
+		spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
 
 		for_each_cpu(cpu, &tmp_mask) {
 			unsigned int j;
 			unsigned int max_freq = 0;
 
 			pcpu = &per_cpu(cpuinfo, cpu);
-			smp_rmb();
-
-			if (!pcpu->governor_enabled)
+			if (!down_read_trylock(&pcpu->enable_sem))
 				continue;
-
-			mutex_lock(&set_speed_lock);
+			if (!pcpu->governor_enabled) {
+				up_read(&pcpu->enable_sem);
+				continue;
+			}
 
 			for_each_cpu(j, pcpu->policy->cpus) {
 				struct cpufreq_interactive_cpuinfo *pjcpu =
@@ -440,57 +499,17 @@
 				__cpufreq_driver_target(pcpu->policy,
 							max_freq,
 							CPUFREQ_RELATION_H);
-			mutex_unlock(&set_speed_lock);
-			trace_cpufreq_interactive_up(cpu, pcpu->target_freq,
+			trace_cpufreq_interactive_setspeed(cpu,
+						     pcpu->target_freq,
 						     pcpu->policy->cur);
+
+			up_read(&pcpu->enable_sem);
 		}
 	}
 
 	return 0;
 }
 
-static void cpufreq_interactive_freq_down(struct work_struct *work)
-{
-	unsigned int cpu;
-	cpumask_t tmp_mask;
-	unsigned long flags;
-	struct cpufreq_interactive_cpuinfo *pcpu;
-
-	spin_lock_irqsave(&down_cpumask_lock, flags);
-	tmp_mask = down_cpumask;
-	cpumask_clear(&down_cpumask);
-	spin_unlock_irqrestore(&down_cpumask_lock, flags);
-
-	for_each_cpu(cpu, &tmp_mask) {
-		unsigned int j;
-		unsigned int max_freq = 0;
-
-		pcpu = &per_cpu(cpuinfo, cpu);
-		smp_rmb();
-
-		if (!pcpu->governor_enabled)
-			continue;
-
-		mutex_lock(&set_speed_lock);
-
-		for_each_cpu(j, pcpu->policy->cpus) {
-			struct cpufreq_interactive_cpuinfo *pjcpu =
-				&per_cpu(cpuinfo, j);
-
-			if (pjcpu->target_freq > max_freq)
-				max_freq = pjcpu->target_freq;
-		}
-
-		if (max_freq != pcpu->policy->cur)
-			__cpufreq_driver_target(pcpu->policy, max_freq,
-						CPUFREQ_RELATION_H);
-
-		mutex_unlock(&set_speed_lock);
-		trace_cpufreq_interactive_down(cpu, pcpu->target_freq,
-					       pcpu->policy->cur);
-	}
-}
-
 static void cpufreq_interactive_boost(void)
 {
 	int i;
@@ -498,17 +517,16 @@
 	unsigned long flags;
 	struct cpufreq_interactive_cpuinfo *pcpu;
 
-	spin_lock_irqsave(&up_cpumask_lock, flags);
+	spin_lock_irqsave(&speedchange_cpumask_lock, flags);
 
 	for_each_online_cpu(i) {
 		pcpu = &per_cpu(cpuinfo, i);
 
 		if (pcpu->target_freq < hispeed_freq) {
 			pcpu->target_freq = hispeed_freq;
-			cpumask_set_cpu(i, &up_cpumask);
-			pcpu->target_set_time_in_idle =
-				get_cpu_idle_time_us(i, &pcpu->target_set_time);
-			pcpu->hispeed_validate_time = pcpu->target_set_time;
+			cpumask_set_cpu(i, &speedchange_cpumask);
+			pcpu->hispeed_validate_time =
+				ktime_to_us(ktime_get());
 			anyboost = 1;
 		}
 
@@ -521,106 +539,126 @@
 		pcpu->floor_validate_time = ktime_to_us(ktime_get());
 	}
 
-	spin_unlock_irqrestore(&up_cpumask_lock, flags);
+	spin_unlock_irqrestore(&speedchange_cpumask_lock, flags);
 
 	if (anyboost)
-		wake_up_process(up_task);
+		wake_up_process(speedchange_task);
 }
 
-/*
- * Pulsed boost on input event raises CPUs to hispeed_freq and lets
- * usual algorithm of min_sample_time  decide when to allow speed
- * to drop.
- */
-
-static void cpufreq_interactive_input_event(struct input_handle *handle,
-					    unsigned int type,
-					    unsigned int code, int value)
+static int cpufreq_interactive_notifier(
+	struct notifier_block *nb, unsigned long val, void *data)
 {
-	if (input_boost_val && type == EV_SYN && code == SYN_REPORT) {
-		trace_cpufreq_interactive_boost("input");
-		cpufreq_interactive_boost();
+	struct cpufreq_freqs *freq = data;
+	struct cpufreq_interactive_cpuinfo *pcpu;
+	int cpu;
+	unsigned long flags;
+
+	if (val == CPUFREQ_POSTCHANGE) {
+		pcpu = &per_cpu(cpuinfo, freq->cpu);
+		if (!down_read_trylock(&pcpu->enable_sem))
+			return 0;
+		if (!pcpu->governor_enabled) {
+			up_read(&pcpu->enable_sem);
+			return 0;
+		}
+
+		for_each_cpu(cpu, pcpu->policy->cpus) {
+			struct cpufreq_interactive_cpuinfo *pjcpu =
+				&per_cpu(cpuinfo, cpu);
+			spin_lock_irqsave(&pjcpu->load_lock, flags);
+			update_load(cpu);
+			spin_unlock_irqrestore(&pjcpu->load_lock, flags);
+		}
+
+		up_read(&pcpu->enable_sem);
 	}
-}
-
-static void cpufreq_interactive_input_open(struct work_struct *w)
-{
-	struct cpufreq_interactive_inputopen *io =
-		container_of(w, struct cpufreq_interactive_inputopen,
-			     inputopen_work);
-	int error;
-
-	error = input_open_device(io->handle);
-	if (error)
-		input_unregister_handle(io->handle);
-}
-
-static int cpufreq_interactive_input_connect(struct input_handler *handler,
-					     struct input_dev *dev,
-					     const struct input_device_id *id)
-{
-	struct input_handle *handle;
-	int error;
-
-	pr_info("%s: connect to %s\n", __func__, dev->name);
-	handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL);
-	if (!handle)
-		return -ENOMEM;
-
-	handle->dev = dev;
-	handle->handler = handler;
-	handle->name = "cpufreq_interactive";
-
-	error = input_register_handle(handle);
-	if (error)
-		goto err;
-
-	inputopen.handle = handle;
-	queue_work(down_wq, &inputopen.inputopen_work);
 	return 0;
-err:
-	kfree(handle);
-	return error;
 }
 
-static void cpufreq_interactive_input_disconnect(struct input_handle *handle)
+static struct notifier_block cpufreq_notifier_block = {
+	.notifier_call = cpufreq_interactive_notifier,
+};
+
+static ssize_t show_target_loads(
+	struct kobject *kobj, struct attribute *attr, char *buf)
 {
-	input_close_device(handle);
-	input_unregister_handle(handle);
-	kfree(handle);
+	int i;
+	ssize_t ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&target_loads_lock, flags);
+
+	for (i = 0; i < ntarget_loads; i++)
+		ret += sprintf(buf + ret, "%u%s", target_loads[i],
+			       i & 0x1 ? ":" : " ");
+
+	ret += sprintf(buf + ret, "\n");
+	spin_unlock_irqrestore(&target_loads_lock, flags);
+	return ret;
 }
 
-static const struct input_device_id cpufreq_interactive_ids[] = {
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT |
-			 INPUT_DEVICE_ID_MATCH_ABSBIT,
-		.evbit = { BIT_MASK(EV_ABS) },
-		.absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
-			    BIT_MASK(ABS_MT_POSITION_X) |
-			    BIT_MASK(ABS_MT_POSITION_Y) },
-	}, /* multi-touch touchscreen */
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_KEYBIT |
-			 INPUT_DEVICE_ID_MATCH_ABSBIT,
-		.keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) },
-		.absbit = { [BIT_WORD(ABS_X)] =
-			    BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
-	}, /* touchpad */
-	{ },
-};
+static ssize_t store_target_loads(
+	struct kobject *kobj, struct attribute *attr, const char *buf,
+	size_t count)
+{
+	int ret;
+	const char *cp;
+	unsigned int *new_target_loads = NULL;
+	int ntokens = 1;
+	int i;
+	unsigned long flags;
 
-static struct input_handler cpufreq_interactive_input_handler = {
-	.event          = cpufreq_interactive_input_event,
-	.connect        = cpufreq_interactive_input_connect,
-	.disconnect     = cpufreq_interactive_input_disconnect,
-	.name           = "cpufreq_interactive",
-	.id_table       = cpufreq_interactive_ids,
-};
+	cp = buf;
+	while ((cp = strpbrk(cp + 1, " :")))
+		ntokens++;
+
+	if (!(ntokens & 0x1))
+		goto err_inval;
+
+	new_target_loads = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL);
+	if (!new_target_loads) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	cp = buf;
+	i = 0;
+	while (i < ntokens) {
+		if (sscanf(cp, "%u", &new_target_loads[i++]) != 1)
+			goto err_inval;
+
+		cp = strpbrk(cp, " :");
+		if (!cp)
+			break;
+		cp++;
+	}
+
+	if (i != ntokens)
+		goto err_inval;
+
+	spin_lock_irqsave(&target_loads_lock, flags);
+	if (target_loads != default_target_loads)
+		kfree(target_loads);
+	target_loads = new_target_loads;
+	ntarget_loads = ntokens;
+	spin_unlock_irqrestore(&target_loads_lock, flags);
+	return count;
+
+err_inval:
+	ret = -EINVAL;
+err:
+	kfree(new_target_loads);
+	return ret;
+}
+
+static struct global_attr target_loads_attr =
+	__ATTR(target_loads, S_IRUGO | S_IWUSR,
+		show_target_loads, store_target_loads);
 
 static ssize_t show_hispeed_freq(struct kobject *kobj,
 				 struct attribute *attr, char *buf)
 {
-	return sprintf(buf, "%llu\n", hispeed_freq);
+	return sprintf(buf, "%u\n", hispeed_freq);
 }
 
 static ssize_t store_hispeed_freq(struct kobject *kobj,
@@ -628,9 +666,9 @@
 				  size_t count)
 {
 	int ret;
-	u64 val;
+	long unsigned int val;
 
-	ret = strict_strtoull(buf, 0, &val);
+	ret = strict_strtoul(buf, 0, &val);
 	if (ret < 0)
 		return ret;
 	hispeed_freq = val;
@@ -729,26 +767,28 @@
 static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644,
 		show_timer_rate, store_timer_rate);
 
-static ssize_t show_input_boost(struct kobject *kobj, struct attribute *attr,
-				char *buf)
+static ssize_t show_timer_slack(
+	struct kobject *kobj, struct attribute *attr, char *buf)
 {
-	return sprintf(buf, "%u\n", input_boost_val);
+	return sprintf(buf, "%d\n", timer_slack_val);
 }
 
-static ssize_t store_input_boost(struct kobject *kobj, struct attribute *attr,
-				 const char *buf, size_t count)
+static ssize_t store_timer_slack(
+	struct kobject *kobj, struct attribute *attr, const char *buf,
+	size_t count)
 {
 	int ret;
 	unsigned long val;
 
-	ret = strict_strtoul(buf, 0, &val);
+	ret = kstrtol(buf, 10, &val);
 	if (ret < 0)
 		return ret;
-	input_boost_val = val;
+
+	timer_slack_val = val;
 	return count;
 }
 
-define_one_global_rw(input_boost);
+define_one_global_rw(timer_slack);
 
 static ssize_t show_boost(struct kobject *kobj, struct attribute *attr,
 			  char *buf)
@@ -790,6 +830,7 @@
 	if (ret < 0)
 		return ret;
 
+	boostpulse_endtime = ktime_to_us(ktime_get()) + boostpulse_duration_val;
 	trace_cpufreq_interactive_boost("pulse");
 	cpufreq_interactive_boost();
 	return count;
@@ -798,15 +839,40 @@
 static struct global_attr boostpulse =
 	__ATTR(boostpulse, 0200, NULL, store_boostpulse);
 
+static ssize_t show_boostpulse_duration(
+	struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", boostpulse_duration_val);
+}
+
+static ssize_t store_boostpulse_duration(
+	struct kobject *kobj, struct attribute *attr, const char *buf,
+	size_t count)
+{
+	int ret;
+	unsigned long val;
+
+	ret = kstrtoul(buf, 0, &val);
+	if (ret < 0)
+		return ret;
+
+	boostpulse_duration_val = val;
+	return count;
+}
+
+define_one_global_rw(boostpulse_duration);
+
 static struct attribute *interactive_attributes[] = {
+	&target_loads_attr.attr,
 	&hispeed_freq_attr.attr,
 	&go_hispeed_load_attr.attr,
 	&above_hispeed_delay.attr,
 	&min_sample_time_attr.attr,
 	&timer_rate_attr.attr,
-	&input_boost.attr,
+	&timer_slack.attr,
 	&boost.attr,
 	&boostpulse.attr,
+	&boostpulse_duration.attr,
 	NULL,
 };
 
@@ -815,102 +881,6 @@
 	.name = "interactive",
 };
 
-static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
-		unsigned int event)
-{
-	int rc;
-	unsigned int j;
-	struct cpufreq_interactive_cpuinfo *pcpu;
-	struct cpufreq_frequency_table *freq_table;
-
-	switch (event) {
-	case CPUFREQ_GOV_START:
-		if (!cpu_online(policy->cpu))
-			return -EINVAL;
-
-		freq_table =
-			cpufreq_frequency_get_table(policy->cpu);
-
-		for_each_cpu(j, policy->cpus) {
-			pcpu = &per_cpu(cpuinfo, j);
-			pcpu->policy = policy;
-			pcpu->target_freq = policy->cur;
-			pcpu->freq_table = freq_table;
-			pcpu->target_set_time_in_idle =
-				get_cpu_idle_time_us(j,
-					     &pcpu->target_set_time);
-			pcpu->floor_freq = pcpu->target_freq;
-			pcpu->floor_validate_time =
-				pcpu->target_set_time;
-			pcpu->hispeed_validate_time =
-				pcpu->target_set_time;
-			pcpu->governor_enabled = 1;
-			pcpu->idle_exit_time = pcpu->target_set_time;
-			mod_timer(&pcpu->cpu_timer,
-				jiffies + usecs_to_jiffies(timer_rate));
-			smp_wmb();
-		}
-
-		if (!hispeed_freq)
-			hispeed_freq = policy->max;
-
-		/*
-		 * Do not register the idle hook and create sysfs
-		 * entries if we have already done so.
-		 */
-		if (atomic_inc_return(&active_count) > 1)
-			return 0;
-
-		rc = sysfs_create_group(cpufreq_global_kobject,
-				&interactive_attr_group);
-		if (rc)
-			return rc;
-
-		rc = input_register_handler(&cpufreq_interactive_input_handler);
-		if (rc)
-			pr_warn("%s: failed to register input handler\n",
-				__func__);
-
-		break;
-
-	case CPUFREQ_GOV_STOP:
-		for_each_cpu(j, policy->cpus) {
-			pcpu = &per_cpu(cpuinfo, j);
-			pcpu->governor_enabled = 0;
-			smp_wmb();
-			del_timer_sync(&pcpu->cpu_timer);
-
-			/*
-			 * Reset idle exit time since we may cancel the timer
-			 * before it can run after the last idle exit time,
-			 * to avoid tripping the check in idle exit for a timer
-			 * that is trying to run.
-			 */
-			pcpu->idle_exit_time = 0;
-		}
-
-		flush_work(&freq_scale_down_work);
-		if (atomic_dec_return(&active_count) > 0)
-			return 0;
-
-		input_unregister_handler(&cpufreq_interactive_input_handler);
-		sysfs_remove_group(cpufreq_global_kobject,
-				&interactive_attr_group);
-
-		break;
-
-	case CPUFREQ_GOV_LIMITS:
-		if (policy->max < policy->cur)
-			__cpufreq_driver_target(policy,
-					policy->max, CPUFREQ_RELATION_H);
-		else if (policy->min > policy->cur)
-			__cpufreq_driver_target(policy,
-					policy->min, CPUFREQ_RELATION_L);
-		break;
-	}
-	return 0;
-}
-
 static int cpufreq_interactive_idle_notifier(struct notifier_block *nb,
 					     unsigned long val,
 					     void *data)
@@ -931,57 +901,148 @@
 	.notifier_call = cpufreq_interactive_idle_notifier,
 };
 
+static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
+		unsigned int event)
+{
+	int rc;
+	unsigned int j;
+	struct cpufreq_interactive_cpuinfo *pcpu;
+	struct cpufreq_frequency_table *freq_table;
+
+	switch (event) {
+	case CPUFREQ_GOV_START:
+		if (!cpu_online(policy->cpu))
+			return -EINVAL;
+
+		mutex_lock(&gov_lock);
+
+		freq_table =
+			cpufreq_frequency_get_table(policy->cpu);
+		if (!hispeed_freq)
+			hispeed_freq = policy->max;
+
+		for_each_cpu(j, policy->cpus) {
+			unsigned long expires;
+
+			pcpu = &per_cpu(cpuinfo, j);
+			pcpu->policy = policy;
+			pcpu->target_freq = policy->cur;
+			pcpu->freq_table = freq_table;
+			pcpu->floor_freq = pcpu->target_freq;
+			pcpu->floor_validate_time =
+				ktime_to_us(ktime_get());
+			pcpu->hispeed_validate_time =
+				pcpu->floor_validate_time;
+			down_write(&pcpu->enable_sem);
+			expires = jiffies + usecs_to_jiffies(timer_rate);
+			pcpu->cpu_timer.expires = expires;
+			add_timer_on(&pcpu->cpu_timer, j);
+			if (timer_slack_val >= 0) {
+				expires += usecs_to_jiffies(timer_slack_val);
+				pcpu->cpu_slack_timer.expires = expires;
+				add_timer_on(&pcpu->cpu_slack_timer, j);
+			}
+			pcpu->governor_enabled = 1;
+			up_write(&pcpu->enable_sem);
+		}
+
+		/*
+		 * Do not register the idle hook and create sysfs
+		 * entries if we have already done so.
+		 */
+		if (++active_count > 1) {
+			mutex_unlock(&gov_lock);
+			return 0;
+		}
+
+		rc = sysfs_create_group(cpufreq_global_kobject,
+				&interactive_attr_group);
+		if (rc) {
+			mutex_unlock(&gov_lock);
+			return rc;
+		}
+
+		idle_notifier_register(&cpufreq_interactive_idle_nb);
+		cpufreq_register_notifier(
+			&cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+		mutex_unlock(&gov_lock);
+		break;
+
+	case CPUFREQ_GOV_STOP:
+		mutex_lock(&gov_lock);
+		for_each_cpu(j, policy->cpus) {
+			pcpu = &per_cpu(cpuinfo, j);
+			down_write(&pcpu->enable_sem);
+			pcpu->governor_enabled = 0;
+			del_timer_sync(&pcpu->cpu_timer);
+			del_timer_sync(&pcpu->cpu_slack_timer);
+			up_write(&pcpu->enable_sem);
+		}
+
+		if (--active_count > 0) {
+			mutex_unlock(&gov_lock);
+			return 0;
+		}
+
+		cpufreq_unregister_notifier(
+			&cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+		idle_notifier_unregister(&cpufreq_interactive_idle_nb);
+		sysfs_remove_group(cpufreq_global_kobject,
+				&interactive_attr_group);
+		mutex_unlock(&gov_lock);
+
+		break;
+
+	case CPUFREQ_GOV_LIMITS:
+		if (policy->max < policy->cur)
+			__cpufreq_driver_target(policy,
+					policy->max, CPUFREQ_RELATION_H);
+		else if (policy->min > policy->cur)
+			__cpufreq_driver_target(policy,
+					policy->min, CPUFREQ_RELATION_L);
+		break;
+	}
+	return 0;
+}
+
+static void cpufreq_interactive_nop_timer(unsigned long data)
+{
+}
+
 static int __init cpufreq_interactive_init(void)
 {
 	unsigned int i;
 	struct cpufreq_interactive_cpuinfo *pcpu;
 	struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 };
 
-	go_hispeed_load = DEFAULT_GO_HISPEED_LOAD;
-	min_sample_time = DEFAULT_MIN_SAMPLE_TIME;
-	above_hispeed_delay_val = DEFAULT_ABOVE_HISPEED_DELAY;
-	timer_rate = DEFAULT_TIMER_RATE;
-
 	/* Initalize per-cpu timers */
 	for_each_possible_cpu(i) {
 		pcpu = &per_cpu(cpuinfo, i);
-		init_timer(&pcpu->cpu_timer);
+		init_timer_deferrable(&pcpu->cpu_timer);
 		pcpu->cpu_timer.function = cpufreq_interactive_timer;
 		pcpu->cpu_timer.data = i;
+		init_timer(&pcpu->cpu_slack_timer);
+		pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer;
+		spin_lock_init(&pcpu->load_lock);
+		init_rwsem(&pcpu->enable_sem);
 	}
 
-	up_task = kthread_create(cpufreq_interactive_up_task, NULL,
-				 "kinteractiveup");
-	if (IS_ERR(up_task))
-		return PTR_ERR(up_task);
+	spin_lock_init(&target_loads_lock);
+	spin_lock_init(&speedchange_cpumask_lock);
+	mutex_init(&gov_lock);
+	speedchange_task =
+		kthread_create(cpufreq_interactive_speedchange_task, NULL,
+			       "cfinteractive");
+	if (IS_ERR(speedchange_task))
+		return PTR_ERR(speedchange_task);
 
-	sched_setscheduler_nocheck(up_task, SCHED_FIFO, &param);
-	get_task_struct(up_task);
+	sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, &param);
+	get_task_struct(speedchange_task);
 
-	/* No rescuer thread, bind to CPU queuing the work for possibly
-	   warm cache (probably doesn't matter much). */
-	down_wq = alloc_workqueue("knteractive_down", 0, 1);
+	/* NB: wake up so the thread does not look hung to the freezer */
+	wake_up_process(speedchange_task);
 
-	if (!down_wq)
-		goto err_freeuptask;
-
-	INIT_WORK(&freq_scale_down_work,
-		  cpufreq_interactive_freq_down);
-
-	spin_lock_init(&up_cpumask_lock);
-	spin_lock_init(&down_cpumask_lock);
-	mutex_init(&set_speed_lock);
-
-	/* Kick the kthread to idle */
-	wake_up_process(up_task);
-
-	idle_notifier_register(&cpufreq_interactive_idle_nb);
-	INIT_WORK(&inputopen.inputopen_work, cpufreq_interactive_input_open);
 	return cpufreq_register_governor(&cpufreq_gov_interactive);
-
-err_freeuptask:
-	put_task_struct(up_task);
-	return -ENOMEM;
 }
 
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE
@@ -993,9 +1054,8 @@
 static void __exit cpufreq_interactive_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_interactive);
-	kthread_stop(up_task);
-	put_task_struct(up_task);
-	destroy_workqueue(down_wq);
+	kthread_stop(speedchange_task);
+	put_task_struct(speedchange_task);
 }
 
 module_exit(cpufreq_interactive_exit);
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index c758b3a..99ace44 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -306,7 +306,7 @@
 config CRYPTO_DEV_QCE
 	tristate "Qualcomm Crypto Engine (QCE) module"
 	select  CRYPTO_DEV_QCE40 if ARCH_MSM8960 || ARCH_MSM9615
-	select  CRYPTO_DEV_QCE50 if ARCH_MSM8974 || ARCH_MSM9625
+	select  CRYPTO_DEV_QCE50 if ARCH_MSM8974 || ARCH_MSM9625 || ARCH_MSM8226
 	default n
 	help
           This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 4282f02..fbe4da0 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1662,8 +1662,8 @@
 		return false;
 	rt_mutex_lock(&heap->lock);
 	list_for_each_entry_safe(buffer, tmp, &heap->free_list, list) {
-		_ion_buffer_destroy(buffer);
 		list_del(&buffer->list);
+		_ion_buffer_destroy(buffer);
 	}
 	BUG_ON(!list_empty(&heap->free_list));
 	rt_mutex_unlock(&heap->lock);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 53d853d..bc9bddd 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -27,6 +27,7 @@
 #include <asm/page.h>
 #include <asm/cacheflush.h>
 #include <mach/iommu_domains.h>
+#include <trace/events/kmem.h>
 
 struct ion_iommu_heap {
 	struct ion_heap heap;
@@ -83,9 +84,13 @@
 		} else {
 			gfp |= GFP_KERNEL;
 		}
+		trace_alloc_pages_iommu_start(gfp, orders[i]);
 		page = alloc_pages(gfp, orders[i]);
-		if (!page)
+		trace_alloc_pages_iommu_end(gfp, orders[i]);
+		if (!page) {
+			trace_alloc_pages_iommu_fail(gfp, orders[i]);
 			continue;
+		}
 
 		info = kmalloc(sizeof(struct page_info), GFP_KERNEL);
 		info->page = page;
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 02f6d93..4e9f55c 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -31,6 +31,7 @@
 #include <asm/cacheflush.h>
 #include <linux/msm_ion.h>
 #include <linux/dma-mapping.h>
+#include <trace/events/kmem.h>
 
 static atomic_t system_heap_allocated;
 static atomic_t system_contig_heap_allocated;
@@ -85,9 +86,13 @@
 
 		if (order > 4)
 			gfp_flags = high_order_gfp_flags;
+		trace_alloc_pages_sys_start(gfp_flags, order);
 		page = alloc_pages(gfp_flags, order);
-		if (!page)
+		trace_alloc_pages_sys_end(gfp_flags, order);
+		if (!page) {
+			trace_alloc_pages_sys_fail(gfp_flags, order);
 			return 0;
+		}
 		sg_init_table(&sg, 1);
 		sg_set_page(&sg, page, PAGE_SIZE << order, 0);
 		dma_sync_sg_for_device(NULL, &sg, 1, DMA_BIDIRECTIONAL);
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 9a2e901..60bab32 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -531,6 +531,7 @@
 
 	result = adreno_dev->gpudev->irq_handler(adreno_dev);
 
+	device->pwrctrl.irq_last = 1;
 	if (device->requested_state == KGSL_STATE_NONE) {
 		if (device->pwrctrl.nap_allowed == true) {
 			kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 479f9b8..61ea916 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1122,6 +1122,7 @@
 		ret = 0;
 
 done:
+	device->pwrctrl.irq_last = 0;
 	kgsl_trace_issueibcmds(device, context ? context->id : 0, ibdesc,
 		numibs, *timestamp, flags, ret,
 		drawctxt ? drawctxt->type : 0);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index ef22c41..b124257 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -18,6 +18,7 @@
 #include <mach/msm_iomap.h>
 #include <mach/msm_bus.h>
 #include <linux/ktime.h>
+#include <linux/delay.h>
 
 #include "kgsl.h"
 #include "kgsl_pwrscale.h"
@@ -33,6 +34,16 @@
 #define UPDATE_BUSY_VAL		1000000
 #define UPDATE_BUSY		50
 
+/*
+ * Expected delay for post-interrupt processing on A3xx.
+ * The delay may be longer, gradually increase the delay
+ * to compensate.  If the GPU isn't done by max delay,
+ * it's working on something other than just the final
+ * command sequence so stop waiting for it to be idle.
+ */
+#define INIT_UDELAY		200
+#define MAX_UDELAY		2000
+
 struct clk_pair {
 	const char *name;
 	uint map;
@@ -1069,6 +1080,8 @@
  */
 void kgsl_idle_check(struct work_struct *work)
 {
+	int delay = INIT_UDELAY;
+	int requested_state;
 	struct kgsl_device *device = container_of(work, struct kgsl_device,
 							idle_check_ws);
 	WARN_ON(device == NULL);
@@ -1081,10 +1094,32 @@
 
 	if (device->state == KGSL_STATE_ACTIVE
 		   || device->state ==  KGSL_STATE_NAP) {
-		if (device->active_cnt > 0 || kgsl_pwrctrl_sleep(device) != 0) {
+		/*
+		 * If no user is explicitly trying to use the GPU
+		 * (active_cnt is zero), then loop with increasing delay,
+		 * waiting for the GPU to become idle.
+		 */
+		while (!device->active_cnt && delay < MAX_UDELAY) {
+			requested_state = device->requested_state;
+			if (!kgsl_pwrctrl_sleep(device))
+				break;
+			/*
+			 * If no new commands have been issued since the
+			 * last interrupt, stay in this loop waiting for
+			 * the GPU to become idle.
+			 */
+			if (!device->pwrctrl.irq_last)
+				break;
+			kgsl_pwrctrl_request_state(device, requested_state);
+			mutex_unlock(&device->mutex);
+			udelay(delay);
+			delay *= 2;
+			mutex_lock(&device->mutex);
+		}
 
-			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
 
+		kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
+		if (device->state == KGSL_STATE_ACTIVE) {
 			mod_timer(&device->idle_timer,
 					jiffies +
 					device->pwrctrl.interval_timeout);
@@ -1098,6 +1133,8 @@
 				kgsl_pwrctrl_busy_time(device, true);
 				device->pwrctrl.clk_stats.no_nap_cnt = 0;
 			}
+		} else {
+			device->pwrctrl.irq_last = 0;
 		}
 	} else if (device->state & (KGSL_STATE_HUNG |
 					KGSL_STATE_DUMP_AND_FT)) {
@@ -1484,10 +1521,10 @@
 			(device->state == KGSL_STATE_ACTIVE &&
 			device->requested_state == KGSL_STATE_NONE)) {
 		kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
-		if (kgsl_pwrctrl_sleep(device) != 0)
-			mod_timer(&device->idle_timer,
-					jiffies
-					+ device->pwrctrl.interval_timeout);
+		if (kgsl_pwrctrl_sleep(device) && device->pwrctrl.irq_last) {
+			kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP);
+			queue_work(device->work_queue, &device->idle_check_ws);
+		}
 	}
 	device->active_cnt--;
 
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index bb45829..b3e8702 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -91,6 +91,7 @@
 	struct pm_qos_request pm_qos_req_dma;
 	unsigned int pm_qos_latency;
 	unsigned int step_mul;
+	unsigned int irq_last;
 };
 
 void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
index 84f7307..9370fc9 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -142,7 +142,7 @@
 	buf_p = msm_gemini_hw_pingpong_active_buffer(&we_pingpong_buf);
 	if (buf_p) {
 		buf_p->framedone_len = msm_gemini_hw_encode_output_size();
-		GMN_DBG("%s:%d] framedone_len %d\n", __func__, __LINE__,
+		pr_debug("%s:%d] framedone_len %d\n", __func__, __LINE__,
 			buf_p->framedone_len);
 	}
 
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
index 0cbb101..79c533e 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010,2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -297,6 +297,8 @@
 
 	struct msm_gemini_hw_cmd *hw_cmd_p;
 
+	pr_debug("%s:%d] pingpong index %d", __func__, __LINE__,
+		pingpong_index);
 	if (pingpong_index == 0) {
 		hw_cmd_p = &hw_cmd_we_ping_update[0];
 
@@ -486,40 +488,38 @@
 	return is_copy_to_user;
 }
 
-void msm_gemini_hw_region_dump(int size)
+#ifdef MSM_GMN_DBG_DUMP
+void msm_gemini_io_dump(int size)
 {
-	uint32_t *p;
-	uint8_t *p8;
-
-	if (size > gemini_region_size)
-		GMN_PR_ERR("%s:%d] wrong region dump size\n",
-			__func__, __LINE__);
-
-	p = (uint32_t *) gemini_region_base;
-	while (size >= 16) {
-		GMN_DBG("0x%08X] %08X %08X %08X %08X\n",
-			gemini_region_size - size,
-			readl(p), readl(p+1), readl(p+2), readl(p+3));
-		p += 4;
-		size -= 16;
-	}
-
-	if (size > 0) {
-		uint32_t d;
-		GMN_DBG("0x%08X] ", gemini_region_size - size);
-		while (size >= 4) {
-			GMN_DBG("%08X ", readl(p++));
-			size -= 4;
+	char line_str[128], *p_str;
+	void __iomem *addr = gemini_region_base;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	pr_info("%s: %p %d reg_size %d\n", __func__, addr, size,
+							gemini_region_size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
 		}
-
-		d = readl(p);
-		p8 = (uint8_t *) &d;
-		while (size) {
-			GMN_DBG("%02X", *p8++);
-			size--;
+		data = readl_relaxed(p++);
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			pr_info("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
 		}
-
-		GMN_DBG("\n");
 	}
+	if (line_str[0] != '\0')
+		pr_info("%s\n", line_str);
 }
+#else
+void msm_gemini_io_dump(int size)
+{
 
+}
+#endif
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
index 1c8de19..aa6c4aa1 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -95,7 +95,7 @@
 int msm_gemini_hw_wait(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us);
 void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us);
 int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds);
-void msm_gemini_hw_region_dump(int size);
+void msm_gemini_io_dump(int size);
 
 #define MSM_GEMINI_PIPELINE_CLK_128MHZ 128 /* 8MP  128MHz */
 #define MSM_GEMINI_PIPELINE_CLK_140MHZ 140 /* 9MP  140MHz */
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
index ea13d68..2fe6038 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_hw_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010, 2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -171,6 +171,6 @@
 #define HWIO_JPEG_IRQ_STATUS_RMSK 0xffffffff
 
 #define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_ADDR (GEMINI_REG_BASE + 0x00000034)
-#define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_RMSK 0xffffff
+#define HWIO_JPEG_STATUS_ENCODE_OUTPUT_SIZE_RMSK 0xffffffff
 
 #endif /* MSM_GEMINI_HW_REG_H */
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
index ed2222a..50c7284 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,8 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <media/msm_gemini.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
 #include "msm_gemini_sync.h"
 #include "msm_gemini_core.h"
 #include "msm_gemini_platform.h"
@@ -23,6 +25,9 @@
 
 static int release_buf;
 
+/* size is based on 4k page size */
+static const int g_max_out_size = 0x7ff000;
+
 /*************** queue helper ****************/
 inline void msm_gemini_q_init(char const *name, struct msm_gemini_q *q_p)
 {
@@ -180,7 +185,7 @@
 {
 	int rc = 0;
 
-	GMN_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	pr_debug("%s:%d] buf_in %p", __func__, __LINE__, buf_in);
 
 	if (buf_in) {
 		buf_in->vbuf.framedone_len = buf_in->framedone_len;
@@ -266,19 +271,88 @@
 
 /*************** output queue ****************/
 
+int msm_gemini_get_out_buffer(struct msm_gemini_device *pgmn_dev,
+	struct msm_gemini_hw_buf *p_outbuf)
+{
+	int buf_size = 0;
+	int bytes_remaining = 0;
+	if (pgmn_dev->out_offset >= pgmn_dev->out_buf.y_len) {
+		GMN_PR_ERR("%s:%d] no more buffers", __func__, __LINE__);
+		return -EINVAL;
+	}
+	bytes_remaining = pgmn_dev->out_buf.y_len - pgmn_dev->out_offset;
+	buf_size = min(bytes_remaining, pgmn_dev->max_out_size);
+
+	pgmn_dev->out_frag_cnt++;
+	pr_debug("%s:%d] buf_size[%d] %d", __func__, __LINE__,
+		pgmn_dev->out_frag_cnt, buf_size);
+	p_outbuf->y_len = buf_size;
+	p_outbuf->y_buffer_addr = pgmn_dev->out_buf.y_buffer_addr +
+		pgmn_dev->out_offset;
+	pgmn_dev->out_offset += buf_size;
+	return 0;
+}
+
+int msm_gemini_outmode_single_we_pingpong_irq(
+	struct msm_gemini_device *pgmn_dev,
+	struct msm_gemini_core_buf *buf_in)
+{
+	int rc = 0;
+	struct msm_gemini_core_buf out_buf;
+	int frame_done = buf_in &&
+		buf_in->vbuf.type == MSM_GEMINI_EVT_FRAMEDONE;
+	pr_debug("%s:%d] framedone %d", __func__, __LINE__, frame_done);
+	if (!pgmn_dev->out_buf_set) {
+		pr_err("%s:%d] output buffer not set",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	if (frame_done) {
+		/* send the buffer back */
+		pgmn_dev->out_buf.vbuf.framedone_len = buf_in->framedone_len;
+		pgmn_dev->out_buf.vbuf.type = MSM_GEMINI_EVT_FRAMEDONE;
+		rc = msm_gemini_q_in_buf(&pgmn_dev->output_rtn_q,
+			&pgmn_dev->out_buf);
+		if (rc) {
+			pr_err("%s:%d] cannot queue the output buffer",
+				 __func__, __LINE__);
+			return -EFAULT;
+		}
+		rc =  msm_gemini_q_wakeup(&pgmn_dev->output_rtn_q);
+		/* reset the output buffer since the ownership is
+			transferred to the rtn queue */
+		if (!rc)
+			pgmn_dev->out_buf_set = 0;
+	} else {
+		/* configure ping/pong */
+		rc = msm_gemini_get_out_buffer(pgmn_dev, &out_buf);
+		if (rc)
+			msm_gemini_core_we_buf_reset(&out_buf);
+		else
+			msm_gemini_core_we_buf_update(&out_buf);
+	}
+	return rc;
+}
+
 int msm_gemini_we_pingpong_irq(struct msm_gemini_device *pgmn_dev,
 	struct msm_gemini_core_buf *buf_in)
 {
 	int rc = 0;
 	struct msm_gemini_core_buf *buf_out;
 
-	GMN_DBG("%s:%d] Enter\n", __func__, __LINE__);
+	pr_debug("%s:%d] Enter mode %d", __func__, __LINE__,
+		pgmn_dev->out_mode);
+
+	if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_SINGLE)
+		return msm_gemini_outmode_single_we_pingpong_irq(pgmn_dev,
+			buf_in);
+
 	if (buf_in) {
-		GMN_DBG("%s:%d] 0x%08x %d\n", __func__, __LINE__,
+		pr_debug("%s:%d] 0x%08x %d\n", __func__, __LINE__,
 			(int) buf_in->y_buffer_addr, buf_in->y_len);
 		rc = msm_gemini_q_in_buf(&pgmn_dev->output_rtn_q, buf_in);
 	} else {
-		GMN_DBG("%s:%d] no output return buffer\n", __func__,
+		pr_debug("%s:%d] no output return buffer\n", __func__,
 			__LINE__);
 		rc = -1;
 		return rc;
@@ -291,7 +365,7 @@
 		kfree(buf_out);
 	} else {
 		msm_gemini_core_we_buf_reset(buf_in);
-		GMN_DBG("%s:%d] no output buffer\n", __func__, __LINE__);
+		pr_debug("%s:%d] no output buffer\n", __func__, __LINE__);
 		rc = -2;
 	}
 
@@ -339,6 +413,43 @@
 	return 0;
 }
 
+int msm_gemini_set_output_buf(struct msm_gemini_device *pgmn_dev,
+	void __user *arg)
+{
+	struct msm_gemini_buf buf_cmd;
+
+	if (pgmn_dev->out_buf_set) {
+		pr_err("%s:%d] outbuffer buffer already provided",
+			__func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_gemini_buf))) {
+		pr_err("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+
+	GMN_DBG("%s:%d] output addr 0x%08x len %d", __func__, __LINE__,
+		(int) buf_cmd.vaddr,
+		buf_cmd.y_len);
+
+	pgmn_dev->out_buf.y_buffer_addr = msm_gemini_platform_v2p(
+		buf_cmd.fd,
+		buf_cmd.y_len,
+		&pgmn_dev->out_buf.file,
+		&pgmn_dev->out_buf.handle);
+	if (!pgmn_dev->out_buf.y_buffer_addr) {
+		pr_err("%s:%d] cannot map the output address",
+			__func__, __LINE__);
+		return -EFAULT;
+	}
+	pgmn_dev->out_buf.y_len = buf_cmd.y_len;
+	pgmn_dev->out_buf.vbuf = buf_cmd;
+	pgmn_dev->out_buf_set = 1;
+
+	return 0;
+}
+
 int msm_gemini_output_buf_enqueue(struct msm_gemini_device *pgmn_dev,
 	void __user *arg)
 {
@@ -456,6 +567,7 @@
 	struct msm_gemini_core_buf *buf_p;
 	struct msm_gemini_buf buf_cmd;
 	int rc = 0;
+	struct msm_bus_scale_pdata *p_bus_scale_data = NULL;
 
 	if (copy_from_user(&buf_cmd, arg, sizeof(struct msm_gemini_buf))) {
 		GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
@@ -484,9 +596,9 @@
 			return rc;
 		}
 	} else {
-	buf_p->y_buffer_addr    = msm_gemini_platform_v2p(buf_cmd.fd,
-		buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
-		&buf_p->handle)	+ buf_cmd.offset + buf_cmd.y_off;
+		buf_p->y_buffer_addr    = msm_gemini_platform_v2p(buf_cmd.fd,
+			buf_cmd.y_len + buf_cmd.cbcr_len, &buf_p->file,
+			&buf_p->handle)	+ buf_cmd.offset + buf_cmd.y_off;
 	}
 	buf_p->y_len          = buf_cmd.y_len;
 
@@ -504,6 +616,30 @@
 		return -1;
 	}
 	buf_p->vbuf           = buf_cmd;
+	buf_p->vbuf.type      = MSM_GEMINI_EVT_RESET;
+
+	/* Set bus vectors */
+	p_bus_scale_data = (struct msm_bus_scale_pdata *)
+		pgmn_dev->pdev->dev.platform_data;
+	if (pgmn_dev->bus_perf_client &&
+		(MSM_GMN_OUTMODE_SINGLE == pgmn_dev->out_mode)) {
+		int rc;
+		struct msm_bus_paths *path = &(p_bus_scale_data->usecase[1]);
+		GMN_DBG("%s:%d] Update bus bandwidth", __func__, __LINE__);
+		if (pgmn_dev->op_mode & MSM_GEMINI_MODE_OFFLINE_ENCODE) {
+			path->vectors[0].ab = (buf_p->y_len + buf_p->cbcr_len) *
+				15 * 2;
+			path->vectors[0].ib = path->vectors[0].ab;
+			path->vectors[1].ab = 0;
+			path->vectors[1].ib = 0;
+		}
+		rc = msm_bus_scale_client_update_request(
+			pgmn_dev->bus_perf_client, 1);
+		if (rc < 0) {
+			GMN_PR_ERR("%s:%d] update_request fails %d",
+				__func__, __LINE__, rc);
+		}
+	}
 
 	msm_gemini_q_in(&pgmn_dev->input_buf_q, buf_p);
 
@@ -545,6 +681,9 @@
 int __msm_gemini_open(struct msm_gemini_device *pgmn_dev)
 {
 	int rc;
+	struct msm_bus_scale_pdata *p_bus_scale_data =
+		(struct msm_bus_scale_pdata *)pgmn_dev->pdev->dev.
+			platform_data;
 
 	mutex_lock(&pgmn_dev->lock);
 	if (pgmn_dev->open_count) {
@@ -576,7 +715,23 @@
 	msm_gemini_q_cleanup(&pgmn_dev->input_rtn_q);
 	msm_gemini_q_cleanup(&pgmn_dev->input_buf_q);
 	msm_gemini_core_init();
+	pgmn_dev->out_mode = MSM_GMN_OUTMODE_FRAGMENTED;
+	pgmn_dev->out_buf_set = 0;
+	pgmn_dev->out_offset = 0;
+	pgmn_dev->max_out_size = g_max_out_size;
+	pgmn_dev->out_frag_cnt = 0;
+	pgmn_dev->bus_perf_client = 0;
 
+	if (p_bus_scale_data) {
+		GMN_DBG("%s:%d] register bus client", __func__, __LINE__);
+		pgmn_dev->bus_perf_client =
+			msm_bus_scale_register_client(p_bus_scale_data);
+		if (!pgmn_dev->bus_perf_client) {
+			GMN_PR_ERR("%s:%d] bus client register failed",
+				__func__, __LINE__);
+			return -EINVAL;
+		}
+	}
 	GMN_DBG("%s:%d] success\n", __func__, __LINE__);
 	return rc;
 }
@@ -593,13 +748,23 @@
 	pgmn_dev->open_count--;
 	mutex_unlock(&pgmn_dev->lock);
 
-	msm_gemini_core_release(release_buf);
+	if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_FRAGMENTED) {
+		msm_gemini_core_release(release_buf);
+	} else if (pgmn_dev->out_buf_set) {
+		msm_gemini_platform_p2v(pgmn_dev->out_buf.file,
+			&pgmn_dev->out_buf.handle);
+	}
 	msm_gemini_q_cleanup(&pgmn_dev->evt_q);
 	msm_gemini_q_cleanup(&pgmn_dev->output_rtn_q);
 	msm_gemini_outbuf_q_cleanup(&pgmn_dev->output_buf_q);
 	msm_gemini_q_cleanup(&pgmn_dev->input_rtn_q);
 	msm_gemini_outbuf_q_cleanup(&pgmn_dev->input_buf_q);
 
+	if (pgmn_dev->bus_perf_client) {
+		msm_bus_scale_unregister_client(pgmn_dev->bus_perf_client);
+		pgmn_dev->bus_perf_client = 0;
+	}
+
 	if (pgmn_dev->open_count)
 		GMN_PR_ERR(KERN_ERR "%s: multiple opens\n", __func__);
 
@@ -699,29 +864,63 @@
 		}
 	}
 
-	for (i = 0; i < 2; i++) {
-		buf_out_free[i] = msm_gemini_q_out(&pgmn_dev->output_buf_q);
+	if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_FRAGMENTED) {
+		for (i = 0; i < 2; i++) {
+			buf_out_free[i] =
+				msm_gemini_q_out(&pgmn_dev->output_buf_q);
 
-		if (buf_out_free[i]) {
-			msm_gemini_core_we_buf_update(buf_out_free[i]);
-		} else if (i == 1) {
-			/* set the pong to same address as ping */
-			buf_out_free[0]->y_len >>= 1;
-			buf_out_free[0]->y_buffer_addr +=
-				buf_out_free[0]->y_len;
-			msm_gemini_core_we_buf_update(buf_out_free[0]);
-			/* since ping and pong are same buf release only once*/
-			release_buf = 0;
-		} else {
-			GMN_DBG("%s:%d] no output buffer\n",
-			__func__, __LINE__);
-			break;
+			if (buf_out_free[i]) {
+				msm_gemini_core_we_buf_update(buf_out_free[i]);
+			} else if (i == 1) {
+				/* set the pong to same address as ping */
+				buf_out_free[0]->y_len >>= 1;
+				buf_out_free[0]->y_buffer_addr +=
+					buf_out_free[0]->y_len;
+				msm_gemini_core_we_buf_update(buf_out_free[0]);
+				/*
+				 * since ping and pong are same buf
+				 * release only once
+				 */
+				release_buf = 0;
+			} else {
+				GMN_DBG("%s:%d] no output buffer\n",
+					__func__, __LINE__);
+				break;
+			}
 		}
+		for (i = 0; i < 2; i++)
+			kfree(buf_out_free[i]);
+	} else {
+		struct msm_gemini_core_buf out_buf;
+		/*
+		 * Since the same buffer is fragmented, p2v need not be
+		 * called for all the buffers
+		 */
+		release_buf = 0;
+		if (!pgmn_dev->out_buf_set) {
+			GMN_PR_ERR("%s:%d] output buffer not set",
+				__func__, __LINE__);
+			return -EFAULT;
+		}
+		/* configure ping */
+		rc = msm_gemini_get_out_buffer(pgmn_dev, &out_buf);
+		if (rc) {
+			GMN_PR_ERR("%s:%d] no output buffer for ping",
+				__func__, __LINE__);
+			return rc;
+		}
+		msm_gemini_core_we_buf_update(&out_buf);
+		/* configure pong */
+		rc = msm_gemini_get_out_buffer(pgmn_dev, &out_buf);
+		if (rc) {
+			GMN_DBG("%s:%d] no output buffer for pong",
+				__func__, __LINE__);
+			/* fall through to configure same buffer */
+		}
+		msm_gemini_core_we_buf_update(&out_buf);
+		msm_gemini_io_dump(0x150);
 	}
 
-	for (i = 0; i < 2; i++)
-		kfree(buf_out_free[i]);
-
 	rc = msm_gemini_ioctl_hw_cmds(pgmn_dev, arg);
 	GMN_DBG("%s:%d]\n", __func__, __LINE__);
 	return rc;
@@ -746,12 +945,22 @@
 	return rc;
 }
 
-int msm_gemini_ioctl_test_dump_region(struct msm_gemini_device *pgmn_dev,
-	unsigned long arg)
+int msm_gemini_ioctl_set_outmode(struct msm_gemini_device *pgmn_dev,
+	void * __user arg)
 {
-	GMN_DBG("%s:%d] Enter\n", __func__, __LINE__);
-	msm_gemini_hw_region_dump(arg);
-	return 0;
+	int rc = 0;
+	enum msm_gmn_out_mode mode;
+
+	if (copy_from_user(&mode, arg, sizeof(mode))) {
+		GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+		return -EFAULT;
+	}
+	GMN_DBG("%s:%d] mode %d", __func__, __LINE__, mode);
+
+	if ((mode == MSM_GMN_OUTMODE_FRAGMENTED)
+		|| (mode == MSM_GMN_OUTMODE_SINGLE))
+		pgmn_dev->out_mode = mode;
+	return rc;
 }
 
 long __msm_gemini_ioctl(struct msm_gemini_device *pgmn_dev,
@@ -790,8 +999,12 @@
 		break;
 
 	case MSM_GMN_IOCTL_OUTPUT_BUF_ENQUEUE:
-		rc = msm_gemini_output_buf_enqueue(pgmn_dev,
-			(void __user *) arg);
+		if (pgmn_dev->out_mode == MSM_GMN_OUTMODE_FRAGMENTED)
+			rc = msm_gemini_output_buf_enqueue(pgmn_dev,
+				(void __user *) arg);
+		else
+			rc = msm_gemini_set_output_buf(pgmn_dev,
+				(void __user *) arg);
 		break;
 
 	case MSM_GMN_IOCTL_OUTPUT_GET:
@@ -818,8 +1031,8 @@
 		rc = msm_gemini_ioctl_hw_cmds(pgmn_dev, (void __user *) arg);
 		break;
 
-	case MSM_GMN_IOCTL_TEST_DUMP_REGION:
-		rc = msm_gemini_ioctl_test_dump_region(pgmn_dev, arg);
+	case MSM_GMN_IOCTL_SET_MODE:
+		rc = msm_gemini_ioctl_set_outmode(pgmn_dev, (void __user *)arg);
 		break;
 
 	default:
diff --git a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
index d1a43e1..88e9615 100644
--- a/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
+++ b/drivers/media/platform/msm/camera_v1/gemini/msm_gemini_sync.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010,2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -74,6 +74,16 @@
 	struct msm_gemini_q input_buf_q;
 
 	struct v4l2_subdev subdev;
+	enum msm_gmn_out_mode out_mode;
+
+	/* single out mode parameters */
+	struct msm_gemini_hw_buf out_buf;
+	int out_offset;
+	int out_buf_set;
+	int max_out_size;
+	int out_frag_cnt;
+
+	uint32_t bus_perf_client;
 };
 
 int __msm_gemini_open(struct msm_gemini_device *pgmn_dev);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
index e5093f8..ba964a2 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/csi2.0/msm_csiphy_hwreg.h
@@ -14,7 +14,7 @@
 #define MSM_CSIPHY_HWREG_H
 
 /*MIPI CSI PHY registers*/
-#define MIPI_CSIPHY_HW_VERSION_ADDR              0x180
+#define MIPI_CSIPHY_HW_VERSION_ADDR              0x17C
 #define MIPI_CSIPHY_LNn_CFG1_ADDR                0x0
 #define MIPI_CSIPHY_LNn_CFG2_ADDR                0x4
 #define MIPI_CSIPHY_LNn_CFG3_ADDR                0x8
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index d880016..1ee9c67 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2394,6 +2394,7 @@
 
 	if (inst->capability.capability_set) {
 		if (msm_vp8_low_tier &&
+			inst->core->hfi_type == VIDC_HFI_VENUS &&
 			inst->fmts[OUTPUT_PORT]->fourcc == V4L2_PIX_FMT_VP8) {
 			capability->width.max = DEFAULT_WIDTH;
 			capability->height.max = DEFAULT_HEIGHT;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 075b391..1311752 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -113,8 +113,6 @@
 
 #define HFI_PROPERTY_SYS_OX_START			\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x0000)
-#define HFI_PROPERTY_SYS_IDLE_INDICATOR		\
-	(HFI_PROPERTY_SYS_OX_START + 0x001)
 
 #define HFI_PROPERTY_PARAM_OX_START				\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x1000)
@@ -333,7 +331,6 @@
 
 #define HFI_MSG_SYS_OX_START			\
 (HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + HFI_MSG_START_OFFSET + 0x0000)
-#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_OX_START + 0x1)
 #define HFI_MSG_SYS_PING_ACK	(HFI_MSG_SYS_OX_START + 0x2)
 #define HFI_MSG_SYS_PROPERTY_INFO	(HFI_MSG_SYS_OX_START + 0x3)
 #define HFI_MSG_SYS_SESSION_ABORT_DONE	(HFI_MSG_SYS_OX_START + 0x4)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 66eade1..6234dba 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -195,6 +195,8 @@
 	(HFI_PROPERTY_SYS_COMMON_START + 0x002)
 #define HFI_PROPERTY_SYS_CONFIG_VCODEC_CLKFREQ				\
 	(HFI_PROPERTY_SYS_COMMON_START + 0x003)
+#define HFI_PROPERTY_SYS_IDLE_INDICATOR         \
+	(HFI_PROPERTY_SYS_COMMON_START + 0x004)
 
 #define HFI_PROPERTY_PARAM_COMMON_START	\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x1000)
@@ -697,6 +699,7 @@
 #define HFI_MSG_SYS_DEBUG			(HFI_MSG_SYS_COMMON_START + 0x4)
 #define HFI_MSG_SYS_SESSION_INIT_DONE	(HFI_MSG_SYS_COMMON_START + 0x6)
 #define HFI_MSG_SYS_SESSION_END_DONE	(HFI_MSG_SYS_COMMON_START + 0x7)
+#define HFI_MSG_SYS_IDLE		(HFI_MSG_SYS_COMMON_START + 0x8)
 
 #define HFI_MSG_SESSION_COMMON_START		\
 	(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET +	\
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index af3cd69..b1b1980 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -1006,6 +1006,7 @@
 	spin_unlock_irqrestore(&inst->inst_lock, flags);
 	WFD_MSG_DBG("Calling videobuf_streamoff\n");
 	vb2_streamoff(&inst->vid_bufq, i);
+	wake_up(&inst->event_handler.wait);
 	return 0;
 }
 static int wfdioc_dqbuf(struct file *filp, void *fh,
@@ -1545,14 +1546,22 @@
 unsigned int wfd_poll(struct file *filp, struct poll_table_struct *pt)
 {
 	struct wfd_inst *inst = file_to_inst(filp);
-	unsigned int flags = 0;
+	unsigned int poll_flags = 0;
+	unsigned long flags;
+	bool streamoff = false;
 
 	poll_wait(filp, &inst->event_handler.wait, pt);
 
-	if (v4l2_event_pending(&inst->event_handler))
-		flags |= POLLPRI;
+	spin_lock_irqsave(&inst->inst_lock, flags);
+	streamoff = inst->streamoff;
+	spin_unlock_irqrestore(&inst->inst_lock, flags);
 
-	return flags;
+	if (v4l2_event_pending(&inst->event_handler))
+		poll_flags |= POLLPRI;
+	if (streamoff)
+		poll_flags |= POLLERR;
+
+	return poll_flags;
 }
 
 static const struct v4l2_file_operations g_wfd_fops = {
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 356aecb..111131a 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -25,6 +25,7 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #include <mach/cpuidle.h>
 
 #define BYTE_BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_BYTE))
@@ -226,9 +227,11 @@
 {
 	int ret;
 	int i;
+	char linebuf[128];
 	struct wcd9xxx *wcd9xxx = data;
 	int num_irq_regs = wcd9xxx_num_irq_regs(wcd9xxx);
-	u8 status[num_irq_regs];
+	u8 status[num_irq_regs], status1[num_irq_regs];
+	static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 1);
 
 	if (unlikely(wcd9xxx_lock_sleep(wcd9xxx) == false)) {
 		dev_err(wcd9xxx->dev, "Failed to hold suspend\n");
@@ -250,12 +253,17 @@
 	for (i = 0; i < num_irq_regs; i++)
 		status[i] &= ~wcd9xxx->irq_masks_cur[i];
 
+	memcpy(status1, status, sizeof(status1));
+
 	/* Find out which interrupt was triggered and call that interrupt's
 	 * handler function
 	 */
 	if (status[BIT_BYTE(WCD9XXX_IRQ_SLIMBUS)] &
-	    BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS))
+	    BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS)) {
 		wcd9xxx_irq_dispatch(wcd9xxx, WCD9XXX_IRQ_SLIMBUS);
+		status1[BIT_BYTE(WCD9XXX_IRQ_SLIMBUS)] &=
+		    ~BYTE_BIT_MASK(WCD9XXX_IRQ_SLIMBUS);
+	}
 
 	/* Since codec has only one hardware irq line which is shared by
 	 * codec's different internal interrupts, so it's possible master irq
@@ -264,13 +272,41 @@
 	 * machine's order */
 	for (i = WCD9XXX_IRQ_MBHC_INSERTION;
 	     i >= WCD9XXX_IRQ_MBHC_REMOVAL; i--) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
+		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
 			wcd9xxx_irq_dispatch(wcd9xxx, i);
+			status1[BIT_BYTE(i)] &= ~BYTE_BIT_MASK(i);
+		}
 	}
 	for (i = WCD9XXX_IRQ_BG_PRECHARGE; i < wcd9xxx->codec_type->num_irqs;
 	     i++) {
-		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i))
+		if (status[BIT_BYTE(i)] & BYTE_BIT_MASK(i)) {
 			wcd9xxx_irq_dispatch(wcd9xxx, i);
+			status1[BIT_BYTE(i)] &= ~BYTE_BIT_MASK(i);
+		}
+	}
+
+	/*
+	 * As a failsafe if unhandled irq is found, clear it to prevent
+	 * interrupt storm.
+	 * Note that we can say there was an unhandled irq only when no irq
+	 * handled by nested irq handler since Taiko supports qdsp as irqs'
+	 * destination for few irqs.  Therefore driver shouldn't clear pending
+	 * irqs when few handled while few others not.
+	 */
+	if (unlikely(!memcmp(status, status1, sizeof(status)))) {
+		if (__ratelimit(&ratelimit)) {
+			pr_warn("%s: Unhandled irq found\n", __func__);
+			hex_dump_to_buffer(status, sizeof(status), 16, 1,
+					   linebuf, sizeof(linebuf), false);
+			pr_warn("%s: status0 : %s\n", __func__, linebuf);
+			hex_dump_to_buffer(status1, sizeof(status1), 16, 1,
+					   linebuf, sizeof(linebuf), false);
+			pr_warn("%s: status1 : %s\n", __func__, linebuf);
+		}
+
+		memset(status, 0, num_irq_regs);
+		wcd9xxx_bulk_write(wcd9xxx, WCD9XXX_A_INTR_STATUS0,
+				   num_irq_regs, status);
 	}
 	wcd9xxx_unlock_sleep(wcd9xxx);
 
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index ac77bfb..fcadc30 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -52,6 +52,8 @@
 #define QSEE_VERSION_02			0x402000
 #define QSEE_VERSION_03			0x403000
 #define QSEE_VERSION_04			0x404000
+#define QSEE_VERSION_05			0x405000
+
 
 
 #define QSEOS_CHECK_VERSION_CMD		0x00001803
@@ -2381,9 +2383,11 @@
 
 	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.flags = flags;
+	ireq.qsee_command_id = QSEOS_GENERATE_KEY;
 
 	__qseecom_enable_clk(CLK_QSEE);
-	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 				&ireq, sizeof(struct qseecom_key_generate_ireq),
 				&resp, sizeof(resp));
 	if (ret) {
@@ -2395,10 +2399,19 @@
 	switch (resp.result) {
 	case QSEOS_RESULT_SUCCESS:
 		break;
+	case QSEOS_RESULT_FAIL_KEY_ID_EXISTS:
+		break;
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
-		if (ret)
-			pr_err("process_incomplete_cmd FAILED\n");
+		if (ret) {
+			if (resp.result == QSEOS_RESULT_FAIL_KEY_ID_EXISTS) {
+				pr_warn("process_incomplete_cmd return Key ID exits.\n");
+				ret = 0;
+			} else {
+				pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
+			}
+		}
 		break;
 	case QSEOS_RESULT_FAILURE:
 	default:
@@ -2425,9 +2438,11 @@
 
 	memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
 	ireq.flags = flags;
+	ireq.qsee_command_id = QSEOS_DELETE_KEY;
 
 	__qseecom_enable_clk(CLK_QSEE);
-	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 				&ireq, sizeof(struct qseecom_key_delete_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
@@ -2442,7 +2457,8 @@
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
 		if (ret)
-			pr_err("process_incomplete_cmd FAILED\n");
+			pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
 		break;
 	case QSEOS_RESULT_FAILURE:
 	default:
@@ -2474,10 +2490,14 @@
 		__qseecom_enable_clk(CLK_CE_DRV);
 
 	memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
+	ireq.qsee_command_id = QSEOS_SET_KEY;
 	ireq.ce = set_key_para->ce_hw;
 	ireq.pipe = set_key_para->pipe;
 	ireq.flags = set_key_para->flags;
 
+	/* set PIPE_ENC */
+	ireq.pipe_type = QSEOS_PIPE_ENC;
+
 	if (set_key_para->set_clear_key_flag ==
 			QSEECOM_SET_CE_KEY_CMD)
 		memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
@@ -2485,11 +2505,22 @@
 	else
 		memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
 
-	ret = scm_call(SCM_SVC_CRYPTO, QSEOS_SET_KEY,
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
 				&ireq, sizeof(struct qseecom_key_select_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
-		pr_err("scm call to set key failed : %d\n", ret);
+		pr_err("scm call to set QSEOS_PIPE_ENC key failed : %d\n", ret);
+		return ret;
+	}
+
+	/* set PIPE_ENC_XTS */
+	ireq.pipe_type = QSEOS_PIPE_ENC_XTS;
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
+				&ireq, sizeof(struct qseecom_key_select_ireq),
+				&resp, sizeof(struct qseecom_command_scm_resp));
+	if (ret) {
+		pr_err("scm call to set QSEOS_PIPE_ENC_XTS key failed : %d\n",
+			ret);
 		return ret;
 	}
 
@@ -2499,7 +2530,8 @@
 	case QSEOS_RESULT_INCOMPLETE:
 		ret = __qseecom_process_incomplete_cmd(data, &resp);
 		if (ret)
-			pr_err("process_incomplete_cmd FAILED\n");
+			pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
 		break;
 	case QSEOS_RESULT_FAILURE:
 	default:
@@ -2878,6 +2910,11 @@
 		break;
 	}
 	case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+		if (qseecom.qsee_version < QSEE_VERSION_05) {
+			pr_err("Create Key feature not supported in qsee version %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
@@ -2890,6 +2927,11 @@
 		break;
 	}
 	case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+		if (qseecom.qsee_version < QSEE_VERSION_05) {
+			pr_err("Wipe Key feature not supported in qsee version %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
 		data->released = true;
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5b7f08f..9f12142 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -67,12 +67,19 @@
 			(rq_data_dir(req) == WRITE))
 #define PACKED_CMD_VER		0x01
 #define PACKED_CMD_WR		0x02
+#define PACKED_TRIGGER_MAX_ELEMENTS	5000
 #define MMC_BLK_UPDATE_STOP_REASON(stats, reason)			\
 	do {								\
 		if (stats->enabled)					\
 			stats->pack_stop_reason[reason]++;		\
 	} while (0)
 
+#define PCKD_TRGR_INIT_MEAN_POTEN	17
+#define PCKD_TRGR_POTEN_LOWER_BOUND	5
+#define PCKD_TRGR_URGENT_PENALTY	2
+#define PCKD_TRGR_LOWER_BOUND		5
+#define PCKD_TRGR_PRECISION_MULTIPLIER	100
+
 static DEFINE_MUTEX(block_mutex);
 
 /*
@@ -1862,6 +1869,80 @@
 }
 EXPORT_SYMBOL(mmc_blk_disable_wr_packing);
 
+static int get_packed_trigger(int potential, struct mmc_card *card,
+			      struct request *req, int curr_trigger)
+{
+	static int num_mean_elements = 1;
+	static unsigned long mean_potential = PCKD_TRGR_INIT_MEAN_POTEN;
+	unsigned int trigger = curr_trigger;
+	unsigned int pckd_trgr_upper_bound = card->ext_csd.max_packed_writes;
+
+	/* scale down the upper bound to 75% */
+	pckd_trgr_upper_bound = (pckd_trgr_upper_bound * 3) / 4;
+
+	/*
+	 * since the most common calls for this function are with small
+	 * potential write values and since we don't want these calls to affect
+	 * the packed trigger, set a lower bound and ignore calls with
+	 * potential lower than that bound
+	 */
+	if (potential <= PCKD_TRGR_POTEN_LOWER_BOUND)
+		return trigger;
+
+	/*
+	 * this is to prevent integer overflow in the following calculation:
+	 * once every PACKED_TRIGGER_MAX_ELEMENTS reset the algorithm
+	 */
+	if (num_mean_elements > PACKED_TRIGGER_MAX_ELEMENTS) {
+		num_mean_elements = 1;
+		mean_potential = PCKD_TRGR_INIT_MEAN_POTEN;
+	}
+
+	/*
+	 * get next mean value based on previous mean value and current
+	 * potential packed writes. Calculation is as follows:
+	 * mean_pot[i+1] =
+	 *	((mean_pot[i] * num_mean_elem) + potential)/(num_mean_elem + 1)
+	 */
+	mean_potential *= num_mean_elements;
+	/*
+	 * add num_mean_elements so that the division of two integers doesn't
+	 * lower mean_potential too much
+	 */
+	if (potential > mean_potential)
+		mean_potential += num_mean_elements;
+	mean_potential += potential;
+	/* this is for gaining more precision when dividing two integers */
+	mean_potential *= PCKD_TRGR_PRECISION_MULTIPLIER;
+	/* this completes the mean calculation */
+	mean_potential /= ++num_mean_elements;
+	mean_potential /= PCKD_TRGR_PRECISION_MULTIPLIER;
+
+	/*
+	 * if current potential packed writes is greater than the mean potential
+	 * then the heuristic is that the following workload will contain many
+	 * write requests, therefore we lower the packed trigger. In the
+	 * opposite case we want to increase the trigger in order to get less
+	 * packing events.
+	 */
+	if (potential >= mean_potential)
+		trigger = (trigger <= PCKD_TRGR_LOWER_BOUND) ?
+				PCKD_TRGR_LOWER_BOUND : trigger - 1;
+	else
+		trigger = (trigger >= pckd_trgr_upper_bound) ?
+				pckd_trgr_upper_bound : trigger + 1;
+
+	/*
+	 * an urgent read request indicates a packed list being interrupted
+	 * by this read, therefore we aim for less packing, hence the trigger
+	 * gets increased
+	 */
+	if (req && (req->cmd_flags & REQ_URGENT) && (rq_data_dir(req) == READ))
+		trigger += PCKD_TRGR_URGENT_PENALTY;
+
+	return trigger;
+}
+
 static void mmc_blk_write_packing_control(struct mmc_queue *mq,
 					  struct request *req)
 {
@@ -1889,6 +1970,10 @@
 		if (mq->num_of_potential_packed_wr_reqs >
 				mq->num_wr_reqs_to_start_packing)
 			mq->wr_packing_enabled = true;
+		mq->num_wr_reqs_to_start_packing =
+			get_packed_trigger(mq->num_of_potential_packed_wr_reqs,
+					   mq->card, req,
+					   mq->num_wr_reqs_to_start_packing);
 		mq->num_of_potential_packed_wr_reqs = 0;
 		return;
 	}
@@ -1897,6 +1982,12 @@
 
 	if (data_dir == READ) {
 		mmc_blk_disable_wr_packing(mq);
+		mq->num_wr_reqs_to_start_packing =
+			get_packed_trigger(mq->num_of_potential_packed_wr_reqs,
+					   mq->card, req,
+					   mq->num_wr_reqs_to_start_packing);
+		mq->num_of_potential_packed_wr_reqs = 0;
+		mq->wr_packing_enabled = false;
 		return;
 	} else if (data_dir == WRITE) {
 		mq->num_of_potential_packed_wr_reqs++;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 9c30cd1..3f3687b 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4683,10 +4683,10 @@
 	}
 	/* Now save the sps pipe handle */
 	ep->pipe_handle = sps_pipe_handle;
-	pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"
-		" desc_fifo.phys_base=0x%x\n", mmc_hostname(host->mmc),
+	pr_debug("%s: %s, success !!! %s: pipe_handle=0x%x,"\
+		" desc_fifo.phys_base=%pa\n", mmc_hostname(host->mmc),
 		__func__, is_producer ? "READ" : "WRITE",
-		(u32)sps_pipe_handle, sps_config->desc.phys_base);
+		(u32)sps_pipe_handle, &sps_config->desc.phys_base);
 	goto out;
 
 reg_event_err:
@@ -4929,11 +4929,8 @@
 	host->bam_base = ioremap(host->bam_memres->start,
 				resource_size(host->bam_memres));
 	if (!host->bam_base) {
-		pr_err("%s: BAM ioremap() failed!!! phys_addr=0x%x,"
-			" size=0x%x", mmc_hostname(host->mmc),
-			host->bam_memres->start,
-			(host->bam_memres->end -
-			host->bam_memres->start));
+		pr_err("%s: BAM ioremap() failed!!! resource: %pr\n",
+			mmc_hostname(host->mmc), host->bam_memres);
 		rc = -ENOMEM;
 		goto out;
 	}
@@ -4954,7 +4951,7 @@
 	 */
 	bam.summing_threshold = SPS_MIN_XFER_SIZE;
 	/* SPS driver wll handle the SDCC BAM IRQ */
-	bam.irq = (u32)host->bam_irqres->start;
+	bam.irq = host->bam_irqres->start;
 	bam.manage = SPS_BAM_MGR_LOCAL;
 	bam.callback = msmsdcc_sps_bam_global_irq_cb;
 	bam.user = (void *)host;
@@ -4990,10 +4987,8 @@
 	if (rc)
 		goto cons_conn_err;
 
-	pr_info("%s: Qualcomm MSM SDCC-BAM at 0x%016llx irq %d\n",
-		mmc_hostname(host->mmc),
-		(unsigned long long)host->bam_memres->start,
-		(unsigned int)host->bam_irqres->start);
+	pr_info("%s: Qualcomm MSM SDCC-BAM at %pr %pr\n",
+		mmc_hostname(host->mmc), host->bam_memres, host->bam_irqres);
 	goto out;
 
 cons_conn_err:
@@ -5180,15 +5175,16 @@
 }
 
 static void msmsdcc_print_regs(const char *name, void __iomem *base,
-			       u32 phys_base, unsigned int no_of_regs)
+				resource_size_t phys_base,
+				unsigned int no_of_regs)
 {
 	unsigned int i;
 
 	if (!base)
 		return;
 
-	pr_err("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
-		" =====\n", name, phys_base, (u32)base);
+	pr_err("===== %s: Register Dumps @phys_base=%pa, @virt_base=0x%x"\
+		" =====\n", name, &phys_base, (u32)base);
 	for (i = 0; i < no_of_regs; i = i + 4) {
 		pr_err("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
 			(u32)readl_relaxed(base + i*4),
@@ -6275,10 +6271,8 @@
 	mmc->clk_scaling.polling_delay_ms = 100;
 	mmc->caps2 |= MMC_CAP2_CLK_SCALE;
 
-	pr_info("%s: Qualcomm MSM SDCC-core at 0x%016llx irq %d,%d dma %d"
-		" dmacrcri %d\n", mmc_hostname(mmc),
-		(unsigned long long)core_memres->start,
-		(unsigned int) core_irqres->start,
+	pr_info("%s: Qualcomm MSM SDCC-core %pr %pr,%d dma %d dmacrcri %d\n",
+		mmc_hostname(mmc), core_memres, core_irqres,
 		(unsigned int) plat->status_irq, host->dma.channel,
 		host->dma.crci);
 
@@ -6300,11 +6294,11 @@
 
 	if (is_dma_mode(host) && host->dma.channel != -1
 			&& host->dma.crci != -1) {
-		pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
-		       mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
-		pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
-		       mmc_hostname(mmc), host->dma.cmd_busaddr,
-		       host->dma.cmdptr_busaddr);
+		pr_info("%s: DM non-cached buffer at %p, dma_addr: %pa\n",
+		       mmc_hostname(mmc), host->dma.nc, &host->dma.nc_busaddr);
+		pr_info("%s: DM cmd busaddr: %pa, cmdptr busaddr: %pa\n",
+		       mmc_hostname(mmc), &host->dma.cmd_busaddr,
+		       &host->dma.cmdptr_busaddr);
 	} else if (is_sps_mode(host)) {
 		pr_info("%s: SPS-BAM data transfer mode available\n",
 			mmc_hostname(mmc));
diff --git a/drivers/mmc/host/msm_sdcc_dml.c b/drivers/mmc/host/msm_sdcc_dml.c
index 91ab7e3..2562436 100644
--- a/drivers/mmc/host/msm_sdcc_dml.c
+++ b/drivers/mmc/host/msm_sdcc_dml.c
@@ -166,17 +166,13 @@
 		host->dml_base = ioremap(host->dml_memres->start,
 					resource_size(host->dml_memres));
 		if (!host->dml_base) {
-			pr_err("%s: DML ioremap() failed!!! phys_addr=0x%x,"
-				" size=0x%x", mmc_hostname(host->mmc),
-				host->dml_memres->start,
-				(host->dml_memres->end -
-				host->dml_memres->start));
+			pr_err("%s: DML ioremap() failed!!! %pr\n",
+				mmc_hostname(host->mmc), host->dml_memres);
 			rc = -ENOMEM;
 			goto out;
 		}
-		pr_info("%s: Qualcomm MSM SDCC-DML at 0x%016llx\n",
-			mmc_hostname(host->mmc),
-			(unsigned long long)host->dml_memres->start);
+		pr_info("%s: Qualcomm MSM SDCC-DML %pr\n",
+			mmc_hostname(host->mmc), host->dml_memres);
 	}
 
 	dml_base = host->dml_base;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 49222b9..cb036dd 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2064,7 +2064,7 @@
 	struct resource *core_memres = NULL;
 	int ret = 0, dead = 0;
 	u32 vdd_max_current;
-	u32 host_version;
+	u16 host_version;
 
 	pr_debug("%s: Enter %s\n", dev_name(&pdev->dev), __func__);
 	msm_host = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_msm_host),
@@ -2192,7 +2192,7 @@
 	host->quirks2 |= SDHCI_QUIRK2_BROKEN_PRESET_VALUE;
 	host->quirks2 |= SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT;
 
-	host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
+	host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
 	dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
 		host_version, ((host_version & SDHCI_VENDOR_VER_MASK) >>
 		  SDHCI_VENDOR_VER_SHIFT));
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index e00e1c3..1ad7f21 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -83,6 +83,7 @@
 #define CHG_COMP_OVR		0x20A
 #define IUSB_FINE_RES		0x2B6
 #define OVP_USB_UVD		0x2B7
+#define PM8921_USB_TRIM_SEL	0x339
 
 /* check EOC every 10 seconds */
 #define EOC_CHECK_PERIOD_MS	10000
@@ -777,6 +778,44 @@
 };
 
 /* USB Trim tables */
+static int usb_trim_pm8921_table_1[USB_TRIM_ENTRIES] = {
+	0x0,
+	0x0,
+	-0x5,
+	0x0,
+	-0x7,
+	0x0,
+	-0x9,
+	-0xA,
+	0x0,
+	0x0,
+	-0xE,
+	0x0,
+	-0xF,
+	0x0,
+	-0x10,
+	0x0
+};
+
+static int usb_trim_pm8921_table_2[USB_TRIM_ENTRIES] = {
+	0x0,
+	0x0,
+	-0x2,
+	0x0,
+	-0x4,
+	0x0,
+	-0x4,
+	-0x5,
+	0x0,
+	0x0,
+	-0x6,
+	0x0,
+	-0x6,
+	0x0,
+	-0x6,
+	0x0
+};
+
 static int usb_trim_8038_table[USB_TRIM_ENTRIES] = {
 	0x0,
 	0x0,
@@ -844,6 +883,8 @@
 #define REG_USB_OVP_TRIM_ORIG_MSB	0x09C
 #define REG_USB_OVP_TRIM_PM8917		0x2B5
 #define REG_USB_OVP_TRIM_PM8917_BIT	BIT(0)
+#define USB_TRIM_MAX_DATA_PM8917	0x3F
+#define USB_TRIM_POLARITY_PM8917_BIT	BIT(6)
 static int pm_chg_usb_trim(struct pm8921_chg_chip *chip, int index)
 {
 	u8 temp, sbi_config, msb, lsb, mask;
@@ -3805,11 +3846,14 @@
 		}
 }
 
+#define PM8921_USB_TRIM_SEL_BIT		BIT(6)
 /* determines the initial present states */
 static void __devinit determine_initial_state(struct pm8921_chg_chip *chip)
 {
 	int fsm_state;
 	int is_fast_chg;
+	int rc = 0;
+	u8 trim_sel_reg = 0, regsbi;
 
 	chip->dc_present = !!is_dc_chg_plugged_in(chip);
 	chip->usb_present = !!is_usb_chg_plugged_in(chip);
@@ -3872,10 +3916,26 @@
 			fsm_state);
 
 	/* Determine which USB trim column to use */
-	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+	if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
 		chip->usb_trim_table = usb_trim_8917_table;
-	else if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8038)
+	} else if (pm8xxx_get_version(chip->dev->parent) ==
+						PM8XXX_VERSION_8038) {
 		chip->usb_trim_table = usb_trim_8038_table;
+	} else if (pm8xxx_get_version(chip->dev->parent) ==
+						PM8XXX_VERSION_8921) {
+		rc = pm8xxx_readb(chip->dev->parent, REG_SBI_CONFIG, &regsbi);
+		rc |= pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, 0x5E);
+		rc |= pm8xxx_readb(chip->dev->parent, PM8921_USB_TRIM_SEL,
+								&trim_sel_reg);
+		rc |= pm8xxx_writeb(chip->dev->parent, REG_SBI_CONFIG, regsbi);
+		if (rc)
+			pr_err("Failed to read trim sel register rc=%d\n", rc);
+
+		if (trim_sel_reg & PM8921_USB_TRIM_SEL_BIT)
+			chip->usb_trim_table = usb_trim_pm8921_table_1;
+		else
+			chip->usb_trim_table = usb_trim_pm8921_table_2;
+	}
 }
 
 struct pm_chg_irq_init_data {
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index a875c92..6a2ce8d 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -85,7 +85,11 @@
 #define CHGR_BUCK_BCK_VBAT_REG_MODE		0x74
 #define MISC_REVISION2				0x01
 #define USB_OVP_CTL				0x42
+#define USB_CHG_GONE_REV_BST			0xED
+#define BUCK_VCHG_OV				0x77
+#define BUCK_TEST_SMBC_MODES			0xE6
 #define SEC_ACCESS				0xD0
+#define BAT_IF_VREF_BAT_THM_CTRL		0x4A
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
 /* SMBB peripheral subtype values */
@@ -120,6 +124,8 @@
 #define CHGR_ON_BAT_FORCE_BIT		BIT(0)
 #define USB_VALID_DEB_20MS		0x03
 #define BUCK_VBAT_REG_NODE_SEL_BIT	BIT(0)
+#define VREF_BATT_THERM_FORCE_ON	0xC0
+#define VREF_BAT_THM_ENABLED_FSM	0x80
 
 /* Interrupt definitions */
 /* smbb_chg_interrupts */
@@ -232,6 +238,7 @@
 	u16				freq_base;
 	unsigned int			usbin_valid_irq;
 	unsigned int			dcin_valid_irq;
+	unsigned int			chg_gone_irq;
 	unsigned int			chg_fastchg_irq;
 	unsigned int			chg_trklchg_irq;
 	unsigned int			chg_failed_irq;
@@ -272,6 +279,7 @@
 	uint32_t			flags;
 	struct qpnp_adc_tm_btm_param	adc_param;
 	struct work_struct		adc_measure_work;
+	struct delayed_work		arb_stop_work;
 };
 
 static struct of_device_id qpnp_charger_match_table[] = {
@@ -524,7 +532,41 @@
 			enable ? USB_SUSPEND_BIT : 0, 1);
 }
 
-static void qpnp_bat_if_adc_measure_work(struct work_struct *work)
+static int
+qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
+{
+	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+			CHGR_CHG_EN,
+			enable ? CHGR_CHG_EN : 0, 1);
+}
+
+static int
+qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
+{
+	/* Don't run on battery for batteryless hardware */
+	if (chip->use_default_batt_values)
+		return 0;
+
+	/* This bit forces the charger to run off of the battery rather
+	 * than a connected charger */
+	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
+			CHGR_ON_BAT_FORCE_BIT,
+			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
+}
+
+static void
+qpnp_arb_stop_work(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct qpnp_chg_chip *chip = container_of(dwork,
+				struct qpnp_chg_chip, arb_stop_work);
+
+	qpnp_chg_charge_en(chip, !chip->charging_disabled);
+	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
+}
+
+static void
+qpnp_bat_if_adc_measure_work(struct work_struct *work)
 {
 	struct qpnp_chg_chip *chip = container_of(work,
 				struct qpnp_chg_chip, adc_measure_work);
@@ -533,6 +575,23 @@
 		pr_err("request ADC error\n");
 }
 
+#define ARB_STOP_WORK_MS	1000
+static irqreturn_t
+qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+
+	pr_debug("chg_gone triggered\n");
+	if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
+		qpnp_chg_charge_en(chip, 0);
+		qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
+		schedule_delayed_work(&chip->arb_stop_work,
+			msecs_to_jiffies(ARB_STOP_WORK_MS));
+	}
+
+	return IRQ_HANDLED;
+}
+
 #define ENUM_T_STOP_BIT		BIT(0)
 static irqreturn_t
 qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
@@ -552,7 +611,8 @@
 	if (chip->usb_present ^ usb_present) {
 		chip->usb_present = usb_present;
 		if (!usb_present)
-			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
+			qpnp_chg_usb_suspend_enable(chip, 1);
+
 		power_supply_set_present(chip->usb_psy,
 			chip->usb_present);
 	}
@@ -661,28 +721,6 @@
 }
 
 static int
-qpnp_chg_charge_en(struct qpnp_chg_chip *chip, int enable)
-{
-	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
-			CHGR_CHG_EN,
-			enable ? CHGR_CHG_EN : 0, 1);
-}
-
-static int
-qpnp_chg_force_run_on_batt(struct qpnp_chg_chip *chip, int disable)
-{
-	/* Don't run on battery for batteryless hardware */
-	if (chip->use_default_batt_values)
-		return 0;
-
-	/* This bit forces the charger to run off of the battery rather
-	 * than a connected charger */
-	return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_CHG_CTRL,
-			CHGR_ON_BAT_FORCE_BIT,
-			disable ? CHGR_ON_BAT_FORCE_BIT : 0, 1);
-}
-
-static int
 qpnp_chg_buck_control(struct qpnp_chg_chip *chip, int enable)
 {
 	int rc;
@@ -1059,8 +1097,8 @@
 			  POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
 		if (ret.intval <= 2 && !chip->use_default_batt_values &&
 						get_prop_batt_present(chip)) {
-			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
 			qpnp_chg_usb_suspend_enable(chip, 1);
+			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
 		} else {
 			qpnp_chg_usb_suspend_enable(chip, 0);
 			qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
@@ -1596,7 +1634,24 @@
 						chip->usbin_valid_irq, rc);
 				return rc;
 			}
+
+			chip->chg_gone_irq = spmi_get_irq_byname(spmi,
+						spmi_resource, "chg-gone");
+			if (chip->chg_gone_irq < 0) {
+				pr_err("Unable to get chg-gone irq\n");
+				return rc;
+			}
+			rc = devm_request_irq(chip->dev, chip->chg_gone_irq,
+				qpnp_chg_usb_chg_gone_irq_handler,
+				IRQF_TRIGGER_RISING,
+					"chg_gone_irq", chip);
+			if (rc < 0) {
+				pr_err("Can't request %d chg_gone: %d\n",
+						chip->chg_gone_irq, rc);
+				return rc;
+			}
 			enable_irq_wake(chip->usbin_valid_irq);
+			enable_irq_wake(chip->chg_gone_irq);
 			break;
 		case SMBB_DC_CHGPTH_SUBTYPE:
 			chip->dcin_valid_irq = spmi_get_irq_byname(spmi,
@@ -1704,6 +1759,15 @@
 	case SMBB_BAT_IF_SUBTYPE:
 	case SMBBP_BAT_IF_SUBTYPE:
 	case SMBCL_BAT_IF_SUBTYPE:
+		/* Force on VREF_BAT_THM */
+		rc = qpnp_chg_masked_write(chip,
+			chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
+			VREF_BATT_THERM_FORCE_ON,
+			VREF_BATT_THERM_FORCE_ON, 1);
+		if (rc) {
+			pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
+			return rc;
+		}
 		break;
 	case SMBB_USB_CHGPTH_SUBTYPE:
 	case SMBBP_USB_CHGPTH_SUBTYPE:
@@ -1730,6 +1794,16 @@
 			ENUM_T_STOP_BIT,
 			ENUM_T_STOP_BIT, 1);
 
+		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + SEC_ACCESS,
+			0xFF,
+			0xA5, 1);
+
+		rc = qpnp_chg_masked_write(chip,
+			chip->usb_chgpth_base + USB_CHG_GONE_REV_BST,
+			0xFF,
+			0x80, 1);
+
 		break;
 	case SMBB_DC_CHGPTH_SUBTYPE:
 		break;
@@ -1931,6 +2005,27 @@
 						subtype, rc);
 				goto fail_chg_enable;
 			}
+
+			rc = qpnp_chg_masked_write(chip,
+				chip->buck_base + SEC_ACCESS,
+				0xFF,
+				0xA5, 1);
+
+			rc = qpnp_chg_masked_write(chip,
+				chip->buck_base + BUCK_VCHG_OV,
+				0xff,
+				0x00, 1);
+
+			rc = qpnp_chg_masked_write(chip,
+				chip->buck_base + SEC_ACCESS,
+				0xFF,
+				0xA5, 1);
+
+			rc = qpnp_chg_masked_write(chip,
+				chip->buck_base + BUCK_TEST_SMBC_MODES,
+				0xFF,
+				0x80, 1);
+
 			break;
 		case SMBB_BAT_IF_SUBTYPE:
 		case SMBBP_BAT_IF_SUBTYPE:
@@ -2025,6 +2120,7 @@
 		}
 		INIT_WORK(&chip->adc_measure_work,
 			qpnp_bat_if_adc_measure_work);
+		INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
 	}
 
 	if (chip->dc_chgpth_base) {
@@ -2119,6 +2215,41 @@
 	return 0;
 }
 
+static int qpnp_chg_resume(struct device *dev)
+{
+	struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
+	int rc = 0;
+
+	rc = qpnp_chg_masked_write(chip,
+	chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
+		VREF_BATT_THERM_FORCE_ON,
+		VREF_BATT_THERM_FORCE_ON, 1);
+	if (rc)
+		pr_debug("failed to force on VREF_BAT_THM rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qpnp_chg_suspend(struct device *dev)
+{
+	struct qpnp_chg_chip *chip = dev_get_drvdata(dev);
+	int rc = 0;
+
+	rc = qpnp_chg_masked_write(chip,
+	chip->bat_if_base + BAT_IF_VREF_BAT_THM_CTRL,
+		VREF_BATT_THERM_FORCE_ON,
+		VREF_BAT_THM_ENABLED_FSM, 1);
+	if (rc)
+		pr_debug("failed to enable FSM ctrl VREF_BAT_THM rc=%d\n", rc);
+
+	return rc;
+}
+
+static const struct dev_pm_ops qpnp_bms_pm_ops = {
+	.resume		= qpnp_chg_resume,
+	.suspend	= qpnp_chg_suspend,
+};
+
 static struct spmi_driver qpnp_charger_driver = {
 	.probe		= qpnp_charger_probe,
 	.remove		= __devexit_p(qpnp_charger_remove),
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 95378c5..991cf2e 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -333,6 +333,8 @@
 	else
 		degc = num/den;
 
+	pr_debug("raw_code:0x%x, sensor_num:%d, degc:%d\n",
+			adc_code, idx, degc);
 	return degc;
 }
 
@@ -345,6 +347,8 @@
 		code = TSENS_THRESHOLD_MAX_CODE;
 	else if (code < TSENS_THRESHOLD_MIN_CODE)
 		code = TSENS_THRESHOLD_MIN_CODE;
+	pr_debug("raw_code:0x%x, sensor_num:%d, degc:%d\n",
+			code, idx, degc);
 	return code;
 }
 
@@ -729,6 +733,7 @@
 
 	tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
 			>> TSENS_8X10_CAL_SEL_SHIFT;
+	pr_debug("calib mode scheme:%x\n", tsens_calibration_mode);
 
 	if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
 		(tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
@@ -783,6 +788,9 @@
 		int32_t num = 0, den = 0;
 		tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
 		tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+		pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
+			i, tmdev->sensor[i].calib_data_point1,
+			tmdev->sensor[i].calib_data_point2);
 		if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
 			/* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
 				temp_120_degc - temp_30_degc (x2 - x1) */
@@ -827,6 +835,7 @@
 
 	tsens_calibration_mode = (calib_data[5] & TSENS_8X26_TSENS_CAL_SEL)
 			>> TSENS_8X26_CAL_SEL_SHIFT;
+	pr_debug("calib mode scheme:%x\n", tsens_calibration_mode);
 
 	if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
 		(tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
@@ -936,6 +945,9 @@
 		int32_t num = 0, den = 0;
 		tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
 		tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+		pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
+			i, tmdev->sensor[i].calib_data_point1,
+			tmdev->sensor[i].calib_data_point2);
 		if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
 			/* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
 				temp_120_degc - temp_30_degc (x2 - x1) */
@@ -976,11 +988,14 @@
 			TSENS_EEPROM_REDUNDANCY_SEL(tmdev->tsens_calib_addr));
 	calib_redun_sel = calib_redun_sel & TSENS_QFPROM_BACKUP_REDUN_SEL;
 	calib_redun_sel >>= TSENS_QFPROM_BACKUP_REDUN_SHIFT;
+	pr_debug("calib_redun_sel:%x\n", calib_redun_sel);
 
-	for (i = 0; i < TSENS_MAIN_CALIB_ADDR_RANGE; i++)
+	for (i = 0; i < TSENS_MAIN_CALIB_ADDR_RANGE; i++) {
 		calib_data[i] = readl_relaxed(
 			(TSENS_EEPROM(tmdev->tsens_calib_addr))
 					+ (i * TSENS_SN_ADDR_OFFSET));
+		pr_debug("calib raw data row%d:0x%x\n", i, calib_data[i]);
+	}
 
 	if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) {
 		tsens_calibration_mode = (calib_data[4] & TSENS_CAL_SEL_0_1)
@@ -988,6 +1003,7 @@
 		temp = (calib_data[5] & TSENS_CAL_SEL_2)
 				>> TSENS_CAL_SEL_SHIFT_2;
 		tsens_calibration_mode |= temp;
+		pr_debug("backup calib mode:%x\n", calib_redun_sel);
 
 		for (i = 0; i < TSENS_BACKUP_CALIB_ADDR_RANGE; i++)
 			calib_data_backup[i] = readl_relaxed(
@@ -1073,6 +1089,7 @@
 		temp = (calib_data[3] & TSENS_CAL_SEL_2)
 			>> TSENS_CAL_SEL_SHIFT_2;
 		tsens_calibration_mode |= temp;
+		pr_debug("calib mode scheme:%x\n", tsens_calibration_mode);
 		if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) ||
 			(tsens_calibration_mode ==
 					TSENS_ONE_POINT_CALIB_OPTION_2) ||
@@ -1184,6 +1201,7 @@
 
 	if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
 			(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+		pr_debug("one point calibration calculation\n");
 		calib_tsens_point1_data[0] =
 			((((tsens_base1_data) + tsens0_point1) << 2) |
 						TSENS_BIT_APPEND);
@@ -1261,6 +1279,9 @@
 		int32_t num = 0, den = 0;
 		tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
 		tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+		pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
+			i, tmdev->sensor[i].calib_data_point1,
+			tmdev->sensor[i].calib_data_point2);
 		if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
 			/* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
 				temp_120_degc - temp_30_degc (x2 - x1) */
@@ -1273,6 +1294,7 @@
 		tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
 			tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
 				tmdev->sensor[i].slope_mul_tsens_factor);
+		pr_debug("offset:%d\n", tmdev->sensor[i].offset);
 		INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
 		tmdev->prev_reading_avail = false;
 	}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 7101d56..d0ebda1 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2108,7 +2108,18 @@
 	if (mReq->zptr) {
 		if ((TD_STATUS_ACTIVE & mReq->zptr->token) != 0)
 			return -EBUSY;
-		dma_pool_free(mEp->td_pool, mReq->zptr, mReq->zdma);
+
+		/* The controller may access this dTD one more time.
+		 * Defer freeing this to next zero length dTD completion.
+		 * It is safe to assume that controller will no longer
+		 * access the previous dTD after next dTD completion.
+		 */
+		if (mEp->last_zptr)
+			dma_pool_free(mEp->td_pool, mEp->last_zptr,
+					mEp->last_zdma);
+		mEp->last_zptr = mReq->zptr;
+		mEp->last_zdma = mReq->zdma;
+
 		mReq->zptr = NULL;
 	}
 
@@ -2260,9 +2271,10 @@
 	usb_ep_fifo_flush(&udc->ep0out.ep);
 	usb_ep_fifo_flush(&udc->ep0in.ep);
 
-	if (udc->status != NULL) {
-		usb_ep_free_request(&udc->ep0in.ep, udc->status);
-		udc->status = NULL;
+	if (udc->ep0in.last_zptr) {
+		dma_pool_free(udc->ep0in.td_pool, udc->ep0in.last_zptr,
+				udc->ep0in.last_zdma);
+		udc->ep0in.last_zptr = NULL;
 	}
 
 	return 0;
@@ -2317,10 +2329,6 @@
 	if (retval)
 		goto done;
 
-	udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_ATOMIC);
-	if (udc->status == NULL)
-		retval = -ENOMEM;
-
 	spin_lock(udc->lock);
 
  done:
@@ -2389,8 +2397,8 @@
 		return;
 	}
 
-	kfree(req->buf);
-	usb_ep_free_request(ep, req);
+	if (req->status)
+		err("GET_STATUS failed");
 }
 
 /**
@@ -2406,8 +2414,7 @@
 __acquires(mEp->lock)
 {
 	struct ci13xxx_ep *mEp = &udc->ep0in;
-	struct usb_request *req = NULL;
-	gfp_t gfp_flags = GFP_ATOMIC;
+	struct usb_request *req = udc->status;
 	int dir, num, retval;
 
 	trace("%p, %p", mEp, setup);
@@ -2415,19 +2422,9 @@
 	if (mEp == NULL || setup == NULL)
 		return -EINVAL;
 
-	spin_unlock(mEp->lock);
-	req = usb_ep_alloc_request(&mEp->ep, gfp_flags);
-	spin_lock(mEp->lock);
-	if (req == NULL)
-		return -ENOMEM;
-
 	req->complete = isr_get_status_complete;
 	req->length   = 2;
-	req->buf      = kzalloc(req->length, gfp_flags);
-	if (req->buf == NULL) {
-		retval = -ENOMEM;
-		goto err_free_req;
-	}
+	req->buf      = udc->status_buf;
 
 	if ((setup->bRequestType & USB_RECIP_MASK) == USB_RECIP_DEVICE) {
 		if (setup->wIndex == OTG_STATUS_SELECTOR) {
@@ -2450,18 +2447,7 @@
 	/* else do nothing; reserved for future use */
 
 	spin_unlock(mEp->lock);
-	retval = usb_ep_queue(&mEp->ep, req, gfp_flags);
-	spin_lock(mEp->lock);
-	if (retval)
-		goto err_free_buf;
-
-	return 0;
-
- err_free_buf:
-	kfree(req->buf);
- err_free_req:
-	spin_unlock(mEp->lock);
-	usb_ep_free_request(&mEp->ep, req);
+	retval = usb_ep_queue(&mEp->ep, req, GFP_ATOMIC);
 	spin_lock(mEp->lock);
 	return retval;
 }
@@ -2504,11 +2490,9 @@
 	trace("%p", udc);
 
 	mEp = (udc->ep0_dir == TX) ? &udc->ep0out : &udc->ep0in;
-	if (udc->status) {
-		udc->status->context = udc;
-		udc->status->complete = isr_setup_status_complete;
-	} else
-		return -EINVAL;
+	udc->status->context = udc;
+	udc->status->complete = isr_setup_status_complete;
+	udc->status->length = 0;
 
 	spin_unlock(mEp->lock);
 	retval = usb_ep_queue(&mEp->ep, udc->status, GFP_ATOMIC);
@@ -2942,6 +2926,12 @@
 
 	} while (mEp->dir != direction);
 
+	if (mEp->last_zptr) {
+		dma_pool_free(mEp->td_pool, mEp->last_zptr,
+				mEp->last_zdma);
+		mEp->last_zptr = NULL;
+	}
+
 	mEp->desc = NULL;
 	mEp->ep.desc = NULL;
 	mEp->ep.maxpacket = USHRT_MAX;
@@ -3476,6 +3466,14 @@
 	retval = usb_ep_enable(&udc->ep0in.ep);
 	if (retval)
 		return retval;
+	udc->status = usb_ep_alloc_request(&udc->ep0in.ep, GFP_KERNEL);
+	if (!udc->status)
+		return -ENOMEM;
+	udc->status_buf = kzalloc(2, GFP_KERNEL); /* for GET_STATUS */
+	if (!udc->status_buf) {
+		usb_ep_free_request(&udc->ep0in.ep, udc->status);
+		return -ENOMEM;
+	}
 	spin_lock_irqsave(udc->lock, flags);
 
 	udc->gadget.ep0 = &udc->ep0in.ep;
@@ -3559,6 +3557,9 @@
 	driver->unbind(&udc->gadget);               /* MAY SLEEP */
 	spin_lock_irqsave(udc->lock, flags);
 
+	usb_ep_free_request(&udc->ep0in.ep, udc->status);
+	kfree(udc->status_buf);
+
 	udc->gadget.dev.driver = NULL;
 
 	/* free resources */
diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h
index 3145418..1530474 100644
--- a/drivers/usb/gadget/ci13xxx_udc.h
+++ b/drivers/usb/gadget/ci13xxx_udc.h
@@ -115,6 +115,8 @@
 	spinlock_t                            *lock;
 	struct device                         *device;
 	struct dma_pool                       *td_pool;
+	struct ci13xxx_td                     *last_zptr;
+	dma_addr_t                            last_zdma;
 	unsigned long dTD_update_fail_count;
 	unsigned long			      prime_fail_count;
 	int				      prime_timer_count;
@@ -153,6 +155,7 @@
 	struct dma_pool           *qh_pool;   /* DMA pool for queue heads */
 	struct dma_pool           *td_pool;   /* DMA pool for transfer descs */
 	struct usb_request        *status;    /* ep0 status request */
+	void                      *status_buf;/* GET_STATUS buffer */
 
 	struct usb_gadget          gadget;     /* USB slave device */
 	struct ci13xxx_ep          ci13xxx_ep[ENDPT_MAX]; /* extended endpts */
diff --git a/drivers/usb/gadget/f_qc_ecm.c b/drivers/usb/gadget/f_qc_ecm.c
index 46a6bba..8e7cbb2 100644
--- a/drivers/usb/gadget/f_qc_ecm.c
+++ b/drivers/usb/gadget/f_qc_ecm.c
@@ -430,8 +430,6 @@
 
 	bam_data_disconnect(&ecm_qc_bam_port, 0);
 
-	ecm_ipa_cleanup(ipa_params.ipa_priv);
-
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 7674d88..ede8bdb 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1851,6 +1851,8 @@
 				"qcom,pool-64-bit-align");
 	pdata->enable_hbm = of_property_read_bool(node,
 				"qcom,enable-hbm");
+	pdata->disable_park_mode = (of_property_read_bool(node,
+				"qcom,disable-park-mode"));
 
 	return pdata;
 }
@@ -2088,7 +2090,7 @@
 		pm_runtime_put_sync(pdev->dev.parent);
 
 	if (mehci->enable_hbm)
-		hbm_init(hcd);
+		hbm_init(hcd, pdata->disable_park_mode);
 
 	return 0;
 
diff --git a/drivers/usb/host/hbm.c b/drivers/usb/host/hbm.c
index 1a0c0aa..d34301d 100644
--- a/drivers/usb/host/hbm.c
+++ b/drivers/usb/host/hbm.c
@@ -44,6 +44,7 @@
 struct hbm_msm {
 	u32 *base;
 	struct usb_hcd *hcd;
+	bool disable_park_mode;
 };
 
 static struct hbm_msm *hbm_ctx;
@@ -173,8 +174,8 @@
 		USB_OTG_HS_HBM_PIPE_PRODUCER, 1 << pipe_num,
 		(is_consumer ? 0 : 1));
 
-	/*  disable park mode as default */
-	set_disable_park_mode(pipe_num, true);
+	/*  set park mode */
+	set_disable_park_mode(pipe_num, hbm_ctx->disable_park_mode);
 
 	/*  enable zlt as default*/
 	set_disable_zlt(pipe_num, false);
@@ -186,7 +187,7 @@
 	return 0;
 }
 
-void hbm_init(struct usb_hcd *hcd)
+void hbm_init(struct usb_hcd *hcd, bool disable_park_mode)
 {
 	pr_info("%s\n", __func__);
 
@@ -198,6 +199,7 @@
 
 	hbm_ctx->base = hcd->regs;
 	hbm_ctx->hcd = hcd;
+	hbm_ctx->disable_park_mode = disable_park_mode;
 
 	/* reset hbm */
 	hbm_reset(true);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 22ff08c..1a64be4 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -813,7 +813,6 @@
 
 	dsi_ctrl |= BIT(0);	/* enable dsi */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
-	mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0); /* enable dsi irq */
 
 	wmb();
 }
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index eb4eee2..a7ea948 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1210,6 +1210,7 @@
 		mdss_fb_wait_for_fence(mfd);
 		if (mfd->mdp.kickoff_fnc)
 			mfd->mdp.kickoff_fnc(mfd);
+		mdss_fb_update_backlight(mfd);
 		mdss_fb_signal_timeline(mfd);
 	} else {
 		var = &fb_backup->disp_commit.var;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
index 694fcde..2cf47fc 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_cec.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -785,12 +785,16 @@
 
 	io = cec_ctrl->init_data.io;
 
-	if (!cec_ctrl->cec_enabled)
-		return 0;
-
 	cec_intr = DSS_REG_R_ND(io, HDMI_CEC_INT);
 	DEV_DBG("%s: cec interrupt status is [0x%x]\n", __func__, cec_intr);
 
+	if (!cec_ctrl->cec_enabled) {
+		DEV_ERR("%s: cec is not enabled. Just clear int and return.\n",
+			__func__);
+		DSS_REG_W(io, HDMI_CEC_INT, cec_intr);
+		return 0;
+	}
+
 	cec_status = DSS_REG_R_ND(io, HDMI_CEC_STATUS);
 	DEV_DBG("%s: cec status is [0x%x]\n", __func__, cec_status);
 
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index ef17229..f726e79 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -1057,11 +1057,16 @@
 
 	io = hdcp_ctrl->init_data.core_io;
 
-	/* Ignore HDCP interrupts if HDCP is disabled */
-	if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state)
-		return 0;
-
 	hdcp_int_val = DSS_REG_R(io, HDMI_HDCP_INT_CTRL);
+
+	/* Ignore HDCP interrupts if HDCP is disabled */
+	if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) {
+		DEV_ERR("%s: HDCP inactive. Just clear int and return.\n",
+			__func__);
+		DSS_REG_W(io, HDMI_HDCP_INT_CTRL, hdcp_int_val);
+		return 0;
+	}
+
 	if (hdcp_int_val & BIT(0)) {
 		/* AUTH_SUCCESS_INT */
 		DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(1)));
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 9a90b88..1ff8acf 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -2298,6 +2298,7 @@
 static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl)
 {
 	int rc = 0;
+	struct dss_io_data *io = NULL;
 
 	if (!hdmi_ctrl) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -2309,6 +2310,15 @@
 		return;
 	}
 
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+	if (!io->base) {
+		DEV_ERR("%s: core io not inititalized\n", __func__);
+		return;
+	}
+
+	/* Turn off HPD interrupts */
+	DSS_REG_W(io, HDMI_HPD_INT_CTRL, 0);
+
 	mdss_disable_irq(&hdmi_tx_hw);
 
 	hdmi_tx_set_mode(hdmi_ctrl, false);
@@ -2411,7 +2421,7 @@
 	struct dss_io_data *io = NULL;
 	struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
 
-	if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
+	if (!hdmi_ctrl) {
 		DEV_WARN("%s: invalid input data, ISR ignored\n", __func__);
 		return IRQ_HANDLED;
 	}
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index d1fdbab..6018e6f 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -122,6 +122,7 @@
 	u32 opmode;
 	u32 flush_bits;
 
+	bool is_video_mode;
 	u32 play_cnt;
 	u32 vsync_cnt;
 	u32 underrun_cnt;
@@ -150,6 +151,7 @@
 	int (*display_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
 	int (*wait_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
 	int (*set_vsync_handler) (struct mdss_mdp_ctl *, mdp_vsync_handler_t);
+	u32 (*read_line_cnt_fnc) (struct mdss_mdp_ctl *);
 
 	void *priv_data;
 };
@@ -317,6 +319,7 @@
 	int borderfill_enable;
 	int overlay_play_enable;
 	int hw_refresh;
+	void *cpu_pm_hdl;
 
 	struct mdss_data_type *mdata;
 	struct mutex ov_lock;
@@ -325,6 +328,7 @@
 	struct list_head overlay_list;
 	struct list_head pipes_used;
 	struct list_head pipes_cleanup;
+	bool mixer_swap;
 };
 
 #define is_vig_pipe(_pipe_id_) ((_pipe_id_) <= MDSS_MDP_SSPP_VIG2)
@@ -399,6 +403,8 @@
 int mdss_mdp_mixer_pipe_unstage(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
 int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_display_wakeup_time(struct mdss_mdp_ctl *ctl,
+				 ktime_t *wakeup_time);
 
 int mdss_mdp_csc_setup(u32 block, u32 blk_idx, u32 tbl_idx, u32 csc_type);
 int mdss_mdp_csc_setup_data(u32 block, u32 blk_idx, u32 tbl_idx,
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 95fef96..434249f 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -47,6 +47,15 @@
 	writel_relaxed(val, mixer->base + reg);
 }
 
+static inline u32 mdss_mdp_get_pclk_rate(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
+
+	return (ctl->intf_type == MDSS_INTF_DSI) ?
+		pinfo->mipi.dsi_pclk_rate :
+		pinfo->clk_rate;
+}
+
 static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags)
 {
 	struct mdss_mdp_ctl *ctl;
@@ -202,13 +211,7 @@
 			max_clk_rate = clk_rate;
 
 		if (ctl->intf_type) {
-			struct mdss_panel_info *pinfo;
-
-			pinfo = &ctl->panel_data->panel_info;
-			clk_rate = (ctl->intf_type == MDSS_INTF_DSI) ?
-					pinfo->mipi.dsi_pclk_rate :
-					pinfo->clk_rate;
-
+			clk_rate = mdss_mdp_get_pclk_rate(ctl);
 			/* minimum clock rate due to inefficiency in 3dmux */
 			clk_rate = mult_frac(clk_rate >> 1, 9, 8);
 			if (clk_rate > max_clk_rate)
@@ -297,6 +300,7 @@
 	ctl->display_fnc = NULL;
 	ctl->wait_fnc = NULL;
 	ctl->set_vsync_handler = NULL;
+	ctl->read_line_cnt_fnc = NULL;
 	mutex_unlock(&mdss_mdp_ctl_lock);
 
 	return 0;
@@ -647,15 +651,18 @@
 	}
 	ctl->mfd = mfd;
 	ctl->panel_data = pdata;
+	ctl->is_video_mode = false;
 
 	switch (pdata->panel_info.type) {
 	case EDP_PANEL:
+		ctl->is_video_mode = true;
 		ctl->intf_num = MDSS_MDP_INTF0;
 		ctl->intf_type = MDSS_INTF_EDP;
 		ctl->opmode = MDSS_MDP_CTL_OP_VIDEO_MODE;
 		ctl->start_fnc = mdss_mdp_video_start;
 		break;
 	case MIPI_VIDEO_PANEL:
+		ctl->is_video_mode = true;
 		if (pdata->panel_info.pdest == DISPLAY_1)
 			ctl->intf_num = MDSS_MDP_INTF1;
 		else
@@ -674,6 +681,7 @@
 		ctl->start_fnc = mdss_mdp_cmd_start;
 		break;
 	case DTV_PANEL:
+		ctl->is_video_mode = true;
 		ctl->intf_num = MDSS_MDP_INTF3;
 		ctl->intf_type = MDSS_INTF_HDMI;
 		ctl->opmode = MDSS_MDP_CTL_OP_VIDEO_MODE;
@@ -1189,16 +1197,19 @@
 struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux)
 {
 	struct mdss_mdp_mixer *mixer = NULL;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(ctl->mfd);
 	if (!ctl)
 		return NULL;
 
 	switch (mux) {
 	case MDSS_MDP_MIXER_MUX_DEFAULT:
 	case MDSS_MDP_MIXER_MUX_LEFT:
-		mixer = ctl->mixer_left;
+		mixer = mdp5_data->mixer_swap ?
+			ctl->mixer_right : ctl->mixer_left;
 		break;
 	case MDSS_MDP_MIXER_MUX_RIGHT:
-		mixer = ctl->mixer_right;
+		mixer = mdp5_data->mixer_swap ?
+			ctl->mixer_left : ctl->mixer_right;
 		break;
 	}
 
@@ -1310,6 +1321,71 @@
 	return 0;
 }
 
+int mdss_mdp_display_wakeup_time(struct mdss_mdp_ctl *ctl,
+				 ktime_t *wakeup_time)
+{
+	struct mdss_panel_info *pinfo;
+	u32 clk_rate, clk_period;
+	u32 current_line, total_line;
+	u32 time_of_line, time_to_vsync;
+	ktime_t current_time = ktime_get();
+
+	if (!ctl->read_line_cnt_fnc)
+		return -ENOSYS;
+
+	pinfo = &ctl->panel_data->panel_info;
+	if (!pinfo)
+		return -ENODEV;
+
+	clk_rate = mdss_mdp_get_pclk_rate(ctl);
+
+	clk_rate /= 1000;	/* in kHz */
+	if (!clk_rate)
+		return -EINVAL;
+
+	/*
+	 * calculate clk_period as pico second to maintain good
+	 * accuracy with high pclk rate and this number is in 17 bit
+	 * range.
+	 */
+	clk_period = 1000000000 / clk_rate;
+	if (!clk_period)
+		return -EINVAL;
+
+	time_of_line = (pinfo->lcdc.h_back_porch +
+		 pinfo->lcdc.h_front_porch +
+		 pinfo->lcdc.h_pulse_width +
+		 pinfo->xres) * clk_period;
+
+	time_of_line /= 1000;	/* in nano second */
+	if (!time_of_line)
+		return -EINVAL;
+
+	current_line = ctl->read_line_cnt_fnc(ctl);
+
+	total_line = pinfo->lcdc.v_back_porch +
+		pinfo->lcdc.v_front_porch +
+		pinfo->lcdc.v_pulse_width +
+		pinfo->yres;
+
+	if (current_line > total_line)
+		return -EINVAL;
+
+	time_to_vsync = time_of_line * (total_line - current_line);
+	if (!time_to_vsync)
+		return -EINVAL;
+
+	*wakeup_time = ktime_add_ns(current_time, time_to_vsync);
+
+	pr_debug("clk_rate=%dkHz clk_period=%d cur_line=%d tot_line=%d\n",
+		clk_rate, clk_period, current_line, total_line);
+	pr_debug("time_to_vsync=%d current_time=%d wakeup_time=%d\n",
+		time_to_vsync, (int)ktime_to_ms(current_time),
+		(int)ktime_to_ms(*wakeup_time));
+
+	return 0;
+}
+
 int mdss_mdp_display_wait4comp(struct mdss_mdp_ctl *ctl)
 {
 	int ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 5221106..a59560e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -403,6 +403,9 @@
 #define MDSS_MDP_REG_INTF_TEST_CTL			0x054
 #define MDSS_MDP_REG_INTF_TP_COLOR0			0x058
 #define MDSS_MDP_REG_INTF_TP_COLOR1			0x05C
+#define MDSS_MDP_REG_INTF_FRAME_LINE_COUNT_EN           0x0A8
+#define MDSS_MDP_REG_INTF_FRAME_COUNT                   0x0AC
+#define MDSS_MDP_REG_INTF_LINE_COUNT                    0x0B0
 
 #define MDSS_MDP_REG_INTF_DEFLICKER_CONFIG		0x0F0
 #define MDSS_MDP_REG_INTF_DEFLICKER_STRNG_COEFF		0x0F4
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 6e631e9..94ae710 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -59,6 +59,22 @@
 	writel_relaxed(val, ctx->base + reg);
 }
 
+static inline u32 mdp_video_read(struct mdss_mdp_video_ctx *ctx,
+				   u32 reg)
+{
+	return readl_relaxed(ctx->base + reg);
+}
+
+static inline u32 mdss_mdp_video_line_count(struct mdss_mdp_ctl *ctl)
+{
+	struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
+	u32 line_cnt = 0;
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+	line_cnt = mdp_video_read(ctx, MDSS_MDP_REG_INTF_LINE_COUNT);
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+	return line_cnt;
+}
+
 int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
 				u32 *offsets,  u32 count)
 {
@@ -171,6 +187,7 @@
 			   p->underflow_clr);
 	mdp_video_write(ctx, MDSS_MDP_REG_INTF_HSYNC_SKEW, p->hsync_skew);
 	mdp_video_write(ctx, MDSS_MDP_REG_INTF_POLARITY_CTL, polarity_ctl);
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_FRAME_LINE_COUNT_EN, 0x3);
 
 	return 0;
 }
@@ -284,7 +301,8 @@
 	vsync_time = ktime_get();
 	ctl->vsync_cnt++;
 
-	pr_debug("intr ctl=%d vsync cnt=%u\n", ctl->num, ctl->vsync_cnt);
+	pr_debug("intr ctl=%d vsync cnt=%u vsync_time=%d\n",
+		 ctl->num, ctl->vsync_cnt, (int)ktime_to_ms(vsync_time));
 
 	complete_all(&ctx->vsync_comp);
 	spin_lock(&ctx->vsync_lock);
@@ -454,6 +472,7 @@
 	ctl->display_fnc = mdss_mdp_video_display;
 	ctl->wait_fnc = mdss_mdp_video_wait4comp;
 	ctl->set_vsync_handler = mdss_mdp_video_set_vsync_handler;
+	ctl->read_line_cnt_fnc = mdss_mdp_video_line_count;
 
 	return 0;
 }
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index c97490b..6c90794 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -24,6 +24,7 @@
 #include <linux/msm_mdp.h>
 
 #include <mach/iommu_domains.h>
+#include <mach/event_timer.h>
 
 #include "mdss.h"
 #include "mdss_fb.h"
@@ -37,6 +38,7 @@
 
 static atomic_t ov_active_panels = ATOMIC_INIT(0);
 static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
+static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd);
 
 static int mdss_mdp_overlay_get(struct msm_fb_data_type *mfd,
 				struct mdp_overlay *req)
@@ -598,6 +600,7 @@
 		list_move(&pipe->cleanup_list, &destroy_pipes);
 		mdss_mdp_overlay_free_buf(&pipe->back_buf);
 		mdss_mdp_overlay_free_buf(&pipe->front_buf);
+		pipe->mfd = NULL;
 	}
 
 	list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
@@ -740,6 +743,19 @@
 	return rc;
 }
 
+static void mdss_mdp_overlay_update_pm(struct mdss_overlay_private *mdp5_data)
+{
+	ktime_t wakeup_time;
+
+	if (!mdp5_data->cpu_pm_hdl)
+		return;
+
+	if (mdss_mdp_display_wakeup_time(mdp5_data->ctl, &wakeup_time))
+		return;
+
+	activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time);
+}
+
 int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd)
 {
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -781,6 +797,8 @@
 	if (IS_ERR_VALUE(ret))
 		goto commit_fail;
 
+	mdss_mdp_overlay_update_pm(mdp5_data);
+
 	ret = mdss_mdp_display_wait4comp(mdp5_data->ctl);
 
 	complete(&mfd->update.comp);
@@ -988,6 +1006,41 @@
 	return ret;
 }
 
+static int mdss_mdp_overlay_force_cleanup(struct msm_fb_data_type *mfd)
+{
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+	struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
+	int ret;
+
+	pr_debug("forcing cleanup to unset dma pipes on fb%d\n", mfd->index);
+
+	/*
+	 * video mode panels require the layer to be unstaged and wait for
+	 * vsync to be able to release buffer.
+	 */
+	if (ctl && ctl->is_video_mode) {
+		ret = mdss_mdp_display_commit(ctl, NULL);
+		if (!IS_ERR_VALUE(ret))
+			mdss_mdp_display_wait4comp(ctl);
+	}
+
+	ret = mdss_mdp_overlay_cleanup(mfd);
+
+	return ret;
+}
+
+static void mdss_mdp_overlay_force_dma_cleanup(struct mdss_data_type *mdata)
+{
+	struct mdss_mdp_pipe *pipe;
+	int i;
+
+	for (i = 0; i < mdata->ndma_pipes; i++) {
+		pipe = mdata->dma_pipes + i;
+		if (atomic_read(&pipe->ref_cnt) && pipe->mfd)
+			mdss_mdp_overlay_force_cleanup(pipe->mfd);
+	}
+}
+
 static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
 				 struct msmfb_overlay_data *req)
 {
@@ -1012,6 +1065,8 @@
 	}
 
 	if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
+		mdss_mdp_overlay_force_dma_cleanup(mfd_to_mdata(mfd));
+
 		ret = mdss_mdp_overlay_rotate(mfd, req);
 	} else if (req->id == BORDERFILL_NDX) {
 		pr_debug("borderfill enable\n");
@@ -1721,11 +1776,8 @@
 			struct msmfb_overlay_data data;
 
 			ret = copy_from_user(&data, argp, sizeof(data));
-			if (!ret) {
+			if (!ret)
 				ret = mdss_mdp_overlay_play(mfd, &data);
-				if (!IS_ERR_VALUE(ret))
-					mdss_fb_update_backlight(mfd);
-			}
 
 			if (ret)
 				pr_debug("OVERLAY_PLAY failed (%d)\n", ret);
@@ -1936,6 +1988,10 @@
 	}
 	mfd->mdp.private1 = mdp5_data;
 
+	rc = mdss_mdp_overlay_fb_parse_dt(mfd);
+	if (rc)
+		return rc;
+
 	rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
 	if (rc) {
 		pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
@@ -1948,8 +2004,27 @@
 	kobject_uevent(&dev->kobj, KOBJ_ADD);
 	pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
 
+	mdp5_data->cpu_pm_hdl = add_event_timer(NULL, (void *)mdp5_data);
+	if (!mdp5_data->cpu_pm_hdl)
+		pr_warn("%s: unable to add event timer\n", __func__);
+
 	return rc;
 init_fail:
 	kfree(mdp5_data);
 	return rc;
 }
+
+static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd)
+{
+	struct platform_device *pdev = mfd->pdev;
+	struct mdss_overlay_private *mdp5_mdata = mfd_to_mdp5_data(mfd);
+
+	mdp5_mdata->mixer_swap = of_property_read_bool(pdev->dev.of_node,
+					   "qcom,mdss-mixer-swap");
+	if (mdp5_mdata->mixer_swap) {
+		pr_info("mixer swap is enabled for fb device=%s\n",
+			pdev->name);
+	}
+
+	return 0;
+}
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 3a9b1b9..0d1f49f 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -77,7 +77,8 @@
 	WCD9XXX_IRQ_HPH_L_PA_STARTUP,
 	WCD9XXX_IRQ_HPH_R_PA_STARTUP,
 	WCD9XXX_IRQ_EAR_PA_STARTUP,
-	WCD9XXX_IRQ_RESERVED_0,
+	WCD9310_NUM_IRQS,
+	WCD9XXX_IRQ_RESERVED_0 = WCD9310_NUM_IRQS,
 	WCD9XXX_IRQ_RESERVED_1,
 	/* INTR_REG 3 */
 	WCD9XXX_IRQ_MAD_AUDIO,
@@ -85,12 +86,14 @@
 	WCD9XXX_IRQ_MAD_ULTRASOUND,
 	WCD9XXX_IRQ_SPEAKER_CLIPPING,
 	WCD9XXX_IRQ_MBHC_JACK_SWITCH,
+	WCD9XXX_IRQ_VBAT_MONITOR_ATTACK,
+	WCD9XXX_IRQ_VBAT_MONITOR_RELEASE,
 	WCD9XXX_NUM_IRQS,
 };
 
 enum {
-	TABLA_NUM_IRQS = WCD9XXX_NUM_IRQS,
-	SITAR_NUM_IRQS = WCD9XXX_NUM_IRQS,
+	TABLA_NUM_IRQS = WCD9310_NUM_IRQS,
+	SITAR_NUM_IRQS = WCD9310_NUM_IRQS,
 	TAIKO_NUM_IRQS = WCD9XXX_NUM_IRQS,
 	TAPAN_NUM_IRQS = WCD9XXX_NUM_IRQS,
 };
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 5e73bd9..3622616 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -422,6 +422,7 @@
 	u32 standalone_latency;
 	bool pool_64_bit_align;
 	bool enable_hbm;
+	bool disable_park_mode;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index b71aa30..992649f 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -108,10 +108,10 @@
 	SUB_MODULE_EEPROM,
 	SUB_MODULE_LED_FLASH,
 	SUB_MODULE_STROBE_FLASH,
-	SUB_MODULE_CSIPHY,
-	SUB_MODULE_CSIPHY_3D,
 	SUB_MODULE_CSID,
 	SUB_MODULE_CSID_3D,
+	SUB_MODULE_CSIPHY,
+	SUB_MODULE_CSIPHY_3D,
 	SUB_MODULE_MAX,
 };
 
diff --git a/include/media/msm_gemini.h b/include/media/msm_gemini.h
index 0167335..2209758 100644
--- a/include/media/msm_gemini.h
+++ b/include/media/msm_gemini.h
@@ -51,10 +51,19 @@
 #define MSM_GMN_IOCTL_TEST_DUMP_REGION \
 	_IOW(MSM_GMN_IOCTL_MAGIC, 15, unsigned long)
 
+#define MSM_GMN_IOCTL_SET_MODE \
+	_IOW(MSM_GMN_IOCTL_MAGIC, 16, enum msm_gmn_out_mode)
+
 #define MSM_GEMINI_MODE_REALTIME_ENCODE 0
 #define MSM_GEMINI_MODE_OFFLINE_ENCODE 1
 #define MSM_GEMINI_MODE_REALTIME_ROTATION 2
 #define MSM_GEMINI_MODE_OFFLINE_ROTATION 3
+
+enum msm_gmn_out_mode {
+	MSM_GMN_OUTMODE_FRAGMENTED,
+	MSM_GMN_OUTMODE_SINGLE
+};
+
 struct msm_gemini_ctrl_cmd {
 	uint32_t type;
 	uint32_t len;
diff --git a/include/trace/events/cpufreq_interactive.h b/include/trace/events/cpufreq_interactive.h
index ea83664..951e6ca 100644
--- a/include/trace/events/cpufreq_interactive.h
+++ b/include/trace/events/cpufreq_interactive.h
@@ -28,13 +28,7 @@
 	      __entry->actualfreq)
 );
 
-DEFINE_EVENT(set, cpufreq_interactive_up,
-	TP_PROTO(u32 cpu_id, unsigned long targfreq,
-	     unsigned long actualfreq),
-	TP_ARGS(cpu_id, targfreq, actualfreq)
-);
-
-DEFINE_EVENT(set, cpufreq_interactive_down,
+DEFINE_EVENT(set, cpufreq_interactive_setspeed,
 	TP_PROTO(u32 cpu_id, unsigned long targfreq,
 	     unsigned long actualfreq),
 	TP_ARGS(cpu_id, targfreq, actualfreq)
@@ -42,44 +36,50 @@
 
 DECLARE_EVENT_CLASS(loadeval,
 	    TP_PROTO(unsigned long cpu_id, unsigned long load,
-		     unsigned long curfreq, unsigned long targfreq),
-	    TP_ARGS(cpu_id, load, curfreq, targfreq),
+		     unsigned long curtarg, unsigned long curactual,
+		     unsigned long newtarg),
+		    TP_ARGS(cpu_id, load, curtarg, curactual, newtarg),
 
 	    TP_STRUCT__entry(
 		    __field(unsigned long, cpu_id    )
 		    __field(unsigned long, load      )
-		    __field(unsigned long, curfreq   )
-		    __field(unsigned long, targfreq  )
+		    __field(unsigned long, curtarg   )
+		    __field(unsigned long, curactual )
+		    __field(unsigned long, newtarg   )
 	    ),
 
 	    TP_fast_assign(
 		    __entry->cpu_id = cpu_id;
 		    __entry->load = load;
-		    __entry->curfreq = curfreq;
-		    __entry->targfreq = targfreq;
+		    __entry->curtarg = curtarg;
+		    __entry->curactual = curactual;
+		    __entry->newtarg = newtarg;
 	    ),
 
-	    TP_printk("cpu=%lu load=%lu cur=%lu targ=%lu",
-		      __entry->cpu_id, __entry->load, __entry->curfreq,
-		      __entry->targfreq)
+	    TP_printk("cpu=%lu load=%lu cur=%lu actual=%lu targ=%lu",
+		      __entry->cpu_id, __entry->load, __entry->curtarg,
+		      __entry->curactual, __entry->newtarg)
 );
 
 DEFINE_EVENT(loadeval, cpufreq_interactive_target,
 	    TP_PROTO(unsigned long cpu_id, unsigned long load,
-		     unsigned long curfreq, unsigned long targfreq),
-	    TP_ARGS(cpu_id, load, curfreq, targfreq)
+		     unsigned long curtarg, unsigned long curactual,
+		     unsigned long newtarg),
+	    TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
 );
 
 DEFINE_EVENT(loadeval, cpufreq_interactive_already,
 	    TP_PROTO(unsigned long cpu_id, unsigned long load,
-		     unsigned long curfreq, unsigned long targfreq),
-	    TP_ARGS(cpu_id, load, curfreq, targfreq)
+		     unsigned long curtarg, unsigned long curactual,
+		     unsigned long newtarg),
+	    TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
 );
 
 DEFINE_EVENT(loadeval, cpufreq_interactive_notyet,
 	    TP_PROTO(unsigned long cpu_id, unsigned long load,
-		     unsigned long curfreq, unsigned long targfreq),
-	    TP_ARGS(cpu_id, load, curfreq, targfreq)
+		     unsigned long curtarg, unsigned long curactual,
+		     unsigned long newtarg),
+	    TP_ARGS(cpu_id, load, curtarg, curactual, newtarg)
 );
 
 TRACE_EVENT(cpufreq_interactive_boost,
diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h
index a1da44f..e76e822 100644
--- a/include/trace/events/kmem.h
+++ b/include/trace/events/kmem.h
@@ -495,6 +495,70 @@
 	TP_ARGS(mode)
 );
 
+DECLARE_EVENT_CLASS(ion_alloc_pages,
+
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order),
+
+	TP_STRUCT__entry(
+		__field(gfp_t, gfp_flags)
+		__field(unsigned int, order)
+		),
+
+	TP_fast_assign(
+		__entry->gfp_flags = gfp_flags;
+		__entry->order = order;
+		),
+
+	TP_printk("gfp_flags=%s order=%d",
+		show_gfp_flags(__entry->gfp_flags),
+		__entry->order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_iommu_start,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_iommu_end,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_iommu_fail,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_sys_start,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_sys_end,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
+DEFINE_EVENT(ion_alloc_pages, alloc_pages_sys_fail,
+	TP_PROTO(gfp_t gfp_flags,
+		unsigned int order),
+
+	TP_ARGS(gfp_flags, order)
+	);
+
 #endif /* _TRACE_KMEM_H */
 
 /* This part must be outside protection */
diff --git a/sound/soc/codecs/wcd9304-tables.c b/sound/soc/codecs/wcd9304-tables.c
index 83c0c1d..7ec0152 100644
--- a/sound/soc/codecs/wcd9304-tables.c
+++ b/sound/soc/codecs/wcd9304-tables.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -235,8 +235,24 @@
 	[SITAR_A_CDC_RX1_B4_CTL] = SITAR_A_CDC_RX1_B4_CTL__POR,
 	[SITAR_A_CDC_RX1_B5_CTL] = SITAR_A_CDC_RX1_B5_CTL__POR,
 	[SITAR_A_CDC_RX1_B6_CTL] = SITAR_A_CDC_RX1_B6_CTL__POR,
+	[SITAR_A_CDC_RX2_B1_CTL] = SITAR_A_CDC_RX2_B1_CTL__POR,
+	[SITAR_A_CDC_RX2_B2_CTL] = SITAR_A_CDC_RX2_B2_CTL__POR,
+	[SITAR_A_CDC_RX2_B3_CTL] = SITAR_A_CDC_RX2_B3_CTL__POR,
+	[SITAR_A_CDC_RX2_B4_CTL] = SITAR_A_CDC_RX2_B4_CTL__POR,
+	[SITAR_A_CDC_RX2_B5_CTL] = SITAR_A_CDC_RX2_B5_CTL__POR,
+	[SITAR_A_CDC_RX2_B6_CTL] = SITAR_A_CDC_RX2_B6_CTL__POR,
+	[SITAR_A_CDC_RX3_B1_CTL] = SITAR_A_CDC_RX3_B1_CTL__POR,
+	[SITAR_A_CDC_RX3_B2_CTL] = SITAR_A_CDC_RX3_B2_CTL__POR,
+	[SITAR_A_CDC_RX3_B3_CTL] = SITAR_A_CDC_RX3_B3_CTL__POR,
+	[SITAR_A_CDC_RX3_B4_CTL] = SITAR_A_CDC_RX3_B4_CTL__POR,
+	[SITAR_A_CDC_RX3_B5_CTL] = SITAR_A_CDC_RX3_B5_CTL__POR,
+	[SITAR_A_CDC_RX3_B6_CTL] = SITAR_A_CDC_RX3_B6_CTL__POR,
 	[SITAR_A_CDC_RX1_VOL_CTL_B1_CTL] = SITAR_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
 	[SITAR_A_CDC_RX1_VOL_CTL_B2_CTL] = SITAR_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+	[SITAR_A_CDC_RX2_VOL_CTL_B1_CTL] = SITAR_A_CDC_RX2_VOL_CTL_B1_CTL__POR,
+	[SITAR_A_CDC_RX2_VOL_CTL_B2_CTL] = SITAR_A_CDC_RX2_VOL_CTL_B2_CTL__POR,
+	[SITAR_A_CDC_RX3_VOL_CTL_B1_CTL] = SITAR_A_CDC_RX3_VOL_CTL_B1_CTL__POR,
+	[SITAR_A_CDC_RX3_VOL_CTL_B2_CTL] = SITAR_A_CDC_RX3_VOL_CTL_B2_CTL__POR,
 	[SITAR_A_CDC_CLK_ANC_RESET_CTL] = SITAR_A_CDC_CLK_ANC_RESET_CTL__POR,
 	[SITAR_A_CDC_CLK_RX_RESET_CTL] = SITAR_A_CDC_CLK_RX_RESET_CTL__POR,
 	[SITAR_A_CDC_CLK_TX_RESET_B1_CTL] =
@@ -322,6 +338,15 @@
 	[SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS] =
 		SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS__POR,
 	[SITAR_A_CDC_COMP1_FS_CFG] = SITAR_A_CDC_COMP1_FS_CFG__POR,
+	[SITAR_A_CDC_COMP2_B1_CTL] = SITAR_A_CDC_COMP2_B1_CTL__POR,
+	[SITAR_A_CDC_COMP2_B2_CTL] = SITAR_A_CDC_COMP2_B2_CTL__POR,
+	[SITAR_A_CDC_COMP2_B3_CTL] = SITAR_A_CDC_COMP2_B3_CTL__POR,
+	[SITAR_A_CDC_COMP2_B4_CTL] = SITAR_A_CDC_COMP2_B4_CTL__POR,
+	[SITAR_A_CDC_COMP2_B5_CTL] = SITAR_A_CDC_COMP2_B5_CTL__POR,
+	[SITAR_A_CDC_COMP2_B6_CTL] = SITAR_A_CDC_COMP2_B6_CTL__POR,
+	[SITAR_A_CDC_COMP2_SHUT_DOWN_STATUS] =
+		SITAR_A_CDC_COMP2_SHUT_DOWN_STATUS__POR,
+	[SITAR_A_CDC_COMP2_FS_CFG] = SITAR_A_CDC_COMP2_FS_CFG__POR,
 	[SITAR_A_CDC_CONN_RX1_B1_CTL] = SITAR_A_CDC_CONN_RX1_B1_CTL__POR,
 	[SITAR_A_CDC_CONN_RX1_B2_CTL] = SITAR_A_CDC_CONN_RX1_B2_CTL__POR,
 	[SITAR_A_CDC_CONN_RX1_B3_CTL] = SITAR_A_CDC_CONN_RX1_B3_CTL__POR,
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index f5f4e23..616f8d5 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,6 +81,11 @@
 
 #define SITAR_OCP_ATTEMPT 1
 
+#define COMP_DIGITAL_DB_GAIN_APPLY(a, b) \
+	(((a) <= 0) ? ((a) - b) : (a))
+/* The wait time value comes from codec HW specification */
+#define COMP_BRINGUP_WAIT_TIME  3000
+
 #define SITAR_MCLK_RATE_12288KHZ 12288000
 #define SITAR_MCLK_RATE_9600KHZ 9600000
 
@@ -148,6 +153,22 @@
 	BAND_MAX,
 };
 
+enum {
+	COMPANDER_1 = 0,
+	COMPANDER_2,
+	COMPANDER_MAX,
+};
+
+enum {
+	COMPANDER_FS_8KHZ = 0,
+	COMPANDER_FS_16KHZ,
+	COMPANDER_FS_32KHZ,
+	COMPANDER_FS_48KHZ,
+	COMPANDER_FS_96KHZ,
+	COMPANDER_FS_192KHZ,
+	COMPANDER_FS_MAX,
+};
+
 /* Flags to track of PA and DAC state.
  * PA and DAC should be tracked separately as AUXPGA loopback requires
  * only PA to be turned on without DAC being on. */
@@ -158,6 +179,33 @@
 	SITAR_HPHR_DAC_OFF_ACK
 };
 
+struct comp_sample_dependent_params {
+	u32 peak_det_timeout;
+	u32 rms_meter_div_fact;
+	u32 rms_meter_resamp_fact;
+};
+
+struct comp_dgtl_gain_offset {
+	u8 whole_db_gain;
+	u8 half_db_gain;
+};
+
+static const struct comp_dgtl_gain_offset comp_dgtl_gain[] = {
+	{0, 0},
+	{1, 1},
+	{3, 0},
+	{4, 1},
+	{6, 0},
+	{7, 1},
+	{9, 0},
+	{10, 1},
+	{12, 0},
+	{13, 1},
+	{15, 0},
+	{16, 1},
+	{18, 0},
+};
+
 /* Data used by MBHC */
 struct mbhc_internal_cal_data {
 	u16 dce_z;
@@ -273,6 +321,11 @@
 	/* num of slim ports required */
 	struct wcd9xxx_codec_dai_data dai[NUM_CODEC_DAIS];
 
+	/*compander*/
+	int comp_enabled[COMPANDER_MAX];
+	u32 comp_fs[COMPANDER_MAX];
+	u8  comp_gain_offset[NUM_INTERPOLATORS];
+
 	/* Currently, only used for mbhc purpose, to protect
 	 * concurrent execution of mbhc threaded irq handlers and
 	 * kill race between DAPM and MBHC.But can serve as a
@@ -295,6 +348,47 @@
 struct sitar_priv *debug_sitar_priv;
 #endif
 
+static const int comp_rx_path[] = {
+	COMPANDER_2,
+	COMPANDER_1,
+	COMPANDER_1,
+	COMPANDER_MAX,
+};
+
+static const struct comp_sample_dependent_params
+		    comp_samp_params[COMPANDER_FS_MAX] = {
+	{
+		.peak_det_timeout = 0x6,
+		.rms_meter_div_fact = 0x9 << 4,
+		.rms_meter_resamp_fact = 0x06,
+	},
+	{
+		.peak_det_timeout = 0x7,
+		.rms_meter_div_fact = 0xA << 4,
+		.rms_meter_resamp_fact = 0x0C,
+	},
+	{
+		.peak_det_timeout = 0x8,
+		.rms_meter_div_fact = 0xB << 4,
+		.rms_meter_resamp_fact = 0x30,
+	},
+	{
+		.peak_det_timeout = 0x9,
+		.rms_meter_div_fact = 0xB << 4,
+		.rms_meter_resamp_fact = 0x28,
+	},
+	{
+		.peak_det_timeout = 0xA,
+		.rms_meter_div_fact = 0xC << 4,
+		.rms_meter_resamp_fact = 0x50,
+	},
+	{
+		.peak_det_timeout = 0xB,
+		.rms_meter_div_fact = 0xC << 4,
+		.rms_meter_resamp_fact = 0x50,
+	},
+};
+
 static int sitar_get_anc_slot(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol)
 {
@@ -539,6 +633,268 @@
 	return 0;
 }
 
+static int sitar_compander_gain_offset(
+	struct snd_soc_codec *codec, u32 enable,
+	unsigned int pa_reg, unsigned int vol_reg,
+	int mask, int event,
+	struct comp_dgtl_gain_offset *gain_offset,
+	int index)
+{
+	unsigned int pa_gain = snd_soc_read(codec, pa_reg);
+	unsigned int digital_vol = snd_soc_read(codec, vol_reg);
+	int pa_mode = pa_gain & mask;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: pa_gain(0x%x=0x%x)digital_vol(0x%x=0x%x)event(0x%x) index(%d)\n",
+		 __func__, pa_reg, pa_gain, vol_reg, digital_vol, event, index);
+	if (((pa_gain & 0xF) + 1) > ARRAY_SIZE(comp_dgtl_gain) ||
+		(index >= ARRAY_SIZE(sitar->comp_gain_offset))) {
+		pr_err("%s: Out of array boundary\n", __func__);
+		return -EINVAL;
+	}
+
+	if (SND_SOC_DAPM_EVENT_ON(event) && (enable != 0)) {
+		gain_offset->whole_db_gain = COMP_DIGITAL_DB_GAIN_APPLY(
+		  (digital_vol - comp_dgtl_gain[pa_gain & 0xF].whole_db_gain),
+		  comp_dgtl_gain[pa_gain & 0xF].half_db_gain);
+		pr_debug("%s: listed whole_db_gain:0x%x, adjusted whole_db_gain:0x%x\n",
+			 __func__, comp_dgtl_gain[pa_gain & 0xF].whole_db_gain,
+			 gain_offset->whole_db_gain);
+		gain_offset->half_db_gain =
+				comp_dgtl_gain[pa_gain & 0xF].half_db_gain;
+		sitar->comp_gain_offset[index] = digital_vol -
+						 gain_offset->whole_db_gain ;
+	}
+	if (SND_SOC_DAPM_EVENT_OFF(event) && (pa_mode == 0)) {
+		gain_offset->whole_db_gain = digital_vol +
+					     sitar->comp_gain_offset[index];
+		pr_debug("%s: listed whole_db_gain:0x%x, adjusted whole_db_gain:0x%x\n",
+			 __func__, comp_dgtl_gain[pa_gain & 0xF].whole_db_gain,
+			 gain_offset->whole_db_gain);
+		gain_offset->half_db_gain = 0;
+	}
+
+	pr_debug("%s: half_db_gain(%d)whole_db_gain(0x%x)comp_gain_offset[%d](%d)\n",
+		 __func__, gain_offset->half_db_gain,
+		 gain_offset->whole_db_gain, index,
+		 sitar->comp_gain_offset[index]);
+	return 0;
+}
+
+static int sitar_config_gain_compander(
+				struct snd_soc_codec *codec,
+				u32 compander, u32 enable, int event)
+{
+	int value = 0;
+	int mask = 1 << 4;
+	struct comp_dgtl_gain_offset gain_offset = {0, 0};
+	if (compander >= COMPANDER_MAX) {
+		pr_err("%s: Error, invalid compander channel\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((enable == 0) || SND_SOC_DAPM_EVENT_OFF(event))
+		value = 1 << 4;
+
+	if (compander == COMPANDER_1) {
+		sitar_compander_gain_offset(codec, enable,
+				SITAR_A_RX_HPH_L_GAIN,
+				SITAR_A_CDC_RX2_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 1);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_L_GAIN, mask, value);
+		snd_soc_update_bits(codec, SITAR_A_CDC_RX2_VOL_CTL_B2_CTL,
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, SITAR_A_CDC_RX2_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		sitar_compander_gain_offset(codec, enable,
+				SITAR_A_RX_HPH_R_GAIN,
+				SITAR_A_CDC_RX3_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 2);
+		snd_soc_update_bits(codec, SITAR_A_RX_HPH_R_GAIN, mask, value);
+		snd_soc_update_bits(codec, SITAR_A_CDC_RX3_VOL_CTL_B2_CTL,
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, SITAR_A_CDC_RX3_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+	} else if (compander == COMPANDER_2) {
+		sitar_compander_gain_offset(codec, enable,
+				SITAR_A_RX_LINE_1_GAIN,
+				SITAR_A_CDC_RX1_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 0);
+		snd_soc_update_bits(codec, SITAR_A_RX_LINE_1_GAIN, mask, value);
+		snd_soc_update_bits(codec, SITAR_A_RX_LINE_2_GAIN, mask, value);
+		snd_soc_update_bits(codec, SITAR_A_CDC_RX1_VOL_CTL_B2_CTL,
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, SITAR_A_CDC_RX1_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+	}
+	return 0;
+}
+
+static int sitar_get_compander(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	int comp = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+
+	ucontrol->value.integer.value[0] = sitar->comp_enabled[comp];
+
+	return 0;
+}
+
+static int sitar_set_compander(struct snd_kcontrol *kcontrol,
+				   struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	int comp = ((struct soc_multi_mixer_control *)
+					kcontrol->private_value)->shift;
+	int value = ucontrol->value.integer.value[0];
+
+	pr_debug("%s: compander #%d enable %d\n",
+		 __func__, comp + 1, value);
+	if (value == sitar->comp_enabled[comp]) {
+		pr_debug("%s: compander #%d enable %d no change\n",
+			 __func__, comp + 1, value);
+		return 0;
+	}
+	sitar->comp_enabled[comp] = value;
+	return 0;
+}
+
+static int sitar_config_compander(struct snd_soc_dapm_widget *w,
+				  struct snd_kcontrol *kcontrol,
+				  int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	u32 rate = sitar->comp_fs[w->shift];
+	u32 value;
+
+	pr_debug("%s: compander #%d enable %d event %d widget name %s\n",
+		 __func__, w->shift + 1,
+		 sitar->comp_enabled[w->shift], event , w->name);
+	if (sitar->comp_enabled[w->shift] == 0)
+		goto rtn;
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		/* Update compander sample rate */
+		snd_soc_update_bits(codec, SITAR_A_CDC_COMP1_FS_CFG +
+				    w->shift * 8, 0x07, rate);
+		/* Enable compander clock */
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLK_RX_B2_CTL,
+				    1 << w->shift,
+				    1 << w->shift);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << w->shift,
+				    1 << w->shift);
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << w->shift, 0);
+		sitar_config_gain_compander(codec, w->shift, 1, event);
+		/* Compander enable -> 0x370/0x378 */
+		snd_soc_update_bits(codec, SITAR_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x03, 0x03);
+		/* Update the RMS meter resampling */
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_COMP1_B3_CTL +
+				    w->shift * 8, 0xFF, 0x01);
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0xF0, 0x50);
+		usleep_range(COMP_BRINGUP_WAIT_TIME, COMP_BRINGUP_WAIT_TIME);
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLSG_CTL,
+				    0x11, 0x00);
+		if (w->shift == COMPANDER_1)
+			value = 0x22;
+		else
+			value = 0x11;
+		snd_soc_write(codec,
+			      SITAR_A_CDC_CONN_CLSG_CTL, value);
+
+		snd_soc_update_bits(codec, SITAR_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0x0F,
+				    comp_samp_params[rate].peak_det_timeout);
+		snd_soc_update_bits(codec, SITAR_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0xF0,
+				    comp_samp_params[rate].rms_meter_div_fact);
+		snd_soc_update_bits(codec, SITAR_A_CDC_COMP1_B3_CTL +
+				w->shift * 8, 0xFF,
+				comp_samp_params[rate].rms_meter_resamp_fact);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, SITAR_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x03, 0x00);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << w->shift,
+				    1 << w->shift);
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << w->shift, 0);
+		/* Disable compander clock */
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLK_RX_B2_CTL,
+				    1 << w->shift,
+				    0);
+		/* Restore the gain */
+		sitar_config_gain_compander(codec, w->shift,
+					    sitar->comp_enabled[w->shift],
+					    event);
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_CLSG_CTL,
+				    0x11, 0x11);
+		snd_soc_write(codec,
+			      SITAR_A_CDC_CONN_CLSG_CTL, 0x14);
+		break;
+	}
+rtn:
+	return 0;
+}
+
+static int sitar_codec_dem_input_selection(struct snd_soc_dapm_widget *w,
+						struct snd_kcontrol *kcontrol,
+						int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
+	pr_debug("%s: compander#1->enable(%d) compander#2->enable(%d) reg(0x%x = 0x%x) event(%d)\n",
+		__func__, sitar->comp_enabled[COMPANDER_1],
+		sitar->comp_enabled[COMPANDER_2],
+		SITAR_A_CDC_RX1_B6_CTL + w->shift * 8,
+		snd_soc_read(codec, SITAR_A_CDC_RX1_B6_CTL + w->shift * 8),
+		event);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (sitar->comp_enabled[COMPANDER_1] ||
+		    sitar->comp_enabled[COMPANDER_2])
+			snd_soc_update_bits(codec,
+					    SITAR_A_CDC_RX1_B6_CTL +
+					    w->shift * 8,
+					    1 << 5, 0);
+		else
+			snd_soc_update_bits(codec,
+					    SITAR_A_CDC_RX1_B6_CTL +
+					    w->shift * 8,
+					    1 << 5, 0x20);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec,
+				    SITAR_A_CDC_RX1_B6_CTL + w->shift * 8,
+				    1 << 5, 0);
+		break;
+	}
+	return 0;
+}
+
 static const char * const sitar_ear_pa_gain_text[] = {"POS_6_DB",
 					"POS_2_DB", "NEG_2P5_DB", "NEG_12_DB"};
 
@@ -652,6 +1008,10 @@
 	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
 	SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
 	sitar_get_iir_band_audio_mixer, sitar_put_iir_band_audio_mixer),
+	SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, COMPANDER_1, 1, 0,
+				sitar_get_compander, sitar_set_compander),
+	SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
+				sitar_get_compander, sitar_set_compander),
 };
 
 static const char *rx_mix1_text[] = {
@@ -1267,9 +1627,14 @@
 		struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 	u16 lineout_gain_reg;
 
-	pr_debug("%s %d %s\n", __func__, event, w->name);
+	pr_debug("%s %d %s comp2 enable %d\n", __func__, event, w->name,
+		 sitar->comp_enabled[COMPANDER_2]);
+
+	if (sitar->comp_enabled[COMPANDER_2])
+		goto rtn;
 
 	switch (w->shift) {
 	case 0:
@@ -1311,6 +1676,7 @@
 		snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x00);
 		break;
 	}
+rtn:
 	return 0;
 }
 
@@ -2010,16 +2376,22 @@
 	struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = w->codec;
+	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
 
-	pr_debug("%s %s %d\n", __func__, w->name, event);
+	pr_debug("%s %s %d comp#1 enable %d\n", __func__,
+		 w->name, event, sitar->comp_enabled[COMPANDER_1]);
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
 		if (w->reg == SITAR_A_RX_HPH_L_DAC_CTL) {
-			snd_soc_update_bits(codec, SITAR_A_CDC_CONN_CLSG_CTL,
-				0x30, 0x20);
-			snd_soc_update_bits(codec, SITAR_A_CDC_CONN_CLSG_CTL,
-				0x0C, 0x08);
+			if (!sitar->comp_enabled[COMPANDER_1]) {
+				snd_soc_update_bits(codec,
+						    SITAR_A_CDC_CONN_CLSG_CTL,
+						    0x30, 0x20);
+				snd_soc_update_bits(codec,
+						    SITAR_A_CDC_CONN_CLSG_CTL,
+						    0x0C, 0x08);
+			}
 		}
 		snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
 		break;
@@ -2338,9 +2710,15 @@
 	SND_SOC_DAPM_MUX("DAC4 MUX", SND_SOC_NOPM, 0, 0,
 		&rx_dac4_mux),
 
-	SND_SOC_DAPM_MIXER("RX1 CHAIN", SITAR_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("RX2 CHAIN", SITAR_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("RX3 CHAIN", SITAR_A_CDC_RX3_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER_E("RX1 CHAIN", SND_SOC_NOPM, 0, 0, NULL,
+		0, sitar_codec_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("RX2 CHAIN", SND_SOC_NOPM, 1, 0, NULL,
+		0, sitar_codec_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("RX3 CHAIN", SND_SOC_NOPM, 2, 0, NULL,
+		0, sitar_codec_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
 
 	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 		&rx_mix1_inp1_mux),
@@ -2463,6 +2841,13 @@
 		sitar_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, COMPANDER_1, 0,
+		sitar_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, COMPANDER_2, 0,
+		sitar_config_compander, SND_SOC_DAPM_PRE_PMU |
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	/* Sidetone */
 	SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
 	SND_SOC_DAPM_PGA("IIR1", SITAR_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
@@ -2592,6 +2977,10 @@
 	{"SLIM RX3", NULL, "SLIM RX3 MUX"},
 	{"SLIM RX4", NULL, "SLIM RX4 MUX"},
 
+	{"RX1 MIX1", NULL, "COMP2_CLK"},
+	{"RX2 MIX1", NULL, "COMP1_CLK"},
+	{"RX3 MIX1", NULL, "COMP1_CLK"},
+
 	/* Slimbus port 5 is non functional in Sitar 1.0 */
 	{"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
 	{"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
@@ -2733,6 +3122,10 @@
 		if (reg == SITAR_A_CDC_RX1_VOL_CTL_B2_CTL + (8 * i))
 			return 1;
 	}
+
+	if ((reg == SITAR_A_CDC_COMP1_SHUT_DOWN_STATUS) ||
+		(reg == SITAR_A_CDC_COMP2_SHUT_DOWN_STATUS))
+			return 1;
 	return 0;
 }
 
@@ -3191,6 +3584,7 @@
 	struct snd_soc_codec *codec = dai->codec;
 	struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
 	u8 path, shift;
+	u32 compander_fs;
 	u16 tx_fs_reg, rx_fs_reg;
 	u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
 
@@ -3200,18 +3594,32 @@
 	case 8000:
 		tx_fs_rate = 0x00;
 		rx_fs_rate = 0x00;
+		compander_fs = COMPANDER_FS_8KHZ;
 		break;
 	case 16000:
 		tx_fs_rate = 0x01;
 		rx_fs_rate = 0x20;
+		compander_fs = COMPANDER_FS_16KHZ;
 		break;
 	case 32000:
 		tx_fs_rate = 0x02;
 		rx_fs_rate = 0x40;
+		compander_fs = COMPANDER_FS_32KHZ;
 		break;
 	case 48000:
 		tx_fs_rate = 0x03;
 		rx_fs_rate = 0x60;
+		compander_fs = COMPANDER_FS_48KHZ;
+		break;
+	case 96000:
+		tx_fs_rate = 0x04;
+		rx_fs_rate = 0x80;
+		compander_fs = COMPANDER_FS_96KHZ;
+		break;
+	case 192000:
+		tx_fs_rate = 0x05;
+		rx_fs_rate = 0xa0;
+		compander_fs = COMPANDER_FS_192KHZ;
 		break;
 	default:
 		pr_err("%s: Invalid sampling rate %d\n", __func__,
@@ -3285,6 +3693,9 @@
 						+ (BITS_PER_REG*(path-1));
 				snd_soc_update_bits(codec, rx_fs_reg,
 						0xE0, rx_fs_rate);
+				if (comp_rx_path[shift] < COMPANDER_MAX)
+					sitar->comp_fs[comp_rx_path[shift]]
+						= compander_fs;
 			}
 		}
 		if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
@@ -5484,6 +5895,11 @@
 	if (sitar->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
 		sitar_i2c_codec_init_reg(codec);
 
+	for (i = 0; i < COMPANDER_MAX; i++) {
+		sitar->comp_enabled[i] = 0;
+		sitar->comp_fs[i] = COMPANDER_FS_48KHZ;
+	}
+
 	ret = sitar_handle_pdata(sitar);
 	if (IS_ERR_VALUE(ret)) {
 		pr_err("%s: bad pdata\n", __func__);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index b8a4a86..29703b9 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -55,9 +55,12 @@
 #define MBHC_FW_READ_ATTEMPTS 15
 #define MBHC_FW_READ_TIMEOUT 2000000
 #define MBHC_VDDIO_SWITCH_WAIT_MS 10
+#define COMP_DIGITAL_DB_GAIN_APPLY(a, b) \
+	(((a) <= 0) ? ((a) - b) : (a))
 
 #define SLIM_CLOSE_TIMEOUT 1000
-
+/* The wait time value comes from codec HW specification */
+#define COMP_BRINGUP_WAIT_TIME  2000
 enum {
 	MBHC_USE_HPHL_TRIGGER = 1,
 	MBHC_USE_MB_TRIGGER = 2
@@ -99,9 +102,7 @@
 	RX_MIX1_INP_SEL_RX6,
 	RX_MIX1_INP_SEL_RX7,
 };
-
-#define TABLA_COMP_DIGITAL_GAIN_HP_OFFSET 3
-#define TABLA_COMP_DIGITAL_GAIN_LINEOUT_OFFSET 6
+#define MAX_PA_GAIN_OPTIONS  13
 
 #define TABLA_MCLK_RATE_12288KHZ 12288000
 #define TABLA_MCLK_RATE_9600KHZ 9600000
@@ -220,6 +221,28 @@
 	u32 shutdown_timeout;
 };
 
+struct comp_dgtl_gain_offset {
+	u8 whole_db_gain;
+	u8 half_db_gain;
+};
+
+static const struct comp_dgtl_gain_offset
+			comp_dgtl_gain[MAX_PA_GAIN_OPTIONS] = {
+	{0, 0},
+	{1, 1},
+	{3, 0},
+	{4, 1},
+	{6, 0},
+	{7, 1},
+	{9, 0},
+	{10, 1},
+	{12, 0},
+	{13, 1},
+	{15, 0},
+	{16, 1},
+	{18, 0},
+};
+
 /* Data used by MBHC */
 struct mbhc_internal_cal_data {
 	u16 dce_z;
@@ -377,6 +400,7 @@
 	/*compander*/
 	int comp_enabled[COMPANDER_MAX];
 	u32 comp_fs[COMPANDER_MAX];
+	u8  comp_gain_offset[TABLA_SB_PGD_MAX_NUMBER_OF_RX_SLAVE_DEV_PORTS - 1];
 
 	/* Maintain the status of AUX PGA */
 	int aux_pga_cnt;
@@ -547,7 +571,10 @@
 {
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	mutex_lock(&codec->dapm.codec->mutex);
 	ucontrol->value.integer.value[0] = (tabla->anc_func == true ? 1 : 0);
+	mutex_unlock(&codec->dapm.codec->mutex);
 	return 0;
 }
 
@@ -802,34 +829,51 @@
 
 static int tabla_compander_gain_offset(
 	struct snd_soc_codec *codec, u32 enable,
-	unsigned int reg, int mask, int event, u32 comp)
+	unsigned int pa_reg, unsigned int vol_reg,
+	int mask, int event,
+	struct comp_dgtl_gain_offset *gain_offset,
+	int index)
 {
-	int pa_mode = snd_soc_read(codec, reg) & mask;
-	int gain_offset = 0;
-	/*  if PMU && enable is 1-> offset is 3
-	 *  if PMU && enable is 0-> offset is 0
-	 *  if PMD && pa_mode is PA -> offset is 0: PMU compander is off
-	 *  if PMD && pa_mode is comp -> offset is -3: PMU compander is on.
-	 */
+	unsigned int pa_gain = snd_soc_read(codec, pa_reg);
+	unsigned int digital_vol = snd_soc_read(codec, vol_reg);
+	int pa_mode = pa_gain & mask;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: pa_gain(0x%x=0x%x)digital_vol(0x%x=0x%x)event(0x%x) index(%d)\n",
+		 __func__, pa_reg, pa_gain, vol_reg, digital_vol, event, index);
+	if (((pa_gain & 0xF) + 1) > ARRAY_SIZE(comp_dgtl_gain) ||
+		(index >= ARRAY_SIZE(tabla->comp_gain_offset))) {
+		pr_err("%s: Out of array boundary\n", __func__);
+		return -EINVAL;
+	}
 
 	if (SND_SOC_DAPM_EVENT_ON(event) && (enable != 0)) {
-		if (comp == COMPANDER_1)
-			gain_offset = TABLA_COMP_DIGITAL_GAIN_HP_OFFSET;
-		if (comp == COMPANDER_2)
-			gain_offset = TABLA_COMP_DIGITAL_GAIN_LINEOUT_OFFSET;
+		gain_offset->whole_db_gain = COMP_DIGITAL_DB_GAIN_APPLY(
+		  (digital_vol - comp_dgtl_gain[pa_gain & 0xF].whole_db_gain),
+		  comp_dgtl_gain[pa_gain & 0xF].half_db_gain);
+		pr_debug("%s: listed whole_db_gain:0x%x, adjusted whole_db_gain:0x%x\n",
+			 __func__, comp_dgtl_gain[pa_gain & 0xF].whole_db_gain,
+			 gain_offset->whole_db_gain);
+		gain_offset->half_db_gain =
+				comp_dgtl_gain[pa_gain & 0xF].half_db_gain;
+		tabla->comp_gain_offset[index] = digital_vol -
+						 gain_offset->whole_db_gain ;
 	}
 	if (SND_SOC_DAPM_EVENT_OFF(event) && (pa_mode == 0)) {
-		if (comp == COMPANDER_1)
-			gain_offset = -TABLA_COMP_DIGITAL_GAIN_HP_OFFSET;
-		if (comp == COMPANDER_2)
-			gain_offset = -TABLA_COMP_DIGITAL_GAIN_LINEOUT_OFFSET;
-
+		gain_offset->whole_db_gain = digital_vol +
+					     tabla->comp_gain_offset[index];
+		pr_debug("%s: listed whole_db_gain:0x%x, adjusted whole_db_gain:0x%x\n",
+			 __func__, comp_dgtl_gain[pa_gain & 0xF].whole_db_gain,
+			 gain_offset->whole_db_gain);
+		gain_offset->half_db_gain = 0;
 	}
-	pr_debug("%s: compander #%d gain_offset %d\n",
-		 __func__, comp + 1, gain_offset);
-	return gain_offset;
-}
 
+	pr_debug("%s: half_db_gain(%d)whole_db_gain(%d)comp_gain_offset[%d](%d)\n",
+		 __func__, gain_offset->half_db_gain,
+		 gain_offset->whole_db_gain, index,
+		 tabla->comp_gain_offset[index]);
+	return 0;
+}
 
 static int tabla_config_gain_compander(
 				struct snd_soc_codec *codec,
@@ -837,8 +881,7 @@
 {
 	int value = 0;
 	int mask = 1 << 4;
-	int gain = 0;
-	int gain_offset;
+	struct comp_dgtl_gain_offset gain_offset = {0, 0};
 	if (compander >= COMPANDER_MAX) {
 		pr_err("%s: Error, invalid compander channel\n", __func__);
 		return -EINVAL;
@@ -848,43 +891,61 @@
 		value = 1 << 4;
 
 	if (compander == COMPANDER_1) {
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_HPH_L_GAIN, mask, event, compander);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_HPH_L_GAIN,
+				TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 0);
 		snd_soc_update_bits(codec, TABLA_A_RX_HPH_L_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX1_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX1_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_HPH_R_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_HPH_R_GAIN,
+				TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 1);
 		snd_soc_update_bits(codec, TABLA_A_RX_HPH_R_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX2_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX2_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
 	} else if (compander == COMPANDER_2) {
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_1_GAIN, mask, event, compander);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_1_GAIN,
+				TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 2);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_1_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX3_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX3_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_3_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX3_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_3_GAIN,
+				TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 3);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_3_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX4_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX4_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_2_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX4_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_2_GAIN,
+				TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 4);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_2_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX5_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX5_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
-		gain_offset = tabla_compander_gain_offset(codec, enable,
-				TABLA_A_RX_LINE_4_GAIN, mask, event, compander);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX5_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
+		tabla_compander_gain_offset(codec, enable,
+				TABLA_A_RX_LINE_4_GAIN,
+				TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
+				mask, event, &gain_offset, 5);
 		snd_soc_update_bits(codec, TABLA_A_RX_LINE_4_GAIN, mask, value);
-		gain = snd_soc_read(codec, TABLA_A_CDC_RX6_VOL_CTL_B2_CTL);
 		snd_soc_update_bits(codec, TABLA_A_CDC_RX6_VOL_CTL_B2_CTL,
-				0xFF, gain - gain_offset);
+				    0xFF, gain_offset.whole_db_gain);
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX6_B6_CTL,
+				    0x02, gain_offset.half_db_gain);
 	}
 	return 0;
 }
@@ -921,7 +982,6 @@
 	return 0;
 }
 
-
 static int tabla_config_compander(struct snd_soc_dapm_widget *w,
 						  struct snd_kcontrol *kcontrol,
 						  int event)
@@ -929,106 +989,161 @@
 	struct snd_soc_codec *codec = w->codec;
 	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
 	u32 rate = tabla->comp_fs[w->shift];
-	u32 status;
-	unsigned long timeout;
-	pr_debug("%s: compander #%d enable %d event %d\n",
+
+	pr_debug("%s: compander #%d enable %d event %d widget name %s\n",
 		 __func__, w->shift + 1,
-		 tabla->comp_enabled[w->shift], event);
+		 tabla->comp_enabled[w->shift], event , w->name);
+	if (tabla->comp_enabled[w->shift] == 0)
+		goto rtn;
+	if ((w->shift == COMPANDER_1) && (tabla->anc_func)) {
+		pr_debug("%s: ANC is enabled so compander #%d cannot be enabled\n",
+			 __func__, w->shift + 1);
+		goto rtn;
+	}
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (tabla->comp_enabled[w->shift] != 0) {
-			/* Enable both L/R compander clocks */
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_CLK_RX_B2_CTL,
-					1 << comp_shift[w->shift],
-					1 << comp_shift[w->shift]);
-			/* Clear the HALT for the compander*/
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_COMP1_B1_CTL +
-					w->shift * 8, 1 << 2, 0);
-			/* Toggle compander reset bits*/
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_CLK_OTHR_RESET_CTL,
-					1 << comp_shift[w->shift],
-					1 << comp_shift[w->shift]);
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_CLK_OTHR_RESET_CTL,
-					1 << comp_shift[w->shift], 0);
-			tabla_config_gain_compander(codec, w->shift, 1, event);
-			/* Compander enable -> 0x370/0x378*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 0x03, 0x03);
-			/* Update the RMS meter resampling*/
-			snd_soc_update_bits(codec,
-					TABLA_A_CDC_COMP1_B3_CTL +
-					w->shift * 8, 0xFF, 0x01);
-			snd_soc_update_bits(codec,
-					    TABLA_A_CDC_COMP1_B2_CTL +
-					    w->shift * 8, 0xF0, 0x50);
-			/* Wait for 1ms*/
-			usleep_range(5000, 5000);
-		}
+		/* Update compander sample rate */
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_FS_CFG +
+				    w->shift * 8, 0x07, rate);
+		/* Enable both L/R compander clocks */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_RX_B2_CTL,
+				    1 << comp_shift[w->shift],
+				    1 << comp_shift[w->shift]);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift],
+				    1 << comp_shift[w->shift]);
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift], 0);
+		tabla_config_gain_compander(codec, w->shift, 1, event);
+		/* Compander enable -> 0x370/0x378 */
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x03, 0x03);
+		/* Update the RMS meter resampling */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_COMP1_B3_CTL +
+				    w->shift * 8, 0xFF, 0x01);
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0xF0, 0x50);
+		usleep_range(COMP_BRINGUP_WAIT_TIME, COMP_BRINGUP_WAIT_TIME);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
-		/* Set sample rate dependent paramater*/
-		if (tabla->comp_enabled[w->shift] != 0) {
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_FS_CFG +
-			w->shift * 8, 0x07,	rate);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
-			w->shift * 8, 0x0F,
-			comp_samp_params[rate].peak_det_timeout);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
-			w->shift * 8, 0xF0,
-			comp_samp_params[rate].rms_meter_div_fact);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B3_CTL +
-			w->shift * 8, 0xFF,
-			comp_samp_params[rate].rms_meter_resamp_fact);
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-			w->shift * 8, 0x38,
-			comp_samp_params[rate].shutdown_timeout);
+		/* Set sample rate dependent paramater */
+		if (w->shift == COMPANDER_1) {
+			snd_soc_update_bits(codec,
+					    TABLA_A_CDC_CLSG_CTL,
+					    0x11, 0x00);
+			snd_soc_write(codec,
+				      TABLA_A_CDC_CONN_CLSG_CTL, 0x11);
 		}
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0x0F,
+				    comp_samp_params[rate].peak_det_timeout);
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B2_CTL +
+				    w->shift * 8, 0xF0,
+				    comp_samp_params[rate].rms_meter_div_fact);
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B3_CTL +
+				w->shift * 8, 0xFF,
+				comp_samp_params[rate].rms_meter_resamp_fact);
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x38,
+				    comp_samp_params[rate].shutdown_timeout);
 		break;
 	case SND_SOC_DAPM_PRE_PMD:
-		if (tabla->comp_enabled[w->shift] != 0) {
-			status = snd_soc_read(codec,
-					TABLA_A_CDC_COMP1_SHUT_DOWN_STATUS +
-					w->shift * 8);
-			pr_debug("%s: compander #%d shutdown status %d in event %d\n",
-				 __func__, w->shift + 1, status, event);
-			/* Halt the compander*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 1 << 2, 1 << 2);
-		}
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (tabla->comp_enabled[w->shift] != 0) {
-			/* Wait up to a second for shutdown complete */
-			timeout = jiffies + HZ;
-			do {
-				status = snd_soc_read(codec,
-					TABLA_A_CDC_COMP1_SHUT_DOWN_STATUS +
-					w->shift * 8);
-				if (status == 0x3)
-					break;
-				usleep_range(5000, 5000);
-			} while (!(time_after(jiffies, timeout)));
-			/* Restore the gain */
-			tabla_config_gain_compander(codec, w->shift,
-						tabla->comp_enabled[w->shift],
-						event);
-			/* Disable the compander*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 0x03, 0x00);
-			/* Turn off the clock for compander in pair*/
-			snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_B2_CTL,
-					    0x03 << comp_shift[w->shift], 0);
-			/* Clear the HALT for the compander*/
+		/* Disable the compander */
+		snd_soc_update_bits(codec, TABLA_A_CDC_COMP1_B1_CTL +
+				    w->shift * 8, 0x03, 0x00);
+		/* Toggle compander reset bits */
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift],
+				    1 << comp_shift[w->shift]);
+		snd_soc_update_bits(codec,
+				    TABLA_A_CDC_CLK_OTHR_RESET_CTL,
+				    1 << comp_shift[w->shift], 0);
+		/* Turn off the clock for compander in pair */
+		snd_soc_update_bits(codec, TABLA_A_CDC_CLK_RX_B2_CTL,
+				    0x03 << comp_shift[w->shift], 0);
+		/* Restore the gain */
+		tabla_config_gain_compander(codec, w->shift,
+					    tabla->comp_enabled[w->shift],
+					    event);
+		if (w->shift == COMPANDER_1) {
 			snd_soc_update_bits(codec,
-					    TABLA_A_CDC_COMP1_B1_CTL +
-					    w->shift * 8, 1 << 2, 0);
+					    TABLA_A_CDC_CLSG_CTL,
+					    0x11, 0x11);
+			snd_soc_write(codec,
+				      TABLA_A_CDC_CONN_CLSG_CTL, 0x14);
 		}
 		break;
 	}
+rtn:
+	return 0;
+}
+
+static int tabla_codec_hphr_dem_input_selection(struct snd_soc_dapm_widget *w,
+						struct snd_kcontrol *kcontrol,
+						int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: compander#1->enable(%d) reg(0x%x = 0x%x) event(%d)\n",
+		__func__, tabla->comp_enabled[COMPANDER_1],
+		TABLA_A_CDC_RX1_B6_CTL,
+		snd_soc_read(codec, TABLA_A_CDC_RX1_B6_CTL), event);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (tabla->comp_enabled[COMPANDER_1] && !tabla->anc_func)
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+					    1 << w->shift, 0);
+		else
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+					    1 << w->shift, 1 << w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX1_B6_CTL,
+				    1 << w->shift, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int tabla_codec_hphl_dem_input_selection(struct snd_soc_dapm_widget *w,
+						struct snd_kcontrol *kcontrol,
+						int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct tabla_priv *tabla = snd_soc_codec_get_drvdata(codec);
+
+	pr_debug("%s: compander#1->enable(%d) reg(0x%x = 0x%x) event(%d)\n",
+		__func__, tabla->comp_enabled[COMPANDER_1],
+		TABLA_A_CDC_RX2_B6_CTL,
+		snd_soc_read(codec, TABLA_A_CDC_RX2_B6_CTL), event);
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		if (tabla->comp_enabled[COMPANDER_1] && !tabla->anc_func)
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+					    1 << w->shift, 0);
+		else
+			snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+					    1 << w->shift, 1 << w->shift);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, TABLA_A_CDC_RX2_B6_CTL,
+				    1 << w->shift, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
 	return 0;
 }
 
@@ -5361,8 +5476,12 @@
 		&rx6_dsm_mux, tabla_codec_reset_interpolator,
 		SND_SOC_DAPM_PRE_PMU),
 
-	SND_SOC_DAPM_MIXER("RX1 CHAIN", TABLA_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
-	SND_SOC_DAPM_MIXER("RX2 CHAIN", TABLA_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER_E("RX1 CHAIN", SND_SOC_NOPM, 5, 0, NULL,
+		0, tabla_codec_hphr_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+	SND_SOC_DAPM_MIXER_E("RX2 CHAIN", SND_SOC_NOPM, 5, 0, NULL,
+		0, tabla_codec_hphl_dem_input_selection,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
 
 	SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
 		&rx_mix1_inp1_mux),
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 778dc10..7acb294 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -2271,6 +2271,7 @@
 	struct snd_soc_card *card = &snd_soc_card_msm8974;
 	struct msm8974_asoc_mach_data *pdata;
 	int ret;
+	const char *auxpcm_pri_gpio_set = NULL;
 
 	if (!pdev->dev.of_node) {
 		dev_err(&pdev->dev, "No platform supplied from device tree\n");
@@ -2396,7 +2397,24 @@
 		goto err;
 	}
 
-	lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
+	ret = of_property_read_string(pdev->dev.of_node,
+			"qcom,prim-auxpcm-gpio-set", &auxpcm_pri_gpio_set);
+	if (ret) {
+		dev_err(&pdev->dev, "Looking up %s property in node %s failed",
+			"qcom,prim-auxpcm-gpio-set",
+			pdev->dev.of_node->full_name);
+		goto err;
+	}
+	if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-prim")) {
+		lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_PRI_MODE_MUXSEL, 4);
+	} else if (!strcmp(auxpcm_pri_gpio_set, "prim-gpio-tert")) {
+		lpaif_pri_muxsel_virt_addr = ioremap(LPAIF_TER_MODE_MUXSEL, 4);
+	} else {
+		dev_err(&pdev->dev, "Invalid value %s for AUXPCM GPIO set\n",
+			auxpcm_pri_gpio_set);
+		ret = -EINVAL;
+		goto err;
+	}
 	if (lpaif_pri_muxsel_virt_addr == NULL) {
 		pr_err("%s Pri muxsel virt addr is null\n", __func__);
 		ret = -EINVAL;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 80bc4f9..e9d0a7e 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -2963,6 +2963,7 @@
 	cvp_mute_cmd.hdr.opcode = VSS_IVOLUME_CMD_MUTE_V2;
 	cvp_mute_cmd.cvp_set_mute.direction = VSS_IVOLUME_DIRECTION_RX;
 	cvp_mute_cmd.cvp_set_mute.mute_flag = v->dev_rx.mute;
+	cvp_mute_cmd.cvp_set_mute.ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
 
 	v->cvp_state = CMD_STATUS_FAIL;
 	ret = apr_send_pkt(common.apr_q6_cvp, (uint32_t *) &cvp_mute_cmd);