Merge "usb: gadget: mbim: protect packets queue corruption"
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt b/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt
index ee9a286..d9ccb09 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-krait-8974.txt
@@ -41,6 +41,8 @@
 - qcom,hfpll-user-vco-mask:
 			The mask to be used when programming the VCO selection
 			bits in the user control register.
+- qcom,pvs-config-ver:
+			The version of the data in qcom,speedX-pvsY-bin-vZ.
 
 Example:
 	qcom,clock-krait@f9016000 {
diff --git a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
index 3a293a3..40abc5f 100644
--- a/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
+++ b/Documentation/devicetree/bindings/arm/msm/cpr-regulator.txt
@@ -11,7 +11,7 @@
 	bits to indicate what bin (and voltage range) a chip is in.
 
 Required properties:
-- compatible:			Must be "qti,cpr-regulator"
+- compatible:			Must be "qcom,cpr-regulator"
 - reg:				Register addresses for RBCPR, RBCPR clock
 				select, PVS and CPR eFuse address
 - reg-names:			Register names. Must be "rbcpr", "rbcpr_clk",
@@ -22,41 +22,41 @@
 				should be 1 for SVS corner
 - regulator-max-microvolt:	Maximum corner value as max constraint, which
 				should be 4 for SUPER_TURBO or 3 for TURBO
-- qti,pvs-init-voltage:  	A list of integers whose length is equal to 2
-				to the power of qti,pvs-fuse[num-of-bits]. The
+- qcom,pvs-init-voltage:  	A list of integers whose length is equal to 2
+				to the power of qcom,pvs-fuse[num-of-bits]. The
 				location or 0-based index of an element in the
 				list corresponds to the bin number. The value of
 				each integer corresponds to the initial voltage
 				of the PVS bin in turbo mode in microvolts.
-- qti,pvs-corner-ceiling-slow:	Ceiling voltages of all corners for APC_PVS_SLOW
-- qti,pvs-corner-ceiling-nom:	Ceiling voltages of all corners for APC_PVS_NOM
-- qti,pvs-corner-ceiling-fast:	Ceiling voltages of all corners for APC_PVS_FAST
+- qcom,pvs-corner-ceiling-slow:	Ceiling voltages of all corners for APC_PVS_SLOW
+- qcom,pvs-corner-ceiling-nom:	Ceiling voltages of all corners for APC_PVS_NOM
+- qcom,pvs-corner-ceiling-fast:	Ceiling voltages of all corners for APC_PVS_FAST
 				The ceiling voltages for each of above three
 				properties may look like this:
 				  0 (SVS voltage):		1050000 uV
 				  1 (NORMAL voltage):		1150000 uV
 				  2 (TURBO voltage):		1275000 uV
 - vdd-apc-supply:		Regulator to supply VDD APC power
-- qti,vdd-apc-step-up-limit:	Limit of vdd-apc-supply steps for scaling up.
-- qti,vdd-apc-step-down-limit:	Limit of vdd-apc-supply steps for scaling down.
-- qti,cpr-ref-clk:		The reference clock in kHz.
-- qti,cpr-timer-delay:		The delay in microseconds for the timer interval.
-- qti,cpr-timer-cons-up:	Consecutive number of timer interval (qti,cpr-timer-delay)
+- qcom,vdd-apc-step-up-limit:	Limit of vdd-apc-supply steps for scaling up.
+- qcom,vdd-apc-step-down-limit:	Limit of vdd-apc-supply steps for scaling down.
+- qcom,cpr-ref-clk:		The reference clock in kHz.
+- qcom,cpr-timer-delay:		The delay in microseconds for the timer interval.
+- qcom,cpr-timer-cons-up:	Consecutive number of timer interval (qcom,cpr-timer-delay)
 				occurred before issuing UP interrupt.
-- qti,cpr-timer-cons-down:	Consecutive number of timer interval (qti,cpr-timer-delay)
+- qcom,cpr-timer-cons-down:	Consecutive number of timer interval (qcom,cpr-timer-delay)
 				occurred before issuing DOWN interrupt.
-- qti,cpr-irq-line:		Internal interrupt route signal of RBCPR, one of 0, 1 or 2.
-- qti,cpr-step-quotient:	Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step
+- qcom,cpr-irq-line:		Internal interrupt route signal of RBCPR, one of 0, 1 or 2.
+- qcom,cpr-step-quotient:	Number of CPR quotient (Ring Oscillator(RO) count) per vdd-apc-supply step
 				to issue error_steps.
-- qti,cpr-up-threshold:	The threshold for CPR to issue interrupt when
+- qcom,cpr-up-threshold:	The threshold for CPR to issue interrupt when
 				error_steps is greater than it when stepping up.
-- qti,cpr-down-threshold:	The threshold for CPR to issue interrupt when
+- qcom,cpr-down-threshold:	The threshold for CPR to issue interrupt when
 				error_steps is greater than it when stepping down.
-- qti,cpr-idle-clocks:		Idle clock cycles RO can be in.
-- qti,cpr-gcnt-time:		The time for gate count in microseconds.
-- qti,cpr-apc-volt-step:	The voltage in microvolt per CPR step, such as 5000uV.
+- qcom,cpr-idle-clocks:		Idle clock cycles RO can be in.
+- qcom,cpr-gcnt-time:		The time for gate count in microseconds.
+- qcom,cpr-apc-volt-step:	The voltage in microvolt per CPR step, such as 5000uV.
 
-- qti,pvs-fuse-redun-sel:	Array of 5 elements to indicate where to read the bits, what value to
+- qcom,pvs-fuse-redun-sel:	Array of 5 elements to indicate where to read the bits, what value to
 				compare with in order to decide if the redundant PVS fuse bits would be
 				used instead of the original bits and method to read fuse row, reading
 				register through SCM or directly. The 5 elements with index [0..4] are:
@@ -70,19 +70,19 @@
 				Otherwise, the original PVS bits should be selected. If the 5th
 				element is 0, read the fuse row from register directly. Otherwise,
 				read it through SCM.
-- qti,pvs-fuse:			Array of 4 elements to indicate the bits for PVS fuse and read method.
+- qcom,pvs-fuse:			Array of 4 elements to indicate the bits for PVS fuse and read method.
 				The array should have index and value like this:
 				  [0] => the PVS fuse row number
 				  [1] => LSB bit position of the bits
 				  [2] => number of bits
 				  [3] => fuse reading method, 0 for direct reading or 1 for SCM reading
-- qti,pvs-fuse-redun:		Array of 4 elements to indicate the bits for redundant PVS fuse.
+- qcom,pvs-fuse-redun:		Array of 4 elements to indicate the bits for redundant PVS fuse.
 				The array should have index and value like this:
 				  [0] => the redundant PVS fuse row number
 				  [1] => LSB bit position of the bits
 				  [2] => number of bits
 				  [3] => fuse reading method, 0 for direct reading or 1 for SCM reading
-- qti,cpr-fuse-redun-sel:	Array of 5 elements to indicate where to read the bits, what value to
+- qcom,cpr-fuse-redun-sel:	Array of 5 elements to indicate where to read the bits, what value to
 				compare with in order to decide if the redundant CPR fuse bits would be
 				used instead of the original bits and method to read fuse row, using SCM
 				to read or read register directly. The 5 elements with index [0..4] are:
@@ -96,32 +96,32 @@
 				Otherwise, the original CPR bits should be selected. If the 5th element
 				is 0, read the fuse row from register directly. Otherwise, read it through
 				SCM.
-- qti,cpr-fuse-row:		Array of row number of CPR fuse and method to read that row. It should have
+- qcom,cpr-fuse-row:		Array of row number of CPR fuse and method to read that row. It should have
 				index and value like this:
 				 [0] => the fuse row number
 				 [1] => fuse reading method, 0 for direct reading or 1 for SCM reading
-- qti,cpr-fuse-bp-cpr-disable:	Bit position of the bit to indicate if CPR should be disable
-- qti,cpr-fuse-bp-scheme:	Bit position of the bit to indicate if it's a global/local scheme
-- qti,cpr-fuse-target-quot:	Array of bit positions in fuse for Target Quotient of all corners.
+- qcom,cpr-fuse-bp-cpr-disable:	Bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-bp-scheme:	Bit position of the bit to indicate if it's a global/local scheme
+- qcom,cpr-fuse-target-quot:	Array of bit positions in fuse for Target Quotient of all corners.
 				It should have index and value like this:
 				  [0] => bit position of the LSB bit for SVS target quotient
 				  [1] => bit position of the LSB bit for NOMINAL target quotient
 				  [2] => bit position of the LSB bit for TURBO target quotient
-- qti,cpr-fuse-ro-sel:		Array of bit positions in fuse for RO select of all corners.
+- qcom,cpr-fuse-ro-sel:		Array of bit positions in fuse for RO select of all corners.
 				It should have index and value like this:
 				  [0] => bit position of the LSB bit for SVS RO select bits
 				  [1] => bit position of the LSB bit for NOMINAL RO select bits
 				  [2] => bit position of the LSB bit for TURBO RO select bits
-- qti,cpr-fuse-redun-row:	Array of row number of redundant CPR fuse and method to read that
+- qcom,cpr-fuse-redun-row:	Array of row number of redundant CPR fuse and method to read that
 				row. It should have index and value like this:
 				 [0] => the redundant fuse row number
 				 [1] => the value to indicate reading the fuse row directly or using SCM
-- qti,cpr-fuse-redun-target-quot:	Array of bit positions in fuse for redundant Target Quotient of all corners.
+- qcom,cpr-fuse-redun-target-quot:	Array of bit positions in fuse for redundant Target Quotient of all corners.
 				It should have index and value like this:
 				  [0] => bit position of the LSB bit for redundant SVS target quotient
 				  [1] => bit position of the LSB bit for redundant NOMINAL target quotient
 				  [2] => bit position of the LSB bit for redundant TURBO target quotient
-- qti,cpr-fuse-redun-ro-sel:	Array of bit positions in eFuse for redundant RO select.
+- qcom,cpr-fuse-redun-ro-sel:	Array of bit positions in eFuse for redundant RO select.
 				It should have index and value like this:
 				  [0] => bit position of the LSB bit for redundant SVS RO select bits
 				  [1] => bit position of the LSB bit for redundant NOMINAL RO select bits
@@ -131,23 +131,23 @@
 Optional properties:
 - vdd-mx-supply:		Regulator to supply memory power as dependency
 				of VDD APC.
-- qti,vdd-mx-vmax:		The maximum voltage in uV for vdd-mx-supply. This
+- qcom,vdd-mx-vmax:		The maximum voltage in uV for vdd-mx-supply. This
 				is required when vdd-mx-supply is present.
-- qti,vdd-mx-vmin-method:	The method to determine the minimum voltage for
+- qcom,vdd-mx-vmin-method:	The method to determine the minimum voltage for
 				vdd-mx-supply, which can be one of following
 				choices compared with VDD APC:
 				  0 => equal to the voltage(vmin) of VDD APC
 				  1 => equal to PVS corner ceiling voltage
 				  2 => equal to slow speed corner ceiling
-				  3 => equal to qti,vdd-mx-vmax
+				  3 => equal to qcom,vdd-mx-vmax
 				This is required when vdd-mx-supply is present.
-- qti,cpr-fuse-redun-bp-cpr-disable:	Redundant bit position of the bit to indicate if CPR should be disable
-- qti,cpr-fuse-redun-bp-scheme:	Redundant bit position of the bit to indicate if it's a global/local scheme
+- qcom,cpr-fuse-redun-bp-cpr-disable:	Redundant bit position of the bit to indicate if CPR should be disable
+- qcom,cpr-fuse-redun-bp-scheme:	Redundant bit position of the bit to indicate if it's a global/local scheme
 					This property is required if cpr-fuse-redun-bp-cpr-disable
 					is present, and vise versa.
-- qti,cpr-enable:		Present: CPR enabled by default.
+- qcom,cpr-enable:		Present: CPR enabled by default.
 				Not Present: CPR disable by default.
-- qti,cpr-fuse-cond-min-volt-sel:	Array of 5 elements to indicate where to read the bits,  what value to
+- qcom,cpr-fuse-cond-min-volt-sel:	Array of 5 elements to indicate where to read the bits,  what value to
 				compare with in order to decide if the conditional minimum apc voltage needs
 				to be applied and the fuse reading method.
 				The 5 elements with index[0..4] are:
@@ -159,11 +159,11 @@
 				When the value of the fuse bits specified by first 3 elements is not equal to
 				the value in 4th element, then set the apc voltage for all parts running
 				at each voltage corner to be not lower than the voltage defined
-				using "qti,cpr-cond-min-voltage".
-- qti,cpr-cond-min-voltage:	Minimum voltage in microvolts for SVS, NOM and TURBO mode if the fuse bits
-				defined in qti,cpr-fuse-cond-min-volt-sel have not been programmed with the
+				using "qcom,cpr-cond-min-voltage".
+- qcom,cpr-cond-min-voltage:	Minimum voltage in microvolts for SVS, NOM and TURBO mode if the fuse bits
+				defined in qcom,cpr-fuse-cond-min-volt-sel have not been programmed with the
 				expected data. This is required if cpr-fuse-cond-min-volt-sel is present.
-- qti,cpr-fuse-uplift-sel: 	Array of 5 elements to indicate where to read the bits, what value to
+- qcom,cpr-fuse-uplift-sel: 	Array of 5 elements to indicate where to read the bits, what value to
 				compare with in order to enable or disable the pvs voltage uplift workaround,
 				and the fuse reading method.
 				The 5 elements with index[0..4] are:
@@ -175,7 +175,7 @@
 				[4]: => fuse reading method, 0 for direct reading or 1 for SCM reading.
 				When the value of the fuse bits specified by first 3 elements equals to the
 				value in 4th element, the pvs voltage uplift workaround will be enabled.
-- qti,speed-bin-fuse-sel:	Array of 4 elements to indicate where to read the speed bin of the processor,
+- qcom,speed-bin-fuse-sel:	Array of 4 elements to indicate where to read the speed bin of the processor,
 				and the fuse reading method.
 				The 4 elements with index[0..3] are:
 				[0]: => the fuse row number of the selector;
@@ -183,22 +183,22 @@
 				[2]: => number of the bits;
 				[3]: => fuse reading method, 0 for direct reading or 1 for SCM reading.
 				This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-uplift-voltage:	Uplift in microvolts used for increasing pvs init voltage. If this property is present,
+- qcom,cpr-uplift-voltage:	Uplift in microvolts used for increasing pvs init voltage. If this property is present,
 				This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-uplift-max-volt:	Maximum voltage in microvolts used for pvs voltage uplift workaround to limit
+- qcom,cpr-uplift-max-volt:	Maximum voltage in microvolts used for pvs voltage uplift workaround to limit
 				the maximum pvs voltage.
 				This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-uplift-quotient:	Three numbers used for pvs voltage uplift workaround to be added to the target
+- qcom,cpr-uplift-quotient:	Three numbers used for pvs voltage uplift workaround to be added to the target
 				quotient for each corner.
 				The 3 quotient increment with index[0..2] are:
 				[0]: => for SVS corner target quotient;
 				[1]: => for NORM corner target quotient;
 				[2]: => for TURBO corner target quotient;
 				This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-uplift-speed-bin:	The speed bin value corresponding to one type of processor which needs to apply the
+- qcom,cpr-uplift-speed-bin:	The speed bin value corresponding to one type of processor which needs to apply the
 				pvs voltage uplift workaround.
 				This is required if cpr-fuse-uplift-disable-sel is present.
-- qti,cpr-quot-adjust-table:	Array of triples in which each triple indicates the speed bin of the CPU, the virtual
+- qcom,cpr-quot-adjust-table:	Array of triples in which each triple indicates the speed bin of the CPU, the virtual
 				corner to use and the quotient adjustment.
 				The 3 elements in one triple are:
 				[0]: => the speed bin of the CPU.
@@ -207,17 +207,29 @@
 				If the speed bin in a triple is equal to the speed bin of the CPU, the adjustment would
 				be subtracted from the quotient value of the voltage corner when the CPU is running at
 				that virtual corner. Each virtual corner value must be in the range 1 to the number of
-				elements in qti,cpr-corner-map.
-- qti,cpr-corner-map:		Array of elements of fuse corner value for each virtual corner.
+				elements in qcom,cpr-corner-map.
+- qcom,cpr-corner-map:		Array of elements of fuse corner value for each virtual corner.
 				The location or 1-based index of an element in the list corresponds to
 				the virtual corner value. For example, the first element in the list is the fuse corner
 				value that virtual corner 1 maps to.
-				This is required if qti,cpr-quot-adjust-table is present.
+				This is required if qcom,cpr-quot-adjust-table is present.
+- qcom,cpr-quotient-adjustment:	Array of three elements of CPR quotient adjustments for each corner.
+				The 3 quotient adjustments with index[0..2] are:
+				[0] => amount to add to the SVS quotient
+				[1] => amount to add to the NORM quotient
+				[2] => amount to add to the TURBO quotient
+				If this property is specified, then the quotient adjustment values are added to the target
+				quotient values read from fuses before writing them into the CPR GCNT target control registers.
+				This property can be used to add static margin to the voltage rail managed by the CPR controller.
+- vdd-apc-optional-prim-supply:	Present: Regulator of highest priority to supply VDD APC power
+				Not Present: No such regulator.
+- vdd-apc-optional-sec-supply:	Present: Regulator of second highest priority to supply VDD APC power.
+				Not Present: No such regulator.
 
 Example:
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
-		compatible = "qti,cpr-regulator";
+		compatible = "qcom,cpr-regulator";
 		reg = <0xf9018000 0x1000>, <0xfc4b8000 0x1000>;
 		reg-names = "rbcpr", "efuse_addr";
 		interrupts = <0 15 0>;
@@ -225,11 +237,11 @@
 		regulator-min-microvolt = <1>;
 		regulator-max-microvolt = <3>;
 
-		qti,pvs-fuse = <22 6 5 1>;
-		qti,pvs-fuse-redun-sel = <22 24 3 2 1>;
-		qti,pvs-fuse-redun = <22 27 5 1>;
+		qcom,pvs-fuse = <22 6 5 1>;
+		qcom,pvs-fuse-redun-sel = <22 24 3 2 1>;
+		qcom,pvs-fuse-redun = <22 27 5 1>;
 
-		qti,pvs-init-voltage = <1330000 1330000 1330000 1320000
+		qcom,pvs-init-voltage = <1330000 1330000 1330000 1320000
 						1310000 1300000 1290000 1280000
 						1270000 1260000 1250000 1240000
 						1230000 1220000 1210000 1200000
@@ -237,46 +249,48 @@
 						1150000 1140000 1140000 1140000
 						1140000 1140000 1140000 1140000
 						1140000 1140000 1140000 1140000>;
-		qti,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
-		qti,pvs-corner-ceiling-nom  =  <975000 1075000 1200000>;
-		qti,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
+		qcom,pvs-corner-ceiling-slow = <1050000 1160000 1275000>;
+		qcom,pvs-corner-ceiling-nom  =  <975000 1075000 1200000>;
+		qcom,pvs-corner-ceiling-fast =  <900000 1000000 1140000>;
 		vdd-apc-supply = <&pm8226_s2>;
+		vdd-apc-optional-prim-supply = <&ncp6335d>;
+		vdd-apc-optional-sec-supply = <&fan53555>;
 		vdd-mx-supply = <&pm8226_l3_ao>;
-		qti,vdd-mx-vmax = <1350000>;
-		qti,vdd-mx-vmin-method = <1>;
-		qti,vdd-apc-step-up-limit = <1>;
-		qti,vdd-apc-step-down-limit = <1>;
-		qti,cpr-ref-clk = <19200>;
-		qti,cpr-timer-delay = <5000>;
-		qti,cpr-timer-cons-up = <1>;
-		qti,cpr-timer-cons-down = <2>;
-		qti,cpr-irq-line = <0>;
-		qti,cpr-step-quotient = <15>;
-		qti,cpr-up-threshold = <1>;
-		qti,cpr-down-threshold = <2>;
-		qti,cpr-idle-clocks = <5>;
-		qti,cpr-gcnt-time = <1>;
-		qti,cpr-apc-volt-step = <5000>;
+		qcom,vdd-mx-vmax = <1350000>;
+		qcom,vdd-mx-vmin-method = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <1>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <15>;
+		qcom,cpr-up-threshold = <1>;
+		qcom,cpr-down-threshold = <2>;
+		qcom,cpr-idle-clocks = <5>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,cpr-apc-volt-step = <5000>;
 
-		qti,cpr-fuse-row = <138 1>;
-		qti,cpr-fuse-bp-cpr-disable = <36>;
-		qti,cpr-fuse-bp-scheme = <37>;
-		qti,cpr-fuse-target-quot = <24 12 0>;
-		qti,cpr-fuse-ro-sel = <54 38 41>;
-		qti,cpr-fuse-redun-sel = <138 57 1 1 1>;
-		qti,cpr-fuse-redun-row = <139 1>;
-		qti,cpr-fuse-redun-target-quot = <24 12 0>;
-		qti,cpr-fuse-redun-ro-sel = <46 36 39>;
-		qti,cpr-fuse-cond-min-volt-sel = <54 42 6 7 1>;
-		qti,cpr-cond-min-voltage = <1140000>;
-		qti,cpr-fuse-uplift-sel = <22 53 1 0 0>;
-		qti,cpr-uplift-voltage = <50000>;
-		qti,cpr-uplift-quotient = <0 0 120>;
-		qti,cpr-uplift-max-volt = <1350000>;
-		qti,cpr-uplift-speed-bin = <1>;
-		qti,speed-bin-fuse-sel = <22 0 3 0>;
-		qti,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
-		qti,cpr-quot-adjust-table = <1 1 0>, <1 2 0>, <1 3 0>,
+		qcom,cpr-fuse-row = <138 1>;
+		qcom,cpr-fuse-bp-cpr-disable = <36>;
+		qcom,cpr-fuse-bp-scheme = <37>;
+		qcom,cpr-fuse-target-quot = <24 12 0>;
+		qcom,cpr-fuse-ro-sel = <54 38 41>;
+		qcom,cpr-fuse-redun-sel = <138 57 1 1 1>;
+		qcom,cpr-fuse-redun-row = <139 1>;
+		qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+		qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
+		qcom,cpr-fuse-cond-min-volt-sel = <54 42 6 7 1>;
+		qcom,cpr-cond-min-voltage = <1140000>;
+		qcom,cpr-fuse-uplift-sel = <22 53 1 0 0>;
+		qcom,cpr-uplift-voltage = <50000>;
+		qcom,cpr-uplift-quotient = <0 0 120>;
+		qcom,cpr-uplift-max-volt = <1350000>;
+		qcom,cpr-uplift-speed-bin = <1>;
+		qcom,speed-bin-fuse-sel = <22 0 3 0>;
+		qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
+		qcom,cpr-quot-adjust-table = <1 1 0>, <1 2 0>, <1 3 0>,
 						<1 4 0>, <1 5 450>, <1 6 375>,
 						<1 7 300>, <1 8 225>, <1 9 187>,
 						<1 10 150>, <1 11 75>, <1 12 0>;
diff --git a/Documentation/devicetree/bindings/arm/msm/cpubw.txt b/Documentation/devicetree/bindings/arm/msm/cpubw.txt
new file mode 100644
index 0000000..1dc3835
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/cpubw.txt
@@ -0,0 +1,30 @@
+MSM CPU bandwidth device
+
+cpubw is a device that represents the CPU subsystem master ports in a MSM SoC
+and the related info that is needed to make CPU to DDR bandwidth votes.
+
+Required properties:
+- compatible:		Must be "qcom,cpubw"
+- qcom,cpu-mem-ports:	A list of tuples where each tuple consists of a bus
+			master (CPU subsystem) port number and a bus slave
+			(memory) port number.
+- qcom,bw-tbl:		A list of meaningful instantaneous bandwidth values
+			(in MB/s) that can be requested from the CPU
+			subsystem to DDR. The list of values depend on the
+			supported DDR frequencies and the bus widths.
+
+Example:
+
+	qcom,cpubw {
+		compatible = "qcom,cpubw";
+		qcom,cpu-mem-ports = <1 512>, <2 512>;
+		qcom,bw-tbl =
+			<  572 /*  75 MHz */ >,
+			< 1144 /* 150 MHz */ >,
+			< 1525 /* 200 MHz */ >,
+			< 2342 /* 307 MHz */ >,
+			< 3509 /* 460 MHz */ >,
+			< 4684 /* 614 MHz */ >,
+			< 6103 /* 800 MHz */ >,
+			< 7102 /* 931 MHz */ >;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/kraitbw-l2pm.txt b/Documentation/devicetree/bindings/arm/msm/kraitbw-l2pm.txt
new file mode 100644
index 0000000..17d55d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/kraitbw-l2pm.txt
@@ -0,0 +1,18 @@
+MSM Krait L2 performance monitor counters for bandwidth measurement device
+
+krait-l2pm is a device that represents the Krait L2 PM counters that can be
+used to measure the bandwidth of read/write traffic from the Krait CPU
+subsystem.
+
+Required properties:
+- compatible:		Must be "qcom,kraitbw_l2pm"
+- interrupts:		Lists the L2 PM counter overflow IRQ.
+- qcom,bytes-per-beat:	The number of bytes transferred in one data beat from
+			the Krait CPU subsystem.
+
+Example:
+	qcom,kraitbw-l2pm {
+		compatible = "qcom,kraitbw-l2pm";
+		interrupts = <0 1 1>;
+		qcom,bytes-per-beat = <8>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm-cpufreq.txt b/Documentation/devicetree/bindings/arm/msm/msm-cpufreq.txt
index 02514d4..fed49c9 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm-cpufreq.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm-cpufreq.txt
@@ -9,23 +9,15 @@
 - compatible:		Must be "qcom,msm-cpufreq"
 - qcom,cpufreq-table:	A list of tuples where each tuple consists of a
 			usable CPU frequency (KHz), an optional cache
-			frequency (KHz) and an optional memory bandwidth
+			frequency (KHz) and a mandatory memory bandwidth
 			value (MBPS) listed in that order.  The cache
 			frequencies shall not be listed if the device cannot
-			run the cache asynchronous to one or more CPUs. The
-			memory bandwidth values shall not be listed if the
-			optional cpu-mem-ports property is not supplied.
-
-Optional properties:
-- qcom,cpu-mem-ports:	A list of tuples where each tuple consists of a bus
-			master (CPU) port number and a bus slave (memory)
-			port number.
+			run the cache asynchronous to one or more CPUs.
 
 Example:
 	qcom,msm-cpufreq@0 {
 		regs = <0 4>
 		compatible = "qcom,msm-cpufreq";
-		qcom,cpu-mem-ports = <1 512>, <2 513>;
 		qcom,cpufreq-table =
 			<  300000  300000  600 >,
 			<  422400  422400 1200 >,
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
index 6283a82..9f74225 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_bus.txt
@@ -20,10 +20,12 @@
 these features:
 
 qcom,ntieredslaves:	Number of tiered slaves on the bus.
-qcom,qos-freq:		QoS frequency (In Hz)
+qcom,qos-freq:		QoS frequency (In KHz)
 qcom,hw-sel:		A string which decides whether QoS data
 			should be sent to RPM, set using BIMC or NoCs.
 			It can be set to "RPM", "NoC" or "BIMC".
+qcom,qos-baseoffset:	Base address offset of QoS registers from the bus device
+			base address.
 qcom,rpm-en:		A boolean flag indicating whether RPM transactions are
 			supported for nodes of the bus.
 qcom,ahb:		A boolean flag indicating whether the bus is ahb type.
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
index 3d70a9b..2b25fcb 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-regulator-smd.txt
@@ -32,6 +32,10 @@
 - qcom,enable-time:    Time in us to delay after enabling the regulator
 - qcom,hpm-min-load:   Load current in uA which corresponds to the minimum load
 			which requires the regulator to be in high power mode.
+- qcom,apps-only:      Flag which indicates that the regulator only has
+			consumers on the application processor. If this flag
+			is specified, then voltage and current updates are
+			only sent to the RPM if the regulator is enabled.
 
 [Second Level Nodes]
 
@@ -84,6 +88,7 @@
 				current updates are only sent if the given
 				regulator has also been enabled by a Linux
 				consumer.
+
 The following properties specify initial values for parameters to be sent to the
 RPM in regulator requests.
 - qcom,init-enable:            0 = regulator disabled
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
index 01cc798..1bb4659 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcrypto.txt
@@ -16,6 +16,13 @@
 Optional properties:
   - qcom,ce-hw-shared : optional, indicates if the hardware is shared between EE.
   - qcom,ce-hw-key : optional, indicates if the hardware supports use of HW KEY.
+  - qcom,use-sw-aes-cbc-ecb-ctr-algo : optional, indicates if use SW aes-cbc/ecb/ctr algorithm.
+  - qcom,use-sw-aes-xts-algo : optional, indicates if use SW aes-xts algorithm.
+  - qcom,use-sw-aead-algo : optional, indicates if use SW aead algorithm.
+  - qcom,use-sw-ahash-algo : optional, indicates if use SW hash algorithm.
+  - qcom,use-sw-hmac-algo : optional, indicates if use SW hmac algorithm.
+  - qcom,use-sw-aes-ccm-algo : optional, indicates if use SW aes-ccm algorithm.
+  - qcom,clk-mgmt-sus-res : optional, indicate if the ce clocks need to be disabled/enabled in suspend/resume function.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 113ded8..d689d70 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -126,6 +126,9 @@
 						implemented during suspend/resume.
 					"dfps_immediate_clk_mode" = FPS change request is
 						implemented immediately using DSI clocks.
+					"dfps_immediate_porch_mode" = FPS change request is
+						implemented immediately by changing panel porch
+						values.
 - qcom,mdss-dsi-bl-pmic-control-type:	A string that specifies the implementation of backlight
 					control for this panel.
 					"bl_ctrl_pwm" = Backlight controlled by PWM gpio.
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 9530c62..c2b963f 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -23,6 +23,10 @@
 				previous property, the amount of fetch ids
 				defined should match the number of offsets
 				defined in property: qcom,mdss-pipe-vig-off
+- qcom,mdss-pipe-vig-xin-id:	Array of VBIF clients ids (xins) corresponding
+				to the respective VIG pipes. Number of xin ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-vig-off
 - qcom,mdss-pipe-rgb-off:	Array of offsets for MDP source surface pipes of
 				type RGB, the offsets are calculated from
 				register "mdp_phys" defined in reg property.
@@ -34,6 +38,10 @@
 				previous property, the amount of fetch ids
 				defined should match the number of offsets
 				defined in property: qcom,mdss-pipe-rgb-off
+- qcom,mdss-pipe-rgb-xin-id:	Array of VBIF clients ids (xins) corresponding
+				to the respective RGB pipes. Number of xin ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-rgb-off
 - qcom,mdss-pipe-dma-off:	Array of offsets for MDP source surface pipes of
 				type DMA, the offsets are calculated from
 				register "mdp_phys" defined in reg property.
@@ -45,6 +53,10 @@
 				previous property, the amount of fetch ids
 				defined should match the number of offsets
 				defined in property: qcom,mdss-pipe-dma-off
+- qcom,mdss-pipe-dma-xin-id:	Array of VBIF clients ids (xins) corresponding
+				to the respective DMA pipes. Number of xin ids
+				defined should match the number of offsets
+				defined in property: qcom,mdss-pipe-dma-off
 - qcom,mdss-smp-data:		Array of shared memory pool data. There should
 				be only two values in this property. The first
 				value corresponds to the number of smp blocks
@@ -105,6 +117,79 @@
 				- "edp"
 				- "hdmi"
 
+Bus Scaling Data:
+- qcom,msm-bus,name:		String property describing MDSS client.
+- qcom,msm-bus,num-cases:	This is the the number of Bus Scaling use cases
+				defined in the vectors property. This must be
+				set to <3> for MDSS driver where use-case 0 is
+				used to take off MDSS BW votes from the system.
+				And use-case 1 & 2 are used in ping-pong fashion
+				to generate run-time BW requests.
+- qcom,msm-bus,active-only:	A boolean flag indicating if it is active only.
+- qcom,msm-bus,num-paths:	This represents the number of paths in each
+				Bus Scaling Usecase. This value depends on
+				how many number of AXI master ports are
+				dedicated to MDSS for particular chipset.
+- qcom,msm-bus,vectors-KBps:	* A series of 4 cell properties, with a format
+				of (src, dst, ab, ib) which is defined at
+				Documentation/devicetree/bindings/arm/msm/msm_bus.txt
+				* Current values of src & dst are defined at
+				arch/arm/mach-msm/msm_bus_board.h
+				src values allowed for MDSS are:
+					22 = MSM_BUS_MASTER_MDP_PORT0
+					23 = MSM_BUS_MASTER_MDP_PORT1
+				dst values allowed for MDSS are:
+					512 = MSM_BUS_SLAVE_EBI_CH0
+				ab: Represents aggregated bandwidth.
+				ib: Represents instantaneous bandwidth.
+				* Total number of 4 cell properties will be
+				(number of use-cases * number of paths).
+				* These values will be overridden by the driver
+				based on the run-time requirements. So initial
+				ab and ib values defined here are random and
+				bare no logic except for the use-case 0 where ab
+				and ib values needs to be 0.
+
+- qcom,mdss-prefill-outstanding-buffer-bytes: The size of mdp outstanding buffer
+				in bytes. The buffer is filled during prefill
+				time and the buffer size shall be included in
+				prefill bandwidth calculation.
+- qcom,mdss-prefill-y-buffer-bytes: The size of mdp y plane buffer in bytes. The
+				buffer is filled during prefill time when format
+				is YUV and the buffer size shall be included in
+				prefill bandwidth calculation.
+- qcom,mdss-prefill-scaler-buffer-lines-bilinear: The value indicates how many lines
+				of scaler line buffer need to be filled during
+				prefill time. If bilinear scalar is enabled, then this
+				number of lines is used to determine how many bytes
+				of scaler buffer to be included in prefill bandwidth
+				calculation.
+- qcom,mdss-prefill-scaler-buffer-lines-caf: The value indicates how many lines of
+				of scaler line buffer need to be filled during
+				prefill time. If CAF mode filter is enabled, then
+				this number of lines is used to determine how many
+				bytes of scaler buffer to be included in prefill
+				bandwidth calculation.
+- qcom,mdss-prefill-post-scaler-buffer: The size of post scaler buffer in bytes.
+				The buffer is used to smooth the output of the
+				scaler. If the buffer is present in h/w, it is
+				filled during prefill time and the number of bytes
+				shall be included in prefill bandwidth calculation.
+- qcom,mdss-prefill-pingpong-buffer-pixels: The size of pingpong buffer in pixels.
+				The buffer is used to keep pixels flowing to the
+				panel interface. If the vertical start position of a
+				layer is in the beginning of the active area, pingpong
+				buffer must be filled during prefill time to generate
+				starting lines. The number of bytes to be filled is
+				determined by the line width, starting position,
+				byte per pixel and scaling ratio, this number shall be
+				included in prefill bandwidth calculation.
+- qcom,mdss-prefill-fbc-lines:  The value indicates how many lines are required to fill
+				fbc buffer during prefill time if FBC (Frame Buffer
+				Compressor) is enabled. The number of bytes to be filled
+				is determined by the line width, bytes per pixel and
+				scaling ratio, this number shall be included in prefill bandwidth
+				calculation.
 Optional properties:
 - vdd-cx-supply :	Phandle for vdd CX regulator device node.
 - batfet-supply :	Phandle for battery FET regulator device node.
@@ -158,6 +243,33 @@
 				applied in scenarios where panel interface can
 				be more tolerant to memory latency such as
 				command mode panels.
+- qcom,mdss-rotator-ot-limit:	This integer value indicates maximum number of pending
+				writes that can be allowed from rotator client. Default
+				value is 16 which is the maximum. This value can be
+				used to reduce the pending writes limit dynamically
+				and can be tuned to match performance requirements
+				depending upon system state.
+
+Fudge Factors:			Fudge factors are used to boost demand for
+				resources like bus bandswidth, clk rate etc. to
+				overcome system inefficiencies and avoid any
+				glitches. These fudge factors are expressed in
+				terms of numerator and denominator. First value
+				is numerator followed by denominator. They all
+				are optional but highly recommended.
+				Ex:
+				x = value to be fudged
+				a = numerator, default value is 1
+				b = denominator, default value is 1
+				FUDGE(x, a, b) = ((x * a) / b)
+- qcom,mdss-ib-factor:		This fudge factor is applied to calculated ib
+				values in default conditions.
+- qcom,mdss-clk-factor:		This fudge factor is applied to calculated mdp
+				clk rate in default conditions.
+- qcom,mdss-highest-bank-bit: Property to indicate tile format as opposed to usual
+				linear format. The value tells the GPU highest memory
+				 bank bit used.
+
 Optional subnodes:
 Child nodes representing the frame buffer virtual devices.
 
@@ -186,6 +298,12 @@
 			 This property is required whenever the continuous splash
 			 screen feature is enabled for the corresponding
 			 framebuffer device.
+- qcom,mdss-fb-splash-logo-enabled:    The boolean entry enables the framebuffer
+					driver to display the splash logo image.
+					It is independent of continuous splash
+					screen feature and has no relation with
+					qcom,cont-splash-enabled entry present in
+					panel configuration.
 
 Example:
 	mdss_mdp: qcom,mdss_mdp@fd900000 {
@@ -201,6 +319,20 @@
 		qcom,max-bandwidth-low-kbps = <2300000>;
 		qcom,max-bandwidth-high-kbps = <3000000>;
 
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "mdss_mdp";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>, <23 512 0 0>,
+			<22 512 0 6400000>, <23 512 0 6400000>,
+			<22 512 0 6400000>, <23 512 0 6400000>;
+
+		/* Fudge factors */
+		qcom,mdss-ab-factor = <2 1>;		/* 2 times    */
+		qcom,mdss-ib-factor = <3 2>;		/* 1.5 times  */
+		qcom,mdss-clk-factor = <5 4>;		/* 1.25 times */
+
 		qcom,max-clk-rate = <320000000>;
 		qcom,vbif-settings = <0x0004 0x00000001>,
 				     <0x00D8 0x00000707>;
@@ -218,8 +350,14 @@
 						<2 2 3>,
 						<2 4 5>,
 						<2 6 7>;
+
+		qcom,mdss-pipe-vig-xin-id = <0 4 8>;
+		qcom,mdss-pipe-rgb-xin-id = <1 5 9>;
+		qcom,mdss-pipe-dma-xin-id = <2 10>;
+
 		qcom,mdss-smp-data = <22 4096>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-rotator-ot-limit = <2>;
 		qcom,mdss-smp-mb-per-pipe = <2>;
 		qcom,mdss-pref-prim-intf = "dsi";
 		qcom,mdss-has-bwc;
@@ -238,11 +376,21 @@
 		qcom,mdss-intf-off = <0x00021100 0x00021300
 					   0x00021500 0x00021700>;
 
+		/* buffer parameters to calculate prefill bandwidth */
+		qcom,mdss-prefill-outstanding-buffer-bytes = <1024>;
+		qcom,mdss-prefill-y-buffer-bytes = <4096>;
+		qcom,mdss-prefill-scaler-buffer-lines-bilinear = <2>;
+		qcom,mdss-prefill-scaler-buffer-lines-caf = <4>;
+		qcom,mdss-prefill-post-scaler-buffer-pixels = <2048>;
+		qcom,mdss-prefill-pingpong-buffer-pixels = <5120>;
+		qcom,mdss-prefill-fbc-lines = <2>;
+
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
 			qcom,mdss-mixer-swap;
 			qcom,mdss-fb-split = <480 240>
+			qcom,mdss-fb-splash-logo-enabled:
 		};
 	};
 
diff --git a/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt b/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt
index 8579ec0..b4bfb92 100644
--- a/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt
+++ b/Documentation/devicetree/bindings/fb/msm-hdmi-tx.txt
@@ -28,6 +28,7 @@
 - qcom,hdmi-tx-mux-sel: gpio required to toggle HDMI output between
   docking station, type A, and liquid device, type D, ports. Required
   property for liquid devices.
+- qcom,hdmi-tx-ddc-mux-sel: gpio for ddc mux select.
 - qcom,hdmi-tx-mux-en: gpio required to enable mux for HDMI output
   on liquid devices. Required property for liquid devices.
 
@@ -57,6 +58,7 @@
 		qcom,hdmi-tx-max-voltage-level = <0 0 1800000 1800000>;
 		qcom,hdmi-tx-peak-current = <0 0 1800000 0>;
 
+		qcom,hdmi-tx-ddc-mux-sel = <&pma8084_gpios 6 0>;
 		qcom,hdmi-tx-cec = <&msmgpio 31 0>;
 		qcom,hdmi-tx-ddc-clk = <&msmgpio 32 0>;
 		qcom,hdmi-tx-ddc-data = <&msmgpio 33 0>;
diff --git a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
index ae7d039..dd0c440 100644
--- a/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
+++ b/Documentation/devicetree/bindings/hwmon/qpnp-adc-voltage.txt
@@ -49,6 +49,7 @@
 				 2 : {1, 4}
 				 3 : {1, 6}
 				 4 : {1, 20}
+				 5 : {1, 8}
 - qcom,calibration-type : Reference voltage to use for channel calibration.
 			  Channel calibration is dependendent on the channel.
 			  Certain channels like XO_THERM, BATT_THERM use ratiometric
@@ -65,6 +66,8 @@
 			3 : Returns current across 0.1 ohm resistor.
 			4 : Returns XO thermistor voltage in degree's Centigrade.
 			5 : Returns result in degC for 150k pull-up.
+			9 : Conversion to temperature based on -15~55 allowable
+			    battery charging tempeature setting for btm parameters.
 - qcom,hw-settle-time : Settling period for the channel before ADC read.
 			Select from the following unsigned int.
 			0 : 0us
diff --git a/Documentation/devicetree/bindings/i2c/i2c-qup.txt b/Documentation/devicetree/bindings/i2c/i2c-qup.txt
index fd7b635..fd96908 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-qup.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-qup.txt
@@ -36,6 +36,10 @@
 		      callbacks.
  - qcom,master-id    : Master endpoint number used for voting on clocks using
 		      bus-scaling driver.
+ - qcom,clk-ctl-xfer : When present, the clocks's state (prepare_enable/
+		      unprepare_disable) is controlled by i2c-transaction's
+		      begining and ending. When missing, the clock's state
+		      is controlled by runtime-pm events.
 
 Example:
 	i2c_3: i2c@f9966000 {
@@ -47,6 +51,7 @@
 		interrupt-names = "qup_err_intr";
 		qcom,i2c-bus-freq = <100000>;
 		qcom,i2c-src-freq = <24000000>;
+		qcom,clk-ctl-xfer;
 		qcom,scl-gpio = <&msmgpio 7 0>;
 		qcom,sda-gpio = <&msmgpio 6 0>;
 	};
diff --git a/Documentation/devicetree/bindings/input/misc/hbtp_input.txt b/Documentation/devicetree/bindings/input/misc/hbtp_input.txt
new file mode 100644
index 0000000..54643c7
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/misc/hbtp_input.txt
@@ -0,0 +1,14 @@
+Platform device for Host Based Touch Processing (hbtp)
+
+Required properties:
+
+ - compatible		: should be "qcom,hbtp"
+ - vcc_ana-supply	: Analog power supply needed to power device
+
+Example:
+	&soc {
+		hbtp {
+			compatible = "qcom,hbtp";
+			vcc_ana-supply = <&pm8941_l18>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
index 854939c..7e5d3a4 100644
--- a/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
+++ b/Documentation/devicetree/bindings/input/misc/mma8x5x.txt
@@ -22,6 +22,7 @@
  - interrupt-parent	: parent of interrupt.
  - interrupts		: sensor signal interrupt to indicate new data ready or
 				 a motion is detected.
+ - fsl,use-interrupt	: to enable interrupt mode.
  - fsl,irq-gpio	: First irq gpio which is to provide interrupts to host, same
 				 as "interrupts" node. It will also contain active low or active
 				 high information.
@@ -36,4 +37,5 @@
 		vio-supply = <&pm8110_l14>;
 		fsl,sensors-position = <5>;
 		fsl,irq-gpio = <&msmgpio 0x81 0x02>;
+		fsl,use-interrupt;
 	};
\ No newline at end of file
diff --git a/Documentation/devicetree/bindings/nfc/nfc-nci.txt b/Documentation/devicetree/bindings/nfc/nfc-nci.txt
index dca7d5c..2c06599 100644
--- a/Documentation/devicetree/bindings/nfc/nfc-nci.txt
+++ b/Documentation/devicetree/bindings/nfc/nfc-nci.txt
@@ -8,13 +8,15 @@
 - reg: NCI i2c slave address.
 - qcom,dis-gpio: specific gpio for hardware reset.
 - qcom,irq-gpio: specific gpio for read interrupt.
-- qcom,clk-src: nfc clock source ("BBCLK2", "RFCLK3", "GPCLK","GPCLK2" ...)
-- qcom,clk-en-gpio: msm gpio clock,used ony if clock source is msm gpio
+- qcom,clk-src: nfc clock source ("BBCLK2", "RFCLK3", "GPCLK", "GPCLK2", ...)
+- qcom,clk-src-gpio: msm gpio clock,used ony if clock source is msm gpio
+- qcom,clk-req-gpio: clk-req input gpio for MSM based clocks.
+                     not used for pmic implementation
 - vlogic-supply: LDO for power supply
 - interrupt-parent: Should be phandle for the interrupt controller
                     that services interrupts for this device.
-- interrupts: should contain the NFC interrupt. NFC has one read interrupt.
-- qcom,clk-gpio: pmic gpio on which bbclk2 signal is coming.
+- interrupts: Nfc read interrupt,gpio-clk-req interrupt
+- qcom,clk-gpio: pmic or msm gpio on which bbclk2 signal is coming.
 
 LDO example:
 
@@ -24,8 +26,8 @@
 			reg = <0x0e>;
 			qcom,irq-gpio = <&msmgpio 77 0x00>;
 			qcom,dis-gpio = <&msmgpio 93 0x00>;
-			qcom,clk-en-gpio = <&msmgpio 78 0x00>;
-			qcom,clk-src = "GPCLK";
+			qcom,clk-src-gpio = <&msmgpio 78 0x00>;
+			qcom,clk-src = "GPCLK2";
 			interrupt-parent = <&msmgpio>;
 			interrupts = <77 0>;
 			qcom,clk-gpio = <&msmgpio 75 0x00>;
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 7d8fe0a..50381a2 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -103,6 +103,9 @@
 - qcom,use-external-rsense		A boolean that controls whether BMS will use
 					an external sensor resistor instead of the default
 					RDS of the batfet.
+- qcom,vbatdet-maxerr-mv		This property in mV is a hystersis value for the charge
+					resume voltage property qcom,vbatdet-delta-mv. If this
+					property is not defined it defaults to 50 mV.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
index ac82387..9e582e2 100644
--- a/Documentation/devicetree/bindings/qseecom/qseecom.txt
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -11,6 +11,9 @@
 - qcom, msm_bus,num_paths: The paths for source and destination ports
 - qcom, msm_bus,vectors: Vectors for bus topology.
 
+Optional properties:
+  - qcom,support-bus-scaling : optional, indicates if driver support scaling the bus for crypto operation.
+
 Example:
 	qcom,qseecom@fe806000 {
 		compatible = "qcom,qseecom";
diff --git a/Documentation/devicetree/bindings/regulator/fan53555.txt b/Documentation/devicetree/bindings/regulator/fan53555.txt
new file mode 100644
index 0000000..57b54d6
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/fan53555.txt
@@ -0,0 +1,50 @@
+Fairchild Semiconductor FAN53555 regulator
+
+The FAN53555 is a step-down switching voltage regulator that delivers a
+digitally programmable output from an input voltage supply of 2.5 V to 5.5 V.
+The output voltage is programmed through an I2C interface capable of operating
+up to 3.4 MHz.
+
+The fan53555 interface is via I2C bus.
+
+Required Properties:
+- compatible:			Must be "fairchild,fan53555-regulator".
+- reg:				The device 8-bit I2C address.
+- fairchild,backup-vsel:	Register ID of backup register.
+				Supported values are 0 or 1.
+				The voltage selection ID used while the system
+				is active will be the other option not used
+				during running.
+- regulator-min-microvolt:	Minimum voltage in microvolts supported by this
+				regulator.
+- regulator-max-microvolt:	Maximum voltage in microvolts supported by this
+				regulator.
+- regulator-ramp-delay:		The slew rate of the regulator, in uV/us.
+				Supported values are 64000, 32000, 16000,
+				8000, 4000, 2000, 1000 and 500.
+
+Optional Properties:
+- fairchild,vsel-gpio:		Present: GPIO connects to the VSEL pin and set
+				the output.
+				Not Present: No GPIO is connected to vsel pin.
+- fairchild,restore-reg:	Present: Restore vsel register from backup
+				register.
+				Not Present: No restore.
+- fairchild,disable-suspend:	Present: Disable regulator suspend method.
+				Not Present: Do not disable regulator suspend
+				method.
+
+Example:
+	i2c_0 {
+		fan53555-regulator@60 {
+			compatible = "fairchild,fan53555-regulator";
+			reg = <0x60>;
+			fairchild,backup-vsel = <1>;
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1350000>;
+			regulator-ramp-delay = <8000>;
+			fairchild,vsel-gpio = <&msmgpio 2 1>;
+			fairchild,restore-reg;
+			fairchild,disable-suspend;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/regulator/onsemi-ncp6335d.txt b/Documentation/devicetree/bindings/regulator/onsemi-ncp6335d.txt
new file mode 100644
index 0000000..648cb11
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/onsemi-ncp6335d.txt
@@ -0,0 +1,71 @@
+ON Semiconductor NCP6335d regulator
+
+NCP6335d is able to deliver up to 5.0 A, with programmable output voltage from
+0.6 V to 1.87 V in 10mV steps, with synchronous rectification and automatic PWM/
+PFM transitions, enable pins and power good/fail signaling.
+
+The NCP6335d interface is via I2C bus.
+
+Required Properties:
+- compatible:			Must be "onnn,ncp6335d-regulator".
+- reg:				The device 8-bit I2C address.
+- regulator-min-microvolt:	Minimum voltage in microvolts supported by this
+				regulator.
+- regulator-max-microvolt:	Maximum voltage in microvolts supported by this
+				regulator.
+- onnn,min-setpoint:		Minimum setpoint voltage in microvolts supported
+				by this regulator.
+- onnn,step-size:		The step size of the regulator, in uV.
+- onnn,min-slew-ns:		Minimum time in ns needed to change voltage by
+				one step size. This value corresponds to DVS
+				mode bit of 00b in command register.
+- onnn,max-slew-ns:		Maximum time in ns needed to change voltage by
+				one step size. This value corresponds to DVS
+				mode bit of 11b in command register.
+- onnn,vsel:			Working vsel register. Supported value are 0
+				or 1.
+- onnn,slew-ns:			Time in ns needed to change voltage by one step
+				size. Supported value are 333, 666, 1333, 2666.
+
+Optional Properties:
+- onnn,discharge-enable:	Present: discharge enabled.
+				Not Present: discharge disabled.
+- onnn,restore-reg:		Present: Restore vsel register from backup register.
+				Not Present: No restore.
+- onnn,vsel-gpio:		Present: GPIO connects to the VSEL pin and set the
+				VSEL pin according to device tree flag.
+				Not Present: No GPIO is connected to vsel pin.
+- onnn,sleep-enable:		Present: Forced in sleep mode when EN and VSEL
+				pins are low.
+				Not Present: Low quiescent current mode when EN and VSEL
+				pins are low.
+- onnn,tlmm-config:		Array of 2 elements to indicate the mask value and the value
+				to write in the masked bits.
+				This property is used to allow the VSEL GPIO to toggle on certain
+				Qualcomm processors. If it is not specified, then no register write is required.
+				The 2 elements with index[0..1] are:
+				[0] => the mask value;
+				[1] => the value to write into the masked bits.
+- onnn,mode:			A string which specifies the initial mode to use for the regulator.
+				Supported values are "pwm" and "auto". PWM mode is more
+				robust, but draws more current than auto mode. If this propery
+				is not specified, then the regulator will be in the hardware default mode.
+
+Example:
+	i2c_0 {
+		ncp6335d-regulator@1c {
+			compatible = "onnn,ncp6335d-regulator";
+			reg = <0x1c>;
+			onnn,vsel = <0>;
+			onnn,slew-rate-ns = <2666>;
+			onnn,discharge-enable;
+			onnn,step-size = <10000>;
+			onnn,min-slew-ns = <333>;
+			onnn,max-slew-ns = <2666>;
+
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1350000>;
+			onnn,min-setpoint = <600000>;
+			onnn,vsel-gpio = <&msmgpio 2 1>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
index e1681ca..e4e05d1 100644
--- a/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
+++ b/Documentation/devicetree/bindings/thermal/qpnp-adc-tm.txt
@@ -53,6 +53,7 @@
 				 2 : pre-div ratio of {1, 4}
 				 3 : pre-div ratio of {1, 6}
 				 4 : pre-div ratio of {1, 20}
+				 5 : pre-div ratio of {1, 8}
 - qcom,calibration-type : Reference voltage to use for channel calibration.
 			  Channel calibration is dependendent on the channel.
 			  Certain channels like XO_THERM, BATT_THERM use ratiometric
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 35e7324..fd826d9 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -17,6 +17,7 @@
 denx	Denx Software Engineering
 epson	Seiko Epson Corp.
 est	ESTeem Wireless Modems
+fairchild	Fairchild Semiconductor International, Inc.
 focaltech Focaltech systems
 fsl	Freescale Semiconductor
 GEFanuc	GE Fanuc Intelligent Platforms Embedded Systems, Inc.
diff --git a/Documentation/usb/uicc.txt b/Documentation/usb/uicc.txt
new file mode 100644
index 0000000..7bf4d86
--- /dev/null
+++ b/Documentation/usb/uicc.txt
@@ -0,0 +1,161 @@
+Introduction
+============
+
+This feature requires supporting Mass Storage and Integrated Circuit Card
+interfaces exposed by the UICC (Universal Integrated Circuit Card) device.
+The MSM acts as a USB host and UICC acts as a peripheral. The UICC device
+that is used here is also referred to as Mega-SIM. This feature will be
+supported on MSM8x26.
+
+Hardware description
+====================
+
+The USB3503 HSIC (High Speed Inter Chip) hub's down stream port is modified
+to support Inter-Chip USB for connecting the UICC device. The USB3503 is
+connected to MSM via HSIC interface. The UICC device operates in Full Speed
+mode.
+
+The UICC device will support CCID (Integrated Circuit Card interface Device)
+specification. This interface supports 1 Bulk In, 1 Bulk Out and 1 Interrupt
+endpoint. The Interrupt endpoint is used by the device to send asynchronous
+notifications like card insertion/removal and hardware error events.
+The Bulk endpoints are used for the data communication.
+
+The UICC device will support the Mass Storage Bulk Only 1.0 specification.
+It supports SCSI Transparent subclass '06', corresponding to support of the
+SCSI Primary Command set. It implements SCSI Peripheral Device Type '00'
+(TYPE_DISK) corresponding to a direct access SCSI block device.
+
+Software description
+====================
+
+The MSM HSIC controller driver(drivers/usb/host/ehci-msm-hsic.c)  takes care
+of HSIC PHY and link management. The USB3503 HSIC hub is managed by the SMSC
+hub driver(drivers/misc/smsc_hubc.c). Both these drivers are well tested on
+APQ8074 dragon board and are re-used to support this feature.
+
+The mass storage interface is managed by the standard Linux USB storage driver.
+This driver interfaces with SCSI and block layers to export the disk to
+user space.
+
+A new USB driver is implemented to manage the CCID interface. This driver is
+referred to as USB CCID driver in this document. This driver is implemented
+as a pass-through module and provides the character device interface to
+user space. The CCID specification is implemented in the user space.
+
+The CCID command and responses are exchanged over the Bulk endpoints. The
+user space application uses write() and read() calls to send commands and
+receive responses.
+
+The CCID class specific requests are sent over the control endpoint. As
+control requests have a specific format, ioctls are implemented.
+
+The UICC device sends asynchronous notifications over the interrupt endpoint.
+The card insertion/removal and hardware error events are sent to user space
+via an ioctl().
+
+Design Goals:
+============
+
+1. Re-use the existing services available in user space. This is achieved
+by implementing the kernel USB CCID driver as a pass-through module.
+
+2. Support runtime card insertion/removal.
+
+3. Support runtime power management.
+
+4. Support Multiple card configuration. More than 1 IC can be connected to
+the USB UICC device.
+
+Power Management
+================
+
+The USB core uses the runtime PM framework to auto suspend the USB devices that
+are not in use. The Auto-suspend is forbidden for all devices except hub class
+devices. The USB CCID driver enables auto-suspend for the UICC device.
+
+An USB device can be suspended only when all of its interfaces are suspended.
+The USB storage interface device acts as a parent device to the underlying
+SCSI host, target and block devices. Runtime PM must be enabled for the
+SCSI device to allow USB storage interface suspend. The SCSI device runtime
+suspend and auto-suspend timeout will be configured from user space via sysfs
+files.
+
+The HSIC platform device and USB3503 HUB device will be runtime suspended
+only after the USB UICC device is suspended.
+
+SMP/multi-core
+==============
+
+The USB CCID driver does not allow multiple clients to open the device file
+concurrently. -EBUSY will be returned if open() is attempted when the
+file is already opened.
+
+The write() and read() methods are implemented synchronously. If another
+write() is called when a previous write() is in progress, -EBUSY is
+returned. The same is applicable to read().
+
+Mutexes will be used to prevent concurrent open(), read() and write() access.
+
+Interface
+=========
+
+A character device file (/dev/ccid_bridge) will be exposed by the USB CCID
+driver. open(), read(), write(), ioctl() and close() methods are implemented.
+This device node is accessible only to the root by default.  User space init
+or udev scripts should change the permissions of this device file if it needs
+to be accessed by non-root applications.
+
+open(): The open() is blocked until the UICC device is detected and the CCID
+interface probe is completed. Returns the appropriate error code in case of
+failure.
+
+read(): An URB is submitted on the Bulk In endpoint. The read() is blocked
+until the URB is completed and the data is copied to the user space buffer
+upon success. An appropriate error code is returned in case of failure.
+-ENODEV must be treated as a serious error and no further I/O will be
+attempted.
+
+write(): An URB is submitted on the Bulk Out endpoint. The write() is blocked
+until the URB is completed. An appropriate error code is returned in case of
+failure. -ENODEV must be treated as a serious error and no further I/O will be
+attempted.
+
+ioctl(): The ioctl() method is required for facilitating Control transfers and
+Interrupt transfers.
+
+USB_CCID_GET_CLASS_DESC: This read-only ioctl returns the smart card class
+descriptor as described in the 5.1 section of USB smart card class spec.
+
+USB_CCID_ABORT: This write-only ioctl sends A ABORT class specific request on
+control endpoint. The class request details are mentioned in section 5.3.1.
+
+USB_CCID_GET_CLOCK_FREQUENCIES: This read and write ioctl returns the clock
+frequencies supported by the CCID device. A GET_CLOCK_FREQUENCIES class request
+is sent on the control endpoint. The class request details are mentioned in
+section 5.3.2.
+
+USB_CCID_GET_DATA_RATES: This read and write ioctl returns the data rates
+supported by the CCID device. A GET_DATA_RATES class request is sent on the
+control endpoint. The class request details are mentioned in section 5.3.3.
+
+USB_CCID_GET_EVENT: This read-only ioctl returns the asynchronous event sent
+by the UICC device. The ioctl() is blocked until such event is received from
+the UICC device. This ioctl() returns -ENOENT error code when the device
+does not have an interrupt endpoint and does not support remote wakeup
+capability.
+
+close(): Cancels any ongoing I/O before it returns.
+
+Config options
+==============
+
+Turn on USB_EHCI_MSM_HSIC, USB_HSIC_SMSC_HUB and USB_CCID_BRIDGE configs to
+enable this feature.
+
+References
+==========
+
+Specification for Integrated Circuit(s) Cards Interface Devices
+
+Smart Cards; UICC-Terminal interface; Physical and logical characteristics
diff --git a/arch/arm/boot/dts/apq8084-mdss.dtsi b/arch/arm/boot/dts/apq8084-mdss.dtsi
index 15d5018..329ab32 100644
--- a/arch/arm/boot/dts/apq8084-mdss.dtsi
+++ b/arch/arm/boot/dts/apq8084-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -24,6 +24,20 @@
 		qcom,max-bandwidth-low-kbps = <6000000>;
 		qcom,max-bandwidth-high-kbps = <6000000>;
 
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "mdss_mdp";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>, <23 512 0 0>,
+			<22 512 0 6400000>, <23 512 0 6400000>,
+			<22 512 0 6400000>, <23 512 0 6400000>;
+
+		/* Fudge factors */
+		qcom,mdss-ab-factor = <2 1>;		/* 2 times    */
+		qcom,mdss-ib-factor = <6 5>;		/* 1.2 times  */
+		qcom,mdss-clk-factor = <105 100>;	/* 1.05 times */
+
 		qcom,max-clk-rate = <320000000>;
 
 		qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
@@ -36,6 +50,10 @@
 		qcom,mdss-pipe-rgb-fetch-id = <16 17 18 22>;
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
 
+		qcom,mdss-pipe-vig-xin-id = <0 4 8 12>;
+		qcom,mdss-pipe-rgb-xin-id = <1 5 9 13>;
+		qcom,mdss-pipe-dma-xin-id = <2 10>;
+
 		qcom,mdss-smp-data = <44 8192>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
@@ -56,6 +74,15 @@
 		qcom,mdss-has-bwc;
 		qcom,mdss-has-decimation;
 
+		/* buffer parameters to calculate prefill bandwidth */
+		qcom,mdss-prefill-outstanding-buffer-bytes = <1024>;
+		qcom,mdss-prefill-y-buffer-bytes = <4096>;
+		qcom,mdss-prefill-scaler-buffer-lines-bilinear = <2>;
+		qcom,mdss-prefill-scaler-buffer-lines-caf = <4>;
+		qcom,mdss-prefill-post-scaler-buffer-pixels = <2048>;
+		qcom,mdss-prefill-pingpong-buffer-pixels = <5120>;
+		qcom,mdss-prefill-fbc-lines = <2>;
+
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
diff --git a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
index 5302d8ae..760ecd7 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
@@ -77,6 +77,8 @@
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
+		qcom,mdss-pan-physical-width-dimension = <59>;
+		qcom,mdss-pan-physical-height-dimension = <104>;
 
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
index be42509..917c637 100644
--- a/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
@@ -66,5 +66,7 @@
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
+		qcom,mdss-pan-physical-width-dimension = <61>;
+		qcom,mdss-pan-physical-height-dimension = <110>;
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
index 60bba5d..39b10b3 100644
--- a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -31,7 +31,7 @@
 		qcom,mdss-dsi-h-pulse-width = <14>;
 		qcom,mdss-dsi-h-sync-skew = <0>;
 		qcom,mdss-dsi-v-back-porch = <14>;
-		qcom,mdss-dsi-v-front-porch = <30>;
+		qcom,mdss-dsi-v-front-porch = <25>;
 		qcom,mdss-dsi-v-pulse-width = <2>;
 		qcom,mdss-dsi-h-left-border = <0>;
 		qcom,mdss-dsi-h-right-border = <0>;
@@ -43,11 +43,12 @@
 		qcom,mdss-dsi-border-color = <0>;
 		qcom,mdss-dsi-pixel-packing = "tight";
 		qcom,mdss-dsi-on-command = [15 01 00 00 00 00 02 FF 01
+			29 01 00 00 00 00 02 53 00
 			29 01 00 00 00 00 05 C6 63 00 81 31
 			29 01 00 00 00 00 05 CB E7 80 73 33
 			29 01 00 00 00 00 02 EC D2
 			29 01 00 00 00 00 03 B3 04 9F
-			29 01 00 00 00 00 04 B2 16 1E 10
+			29 01 00 00 00 00 04 B2 16 26 10
 			29 01 00 00 00 00 02 B4 00
 			29 01 00 00 00 00 02 C1 04
 			29 01 00 00 00 00 04 C2 BE 00 58
@@ -63,19 +64,19 @@
 			29 01 00 00 00 00 04 E6 FF FF 0F
 			29 01 00 00 00 00 02 C7 3F
 			29 01 00 00 00 00 07 B5 47 00 00 08 00 01
-			29 01 00 00 00 00 08 C4 DF 72 12 12 66 E3 99
-			29 01 00 00 00 00 07 D0 0A 00 0D 15 1F 2E
-			29 01 00 00 00 00 06 D1 28 27 14 02 01
-			29 01 00 00 00 00 07 D2 0A 00 0D 15 1F 2E
-			29 01 00 00 00 00 06 D3 28 27 14 02 01
-			29 01 00 00 00 00 07 D4 0A 00 0D 15 1F 2E
-			29 01 00 00 00 00 06 D5 28 27 14 02 01
-			29 01 00 00 00 00 07 D6 0A 00 0D 15 1F 2E
-			29 01 00 00 00 00 06 D7 28 27 14 02 01
-			29 01 00 00 00 00 07 D8 0A 00 0D 15 1F 2E
-			29 01 00 00 00 00 06 D9 28 27 14 02 01
-			29 01 00 00 00 00 07 DA 0A 00 0D 15 1F 2E
-			29 01 00 00 00 00 06 DB 28 27 14 02 01
+			29 01 00 00 00 00 08 C4 DF C2 0C 0C 63 E3 99
+			29 01 00 00 00 00 07 D0 0A 00 06 09 10 20
+			29 01 00 00 00 00 06 D1 1D 32 1B 00 00
+			29 01 00 00 00 00 07 D2 0A 00 06 09 10 20
+			29 01 00 00 00 00 06 D3 1D 32 1B 00 00
+			29 01 00 00 00 00 07 D4 0A 00 06 09 10 20
+			29 01 00 00 00 00 06 D5 1D 32 1B 00 00
+			29 01 00 00 00 00 07 D6 0A 00 06 09 10 20
+			29 01 00 00 00 00 06 D7 1D 32 1B 00 00
+			29 01 00 00 00 00 07 D8 0A 00 06 09 10 20
+			29 01 00 00 00 00 06 D9 1D 32 1B 00 00
+			29 01 00 00 00 00 07 DA 0A 00 06 09 10 20
+			29 01 00 00 00 00 06 DB 1D 32 1B 00 00
 			29 01 00 00 00 00 03 CC 10 00
 			29 01 00 00 00 00 04 CE 4E 55 A5
 			29 01 00 00 00 00 04 E0 01 02 02
@@ -84,18 +85,20 @@
 			29 01 00 00 00 00 03 E1 90 00
 			29 01 00 00 00 00 07 DE 95 CF E2 CE 11 15
 			29 01 00 00 00 00 02 CF 46
-			29 01 00 00 00 00 03 C5 77 47
+			29 01 00 00 00 00 02 C5 66
 			29 01 00 00 00 00 03 ED 00 20
-			05 01 00 00 B4 00 02 11 00
-			05 01 00 00 82 00 02 29 00
-			15 01 00 00 00 00 02 53 2c];
-		qcom,mdss-dsi-off-command = [15 01 00 00 32 00 02 10 00
-			15 01 00 00 32 00 02 53 00
-			15 01 00 00 00 00 02 c2 00
+			15 01 00 00 00 00 02 53 2c
+			05 01 00 00 20 00 02 11 00
+			05 01 00 00 20 00 02 29 00];
+
+		qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 10 00
+			39 01 00 00 20 00 02 53 00
+			39 01 00 00 20 00 02 c2 00
 			39 01 00 00 00 00 02 cf 40
-			15 01 00 00 50 00 03 de 84 00
+			39 01 00 00 20 00 03 de 84 00
 			39 01 00 00 00 00 02 cb 22
-			15 01 00 00 00 00 02 c3 00];
+			39 01 00 00 00 00 02 c3 00];
+
 		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
 		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
 		qcom,mdss-dsi-h-sync-pulse = <1>;
@@ -115,5 +118,7 @@
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+		qcom,mdss-dsi-lp11-init;
+		qcom,mdss-dsi-init-delay-us = <50000>;
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
index 168dda4..4cd1563 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
@@ -165,5 +165,7 @@
 		qcom,mdss-dsi-mdp-trigger = "trigger_te";
 		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+		qcom,mdss-pan-physical-width-dimension = <52>;
+		qcom,mdss-pan-physical-height-dimension = <86>;
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
index 121e54d..bdc43a9 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
@@ -163,5 +163,7 @@
 		qcom,mdss-dsi-mdp-trigger = "none";
 		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
 		qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+		qcom,mdss-pan-physical-width-dimension = <52>;
+		qcom,mdss-pan-physical-height-dimension = <86>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index 6d506cc..a13e66a 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -860,22 +860,6 @@
 				qcom,current = <625>;
 			};
 
-			pm8226_flash1: qcom,flash_1 {
-				qcom,max-current = <1000>;
-				qcom,default-state = "off";
-				qcom,headroom = <3>;
-				qcom,duration = <1280>;
-				qcom,clamp-curr = <200>;
-				qcom,startup-dly = <3>;
-				qcom,safety-timer;
-				linux,default-trigger =
-						"flash1_trigger";
-				label = "flash";
-				qcom,id = <2>;
-				linux,name = "led:flash_1";
-				qcom,current = <625>;
-			};
-
 			pm8226_torch: qcom,flash_torch {
 				qcom,max-current = <200>;
 				qcom,default-state = "off";
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index fa5c739..20bb2aa 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -17,7 +17,7 @@
 		cell-index = <0>;
 		compatible = "qcom,camera-led-flash";
 		qcom,flash-type = <1>;
-		qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+		qcom,flash-source = <&pm8226_flash0>;
 		qcom,torch-source = <&pm8226_torch>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index 5d1e1c8..07a4383 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -17,7 +17,7 @@
 		cell-index = <0>;
 		compatible = "qcom,camera-led-flash";
 		qcom,flash-type = <1>;
-		qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+		qcom,flash-source = <&pm8226_flash0>;
 		qcom,torch-source = <&pm8226_torch>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index fd6d618..0436600 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -17,7 +17,7 @@
 		cell-index = <0>;
 		compatible = "qcom,camera-led-flash";
 		qcom,flash-type = <1>;
-		qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+		qcom,flash-source = <&pm8226_flash0>;
 		qcom,torch-source = <&pm8226_torch>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 38cfe66..8a98d5c 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -21,6 +21,21 @@
 
 		qcom,max-bandwidth-low-kbps = <1660000>;
 		qcom,max-bandwidth-high-kbps = <1660000>;
+
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "mdss_mdp";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>,
+			<22 512 0 6400000>,
+			<22 512 0 6400000>;
+
+		/* Fudge factors */
+		qcom,mdss-ab-factor = <2 1>;		/* 2 times    */
+		qcom,mdss-ib-factor = <6 5>;		/* 1.2 times  */
+		qcom,mdss-clk-factor = <5 4>;		/* 1.25 times */
+
 		qcom,max-clk-rate = <200000000>;
 		qcom,mdss-pipe-vig-off = <0x00001200>;
 		qcom,mdss-pipe-rgb-off = <0x00001E00>;
@@ -28,6 +43,11 @@
 		qcom,mdss-pipe-vig-fetch-id = <1>;
 		qcom,mdss-pipe-rgb-fetch-id = <7>;
 		qcom,mdss-pipe-dma-fetch-id = <4>;
+
+		qcom,mdss-pipe-vig-xin-id = <0>;
+		qcom,mdss-pipe-rgb-xin-id = <1>;
+		qcom,mdss-pipe-dma-xin-id = <2>;
+
 		qcom,mdss-smp-data = <7 4096>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700>;
@@ -38,6 +58,7 @@
 		qcom,mdss-wb-off = <0x00011100 0x00013100>;
 		qcom,mdss-intf-off = <0x00000000 0x00021300>;
 		qcom,mdss-rot-block-size = <64>;
+		qcom,mdss-rotator-ot-limit = <2>;
 		qcom,mdss-smp-mb-per-pipe = <4>;
 		vdd-cx-supply = <&pm8226_s1_corner>;
 
@@ -47,6 +68,15 @@
 		qcom,mdp-settings = <0x02E0 0x000000A5>,
 				    <0x02E4 0x00000055>;
 
+		/* buffer parameters to calculate prefill bandwidth */
+		qcom,mdss-prefill-outstanding-buffer-bytes = <1024>;
+		qcom,mdss-prefill-y-buffer-bytes = <0>;
+		qcom,mdss-prefill-scaler-buffer-lines-bilinear = <2>;
+		qcom,mdss-prefill-scaler-buffer-lines-caf = <4>;
+		qcom,mdss-prefill-post-scaler-buffer-pixels = <0>;
+		qcom,mdss-prefill-pingpong-buffer-pixels = <4096>;
+		qcom,mdss-prefill-fbc-lines = <0>;
+
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
diff --git a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
index 2e32ac4..c3fcedb 100755
--- a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
@@ -82,7 +82,7 @@
 			avdd-supply = <&tp_power>;
 			goodix,panel-coords = <0 0 720 1200>;
 			goodix,display-coords = <0 0 720 1080>;
-			goodix,button-map= <158 102 139>;
+			goodix,button-map= <139 172 158>;
 			goodix,product-id = "915";
 			goodix,cfg-data0 = [
 				41 D0 02 00 05 05 35 11 01 0F
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 7ff97f6..84e46ea 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -17,6 +17,20 @@
 		status = "ok";
 	};
 
+        i2c@f9925000 { /* BLSP1 QUP3 */
+                nfc-nci@0e {
+                        compatible = "qcom,nfc-nci";
+                        reg = <0x0e>;
+                        qcom,irq-gpio = <&msmgpio 21 0x00>;
+                        qcom,dis-gpio = <&msmgpio 20 0x00>;
+                        qcom,clk-src = "BBCLK2";
+                        qcom,clk-en-gpio = <&msmgpio 0 0x00>;
+                        interrupt-parent = <&msmgpio>;
+                        interrupts = <21 0>;
+                        qcom,clk-gpio = <&pm8226_gpios 3 0>;
+                };
+        };
+
 	i2c@f9927000 { /* BLSP1 QUP5 */
 		synaptics@20 {
 			compatible = "synaptics,rmi4";
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index dbeaa97..0146367 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -30,7 +30,7 @@
 &soc {
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
-		compatible = "qti,cpr-regulator";
+		compatible = "qcom,cpr-regulator";
 		reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
 		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
 		interrupts = <0 15 0>;
@@ -38,61 +38,61 @@
 		regulator-min-microvolt = <1>;
 		regulator-max-microvolt = <12>;
 
-		qti,pvs-fuse-redun-sel = <22 24 3 2 0>;
-		qti,pvs-fuse = <22 6 5 0>;
-		qti,pvs-fuse-redun = <22 27 5 0>;
+		qcom,pvs-fuse-redun-sel = <22 24 3 2 0>;
+		qcom,pvs-fuse = <22 6 5 0>;
+		qcom,pvs-fuse-redun = <22 27 5 0>;
 
-		qti,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
+		qcom,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
 					1275000 1260000 1245000 1230000 1215000
 					1200000 1185000 1170000 1155000 1140000
 					1140000 1140000 1140000 1140000 1140000
 					1150000 1140000 1140000 1140000 1140000
 					1140000 1140000 1140000 1275000 1275000
 					1275000 1275000>;
-		qti,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
-		qti,pvs-corner-ceiling-nom  = <1050000 1075000 1200000>;
-		qti,pvs-corner-ceiling-fast = <1050000 1050000 1100000>;
+		qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
+		qcom,pvs-corner-ceiling-nom  = <1050000 1075000 1200000>;
+		qcom,pvs-corner-ceiling-fast = <1050000 1050000 1100000>;
 		vdd-apc-supply = <&pm8226_s2>;
 
 		vdd-mx-supply = <&pm8226_l3_ao>;
-		qti,vdd-mx-vmax = <1350000>;
-		qti,vdd-mx-vmin-method = <1>;
+		qcom,vdd-mx-vmax = <1350000>;
+		qcom,vdd-mx-vmin-method = <1>;
 
-		qti,cpr-ref-clk = <19200>;
-		qti,cpr-timer-delay = <5000>;
-		qti,cpr-timer-cons-up = <0>;
-		qti,cpr-timer-cons-down = <2>;
-		qti,cpr-irq-line = <0>;
-		qti,cpr-step-quotient = <15>;
-		qti,cpr-up-threshold = <0>;
-		qti,cpr-down-threshold = <10>;
-		qti,cpr-idle-clocks = <0>;
-		qti,cpr-gcnt-time = <1>;
-		qti,vdd-apc-step-up-limit = <1>;
-		qti,vdd-apc-step-down-limit = <1>;
-		qti,cpr-apc-volt-step = <5000>;
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <15>;
+		qcom,cpr-up-threshold = <0>;
+		qcom,cpr-down-threshold = <10>;
+		qcom,cpr-idle-clocks = <0>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <5000>;
 
-		qti,cpr-fuse-redun-sel = <138 57 1 1 0>;
-		qti,cpr-fuse-row = <138 0>;
-		qti,cpr-fuse-bp-cpr-disable = <36>;
-		qti,cpr-fuse-bp-scheme = <37>;
-		qti,cpr-fuse-target-quot = <24 12 0>;
-		qti,cpr-fuse-ro-sel = <54 38 41>;
-		qti,cpr-fuse-redun-row = <139 0>;
-		qti,cpr-fuse-redun-target-quot = <24 12 0>;
-		qti,cpr-fuse-redun-ro-sel = <46 36 39>;
+		qcom,cpr-fuse-redun-sel = <138 57 1 1 0>;
+		qcom,cpr-fuse-row = <138 0>;
+		qcom,cpr-fuse-bp-cpr-disable = <36>;
+		qcom,cpr-fuse-bp-scheme = <37>;
+		qcom,cpr-fuse-target-quot = <24 12 0>;
+		qcom,cpr-fuse-ro-sel = <54 38 41>;
+		qcom,cpr-fuse-redun-row = <139 0>;
+		qcom,cpr-fuse-redun-target-quot = <24 12 0>;
+		qcom,cpr-fuse-redun-ro-sel = <46 36 39>;
 
-		qti,cpr-enable;
-		qti,cpr-fuse-cond-min-volt-sel = <54 42 6 7 1>;
-		qti,cpr-cond-min-voltage = <1140000>;
-		qti,cpr-fuse-uplift-sel = <22 53 1 0 0>;
-		qti,cpr-uplift-voltage = <50000>;
-		qti,cpr-uplift-quotient = <0 0 120>;
-		qti,cpr-uplift-max-volt = <1350000>;
-		qti,cpr-uplift-speed-bin = <1>;
-		qti,speed-bin-fuse-sel = <22 0 3 0>;
-		qti,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
-		qti,cpr-quot-adjust-table =
+		qcom,cpr-enable;
+		qcom,cpr-fuse-cond-min-volt-sel = <54 42 6 7 1>;
+		qcom,cpr-cond-min-voltage = <1140000>;
+		qcom,cpr-fuse-uplift-sel = <22 53 1 0 0>;
+		qcom,cpr-uplift-voltage = <50000>;
+		qcom,cpr-uplift-quotient = <0 0 120>;
+		qcom,cpr-uplift-max-volt = <1350000>;
+		qcom,cpr-uplift-speed-bin = <1>;
+		qcom,speed-bin-fuse-sel = <22 0 3 0>;
+		qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
+		qcom,cpr-quot-adjust-table =
 					<1 5 450>,
 					<1 6 375>,
 					<1 7 300>,
diff --git a/arch/arm/boot/dts/msm8226-v2.dtsi b/arch/arm/boot/dts/msm8226-v2.dtsi
index 4149169..a285ec9 100644
--- a/arch/arm/boot/dts/msm8226-v2.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -52,20 +52,20 @@
 };
 
 &apc_vreg_corner {
-	qti,pvs-init-voltage = <1330000 1330000 1330000 1320000 1310000
+	qcom,pvs-init-voltage = <1330000 1330000 1330000 1320000 1310000
 					1300000 1290000 1280000 1270000 1260000
 					1250000 1240000 1230000 1220000 1210000
 					1200000 1190000 1180000 1170000 1160000
 					1150000 1140000 1140000 1140000 1140000
 					1140000 1140000 1140000 1140000 1140000
 					1140000 1140000>;
-	qti,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
-	qti,pvs-corner-ceiling-nom  = <1050000 1080000 1200000>;
-	qti,pvs-corner-ceiling-fast = <1050000 1050000 1100000>;
-	qti,cpr-step-quotient = <30>;
-	qti,cpr-up-threshold = <0>;
-	qti,cpr-down-threshold = <5>;
-	qti,cpr-apc-volt-step = <10000>;
+	qcom,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
+	qcom,pvs-corner-ceiling-nom  = <1050000 1080000 1200000>;
+	qcom,pvs-corner-ceiling-fast = <1050000 1050000 1100000>;
+	qcom,cpr-step-quotient = <30>;
+	qcom,cpr-up-threshold = <0>;
+	qcom,cpr-down-threshold = <5>;
+	qcom,cpr-apc-volt-step = <10000>;
 };
 
 &msm_gpu {
@@ -80,39 +80,26 @@
 		reg-names = "rcg-base", "efuse";
 		qcom,speed0-bin-v2 =
 			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1190400000 3>;
-		qcom,speed6-bin-v2 =
-			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1190400000 3>;
+			< 384000000 2>,
+			< 787200000 4>,
+			<1190400000 7>;
 		qcom,speed2-bin-v2 =
 			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1401600000 3>;
-		qcom,speed5-bin-v2 =
-			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1401600000 3>;
-		qcom,speed4-bin-v2 =
-			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1401600000 3>;
-		qcom,speed7-bin-v2 =
-			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1401600000 3>;
+			< 384000000 2>,
+			< 787200000 4>,
+			<1401600000 10>;
 		qcom,speed1-bin-v2 =
 			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1593600000 3>;
+			< 384000000 2>,
+			< 787200000 4>,
+			< 998400000 5>,
+			<1094400000 6>,
+			<1190400000 7>,
+			<1305600000 8>,
+			<1344000000 9>,
+			<1401600000 10>,
+			<1497600000 11>,
+			<1593600000 12>;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index baa81cc..a712ea7 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -977,7 +977,7 @@
 		qcom,scl-gpio = <&msmgpio 11 0>;
 		qcom,master-id = <86>;
 	};
-	i2c@f9926000 { /* BLSP-1 QUP-4 */
+	i2c_0: i2c@f9926000 { /* BLSP-1 QUP-4 */
 		cell-index = <0>;
 		compatible = "qcom,i2c-qup";
 		reg = <0xf9926000 0x1000>;
@@ -987,6 +987,8 @@
 		interrupts = <0 98 0>;
 		interrupt-names = "qup_err_intr";
 		qcom,i2c-bus-freq = <100000>;
+		qcom,i2c-src-freq = <19200000>;
+		qcom,master-id = <86>;
 	};
 
 	i2c@f9927000 { /* BLSP1 QUP5 */
@@ -1011,30 +1013,39 @@
 		clock-names = "clk-4", "clk-5";
 		qcom,speed0-bin-v0 =
 			<         0 0>,
-			< 384000000 1>,
-			< 787200000 2>,
-			<1190400000 3>;
+			< 384000000 2>,
+			< 787200000 4>,
+			<1190400000 7>;
 
 		cpu-vdd-supply = <&apc_vreg_corner>;
 	};
 
+	qcom,cpubw {
+		compatible = "qcom,cpubw";
+		qcom,cpu-mem-ports = <1 512>;
+		qcom,bw-tbl =
+			< 1525 /* 200 MHz */ >,
+			< 2441 /* 320 MHz */ >,
+			< 3051 /* 400 MHz */ >,
+			< 4066 /* 533 MHz */ >;
+	};
+
 	qcom,msm-cpufreq@0 {
 		reg = <0 4>;
 		compatible = "qcom,msm-cpufreq";
-		qcom,cpu-mem-ports = <1 512>;
 		qcom,cpufreq-table =
-			<  300000 1600 /* 200 MHz */ >,
-			<  384000 1600 /* 200 MHz */ >,
-			<  600000 1600 /* 200 MHz */ >,
-			<  787200 3200 /* 400 MHz */ >,
-			<  998400 4264 /* 533 MHz */ >,
-			< 1094400 4264 /* 533 MHz */ >,
-			< 1190400 4264 /* 533 MHz */ >,
-			< 1305600 4264 /* 533 MHz */ >,
-			< 1344000 4264 /* 533 MHz */ >,
-			< 1401600 4264 /* 533 MHz */ >,
-			< 1497600 4264 /* 533 MHz */ >,
-			< 1593600 4264 /* 533 MHz */ >;
+			<  300000 1525 >,
+			<  384000 1525 >,
+			<  600000 1525 >,
+			<  787200 3051 >,
+			<  998400 4066 >,
+			< 1094400 4066 >,
+			< 1190400 4066 >,
+			< 1305600 4066 >,
+			< 1344000 4066 >,
+			< 1401600 4066 >,
+			< 1497600 4066 >,
+			< 1593600 4066 >;
 	};
 
 	qcom,ocmem@fdd00000 {
diff --git a/arch/arm/boot/dts/msm8610-gpu.dtsi b/arch/arm/boot/dts/msm8610-gpu.dtsi
index 7e3ee0d..de480df 100644
--- a/arch/arm/boot/dts/msm8610-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8610-gpu.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -38,7 +38,7 @@
 			<26 512 0 0>,
 			<26 512 0 800000>,
 			<26 512 0 1600000>,
-			<26 512 0 2128000>;
+			<26 512 0 2664000>;
 
 		/* GDSC oxili regulators */
 		vdd-supply = <&gdsc_oxili_cx>;
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 3b0f2a2..aad838e 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-14, 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
@@ -39,14 +39,14 @@
 				/* Object 6, Instance = 0 */
 				00 00 00 00 00 00
 				/* Object 38, Instance = 0 */
-				1D 03 00 1E 07 0D 00 00
+				1D 05 01 0D 01 0E 00 00
 				/* Object 7, Instance = 0 */
 				20 08 32
 				/* Object 8, Instance = 0 */
 				19 00 14 14 FF 00 FF 00 00 00
 				/* Object 9, Instance = 0 */
 				83 00 00 13 0B 00 20 32 01 03
-				00 32 05 30 0A 05 0A 00 70 03
+				00 32 05 30 05 05 0A 00 70 03
 				FC 01 04 2F F8 DC 00 00 40 00
 				00 0A 00 00 02
 				/* Object 18, Instance = 0 */
@@ -151,10 +151,11 @@
 			reg = <0x0e>;
 			qcom,irq-gpio = <&msmgpio 77 0x00>;
 			qcom,dis-gpio = <&msmgpio 93 0x00>;
-			qcom,clk-en-gpio = <&msmgpio 78 0x00>;
+			qcom,clk-req-gpio = <&msmgpio 75 0x00>;
+			qcom,clk-src-gpio = <&msmgpio 78 0x00>;
 			qcom,clk-src = "GPCLK";
 			interrupt-parent = <&msmgpio>;
-			interrupts = <77 0>;
+			interrupts = <77 75 0>;
 			qcom,clk-gpio = <&pm8110_gpios 1 0>;
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
index 719830e..53abb95 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuaa.dtsi
@@ -38,11 +38,12 @@
 			compatible = "qcom,nfc-nci";
 			reg = <0x0e>;
 			qcom,irq-gpio = <&msmgpio 77 0x00>;
+			qcom,clk-req-gpio = <&msmgpio 75 0x00>;
 			qcom,dis-gpio = <&msmgpio 93 0x00>;
-			qcom,clk-en-gpio = <&msmgpio 78 0x00>;
+			qcom,clk-src-gpio = <&msmgpio 78 0x00>;
 			qcom,clk-src = "GPCLK2";
 			interrupt-parent = <&msmgpio>;
-			interrupts = <77 0>;
+			interrupts = <77 75 0>;
 			qcom,clk-gpio = <&msmgpio 75 0x00>;
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
index a22958a..c7fa9db 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
@@ -65,7 +65,7 @@
 			vcc-i2c-supply = <&pm8110_l14>;
 			goodix,panel-coords = <0 0 540 980>;
 			goodix,display-coords = <0 0 540 960>;
-			goodix,button-map= <139 102 158>;
+			goodix,button-map= <139 172 158>;
 			goodix,product-id = "915";
 			goodix,enable-power-off;
 			goodix,cfg-data0 = [
@@ -101,6 +101,20 @@
 		qcom,y-offset = <0>;
 	};
 
+	i2c@f9924000 { /* BLSP-1 QUP-2 */
+		nfc-nci@e {
+			compatible = "qcom,nfc-nci";
+			reg = <0x0e>;
+			qcom,irq-gpio = <&msmgpio 77 0x00>;
+			qcom,dis-gpio = <&msmgpio 93 0x00>;
+			qcom,clk-en-gpio = <&msmgpio 78 0x00>;
+			qcom,clk-src = "GPCLK2";
+			interrupt-parent = <&msmgpio>;
+			interrupts = <77 0>;
+			qcom,clk-gpio = <&msmgpio 75 0x00>;
+		};
+	};
+
     i2c@f9925000 {
 		fsl@1c {
 			compatible = "fsl,mma8x5x";
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index 51a9516..30c557d 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -30,62 +30,61 @@
 &soc {
 	apc_vreg_corner: regulator@f9018000 {
 		status = "okay";
-		compatible = "qti,cpr-regulator";
+		compatible = "qcom,cpr-regulator";
 		reg = <0xf9018000 0x1000>, <0xf9011064 4>, <0xfc4b8000 0x1000>;
 		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
 		interrupts = <0 15 0>;
 		regulator-name = "apc_corner";
 		regulator-min-microvolt = <1>;
-		regulator-max-microvolt = <12>;
+		regulator-max-microvolt = <3>;
 
-		qti,pvs-fuse-redun-sel = <53 25 3 2 1>;
-		qti,pvs-fuse = <23 6 5 1>;
-		qti,pvs-fuse-redun = <61 47 5 1>;
+		qcom,pvs-fuse-redun-sel = <53 25 3 2 1>;
+		qcom,pvs-fuse = <23 6 5 1>;
+		qcom,pvs-fuse-redun = <61 47 5 1>;
 
-		qti,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
+		qcom,pvs-init-voltage = <1275000 1275000 1275000 1275000 1275000
 					1275000 1275000 1275000 1275000 1275000
 					1275000 1275000 1275000 1275000 1275000
 					1275000 1275000 1275000 1275000 1275000
 					1275000 1275000 1275000 1275000 1275000
 					1275000 1275000 1275000 1275000 1275000
 					1275000 1275000>;
-		qti,pvs-corner-ceiling-slow = <1150000 1150000 1275000>;
-		qti,pvs-corner-ceiling-nom  = <1075000 1075000 1275000>;
-		qti,pvs-corner-ceiling-fast = <1050000 1050000 1275000>;
+		qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000>;
+		qcom,pvs-corner-ceiling-nom  = <1050000 1075000 1275000>;
+		qcom,pvs-corner-ceiling-fast = <1050000 1050000 1275000>;
 		vdd-apc-supply = <&pm8110_s2>;
 
 		vdd-mx-supply = <&pm8110_l3_ao>;
-		qti,vdd-mx-vmax = <1350000>;
-		qti,vdd-mx-vmin-method = <1>;
+		qcom,vdd-mx-vmax = <1350000>;
+		qcom,vdd-mx-vmin-method = <1>;
 
-		qti,cpr-ref-clk = <19200>;
-		qti,cpr-timer-delay = <5000>;
-		qti,cpr-timer-cons-up = <0>;
-		qti,cpr-timer-cons-down = <2>;
-		qti,cpr-irq-line = <0>;
-		qti,cpr-step-quotient = <15>;
-		qti,cpr-up-threshold = <0>;
-		qti,cpr-down-threshold = <10>;
-		qti,cpr-idle-clocks = <5>;
-		qti,cpr-gcnt-time = <1>;
-		qti,vdd-apc-step-up-limit = <1>;
-		qti,vdd-apc-step-down-limit = <1>;
-		qti,cpr-apc-volt-step = <5000>;
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <15>;
+		qcom,cpr-up-threshold = <0>;
+		qcom,cpr-down-threshold = <10>;
+		qcom,cpr-idle-clocks = <5>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <5000>;
 
-		qti,cpr-fuse-redun-sel = <53 25 3 2 1>;
-		qti,cpr-fuse-row = <61 1>;
-		qti,cpr-fuse-bp-cpr-disable = <39>;
-		qti,cpr-fuse-bp-scheme = <40>;
-		qti,cpr-fuse-target-quot = <27 15 3>;
-		qti,cpr-fuse-ro-sel = <47 41 44>;
-		qti,cpr-fuse-redun-row = <52 1>;
-		qti,cpr-fuse-redun-bp-cpr-disable = <24>;
-		qti,cpr-fuse-redun-bp-scheme = <25>;
-		qti,cpr-fuse-redun-target-quot = <32 12 0>;
-		qti,cpr-fuse-redun-ro-sel = <44 26 29>;
-		qti,cpr-corner-map = <1 1 2 2 3 3 3 3 3 3 3 3>;
+		qcom,cpr-fuse-redun-sel = <53 25 3 2 1>;
+		qcom,cpr-fuse-row = <61 1>;
+		qcom,cpr-fuse-bp-cpr-disable = <39>;
+		qcom,cpr-fuse-bp-scheme = <40>;
+		qcom,cpr-fuse-target-quot = <27 15 3>;
+		qcom,cpr-fuse-ro-sel = <47 41 44>;
+		qcom,cpr-fuse-redun-row = <52 1>;
+		qcom,cpr-fuse-redun-bp-cpr-disable = <24>;
+		qcom,cpr-fuse-redun-bp-scheme = <25>;
+		qcom,cpr-fuse-redun-target-quot = <32 12 0>;
+		qcom,cpr-fuse-redun-ro-sel = <44 26 29>;
 
-		qti,cpr-enable;
+		qcom,cpr-enable;
 	};
 };
 
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index ea37413..e075c71 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -302,6 +302,8 @@
 		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 		qcom,pc-resets-timer;
+		qcom,cpus-as-clocks;
+		qcom,synced-clocks;
 	};
 
 	qcom,cpu-sleep-status@f9088008{
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 19fb185..447290d 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -304,6 +304,8 @@
 		qcom,pc-mode = "tz_l2_int";
 		qcom,use-sync-timer;
 		qcom,pc-resets-timer;
+		qcom,cpus-as-clocks;
+		qcom,synced-clocks;
 	};
 
 	qcom,cpu-sleep-status@f9088008{
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 03ef738..61fa6bc 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -240,7 +240,6 @@
 		qcom,hsusb-otg-otg-control = <2>;
 		qcom,hsusb-otg-disable-reset;
 		qcom,dp-manual-pullup;
-		qcom,ahb-async-bridge-bypass;
 		qcom,disable-retention-with-vdd-min;
 
 		qcom,msm-bus,name = "usb2";
@@ -464,11 +463,39 @@
 		qcom,ipi-ping;
 	};
 
-	qcom,acpuclk@f9011050 {
-		compatible = "qcom,acpuclk-a7";
+	qcom,clock-a7@f9011050 {
+		compatible = "qcom,clock-a7-8226";
 		reg = <0xf9011050 0x8>;
-		reg-names = "rcg_base";
-		a7_cpu-supply = <&apc_vreg_corner>;
+		reg-names = "rcg-base";
+		clock-names = "clk-4", "clk-5";
+		qcom,speed0-bin-v0 =
+			<         0 0>,
+			< 384000000 1>,
+			< 787200000 2>,
+			<1190400000 3>;
+
+		cpu-vdd-supply = <&apc_vreg_corner>;
+	};
+
+	qcom,cpubw {
+		compatible = "qcom,cpubw";
+		qcom,cpu-mem-ports = <1 512>;
+		qcom,bw-tbl =
+			<  762 /* 100 MHz */ >,
+			< 1525 /* 200 MHz */ >,
+			< 2540 /* 333 MHz */ >;
+	};
+
+	qcom,msm-cpufreq@0 {
+		reg = <0 4>;
+		compatible = "qcom,msm-cpufreq";
+		qcom,cpufreq-table =
+			<  300000  762 >,
+			<  384000  762 >,
+			<  600000 1525 >,
+			<  787200 1525 >,
+			<  998400 2540 >,
+			< 1190400 2540 >;
 	};
 
 	spmi_bus: qcom,spmi@fc4c0000 {
@@ -535,6 +562,8 @@
 	i2c@f9924000 { /* BLSP-1 QUP-3 */
 		cell-index = <2>;
 		compatible = "qcom,i2c-qup";
+		#address-cells = <1>;
+		#size-cells = <0>;
 		reg-names = "qup_phys_addr";
 		reg = <0xf9924000 0x1000>;
 		interrupt-names = "qup_err_intr";
@@ -1042,7 +1071,7 @@
 		label = "vchg_sns";
 		reg = <2>;
 		qcom,decimation = <0>;
-		qcom,pre-div-channel-scaling = <2>;
+		qcom,pre-div-channel-scaling = <5>;
 		qcom,calibration-type = "absolute";
 		qcom,scale-function = <0>;
 		qcom,hw-settle-time = <0>;
diff --git a/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi
index 9b812da..ac2d908 100644
--- a/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi
@@ -17,7 +17,7 @@
 		cell-index = <0>;
 		compatible = "qcom,camera-led-flash";
 		qcom,flash-type = <1>;
-		qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+		qcom,flash-source = <&pm8226_flash0>;
 		qcom,torch-source = <&pm8226_torch>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8926-qrd-skug.dts b/arch/arm/boot/dts/msm8926-qrd-skug.dtsi
similarity index 90%
rename from arch/arm/boot/dts/msm8926-qrd-skug.dts
rename to arch/arm/boot/dts/msm8926-qrd-skug.dtsi
index 15a2d58..c93ea12 100644
--- a/arch/arm/boot/dts/msm8926-qrd-skug.dts
+++ b/arch/arm/boot/dts/msm8926-qrd-skug.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -10,17 +10,9 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
-/include/ "msm8926.dtsi"
 /include/ "msm8226-qrd.dtsi"
 /include/ "msm8926-camera-sensor-qrd.dtsi"
 
-/ {
-	model = "Qualcomm MSM 8926 QRD SKUG";
-	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 5>;
-};
-
 &qrd_batterydata {
 	qcom,rpull-up-kohm = <100>;
 	qcom,vref-batt-therm = <1800000>;
diff --git a/arch/arm/boot/dts/msm8926-1080p-cdp.dts b/arch/arm/boot/dts/msm8926-v1-1080p-cdp.dts
similarity index 89%
copy from arch/arm/boot/dts/msm8926-1080p-cdp.dts
copy to arch/arm/boot/dts/msm8926-v1-1080p-cdp.dts
index 33e484a..1b6f971 100644
--- a/arch/arm/boot/dts/msm8926-1080p-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-v1-1080p-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v1.dtsi"
 /include/ "msm8226-1080p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-1080p-mtp.dts b/arch/arm/boot/dts/msm8926-v1-1080p-mtp.dts
similarity index 87%
rename from arch/arm/boot/dts/msm8926-1080p-mtp.dts
rename to arch/arm/boot/dts/msm8926-v1-1080p-mtp.dts
index c1217a2..0812c54 100644
--- a/arch/arm/boot/dts/msm8926-1080p-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-v1-1080p-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v1.dtsi"
 /include/ "msm8226-1080p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-720p-cdp.dts b/arch/arm/boot/dts/msm8926-v1-720p-cdp.dts
similarity index 89%
copy from arch/arm/boot/dts/msm8926-720p-cdp.dts
copy to arch/arm/boot/dts/msm8926-v1-720p-cdp.dts
index 80bb5e6..37da01c 100644
--- a/arch/arm/boot/dts/msm8926-720p-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-v1-720p-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v1.dtsi"
 /include/ "msm8226-720p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-720p-mtp.dts b/arch/arm/boot/dts/msm8926-v1-720p-mtp.dts
similarity index 87%
copy from arch/arm/boot/dts/msm8926-720p-mtp.dts
copy to arch/arm/boot/dts/msm8926-v1-720p-mtp.dts
index 32301fd..7b49930 100644
--- a/arch/arm/boot/dts/msm8926-720p-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-v1-720p-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v1.dtsi"
 /include/ "msm8226-720p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v1-qrd-skug-pvt.dts
similarity index 65%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v1-qrd-skug-pvt.dts
index 8ee8828..fb5bc01 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v1-qrd-skug-pvt.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -11,11 +11,18 @@
  */
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8926-v1.dtsi"
+/include/ "msm8926-qrd-skug.dtsi"
 
 / {
-	model = "Qualcomm MSM 8926 QRD";
+	model = "Qti MSM 8926 QRD SKUG PVT";
 	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
+	qcom,board-id = <0x2000b 5>;
+};
+
+&pm8226_vadc {
+	chan@30 {
+		label = "batt_therm";
+		qcom,scale-function = <9>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v1-qrd-skug.dts
similarity index 73%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v1-qrd-skug.dts
index 8ee8828..0cb6119 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v1-qrd-skug.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -11,11 +11,12 @@
  */
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8926-v1.dtsi"
+/include/ "msm8926-qrd-skug.dtsi"
 
 / {
-	model = "Qualcomm MSM 8926 QRD";
+	model = "Qualcomm MSM 8926 QRD SKUG";
 	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
+	qcom,board-id = <11 5>;
 };
+
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v1-qrd.dts
similarity index 86%
rename from arch/arm/boot/dts/msm8926-qrd.dts
rename to arch/arm/boot/dts/msm8926-v1-qrd.dts
index 8ee8828..fa6ff64 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v1-qrd.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -11,7 +11,7 @@
  */
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v1.dtsi"
 /include/ "msm8226-qrd.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v1.dtsi
similarity index 68%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v1.dtsi
index 8ee8828..c70cf71 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v1.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -10,12 +10,11 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
 /include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
 
 / {
-	model = "Qualcomm MSM 8926 QRD";
-	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
+	qcom,msm-id = <200 0>,
+		      <224 0>,
+		      <200 0x10001>,
+		      <224 0x10001>;
 };
diff --git a/arch/arm/boot/dts/msm8926-1080p-cdp.dts b/arch/arm/boot/dts/msm8926-v2-1080p-cdp.dts
similarity index 89%
rename from arch/arm/boot/dts/msm8926-1080p-cdp.dts
rename to arch/arm/boot/dts/msm8926-v2-1080p-cdp.dts
index 33e484a..a4ebbe1 100644
--- a/arch/arm/boot/dts/msm8926-1080p-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-v2-1080p-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2.dtsi"
 /include/ "msm8226-1080p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-1080p-cdp.dts b/arch/arm/boot/dts/msm8926-v2-1080p-ext-buck-cdp.dts
similarity index 86%
copy from arch/arm/boot/dts/msm8926-1080p-cdp.dts
copy to arch/arm/boot/dts/msm8926-v2-1080p-ext-buck-cdp.dts
index 33e484a..64e872b 100644
--- a/arch/arm/boot/dts/msm8926-1080p-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-v2-1080p-ext-buck-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,14 +12,14 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2-ext-buck.dtsi"
 /include/ "msm8226-1080p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 CDP";
 	compatible = "qcom,msm8926-cdp", "qcom,msm8926", "qcom,cdp";
-	qcom,board-id = <1 2>;
+	qcom,board-id = <1 3>;
 };
 
 &pm8226_chg {
diff --git a/arch/arm/boot/dts/msm8926-1080p-mtp.dts b/arch/arm/boot/dts/msm8926-v2-1080p-ext-buck-mtp.dts
similarity index 83%
copy from arch/arm/boot/dts/msm8926-1080p-mtp.dts
copy to arch/arm/boot/dts/msm8926-v2-1080p-ext-buck-mtp.dts
index c1217a2..f9a3cd8 100644
--- a/arch/arm/boot/dts/msm8926-1080p-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-v2-1080p-ext-buck-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,12 +12,12 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2-ext-buck.dtsi"
 /include/ "msm8226-1080p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm MSM 8926 MTP";
 	compatible = "qcom,msm8926-mtp", "qcom,msm8926", "qcom,mtp";
-	qcom,board-id = <8 2>;
+	qcom,board-id = <8 3>;
 };
diff --git a/arch/arm/boot/dts/msm8926-1080p-mtp.dts b/arch/arm/boot/dts/msm8926-v2-1080p-mtp.dts
similarity index 87%
copy from arch/arm/boot/dts/msm8926-1080p-mtp.dts
copy to arch/arm/boot/dts/msm8926-v2-1080p-mtp.dts
index c1217a2..1f0bab1 100644
--- a/arch/arm/boot/dts/msm8926-1080p-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-v2-1080p-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2.dtsi"
 /include/ "msm8226-1080p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-720p-cdp.dts b/arch/arm/boot/dts/msm8926-v2-720p-cdp.dts
similarity index 89%
rename from arch/arm/boot/dts/msm8926-720p-cdp.dts
rename to arch/arm/boot/dts/msm8926-v2-720p-cdp.dts
index 80bb5e6..1e6e197 100644
--- a/arch/arm/boot/dts/msm8926-720p-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-v2-720p-cdp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2.dtsi"
 /include/ "msm8226-720p-cdp.dtsi"
 /include/ "msm8226-camera-sensor-cdp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-720p-mtp.dts b/arch/arm/boot/dts/msm8926-v2-720p-mtp.dts
similarity index 87%
rename from arch/arm/boot/dts/msm8926-720p-mtp.dts
rename to arch/arm/boot/dts/msm8926-v2-720p-mtp.dts
index 32301fd..59ad506 100644
--- a/arch/arm/boot/dts/msm8926-720p-mtp.dts
+++ b/arch/arm/boot/dts/msm8926-v2-720p-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -12,7 +12,7 @@
 
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2.dtsi"
 /include/ "msm8226-720p-mtp.dtsi"
 /include/ "msm8226-camera-sensor-mtp.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v2-ext-buck.dtsi
similarity index 64%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v2-ext-buck.dtsi
index 8ee8828..07d91a8 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v2-ext-buck.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -10,12 +10,8 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
-/include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8926-v2.dtsi"
 
-/ {
-	model = "Qualcomm MSM 8926 QRD";
-	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
+&soc {
+
 };
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v2-qrd-skug-pvt.dts
similarity index 65%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v2-qrd-skug-pvt.dts
index 8ee8828..f8cd88d 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v2-qrd-skug-pvt.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -11,11 +11,18 @@
  */
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8926-v2.dtsi"
+/include/ "msm8926-qrd-skug.dtsi"
 
 / {
-	model = "Qualcomm MSM 8926 QRD";
+	model = "Qti MSM 8926 QRD SKUG PVT";
 	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
+	qcom,board-id = <0x2000b 5>;
+};
+
+&pm8226_vadc {
+	chan@30 {
+		label = "batt_therm";
+		qcom,scale-function = <9>;
+	};
 };
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v2-qrd-skug.dts
similarity index 73%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v2-qrd-skug.dts
index 8ee8828..0d69e51 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v2-qrd-skug.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -11,11 +11,12 @@
  */
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8926-v2.dtsi"
+/include/ "msm8926-qrd-skug.dtsi"
 
 / {
-	model = "Qualcomm MSM 8926 QRD";
+	model = "Qualcomm MSM 8926 QRD SKUG";
 	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
+	qcom,board-id = <11 5>;
 };
+
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/arch/arm/boot/dts/msm8926-v2-qrd.dts
similarity index 86%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to arch/arm/boot/dts/msm8926-v2-qrd.dts
index 8ee8828..6223055 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/arch/arm/boot/dts/msm8926-v2-qrd.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -11,7 +11,7 @@
  */
 
 /dts-v1/;
-/include/ "msm8926.dtsi"
+/include/ "msm8926-v2.dtsi"
 /include/ "msm8226-qrd.dtsi"
 
 / {
diff --git a/arch/arm/boot/dts/msm8926-v2.dtsi b/arch/arm/boot/dts/msm8926-v2.dtsi
new file mode 100644
index 0000000..db8e02f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8926-v2.dtsi
@@ -0,0 +1,71 @@
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/include/ "msm8926.dtsi"
+
+/ {
+	qcom,msm-id = <200 0x20000>,
+		      <224 0x20000>;
+};
+
+&msm_gpu {
+	/* Updated chip ID */
+	qcom,chipid = <0x03000512>;
+
+	/* Bus Scale Settings */
+	qcom,msm-bus,num-cases = <4>;
+	qcom,msm-bus,vectors-KBps =
+		<26 512 0 0>, <89 604 0 0>,
+		<26 512 0 1800000>, <89 604 0 3200000>,
+		<26 512 0 3600000>, <89 604 0 5120000>,
+		<26 512 0 4800000>, <89 604 0 6400000>;
+
+	/* Power levels */
+	qcom,gpu-pwrlevels {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "qcom,gpu-pwrlevels";
+
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <500000000>;
+			qcom,bus-freq = <3>;
+			qcom,io-fraction = <0>;
+		};
+
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <320000000>;
+			qcom,bus-freq = <2>;
+			qcom,io-fraction = <33>;
+		};
+
+		qcom,gpu-pwrlevel@2 {
+			reg = <2>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <1>;
+			qcom,io-fraction = <100>;
+		};
+
+		qcom,gpu-pwrlevel@3 {
+			reg = <3>;
+			qcom,gpu-freq = <19000000>;
+			qcom,bus-freq = <0>;
+			qcom,io-fraction = <0>;
+		};
+	};
+};
+
+&apc_vreg_corner {
+	/delete-property/ qcom,cpr-enable;
+};
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 0b876a1..2bb202f 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -22,10 +22,40 @@
 / {
 	model = "Qualcomm MSM 8926";
 	compatible = "qcom,msm8926";
-	qcom,msm-id = <200 0>,
-		      <224 0>,
-		      <200 0x10001>,
-		      <224 0x10001>;
+};
+
+&i2c_0 {
+	qcom,sda-gpio = <&msmgpio 14 0>;
+	qcom,scl-gpio = <&msmgpio 15 0>;
+
+	ncp6335d: ncp6335d-regulator@1c {
+		compatible = "onnn,ncp6335d-regulator";
+		reg = <0x1c>;
+		onnn,vsel = <0>;
+		onnn,slew-ns = <2666>;
+		onnn,step-size = <10000>;
+		onnn,min-slew-ns = <333>;
+		onnn,max-slew-ns = <2666>;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1350000>;
+		onnn,min-setpoint = <600000>;
+		onnn,vsel-gpio = <&msmgpio 2 1>;
+		onnn,discharge-enable;
+		onnn,restore-reg;
+		onnn,tlmm-config = <0x80 0x0>;
+	};
+
+	fan53555: fan53555-regulator@60 {
+		compatible = "fairchild,fan53555-regulator";
+		reg = <0x60>;
+		fairchild,backup-vsel = <1>;
+		regulator-min-microvolt = <1050000>;
+		regulator-max-microvolt = <1350000>;
+		regulator-ramp-delay = <8000>;
+		fairchild,vsel-gpio = <&msmgpio 2 1>;
+		fairchild,restore-reg;
+		fairchild,disable-suspend;
+	};
 };
 
 &soc {
@@ -39,10 +69,32 @@
 		vdd_mss-supply = <&pm8226_s5>;
 	};
 
-	qcom,acpuclk@f9011050 {
+	qcom,clock-a7@f9011050 {
 		reg =	<0xf9011050 0x8>,
 			<0xfc4b80b0 0x8>;
-		reg-names = "rcg_base", "pte_efuse";
+		reg-names = "rcg-base", "efuse";
+		qcom,speed0-bin-v1 =
+			<         0 0>,
+			< 384000000 2>,
+			< 787200000 4>,
+			<1190400000 7>;
+		qcom,speed2-bin-v1 =
+			<         0 0>,
+			< 384000000 2>,
+			< 787200000 4>,
+			<1401600000 10>;
+		qcom,speed1-bin-v1 =
+			<         0 0>,
+			< 384000000 2>,
+			< 787200000 4>,
+			< 998400000 5>,
+			<1094400000 6>,
+			<1190400000 7>,
+			<1305600000 8>,
+			<1344000000 9>,
+			<1401600000 10>,
+			<1497600000 11>,
+			<1593600000 12>;
 	};
 
 	qcom,msm-thermal {
@@ -116,20 +168,23 @@
 };
 
 &apc_vreg_corner {
-	qti,pvs-init-voltage = <1350000 1340000 1330000 1320000 1310000
+	qcom,pvs-init-voltage = <1350000 1340000 1330000 1320000 1310000
 					1300000 1290000 1280000 1270000 1260000
 					1250000 1240000 1230000 1220000 1210000
 					1200000 1190000 1180000 1170000 1160000
 					1150000 1140000 1140000 1140000 1140000
 					1140000 1140000 1140000 1140000 1140000
 					1140000 1140000>;
-	qti,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
-	qti,pvs-corner-ceiling-nom  = <1050000 1080000 1200000>;
-	qti,pvs-corner-ceiling-fast = <1050000 1050000 1100000>;
-	qti,cpr-step-quotient = <30>;
-	qti,cpr-up-threshold = <0>;
-	qti,cpr-down-threshold = <5>;
-	qti,cpr-apc-volt-step = <10000>;
+	qcom,pvs-corner-ceiling-slow = <1050000 1150000 1280000>;
+	qcom,pvs-corner-ceiling-nom  = <1050000 1080000 1200000>;
+	qcom,pvs-corner-ceiling-fast = <1050000 1050000 1100000>;
+	qcom,cpr-step-quotient = <30>;
+	qcom,cpr-up-threshold = <0>;
+	qcom,cpr-down-threshold = <2>;
+	qcom,cpr-apc-volt-step = <10000>;
+	qcom,cpr-quotient-adjustment = <0 72 72>;
+	vdd-apc-optional-prim-supply = <&ncp6335d>;
+	vdd-apc-optional-sec-supply = <&fan53555>;
 };
 
 &tsens {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index af51327..b33b2b5 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -1168,12 +1168,18 @@
 			qcom,masterp = <0>;
 			qcom,tier = <2>;
 			qcom,hw-sel = "BIMC";
-			qcom,mode = "Fixed";
+			qcom,mode = "Limiter";
 			qcom,qport = <0>;
 			qcom,ws = <10000>;
 			qcom,mas-hw-id = <0>;
 			qcom,prio-rd = <0>;
 			qcom,prio-wr = <0>;
+			qcom,mode-thresh = "Fixed";
+			qcom,thresh = <2000000>;
+			qcom,dual-conf;
+			qcom,bimc,bw = <300000>;
+			qcom,bimc,gp = <5000>;
+			qcom,bimc,thmp = <50>;
 		};
 
 		mas-ampss-m1 {
@@ -1182,12 +1188,18 @@
 			qcom,masterp = <1>;
 			qcom,tier = <2>;
 			qcom,hw-sel = "BIMC";
-			qcom,mode = "Fixed";
+			qcom,mode = "Limiter";
 			qcom,qport = <1>;
 			qcom,ws = <10000>;
 			qcom,mas-hw-id = <0>;
 			qcom,prio-rd = <0>;
 			qcom,prio-wr = <0>;
+			qcom,mode-thresh = "Fixed";
+			qcom,thresh = <2000000>;
+			qcom,dual-conf;
+			qcom,bimc,bw = <300000>;
+			qcom,bimc,gp = <5000>;
+			qcom,bimc,thmp = <50>;
 		};
 
 		mas-mss-proc {
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 9d44bda..29e2aaa 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -16,6 +16,7 @@
 		cell-index = <0>;
 		compatible = "qcom,camera-led-flash";
 		qcom,flash-type = <1>;
+		qcom,torch-source = <&pm8941_torch>;
 		qcom,flash-source = <&pm8941_flash0 &pm8941_flash1>;
 	};
 };
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 9e7b2e6..27536db 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -757,3 +757,11 @@
 &dsi_tosh_720_vid {
        qcom,cont-splash-enabled;
 };
+
+&dsi_generic_720p_cmd {
+       qcom,cont-splash-enabled;
+};
+
+&dsi_jdi_1080_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index d0ca01d..f4b4d4a 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -133,6 +133,20 @@
 		};
 	};
 
+	i2c@f9928000 { /* BLSP1 QUP6 */
+		nfc-nci@e {
+			compatible = "qcom,nfc-nci";
+			reg = <0x0e>;
+			qcom,irq-gpio = <&msmgpio 59 0x00>;
+			qcom,dis-gpio = <&msmgpio 13 0x00>;
+			qcom,clk-src = "BBCLK2";
+			qcom,clk-en-gpio = <&msmgpio 0 0x00>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <59 0>;
+			qcom,clk-gpio = <&pm8941_gpios 32 0>;
+		};
+	};
+
 	i2c@f9967000 {
 		sii8334@72 {
 			compatible = "qcom,mhl-sii8334";
@@ -606,6 +620,11 @@
 	};
 
 	gpio@df00 { /* GPIO 32 */
+		qcom,mode = <0>;		/* QPNP_PIN_MODE_DIG_IN */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,src-sel = <2>;		/* QPNP_PIN_SEL_FUNC_1 */
+		qcom,master-en = <1>;
 	};
 
 	gpio@e000 { /* GPIO 33 */
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 922e3e0..397e10e 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -26,13 +26,13 @@
 
         qcom,mdss_mdp@fd900000 {
                 qcom,mdss-pref-prim-intf = "edp";
-		qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
-		qcom,panel-pwm-period = <53>;
         };
 
 	qcom,mdss_edp@fd923400 {
 		status = "ok";
 		qcom,cont-splash-enabled;
+		qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
+		qcom,panel-pwm-period = <53>;
 	};
 
 	i2c@f9967000 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index e409c94..89f4af8 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -21,6 +21,21 @@
 
 		qcom,max-bandwidth-low-kbps = <2300000>;
 		qcom,max-bandwidth-high-kbps = <3000000>;
+
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "mdss_mdp";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>,
+			<22 512 0 6400000>,
+			<22 512 0 6400000>;
+
+		/* Fudge factors */
+		qcom,mdss-ab-factor = <2 1>;		/* 2 times    */
+		qcom,mdss-ib-factor = <6 5>;		/* 1.2 times  */
+		qcom,mdss-clk-factor = <5 4>;		/* 1.25 times */
+
 		qcom,max-clk-rate = <320000000>;
 		qcom,mdss-pipe-vig-off = <0x00001200 0x00001600
 					       0x00001A00>;
@@ -30,6 +45,11 @@
 		qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
 		qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
 		qcom,mdss-pipe-dma-fetch-id = <10 13>;
+
+		qcom,mdss-pipe-vig-xin-id = <0 4 8>;
+		qcom,mdss-pipe-rgb-xin-id = <1 5 9>;
+		qcom,mdss-pipe-dma-xin-id = <2 10>;
+
 		qcom,mdss-smp-data = <22 4096>;
 
 		qcom,mdss-ctl-off = <0x00000600 0x00000700 0x00000800
@@ -61,6 +81,15 @@
 				    <0x04B0 0xCCCCC0C0>,
 				    <0x04B8 0xCCCCC000>;
 
+		/* buffer parameters to calculate prefill bandwidth */
+		qcom,mdss-prefill-outstanding-buffer-bytes = <1024>;
+		qcom,mdss-prefill-y-buffer-bytes = <4096>;
+		qcom,mdss-prefill-scaler-buffer-lines-bilinear = <2>;
+		qcom,mdss-prefill-scaler-buffer-lines-caf = <4>;
+		qcom,mdss-prefill-post-scaler-buffer-pixels = <0>;
+		qcom,mdss-prefill-pingpong-buffer-pixels = <4096>;
+		qcom,mdss-prefill-fbc-lines = <2>;
+
 		mdss_fb0: qcom,mdss_fb_primary {
 			cell-index = <0>;
 			compatible = "qcom,mdss-fb";
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index f73bcdc..6cc49c4 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -733,3 +733,11 @@
 &dsi_tosh_720_vid {
        qcom,cont-splash-enabled;
 };
+
+&dsi_generic_720p_cmd {
+       qcom,cont-splash-enabled;
+};
+
+&dsi_jdi_1080_vid {
+       qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8974-v1-pm.dtsi b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
index 179edac..886177d 100644
--- a/arch/arm/boot/dts/msm8974-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1-pm.dtsi
@@ -124,7 +124,7 @@
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
 		qcom,saw2-spm-cmd-ret = [1f 00 20 03 22 00 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 20 32 42 07 44 22 50 02 32 50 0f];
+		qcom,saw2-spm-cmd-gdhs = [00 20 32 42 03 44 22 50 02 32 50 0f];
 		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
 				50 02 32 50 0f];
 		qcom,L2-spm-is-apcs-master;
diff --git a/arch/arm/boot/dts/msm8974-v2-pm.dtsi b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
index e2d40f7..5e6efb9 100644
--- a/arch/arm/boot/dts/msm8974-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2-pm.dtsi
@@ -120,7 +120,7 @@
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
 		qcom,saw2-spm-cmd-ret = [1f 00 03 00 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 32 42 07 44 50 02 32 50 0f];
+		qcom,saw2-spm-cmd-gdhs = [00 32 42 03 44 50 02 32 50 0f];
 		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
 				50 02 32 50 0f];
 		qcom,L2-spm-is-apcs-master;
@@ -212,6 +212,7 @@
 			<50 172>, /* usb1_hs_async_wakeup_irq */
 			<53 104>, /* mdss_irq */
 			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 33>,  /* APCC_qgicL2PerfMonIrptReq */
 			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
 			<0xff 35>,  /* WDT_barkInt */
 			<0xff 40>,  /* qtimer_phy_irq */
diff --git a/arch/arm/boot/dts/msm8974-v2.2.dtsi b/arch/arm/boot/dts/msm8974-v2.2.dtsi
index 3ed5720..14897ba 100644
--- a/arch/arm/boot/dts/msm8974-v2.2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.2.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -93,3 +93,7 @@
 	qcom,retain-periph;
 	qcom,retain-mem;
 };
+
+&gdsc_venus {
+	qcom,skip-logic-collapse;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 9176117..5607257 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -122,7 +122,7 @@
 	qcom,dec-ocmem-ab-ib = <0 0>,
 		<176000 519000>,
 		<456000 519000>,
-		<864000 519000>,
+		<864000 629000>,
 		<1728000 1038000>,
 		<2766000 1661000>,
 		<3456000 2076000>,
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index a912da8..030a1f3 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -215,7 +215,7 @@
 		vdd-supply = <&gdsc_venus>;
 		qcom,hfi = "venus";
 		qcom,has-ocmem;
-		qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/
+		qcom,max-hw-load = <1216800>; /* 3840 x 2160 @ 30 + 1080p @ 30*/
 	};
 
 	qcom,vidc {
@@ -911,7 +911,8 @@
 		hfpll-dig-supply = <&pm8841_s2_corner_ao>;
 		hfpll-analog-supply = <&pm8941_l12_ao>;
 		qcom,hfpll-config-val = <0x04D0405D>;
-                qcom,hfpll-user-vco-mask = <0x00100000>;
+		qcom,hfpll-user-vco-mask = <0x00100000>;
+		qcom,pvs-config-ver = <1>;
 
 		qcom,l2-fmax =
 			<          0 0			 >,
@@ -1515,25 +1516,45 @@
 			< 2265600000  925000 691 >;
 	};
 
+	qcom,cpubw {
+		compatible = "qcom,cpubw";
+		qcom,cpu-mem-ports = <1 512>, <2 512>;
+		qcom,bw-tbl =
+			<  572 /*  75 MHz */ >,
+			< 1144 /* 150 MHz */ >,
+			< 1525 /* 200 MHz */ >,
+			< 2342 /* 307 MHz */ >,
+			< 3509 /* 460 MHz */ >,
+			< 4684 /* 614 MHz */ >,
+			< 6103 /* 800 MHz */ >,
+			< 7102 /* 931 MHz */ >;
+	};
+
+	qcom,kraitbw-l2pm {
+		compatible = "qcom,kraitbw-l2pm";
+		interrupts = <0 1 1>;
+		qcom,bytes-per-beat = <8>;
+	};
+
 	qcom,msm-cpufreq@0 {
 		reg = <0 4>;
 		compatible = "qcom,msm-cpufreq";
-		qcom,cpu-mem-ports = <1 512>, <2 512>;
 		qcom,cpufreq-table =
-			<  300000  300000  600 /*  75 MHz */ >,
-			<  422400  422400 1200 /* 150 MHz */ >,
-			<  652800  499200 1600 /* 200 MHz */ >,
-			<  729600  576000 2456 /* 307 MHz */ >,
-			<  883200  576000 2456 /* 307 MHz */ >,
-			<  960000  960000 3680 /* 460 MHz */ >,
-			< 1036800 1036800 3680 /* 460 MHz */ >,
-			< 1190400 1036800 3680 /* 460 MHz */ >,
-			< 1267200 1267200 4912 /* 614 MHz */ >,
-			< 1497600 1497600 4912 /* 614 MHz */ >,
-			< 1574400 1574400 6400 /* 800 MHz */ >,
-			< 1728000 1651200 6400 /* 800 MHz */ >,
-			< 1958400 1728000 7448 /* 931 MHz */ >,
-			< 2265600 1728000 7448 /* 931 MHz */ >;
+			<  300000  300000  572 >,
+			<  422400  422400 1144 >,
+			<  652800  499200 1525 >,
+			<  729600  576000 2342 >,
+			<  883200  576000 2342 >,
+			<  960000  960000 3509 >,
+			< 1036800 1036800 3509 >,
+			< 1190400 1036800 3509 >,
+			< 1267200 1267200 4684 >,
+			< 1497600 1497600 4684 >,
+			< 1574400 1574400 6103 >,
+			< 1728000 1651200 6103 >,
+			< 1958400 1728000 7102 >,
+			< 2265600 1728000 7102 >,
+			< 2457600 1728000 7102 >;
 	};
 
 	usb3: qcom,ssusb@f9200000 {
@@ -1980,8 +2001,8 @@
 		qcom,msm-bus,num-cases = <2>;
 		qcom,msm-bus,num-paths = <1>;
 		qcom,msm-bus,vectors-KBps =
-				<1 618 0 0>,
-				<1 618 0 800>;
+				<88 618 0 0>,
+				<88 618 0 800>;
         };
 
 	qseecom: qcom,qseecom@7b00000 {
@@ -2326,6 +2347,22 @@
 		compatible = "qcom,bcl";
 	};
 
+	i2c@f9928000 { /* BLSP-1 QUP-6 */
+		cell-index = <3>;
+		compatible = "qcom,i2c-qup";
+		reg = <0xf9928000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		interrupts = <0 100 0>;
+		interrupt-names = "qup_err_intr";
+		qcom,i2c-bus-freq = <400000>;
+		qcom,i2c-src-freq = <19200000>;
+		qcom,scl-gpio = <&msmgpio 30 0>;
+		qcom,sda-gpio = <&msmgpio 29 0>;
+		qcom,master-id = <86>;
+	};
+
 	qcom,ssm {
 		compatible = "qcom,ssm";
 		qcom,channel-name = "SSM_RTR";
diff --git a/arch/arm/boot/dts/msm8974pro-ab-pm8941-fluid-hbtp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-fluid-hbtp.dts
new file mode 100644
index 0000000..f4f7968
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-fluid-hbtp.dts
@@ -0,0 +1,42 @@
+/* Copyright (c) 2014, 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/ "msm8974pro-ab-pm8941.dtsi"
+/include/ "msm8974-fluid.dtsi"
+
+/ {
+	model = "Qualcomm MSM 8974Pro-AA/AB FLUID";
+	compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
+	qcom,board-id = <3 1>;
+};
+
+&soc {
+	spi@f9966000 { /* BLSP2 QUP4 */
+		/* Leave the SPI bus for QDSP to use */
+		status = "disabled";
+	};
+
+	hbtp {
+		compatible = "qcom,hbtp";
+		vcc_ana-supply = <&pm8941_l18>;
+	};
+};
+
+&i2c_0 {
+	/* mhl-sii8334 is on i2c_0 and uses gpio 12 as mhl-pwr-gpio.
+	 * Display panel needs gpio 12 as TE gpio in command mode.
+	 * Disabling the bus to make sure that display gets the gpio.
+	 */
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
index 6b62391..d4bb37b 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -22,5 +22,5 @@
 };
 
 &sdhc_1 {
-	qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+	qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
 };
diff --git a/arch/arm/boot/dts/msm8974pro-pm.dtsi b/arch/arm/boot/dts/msm8974pro-pm.dtsi
index 63cb68b..a1e981e 100644
--- a/arch/arm/boot/dts/msm8974pro-pm.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm.dtsi
@@ -120,7 +120,7 @@
 		qcom,phase-port = <0x1>;
 		qcom,pfm-port = <0x2>;
 		qcom,saw2-spm-cmd-ret = [1f 00 03 00 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 32 42 07 44 50 02 32 50 0f];
+		qcom,saw2-spm-cmd-gdhs = [00 32 42 03 44 50 02 32 50 0f];
 		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
 				50 02 32 50 0f];
 		qcom,L2-spm-is-apcs-master;
@@ -217,7 +217,7 @@
 			<0xff 18>,  /* APCx_qgicQTmrSecPhysIrptReq */
 			<0xff 19>,  /* APCx_qgicQTmrSecPhysIrptReq */
 			<0xff 25>,  /* APCx_qgicExtFaultIrptReq */
-			<0xff 33>, /*l2_perf_mon*/
+			<0xff 33>,  /* APCC_qgicL2PerfMonIrptReq */
 			<0xff 34>,  /* APCC_qgicL2ErrorIrptReq */
 			<0xff 35>,  /* WDT_barkInt */
 			<0xff 40>,  /* qtimer_phy_irq */
diff --git a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
index 2783ffd..8b13c9f 100644
--- a/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
@@ -38,22 +38,22 @@
 
 &krait0_vreg {
 		regulator-max-microvolt = <1120000>;
-		qcom,ldo-delta-voltage = <25000>;
+		qcom,ldo-delta-voltage = <12500>;
 };
 
 &krait1_vreg {
 		regulator-max-microvolt = <1120000>;
-		qcom,ldo-delta-voltage = <25000>;
+		qcom,ldo-delta-voltage = <12500>;
 };
 
 &krait2_vreg {
 		regulator-max-microvolt = <1120000>;
-		qcom,ldo-delta-voltage = <25000>;
+		qcom,ldo-delta-voltage = <12500>;
 };
 
 &krait3_vreg {
 		regulator-max-microvolt = <1120000>;
-		qcom,ldo-delta-voltage = <25000>;
+		qcom,ldo-delta-voltage = <12500>;
 };
 
 &tspp {
diff --git a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
index 00e3b8b..79d7412 100644
--- a/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
@@ -494,7 +494,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <25000>;
+			qcom,ldo-delta-voltage = <12500>;
 			qcom,cpu-num = <0>;
 		};
 
@@ -510,7 +510,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <25000>;
+			qcom,ldo-delta-voltage = <12500>;
 			qcom,cpu-num = <1>;
 		};
 
@@ -526,7 +526,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <25000>;
+			qcom,ldo-delta-voltage = <12500>;
 			qcom,cpu-num = <2>;
 		};
 
@@ -542,7 +542,7 @@
 			qcom,retention-voltage = <675000>;
 			qcom,ldo-default-voltage = <750000>;
 			qcom,ldo-threshold-voltage = <850000>;
-			qcom,ldo-delta-voltage = <25000>;
+			qcom,ldo-delta-voltage = <12500>;
 			qcom,cpu-num = <3>;
 		};
 	};
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 41f02fe..f9cdb6e 100755
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -699,17 +699,17 @@
 			<  345600000  775000   87 >,
 			<  422400000  775000  108 >,
 			<  499200000  775000  129 >,
-			<  576000000  780000  150 >,
-			<  652800000  790000  171 >,
-			<  729600000  800000  193 >,
-			<  806400000  810000  215 >,
-			<  883200000  820000  237 >,
-			<  960000000  830000  260 >,
-			< 1036800000  840000  282 >,
-			< 1113600000  850000  306 >,
-			< 1190400000  860000  330 >,
-			< 1267200000  870000  354 >,
-			< 1344000000  880000  378 >,
+			<  576000000  785000  150 >,
+			<  652800000  795000  171 >,
+			<  729600000  805000  193 >,
+			<  806400000  815000  215 >,
+			<  883200000  825000  237 >,
+			<  960000000  835000  260 >,
+			< 1036800000  845000  282 >,
+			< 1113600000  855000  306 >,
+			< 1190400000  865000  330 >,
+			< 1267200000  875000  354 >,
+			< 1344000000  885000  378 >,
 			< 1420800000  895000  404 >,
 			< 1497600000  910000  431 >,
 			< 1574400000  925000  458 >,
@@ -730,18 +730,18 @@
 			<  345600000  775000   87 >,
 			<  422400000  775000  108 >,
 			<  499200000  775000  129 >,
-			<  576000000  775000  150 >,
-			<  652800000  780000  171 >,
-			<  729600000  790000  193 >,
-			<  806400000  800000  215 >,
-			<  883200000  810000  237 >,
-			<  960000000  820000  260 >,
-			< 1036800000  830000  282 >,
-			< 1113600000  840000  306 >,
-			< 1190400000  850000  330 >,
-			< 1267200000  860000  354 >,
-			< 1344000000  870000  378 >,
-			< 1420800000  885000  404 >,
+			<  576000000  780000  150 >,
+			<  652800000  790000  171 >,
+			<  729600000  800000  193 >,
+			<  806400000  810000  215 >,
+			<  883200000  820000  237 >,
+			<  960000000  830000  260 >,
+			< 1036800000  840000  282 >,
+			< 1113600000  850000  306 >,
+			< 1190400000  860000  330 >,
+			< 1267200000  870000  354 >,
+			< 1344000000  880000  378 >,
+			< 1420800000  890000  404 >,
 			< 1497600000  900000  431 >,
 			< 1574400000  915000  458 >,
 			< 1651200000  930000  486 >,
@@ -762,17 +762,17 @@
 			<  422400000  775000  108 >,
 			<  499200000  775000  129 >,
 			<  576000000  775000  150 >,
-			<  652800000  775000  171 >,
-			<  729600000  780000  193 >,
-			<  806400000  790000  215 >,
-			<  883200000  800000  237 >,
-			<  960000000  810000  260 >,
-			< 1036800000  820000  282 >,
-			< 1113600000  830000  306 >,
-			< 1190400000  840000  330 >,
-			< 1267200000  850000  354 >,
-			< 1344000000  860000  378 >,
-			< 1420800000  875000  404 >,
+			<  652800000  780000  171 >,
+			<  729600000  790000  193 >,
+			<  806400000  800000  215 >,
+			<  883200000  810000  237 >,
+			<  960000000  820000  260 >,
+			< 1036800000  830000  282 >,
+			< 1113600000  840000  306 >,
+			< 1190400000  850000  330 >,
+			< 1267200000  860000  354 >,
+			< 1344000000  870000  378 >,
+			< 1420800000  880000  404 >,
 			< 1497600000  890000  431 >,
 			< 1574400000  905000  458 >,
 			< 1651200000  920000  486 >,
@@ -794,17 +794,17 @@
 			<  499200000  775000  129 >,
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
-			<  729600000  775000  193 >,
-			<  806400000  780000  215 >,
-			<  883200000  790000  237 >,
-			<  960000000  800000  260 >,
-			< 1036800000  810000  282 >,
-			< 1113600000  820000  306 >,
-			< 1190400000  830000  330 >,
-			< 1267200000  840000  354 >,
-			< 1344000000  850000  378 >,
-			< 1420800000  865000  404 >,
-			< 1497600000  880000  431 >,
+			<  729600000  785000  193 >,
+			<  806400000  795000  215 >,
+			<  883200000  805000  237 >,
+			<  960000000  815000  260 >,
+			< 1036800000  825000  282 >,
+			< 1113600000  835000  306 >,
+			< 1190400000  845000  330 >,
+			< 1267200000  855000  354 >,
+			< 1344000000  865000  378 >,
+			< 1420800000  875000  404 >,
+			< 1497600000  885000  431 >,
 			< 1574400000  895000  458 >,
 			< 1651200000  910000  486 >,
 			< 1728000000  925000  515 >,
@@ -825,18 +825,18 @@
 			<  499200000  775000  129 >,
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
-			<  729600000  775000  193 >,
-			<  806400000  775000  215 >,
-			<  883200000  780000  237 >,
-			<  960000000  790000  260 >,
-			< 1036800000  800000  282 >,
-			< 1113600000  810000  306 >,
-			< 1190400000  820000  330 >,
-			< 1267200000  830000  354 >,
-			< 1344000000  840000  378 >,
-			< 1420800000  855000  404 >,
-			< 1497600000  870000  431 >,
-			< 1574400000  885000  458 >,
+			<  729600000  780000  193 >,
+			<  806400000  790000  215 >,
+			<  883200000  800000  237 >,
+			<  960000000  810000  260 >,
+			< 1036800000  820000  282 >,
+			< 1113600000  830000  306 >,
+			< 1190400000  840000  330 >,
+			< 1267200000  850000  354 >,
+			< 1344000000  860000  378 >,
+			< 1420800000  870000  404 >,
+			< 1497600000  880000  431 >,
+			< 1574400000  890000  458 >,
 			< 1651200000  900000  486 >,
 			< 1728000000  915000  515 >,
 			< 1804800000  930000  543 >,
@@ -857,18 +857,18 @@
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
 			<  729600000  775000  193 >,
-			<  806400000  775000  215 >,
-			<  883200000  775000  237 >,
-			<  960000000  780000  260 >,
-			< 1036800000  790000  282 >,
-			< 1113600000  800000  306 >,
-			< 1190400000  810000  330 >,
-			< 1267200000  820000  354 >,
-			< 1344000000  830000  378 >,
-			< 1420800000  845000  404 >,
-			< 1497600000  860000  431 >,
-			< 1574400000  875000  458 >,
-			< 1651200000  890000  486 >,
+			<  806400000  785000  215 >,
+			<  883200000  795000  237 >,
+			<  960000000  805000  260 >,
+			< 1036800000  815000  282 >,
+			< 1113600000  825000  306 >,
+			< 1190400000  835000  330 >,
+			< 1267200000  845000  354 >,
+			< 1344000000  855000  378 >,
+			< 1420800000  865000  404 >,
+			< 1497600000  875000  431 >,
+			< 1574400000  885000  458 >,
+			< 1651200000  895000  486 >,
 			< 1728000000  905000  515 >,
 			< 1804800000  920000  543 >,
 			< 1881600000  935000  572 >,
@@ -888,19 +888,19 @@
 			<  576000000  775000  150 >,
 			<  652800000  775000  171 >,
 			<  729600000  775000  193 >,
-			<  806400000  775000  215 >,
-			<  883200000  775000  237 >,
-			<  960000000  775000  260 >,
-			< 1036800000  780000  282 >,
-			< 1113600000  790000  306 >,
-			< 1190400000  800000  330 >,
-			< 1267200000  810000  354 >,
-			< 1344000000  820000  378 >,
-			< 1420800000  835000  404 >,
-			< 1497600000  850000  431 >,
-			< 1574400000  865000  458 >,
-			< 1651200000  880000  486 >,
-			< 1728000000  895000  515 >,
+			<  806400000  780000  215 >,
+			<  883200000  790000  237 >,
+			<  960000000  800000  260 >,
+			< 1036800000  810000  282 >,
+			< 1113600000  820000  306 >,
+			< 1190400000  830000  330 >,
+			< 1267200000  840000  354 >,
+			< 1344000000  850000  378 >,
+			< 1420800000  860000  404 >,
+			< 1497600000  870000  431 >,
+			< 1574400000  880000  458 >,
+			< 1651200000  890000  486 >,
+			< 1728000000  900000  515 >,
 			< 1804800000  910000  543 >,
 			< 1881600000  925000  572 >,
 			< 1958400000  940000  604 >,
@@ -920,19 +920,19 @@
 			<  652800000  775000  171 >,
 			<  729600000  775000  193 >,
 			<  806400000  775000  215 >,
-			<  883200000  775000  237 >,
-			<  960000000  775000  260 >,
-			< 1036800000  775000  282 >,
-			< 1113600000  780000  306 >,
-			< 1190400000  790000  330 >,
-			< 1267200000  800000  354 >,
-			< 1344000000  810000  378 >,
-			< 1420800000  825000  404 >,
-			< 1497600000  840000  431 >,
-			< 1574400000  855000  458 >,
-			< 1651200000  870000  486 >,
-			< 1728000000  885000  515 >,
-			< 1804800000  900000  543 >,
+			<  883200000  785000  237 >,
+			<  960000000  795000  260 >,
+			< 1036800000  805000  282 >,
+			< 1113600000  815000  306 >,
+			< 1190400000  825000  330 >,
+			< 1267200000  835000  354 >,
+			< 1344000000  845000  378 >,
+			< 1420800000  855000  404 >,
+			< 1497600000  865000  431 >,
+			< 1574400000  875000  458 >,
+			< 1651200000  885000  486 >,
+			< 1728000000  895000  515 >,
+			< 1804800000  905000  543 >,
 			< 1881600000  915000  572 >,
 			< 1958400000  930000  604 >,
 			< 2035200000  945000  636 >,
@@ -949,22 +949,22 @@
 			<  499200000  750000  129 >,
 			<  576000000  750000  150 >,
 			<  652800000  750000  171 >,
-			<  729600000  750000  193 >,
-			<  806400000  750000  215 >,
-			<  883200000  750000  237 >,
-			<  960000000  750000  260 >,
-			< 1036800000  760000  282 >,
-			< 1113600000  770000  306 >,
-			< 1190400000  780000  330 >,
-			< 1267200000  790000  354 >,
-			< 1344000000  800000  378 >,
-			< 1420800000  815000  404 >,
-			< 1497600000  830000  431 >,
-			< 1574400000  845000  458 >,
-			< 1651200000  860000  486 >,
-			< 1728000000  875000  515 >,
-			< 1804800000  890000  543 >,
-			< 1881600000  905000  572 >,
+			<  729600000  760000  193 >,
+			<  806400000  770000  215 >,
+			<  883200000  780000  237 >,
+			<  960000000  790000  260 >,
+			< 1036800000  800000  282 >,
+			< 1113600000  810000  306 >,
+			< 1190400000  820000  330 >,
+			< 1267200000  830000  354 >,
+			< 1344000000  840000  378 >,
+			< 1420800000  850000  404 >,
+			< 1497600000  860000  431 >,
+			< 1574400000  870000  458 >,
+			< 1651200000  880000  486 >,
+			< 1728000000  890000  515 >,
+			< 1804800000  900000  543 >,
+			< 1881600000  910000  572 >,
 			< 1958400000  920000  604 >,
 			< 2035200000  935000  636 >,
 			< 2112000000  950000  669 >,
@@ -980,23 +980,23 @@
 			<  499200000  750000  129 >,
 			<  576000000  750000  150 >,
 			<  652800000  750000  171 >,
-			<  729600000  750000  193 >,
-			<  806400000  750000  215 >,
-			<  883200000  750000  237 >,
-			<  960000000  750000  260 >,
-			< 1036800000  750000  282 >,
-			< 1113600000  760000  306 >,
-			< 1190400000  770000  330 >,
-			< 1267200000  780000  354 >,
-			< 1344000000  790000  378 >,
-			< 1420800000  805000  404 >,
-			< 1497600000  820000  431 >,
-			< 1574400000  835000  458 >,
-			< 1651200000  850000  486 >,
-			< 1728000000  865000  515 >,
-			< 1804800000  880000  543 >,
-			< 1881600000  895000  572 >,
-			< 1958400000  910000  604 >,
+			<  729600000  755000  193 >,
+			<  806400000  765000  215 >,
+			<  883200000  775000  237 >,
+			<  960000000  785000  260 >,
+			< 1036800000  795000  282 >,
+			< 1113600000  805000  306 >,
+			< 1190400000  815000  330 >,
+			< 1267200000  825000  354 >,
+			< 1344000000  835000  378 >,
+			< 1420800000  845000  404 >,
+			< 1497600000  855000  431 >,
+			< 1574400000  865000  458 >,
+			< 1651200000  875000  486 >,
+			< 1728000000  885000  515 >,
+			< 1804800000  895000  543 >,
+			< 1881600000  905000  572 >,
+			< 1958400000  915000  604 >,
 			< 2035200000  925000  636 >,
 			< 2112000000  940000  669 >,
 			< 2150400000  955000  703 >,
@@ -1249,18 +1249,18 @@
 			<  499200000  775000  126 >,
 			<  576000000  775000  147 >,
 			<  652800000  775000  168 >,
-			<  729600000  775000  189 >,
-			<  806400000  780000  211 >,
-			<  883200000  790000  233 >,
-			<  960000000  800000  256 >,
-			< 1036800000  810000  278 >,
-			< 1113600000  820000  301 >,
-			< 1190400000  830000  324 >,
-			< 1267200000  840000  348 >,
-			< 1344000000  850000  372 >,
-			< 1420800000  860000  396 >,
-			< 1497600000  870000  421 >,
-			< 1574400000  880000  446 >,
+			<  729600000  780000  189 >,
+			<  806400000  785000  211 >,
+			<  883200000  795000  233 >,
+			<  960000000  805000  256 >,
+			< 1036800000  815000  278 >,
+			< 1113600000  825000  301 >,
+			< 1190400000  835000  324 >,
+			< 1267200000  845000  348 >,
+			< 1344000000  855000  372 >,
+			< 1420800000  865000  396 >,
+			< 1497600000  875000  421 >,
+			< 1574400000  885000  446 >,
 			< 1651200000  895000  473 >,
 			< 1728000000  910000  501 >,
 			< 1804800000  925000  529 >,
@@ -1284,17 +1284,17 @@
 			<  576000000  775000  147 >,
 			<  652800000  775000  168 >,
 			<  729600000  775000  189 >,
-			<  806400000  775000  211 >,
-			<  883200000  780000  233 >,
-			<  960000000  790000  256 >,
-			< 1036800000  800000  278 >,
-			< 1113600000  810000  301 >,
-			< 1190400000  820000  324 >,
-			< 1267200000  830000  348 >,
-			< 1344000000  840000  372 >,
-			< 1420800000  850000  396 >,
-			< 1497600000  860000  421 >,
-			< 1574400000  870000  446 >,
+			<  806400000  780000  211 >,
+			<  883200000  785000  233 >,
+			<  960000000  795000  256 >,
+			< 1036800000  805000  278 >,
+			< 1113600000  815000  301 >,
+			< 1190400000  825000  324 >,
+			< 1267200000  835000  348 >,
+			< 1344000000  845000  372 >,
+			< 1420800000  855000  396 >,
+			< 1497600000  865000  421 >,
+			< 1574400000  875000  446 >,
 			< 1651200000  885000  473 >,
 			< 1728000000  900000  501 >,
 			< 1804800000  915000  529 >,
@@ -1319,17 +1319,17 @@
 			<  652800000  775000  168 >,
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
-			<  883200000  775000  233 >,
-			<  960000000  780000  256 >,
-			< 1036800000  790000  278 >,
-			< 1113600000  800000  301 >,
-			< 1190400000  810000  324 >,
-			< 1267200000  820000  348 >,
-			< 1344000000  830000  372 >,
-			< 1420800000  840000  396 >,
-			< 1497600000  850000  421 >,
-			< 1574400000  860000  446 >,
-			< 1651200000  875000  473 >,
+			<  883200000  780000  233 >,
+			<  960000000  790000  256 >,
+			< 1036800000  800000  278 >,
+			< 1113600000  810000  301 >,
+			< 1190400000  820000  324 >,
+			< 1267200000  830000  348 >,
+			< 1344000000  840000  372 >,
+			< 1420800000  850000  396 >,
+			< 1497600000  860000  421 >,
+			< 1574400000  870000  446 >,
+			< 1651200000  880000  473 >,
 			< 1728000000  890000  501 >,
 			< 1804800000  905000  529 >,
 			< 1881600000  920000  558 >,
@@ -1353,18 +1353,18 @@
 			<  652800000  775000  168 >,
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
-			<  883200000  775000  233 >,
-			<  960000000  775000  256 >,
-			< 1036800000  780000  278 >,
-			< 1113600000  790000  301 >,
-			< 1190400000  800000  324 >,
-			< 1267200000  810000  348 >,
-			< 1344000000  820000  372 >,
-			< 1420800000  830000  396 >,
-			< 1497600000  840000  421 >,
-			< 1574400000  850000  446 >,
-			< 1651200000  865000  473 >,
-			< 1728000000  880000  501 >,
+			<  883200000  780000  233 >,
+			<  960000000  785000  256 >,
+			< 1036800000  795000  278 >,
+			< 1113600000  805000  301 >,
+			< 1190400000  815000  324 >,
+			< 1267200000  825000  348 >,
+			< 1344000000  835000  372 >,
+			< 1420800000  845000  396 >,
+			< 1497600000  855000  421 >,
+			< 1574400000  865000  446 >,
+			< 1651200000  875000  473 >,
+			< 1728000000  885000  501 >,
 			< 1804800000  895000  529 >,
 			< 1881600000  910000  558 >,
 			< 1958400000  925000  588 >,
@@ -1388,18 +1388,18 @@
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
 			<  883200000  775000  233 >,
-			<  960000000  775000  256 >,
-			< 1036800000  775000  278 >,
-			< 1113600000  780000  301 >,
-			< 1190400000  790000  324 >,
-			< 1267200000  800000  348 >,
-			< 1344000000  810000  372 >,
-			< 1420800000  820000  396 >,
-			< 1497600000  830000  421 >,
-			< 1574400000  840000  446 >,
-			< 1651200000  855000  473 >,
-			< 1728000000  870000  501 >,
-			< 1804800000  885000  529 >,
+			<  960000000  780000  256 >,
+			< 1036800000  790000  278 >,
+			< 1113600000  800000  301 >,
+			< 1190400000  810000  324 >,
+			< 1267200000  820000  348 >,
+			< 1344000000  830000  372 >,
+			< 1420800000  840000  396 >,
+			< 1497600000  850000  421 >,
+			< 1574400000  860000  446 >,
+			< 1651200000  870000  473 >,
+			< 1728000000  880000  501 >,
+			< 1804800000  890000  529 >,
 			< 1881600000  900000  558 >,
 			< 1958400000  915000  588 >,
 			< 2035200000  930000  617 >,
@@ -1422,19 +1422,19 @@
 			<  729600000  775000  189 >,
 			<  806400000  775000  211 >,
 			<  883200000  775000  233 >,
-			<  960000000  775000  256 >,
-			< 1036800000  775000  278 >,
-			< 1113600000  775000  301 >,
-			< 1190400000  780000  324 >,
-			< 1267200000  790000  348 >,
-			< 1344000000  800000  372 >,
-			< 1420800000  810000  396 >,
-			< 1497600000  820000  421 >,
-			< 1574400000  830000  446 >,
-			< 1651200000  845000  473 >,
-			< 1728000000  860000  501 >,
-			< 1804800000  875000  529 >,
-			< 1881600000  890000  558 >,
+			<  960000000  780000  256 >,
+			< 1036800000  785000  278 >,
+			< 1113600000  795000  301 >,
+			< 1190400000  805000  324 >,
+			< 1267200000  815000  348 >,
+			< 1344000000  825000  372 >,
+			< 1420800000  835000  396 >,
+			< 1497600000  845000  421 >,
+			< 1574400000  855000  446 >,
+			< 1651200000  865000  473 >,
+			< 1728000000  875000  501 >,
+			< 1804800000  885000  529 >,
+			< 1881600000  895000  558 >,
 			< 1958400000  905000  588 >,
 			< 2035200000  920000  617 >,
 			< 2112000000  935000  649 >,
@@ -1457,19 +1457,19 @@
 			<  806400000  775000  211 >,
 			<  883200000  775000  233 >,
 			<  960000000  775000  256 >,
-			< 1036800000  775000  278 >,
-			< 1113600000  775000  301 >,
-			< 1190400000  775000  324 >,
-			< 1267200000  780000  348 >,
-			< 1344000000  790000  372 >,
-			< 1420800000  800000  396 >,
-			< 1497600000  810000  421 >,
-			< 1574400000  820000  446 >,
-			< 1651200000  835000  473 >,
-			< 1728000000  850000  501 >,
-			< 1804800000  865000  529 >,
-			< 1881600000  880000  558 >,
-			< 1958400000  895000  588 >,
+			< 1036800000  780000  278 >,
+			< 1113600000  790000  301 >,
+			< 1190400000  800000  324 >,
+			< 1267200000  810000  348 >,
+			< 1344000000  820000  372 >,
+			< 1420800000  830000  396 >,
+			< 1497600000  840000  421 >,
+			< 1574400000  850000  446 >,
+			< 1651200000  860000  473 >,
+			< 1728000000  870000  501 >,
+			< 1804800000  880000  529 >,
+			< 1881600000  890000  558 >,
+			< 1958400000  900000  588 >,
 			< 2035200000  910000  617 >,
 			< 2112000000  925000  649 >,
 			< 2150400000  940000  682 >,
@@ -1489,22 +1489,22 @@
 			<  652800000  750000  168 >,
 			<  729600000  750000  189 >,
 			<  806400000  750000  211 >,
-			<  883200000  750000  233 >,
-			<  960000000  750000  256 >,
-			< 1036800000  750000  278 >,
-			< 1113600000  750000  301 >,
-			< 1190400000  760000  324 >,
-			< 1267200000  770000  348 >,
-			< 1344000000  780000  372 >,
-			< 1420800000  790000  396 >,
-			< 1497600000  800000  421 >,
-			< 1574400000  810000  446 >,
-			< 1651200000  825000  473 >,
-			< 1728000000  840000  501 >,
-			< 1804800000  855000  529 >,
-			< 1881600000  870000  558 >,
-			< 1958400000  885000  588 >,
-			< 2035200000  900000  617 >,
+			<  883200000  755000  233 >,
+			<  960000000  765000  256 >,
+			< 1036800000  775000  278 >,
+			< 1113600000  785000  301 >,
+			< 1190400000  795000  324 >,
+			< 1267200000  805000  348 >,
+			< 1344000000  815000  372 >,
+			< 1420800000  825000  396 >,
+			< 1497600000  835000  421 >,
+			< 1574400000  845000  446 >,
+			< 1651200000  855000  473 >,
+			< 1728000000  865000  501 >,
+			< 1804800000  875000  529 >,
+			< 1881600000  885000  558 >,
+			< 1958400000  895000  588 >,
+			< 2035200000  905000  617 >,
 			< 2112000000  915000  649 >,
 			< 2150400000  930000  682 >,
 			< 2188800000  930000  682 >,
@@ -1523,23 +1523,23 @@
 			<  652800000  750000  168 >,
 			<  729600000  750000  189 >,
 			<  806400000  750000  211 >,
-			<  883200000  750000  233 >,
-			<  960000000  750000  256 >,
-			< 1036800000  750000  278 >,
-			< 1113600000  750000  301 >,
-			< 1190400000  750000  324 >,
-			< 1267200000  760000  348 >,
-			< 1344000000  770000  372 >,
-			< 1420800000  780000  396 >,
-			< 1497600000  790000  421 >,
-			< 1574400000  800000  446 >,
-			< 1651200000  815000  473 >,
-			< 1728000000  830000  501 >,
-			< 1804800000  845000  529 >,
-			< 1881600000  860000  558 >,
-			< 1958400000  875000  588 >,
-			< 2035200000  890000  617 >,
-			< 2112000000  905000  649 >,
+			<  883200000  755000  233 >,
+			<  960000000  760000  256 >,
+			< 1036800000  770000  278 >,
+			< 1113600000  780000  301 >,
+			< 1190400000  790000  324 >,
+			< 1267200000  800000  348 >,
+			< 1344000000  810000  372 >,
+			< 1420800000  820000  396 >,
+			< 1497600000  830000  421 >,
+			< 1574400000  840000  446 >,
+			< 1651200000  850000  473 >,
+			< 1728000000  860000  501 >,
+			< 1804800000  870000  529 >,
+			< 1881600000  880000  558 >,
+			< 1958400000  890000  588 >,
+			< 2035200000  900000  617 >,
+			< 2112000000  910000  649 >,
 			< 2150400000  920000  682 >,
 			< 2188800000  920000  682 >,
 			< 2265600000  935000  716 >,
@@ -1548,25 +1548,6 @@
 			< 2457600000  970000  802 >;
 	};
 
-	qcom,msm-cpufreq@0 {
-		qcom,cpufreq-table =
-			<  300000  300000 300 /* 37.5 MHz */ >,
-			<  422400  422400 300 /* 37.5 MHz */ >,
-			<  652800  499200 300 /* 37.5 MHz */ >,
-			<  729600  576000 300 /* 37.5 MHz */ >,
-			<  883200  576000 300 /* 37.5 MHz */ >,
-			<  960000  960000 300 /* 37.5 MHz */ >,
-			< 1036800 1036800 300 /* 37.5 MHz */ >,
-			< 1190400 1036800 300 /* 37.5 MHz */ >,
-			< 1267200 1267200 300 /* 37.5 MHz */ >,
-			< 1497600 1497600 300 /* 37.5 MHz */ >,
-			< 1574400 1574400 300 /* 37.5 MHz */ >,
-			< 1728000 1651200 300 /* 37.5 MHz */ >,
-			< 1958400 1728000 300 /* 37.5 MHz */ >,
-			< 2265600 1728000 300 /* 37.5 MHz */ >,
-			< 2496000 1728000 300 /* 37.5 MHz */ >;
-	};
-
 	i2c@f9928000 { /* BLSP-1 QUP-6 */
 		cell-index = <3>;
 		compatible = "qcom,i2c-qup";
@@ -1635,42 +1616,42 @@
                        reg = <0>;
                        qcom,gpu-freq = <578000000>;
                        qcom,bus-freq = <14>;
-                       qcom,io-fraction = <33>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@1 {
                        reg = <1>;
                        qcom,gpu-freq = <462400000>;
                        qcom,bus-freq = <11>;
-                       qcom,io-fraction = <66>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@2 {
                        reg = <2>;
                        qcom,gpu-freq = <389000000>;
                        qcom,bus-freq = <8>;
-                       qcom,io-fraction = <66>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@3 {
                        reg = <3>;
-                       qcom,gpu-freq = <320000000>;
+                       qcom,gpu-freq = <330000000>;
                        qcom,bus-freq = <5>;
-                       qcom,io-fraction = <100>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@4 {
                        reg = <4>;
                        qcom,gpu-freq = <200000000>;
                        qcom,bus-freq = <2>;
-                       qcom,io-fraction = <100>;
+                       qcom,io-fraction = <101>;
                };
 
                qcom,gpu-pwrlevel@5 {
                        reg = <5>;
                        qcom,gpu-freq = <27000000>;
                        qcom,bus-freq = <0>;
-                       qcom,io-fraction = <0>;
+                       qcom,io-fraction = <101>;
                };
        };
 };
@@ -1720,7 +1701,7 @@
 	qcom,dec-ocmem-ab-ib = <0 0>,
 		<176000 519000>,
 		<456000 519000>,
-		<864000 519000>,
+		<864000 629000>,
 		<1728000 1038000>,
 		<2766000 1661000>,
 		<3456000 2076000>,
@@ -1770,3 +1751,7 @@
 	qcom,memblock-remove = <0x05a00000 0x7800000
 				0x0fa00000 0x500000>; /* Address and size of the hole */
 };
+
+&gdsc_venus {
+	qcom,skip-logic-collapse;
+};
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 968a5ee..823e4f8 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -301,6 +301,11 @@
 # CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_EHCI_HCD=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 1e32cfa..3dd9c55 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -216,10 +216,12 @@
 CONFIG_BT_HCISMD=y
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
 CONFIG_CMA=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_QSEECOM=y
+CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -250,6 +252,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -260,6 +263,10 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
@@ -296,6 +303,8 @@
 CONFIG_THERMAL_QPNP_ADC_TM=y
 CONFIG_WCD9306_CODEC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_FAN53555=y
+CONFIG_REGULATOR_ONSEMI_NCP6335D=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_REGULATOR_QPNP=y
 CONFIG_MEDIA_SUPPORT=y
@@ -348,6 +357,8 @@
 CONFIG_UHID=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_MON=y
@@ -356,6 +367,7 @@
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
+CONFIG_USB_CCID_BRIDGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
@@ -455,8 +467,6 @@
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
-CONFIG_TOUCHSCREEN_GT9XX=y
-CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
 CONFIG_MSM_RDBG=m
 CONFIG_DEVMEM=n
 CONFIG_DEVKMEM=n
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index cedb6dc..38171e6 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -221,6 +221,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_QSEECOM=y
+CONFIG_USB_HSIC_SMSC_HUB=y
 CONFIG_SCSI=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
@@ -251,6 +252,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -261,6 +263,10 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
@@ -299,6 +305,8 @@
 CONFIG_THERMAL_QPNP_ADC_TM=y
 CONFIG_WCD9306_CODEC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_FAN53555=y
+CONFIG_REGULATOR_ONSEMI_NCP6335D=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_REGULATOR_QPNP=y
 CONFIG_MEDIA_SUPPORT=y
@@ -373,6 +381,8 @@
 CONFIG_UHID=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_MON=y
@@ -381,6 +391,7 @@
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_MSM_HSIC=y
 CONFIG_USB_ACM=y
+CONFIG_USB_CCID_BRIDGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
@@ -509,6 +520,4 @@
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
 CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
-CONFIG_TOUCHSCREEN_GT9XX=y
-CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
 CONFIG_MSM_RDBG=m
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index e46bfef..c7abf42 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -78,7 +78,6 @@
 CONFIG_KSM=y
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_KSM=y
-CONFIG_ENABLE_VMALLOC_SAVING=y
 CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -207,6 +206,7 @@
 CONFIG_BT_HCISMD=y
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
 CONFIG_CMA=y
 CONFIG_CMA_SIZE_MBYTES=4
 CONFIG_BLK_DEV_LOOP=y
@@ -223,6 +223,9 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+# CONFIG_INPUT_MOUSEDEV is not set
+>>>>>>> 3e5f4f6... defconfig: Enable WCNSS register dump on WCNSS bite
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -235,6 +238,8 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_TOUCHSCREEN_GT9XX=y
 CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
@@ -328,6 +333,8 @@
 CONFIG_UHID=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 899ed30..fe84f96 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -79,7 +79,6 @@
 CONFIG_KSM=y
 CONFIG_CC_STACKPROTECTOR=y
 CONFIG_KSM=y
-CONFIG_ENABLE_VMALLOC_SAVING=y
 CONFIG_CP_ACCESS=y
 CONFIG_USE_OF=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -225,6 +224,9 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+# CONFIG_INPUT_MOUSEDEV is not set
+>>>>>>> 3e5f4f6... defconfig: Enable WCNSS register dump on WCNSS bite
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -237,6 +239,8 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_TOUCHSCREEN_GT9XX=y
 CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_GT9XX_TOUCHPANEL_UPDATE=y
+CONFIG_GT9XX_TOUCHPANEL_DEBUG=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_INPUT_GPIO=m
@@ -351,6 +355,8 @@
 CONFIG_UHID=y
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 10f2919..915b1c3 100755
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -245,6 +245,7 @@
 CONFIG_MSM_BT_POWER=y
 CONFIG_CFG80211=y
 CONFIG_NL80211_TESTMODE=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
 CONFIG_RFKILL=y
 CONFIG_GENLOCK=y
 CONFIG_GENLOCK_MISCDEVICE=y
@@ -282,6 +283,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -293,6 +295,7 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_HSL=y
@@ -389,6 +392,7 @@
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_XHCI_HCD=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 0b9ba76..f1c285d 100755
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -82,7 +82,6 @@
 CONFIG_MSM_L1_ERR_LOG=y
 CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
 CONFIG_MSM_L2_ERP_PORT_PANIC=y
-CONFIG_MSM_L2_ERP_1BIT_PANIC=y
 CONFIG_MSM_L2_ERP_2BIT_PANIC=y
 CONFIG_MSM_CACHE_DUMP=y
 CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
@@ -290,6 +289,7 @@
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -301,6 +301,7 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
 CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_UINPUT=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_HSL=y
@@ -397,6 +398,7 @@
 CONFIG_HID_APPLE=y
 CONFIG_HID_MAGICMOUSE=y
 CONFIG_HID_MICROSOFT=y
+CONFIG_HID_ELECOM=y
 CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 CONFIG_USB_SUSPEND=y
 CONFIG_USB_XHCI_HCD=y
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index e1fc42f..d3e2eb6 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -141,6 +141,8 @@
 	struct pmu_hw_events	*(*get_hw_events)(void);
 	int	(*test_set_event_constraints)(struct perf_event *event);
 	int	(*clear_event_constraints)(struct perf_event *event);
+	void		(*save_pm_registers)(void *hcpu);
+	void		(*restore_pm_registers)(void *hcpu);
 };
 
 #define to_arm_pmu(p) (container_of(p, struct arm_pmu, pmu))
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 2eb0c2c..7013a5c 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -148,6 +148,7 @@
 #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
 #define TIF_SYSCALL_TRACE	8
 #define TIF_SYSCALL_AUDIT	9
+#define TIF_SYSCALL_RESTARTSYS	10
 #define TIF_POLLING_NRFLAG	16
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
@@ -163,9 +164,11 @@
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
 #define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
+#define _TIF_SYSCALL_RESTARTSYS	(1 << TIF_SYSCALL_RESTARTSYS)
 
 /* Checks for any syscall work in entry-common.S */
-#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT)
+#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
+			   _TIF_SYSCALL_RESTARTSYS)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 2a3ab6e..7814288 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -197,6 +197,9 @@
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	u64 delta, prev_raw_count, new_raw_count;
 
+	if (event->state <= PERF_EVENT_STATE_OFF)
+		return 0;
+
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
 	new_raw_count = armpmu->read_counter(idx);
@@ -425,15 +428,37 @@
 	return err;
 }
 
-void
+#ifdef CONFIG_SMP
+static __ref int armpmu_cpu_up(int cpu)
+{
+	int ret = 0;
+
+	if (!cpumask_test_cpu(cpu, cpu_online_mask)) {
+		ret = cpu_up(cpu);
+		if (ret)
+			pr_err("Failed to bring up CPU: %d, ret: %d\n",
+			       cpu, ret);
+	}
+	return ret;
+}
+#else
+static inline int armpmu_cpu_up(int cpu)
+{
+	return 0;
+}
+#endif
+
+void __ref
 multicore_free_irq(int irq)
 {
 	int cpu;
+	struct irq_desc *desc = irq_to_desc(irq);
 
 	if (irq >= 0) {
-		for_each_cpu(cpu, cpu_online_mask) {
-			smp_call_function_single(cpu,
-					disable_irq_callback, &irq, 1);
+		for_each_cpu(cpu, desc->percpu_enabled) {
+			if (!armpmu_cpu_up(cpu))
+				smp_call_function_single(cpu,
+						disable_irq_callback, &irq, 1);
 		}
 		free_percpu_irq(irq, &pmu_irq_cookie);
 	}
@@ -716,6 +741,7 @@
 	armpmu->pmu.start = armpmu_start;
 	armpmu->pmu.stop = armpmu_stop;
 	armpmu->pmu.read = armpmu_read;
+	armpmu->pmu.events_across_hotplug = 1;
 }
 
 int armpmu_register(struct arm_pmu *armpmu, char *name, int type)
@@ -826,62 +852,6 @@
 	return 0;
 }
 
-/*
- * PMU hardware loses all context when a CPU goes offline.
- * When a CPU is hotplugged back in, since some hardware registers are
- * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
- * junk values out of them.
- */
-static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
-					unsigned long action, void *hcpu)
-{
-	int irq;
-
-	if (cpu_has_active_perf((int)hcpu)) {
-		switch ((action & ~CPU_TASKS_FROZEN)) {
-
-		case CPU_DOWN_PREPARE:
-			/*
-			 * If this is on a multicore CPU, we need
-			 * to disarm the PMU IRQ before disappearing.
-			 */
-			if (cpu_pmu &&
-				cpu_pmu->plat_device->dev.platform_data) {
-				irq = platform_get_irq(cpu_pmu->plat_device, 0);
-				smp_call_function_single((int)hcpu,
-						disable_irq_callback, &irq, 1);
-			}
-			return NOTIFY_DONE;
-
-		case CPU_UP_PREPARE:
-			/*
-			 * If this is on a multicore CPU, we need
-			 * to arm the PMU IRQ before appearing.
-			 */
-			if (cpu_pmu &&
-				cpu_pmu->plat_device->dev.platform_data) {
-				irq = platform_get_irq(cpu_pmu->plat_device, 0);
-				smp_call_function_single((int)hcpu,
-						enable_irq_callback, &irq, 1);
-			}
-			return NOTIFY_DONE;
-
-		case CPU_STARTING:
-			if (cpu_pmu && cpu_pmu->reset) {
-				cpu_pmu->reset(NULL);
-				return NOTIFY_OK;
-			}
-		default:
-			return NOTIFY_DONE;
-		}
-	}
-
-	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
-		return NOTIFY_DONE;
-
-	return NOTIFY_OK;
-}
-
 static void armpmu_update_counters(void)
 {
 	struct pmu_hw_events *hw_events;
@@ -902,6 +872,79 @@
 	}
 }
 
+/*
+ * PMU hardware loses all context when a CPU goes offline.
+ * When a CPU is hotplugged back in, since some hardware registers are
+ * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
+ * junk values out of them.
+ */
+static int __cpuinit pmu_cpu_notify(struct notifier_block *b,
+					unsigned long action, void *hcpu)
+{
+	int irq;
+	struct pmu *pmu;
+	int cpu = (int)hcpu;
+
+	switch ((action & ~CPU_TASKS_FROZEN)) {
+	case CPU_DOWN_PREPARE:
+		if (cpu_pmu && cpu_pmu->save_pm_registers)
+			smp_call_function_single(cpu,
+						 cpu_pmu->save_pm_registers,
+						 hcpu, 1);
+		break;
+	case CPU_STARTING:
+		if (cpu_pmu && cpu_pmu->restore_pm_registers)
+			smp_call_function_single(cpu,
+						 cpu_pmu->restore_pm_registers,
+						 hcpu, 1);
+	}
+
+	if (cpu_has_active_perf((int)hcpu)) {
+		switch ((action & ~CPU_TASKS_FROZEN)) {
+
+		case CPU_DOWN_PREPARE:
+			armpmu_update_counters();
+			/*
+			 * If this is on a multicore CPU, we need
+			 * to disarm the PMU IRQ before disappearing.
+			 */
+			if (cpu_pmu &&
+				cpu_pmu->plat_device->dev.platform_data) {
+				irq = platform_get_irq(cpu_pmu->plat_device, 0);
+				smp_call_function_single((int)hcpu,
+						disable_irq_callback, &irq, 1);
+			}
+			return NOTIFY_DONE;
+
+		case CPU_STARTING:
+			/*
+			 * If this is on a multicore CPU, we need
+			 * to arm the PMU IRQ before appearing.
+			 */
+			if (cpu_pmu &&
+				cpu_pmu->plat_device->dev.platform_data) {
+				irq = platform_get_irq(cpu_pmu->plat_device, 0);
+				enable_irq_callback(&irq);
+			}
+
+			if (cpu_pmu && cpu_pmu->reset) {
+				__get_cpu_var(from_idle) = 1;
+				cpu_pmu->reset(NULL);
+				pmu = &cpu_pmu->pmu;
+				pmu->pmu_enable(pmu);
+				return NOTIFY_OK;
+			}
+		default:
+			return NOTIFY_DONE;
+		}
+	}
+
+	if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
+		return NOTIFY_DONE;
+
+	return NOTIFY_OK;
+}
+
 static struct notifier_block __cpuinitdata pmu_cpu_notifier = {
 	.notifier_call = pmu_cpu_notify,
 };
@@ -913,6 +956,8 @@
 	struct pmu *pmu;
 	switch (cmd) {
 	case CPU_PM_ENTER:
+		if (cpu_pmu && cpu_pmu->save_pm_registers)
+			cpu_pmu->save_pm_registers((void *)smp_processor_id());
 		if (cpu_has_active_perf((int)v)) {
 			armpmu_update_counters();
 			pmu = &cpu_pmu->pmu;
@@ -922,6 +967,9 @@
 
 	case CPU_PM_ENTER_FAILED:
 	case CPU_PM_EXIT:
+		if (cpu_pmu && cpu_pmu->restore_pm_registers)
+			cpu_pmu->restore_pm_registers(
+				(void *)smp_processor_id());
 		if (cpu_has_active_perf((int)v) && cpu_pmu->reset) {
 			/*
 			 * Flip this bit so armpmu_enable knows it needs
diff --git a/arch/arm/kernel/perf_event_msm_krait.c b/arch/arm/kernel/perf_event_msm_krait.c
index 5708d74..1fb5fd3 100644
--- a/arch/arm/kernel/perf_event_msm_krait.c
+++ b/arch/arm/kernel/perf_event_msm_krait.c
@@ -572,6 +572,33 @@
 	return 1;
 }
 
+static DEFINE_PER_CPU(u32, krait_pm_pmactlr);
+
+static void krait_save_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	/* Read PMACTLR */
+	asm volatile("mrc p15, 0, %0, c9, c15, 5" : "=r" (val));
+	per_cpu(krait_pm_pmactlr, cpu) = val;
+
+	armv7pmu_save_pm_registers(hcpu);
+}
+
+static void krait_restore_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	val = per_cpu(krait_pm_pmactlr, cpu);
+	if (val != 0)
+		/* Restore PMACTLR */
+		asm volatile("mcr p15, 0, %0, c9, c15, 5" : : "r" (val));
+
+	armv7pmu_restore_pm_registers(hcpu);
+}
+
 static struct arm_pmu krait_pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= krait_pmu_enable_event,
@@ -585,6 +612,8 @@
 	.test_set_event_constraints	= msm_test_set_ev_constraint,
 	.clear_event_constraints	= msm_clear_ev_constraint,
 	.max_period		= (1LLU << 32) - 1,
+	.save_pm_registers	= krait_save_pm_registers,
+	.restore_pm_registers	= krait_restore_pm_registers,
 };
 
 /* NRCCG format for perf RAW codes. */
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 58e9068..7c7a9d1 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1238,6 +1238,29 @@
 				&armv7_a7_perf_cache_map, 0xFF);
 }
 
+static DEFINE_PER_CPU(u32, armv7_pm_pmuserenr);
+
+static void armv7pmu_save_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	/* Read PMUSERENR */
+	asm volatile("mrc p15, 0, %0, c9, c14, 0" : "=r" (val));
+	per_cpu(armv7_pm_pmuserenr, cpu) = val;
+}
+
+static void armv7pmu_restore_pm_registers(void *hcpu)
+{
+	u32 val;
+	u32 cpu = (int)hcpu;
+
+	val = per_cpu(armv7_pm_pmuserenr, cpu);
+	if (val != 0)
+		/* Restore PMUSERENR */
+		asm volatile("mcr p15, 0, %0, c9, c14, 0" : : "r" (val));
+}
+
 static struct arm_pmu armv7pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= armv7pmu_enable_event,
@@ -1249,6 +1272,8 @@
 	.stop			= armv7pmu_stop,
 	.reset			= armv7pmu_reset,
 	.max_period		= (1LLU << 32) - 1,
+	.save_pm_registers	= armv7pmu_save_pm_registers,
+	.restore_pm_registers	= armv7pmu_restore_pm_registers,
 };
 
 static u32 __init armv7_read_num_pmnc_events(void)
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index c6c6be7..6533c4b 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -24,6 +24,7 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/regset.h>
 #include <linux/audit.h>
+#include <linux/unistd.h>
 
 #include <asm/pgtable.h>
 #include <asm/traps.h>
@@ -916,6 +917,8 @@
 		audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0,
 				    regs->ARM_r1, regs->ARM_r2, regs->ARM_r3);
 
+	if (why == 0 && test_and_clear_thread_flag(TIF_SYSCALL_RESTARTSYS))
+		scno = __NR_restart_syscall - __NR_SYSCALL_BASE;
 	if (!test_thread_flag(TIF_SYSCALL_TRACE))
 		return scno;
 	if (!(current->ptrace & PT_PTRACED))
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index edb73b4..7f9d4ee 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -649,12 +649,10 @@
 		case -ERESTARTNOHAND:
 		case -ERESTARTSYS:
 		case -ERESTARTNOINTR:
+		case -ERESTART_RESTARTBLOCK:
 			regs->ARM_r0 = regs->ARM_ORIG_r0;
 			regs->ARM_pc = restart_addr;
 			break;
-		case -ERESTART_RESTARTBLOCK:
-			regs->ARM_r0 = -EINTR;
-			break;
 		}
 	}
 
@@ -675,12 +673,14 @@
 		 * debugger has chosen to restart at a different PC.
 		 */
 		if (regs->ARM_pc == restart_addr) {
-			if (retval == -ERESTARTNOHAND
+			if (retval == -ERESTARTNOHAND ||
+			    retval == -ERESTART_RESTARTBLOCK
 			    || (retval == -ERESTARTSYS
 				&& !(ka.sa.sa_flags & SA_RESTART))) {
 				regs->ARM_r0 = -EINTR;
 				regs->ARM_pc = continue_addr;
 			}
+			clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
 		}
 
 		if (test_thread_flag(TIF_RESTORE_SIGMASK))
@@ -708,38 +708,15 @@
 		 * ignore the restart.
 		 */
 		if (retval == -ERESTART_RESTARTBLOCK
-		    && regs->ARM_pc == continue_addr) {
-			if (thumb_mode(regs)) {
-				regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
-				regs->ARM_pc -= 2;
-			} else {
-#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
-				regs->ARM_r7 = __NR_restart_syscall;
-				regs->ARM_pc -= 4;
-#else
-				u32 __user *usp;
-
-				regs->ARM_sp -= 4;
-				usp = (u32 __user *)regs->ARM_sp;
-
-				if (put_user(regs->ARM_pc, usp) == 0) {
-					regs->ARM_pc = KERN_RESTART_CODE;
-				} else {
-					regs->ARM_sp += 4;
-					force_sigsegv(0, current);
-				}
-#endif
-			}
-		}
-
-		/* If there's no signal to deliver, we just put the saved sigmask
-		 * back.
-		 */
-		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-			clear_thread_flag(TIF_RESTORE_SIGMASK);
-			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-		}
+		    && regs->ARM_pc == restart_addr)
+			set_thread_flag(TIF_SYSCALL_RESTARTSYS);
 	}
+
+	/* If there's no signal to deliver, we just put the saved sigmask
+	 * back.
+	 */
+	if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
+		set_current_blocked(&current->saved_sigmask);
 }
 
 asmlinkage void
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 4b8d443..f2d65fe 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -261,6 +261,8 @@
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
 	select MSM_MULTIMEDIA_USE_ION
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select MSM_PIL
 	select MSM_SPM_V2
 	select MSM_L2_SPM
@@ -309,11 +311,15 @@
 	select MSM_SPM_V2
 	select MSM_L2_SPM
 	select MSM_RPM_SMD
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select ENABLE_VMALLOC_SAVINGS
 
 config ARCH_MPQ8092
 	bool "MPQ8092"
 	select ARCH_MSM_KRAITMP
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select GPIO_MSM_V3
 	select ARM_GIC
 	select MULTI_IRQ_HANDLER
@@ -332,6 +338,8 @@
 	select MSM_SCM
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select MSM_PIL
 	select MSM_NATIVE_RESTART
 	select MSM_RESTART_V2
@@ -435,6 +443,8 @@
 	select MEMORY_HOLE_CARVEOUT
 	select QMI_ENCDEC
 	select MSM_CORTEX_A7
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 
 config ARCH_MSM8610
 	bool "MSM8610"
@@ -464,6 +474,8 @@
 	select MSM_CORTEX_A7
 	select CPU_FREQ_MSM
 	select CPU_FREQ
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select MSM_PIL
 	select MSM_RUN_QUEUE_STATS
 	select ARM_HAS_SG_CHAIN
@@ -475,7 +487,6 @@
 	select MSM_RPM_LOG
 	select MSM_IOMMU_SYNC
 	select MSM_RPM_STATS_LOG
-	select ENABLE_VMALLOC_SAVINGS
 
 config ARCH_MSM8226
 	bool "MSM8226"
@@ -505,6 +516,8 @@
 	select MSM_CORTEX_A7
 	select CPU_FREQ_MSM
 	select CPU_FREQ
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select MSM_PIL
 	select MSM_RUN_QUEUE_STATS
 	select ARM_HAS_SG_CHAIN
@@ -525,6 +538,8 @@
 	select ARM_GIC
 	select CPU_V7
 	select MSM_SCM
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_CPUBW
 	select MSM_PIL
 	select MSM_GPIOMUX
 	select MULTI_IRQ_HANDLER
@@ -574,6 +589,7 @@
 config  ARCH_MSM_KRAIT
 	bool
 	select ARM_L1_CACHE_SHIFT_6
+	select DEVFREQ_GOV_MSM_CPUBW_HWMON
 
 config  MSM_CORTEX_A7
 	bool
@@ -1563,20 +1579,6 @@
 	  Enables the PCIe functionality by configures PCIe core on
 	  MSM chipset and by enabling the ARM PCI framework extension.
 
-config MSM_RPC_SDIO_XPRT
-	depends on MSM_SDIO_AL
-	default y
-	bool "MSM SDIO XPRT Layer"
-	help
-	  SDIO Transport Layer for RPC Rouer
-
-config MSM_RPC_SDIO_DEBUG
-	depends on MSM_RPC_SDIO_XPRT
-	default y
-	bool "MSM SDIO XPRT debug support"
-	help
-	  Support for debugging SDIO XPRT
-
 config MSM_SMD_DEBUG
 	depends on MSM_SMD
 	default y
@@ -1585,21 +1587,6 @@
 	  Support for debugging the SMD for communication
 	  between the ARM9 and ARM11
 
-config MSM_SDIO_AL
-	depends on ((ARCH_MSM7X30 || MACH_MSM8X60_FUSN_FFA || MACH_TYPE_MSM8X60_FUSION) && HAS_WAKELOCK)
-	default y
-	tristate "SDIO-Abstraction-Layer"
-	help
-	  Support MSM<->MDM Communication over SDIO bus.
-	  MDM SDIO-Client should have pipes support.
-
-config MSM_SDIO_DMUX
-	bool "SDIO Data Mux Driver"
-	depends on MSM_SDIO_AL
-	default n
-	help
-	  Support Muxed Data Channels over SDIO interface.
-
 config MSM_BAM_DMUX
 	bool "BAM Data Mux Driver"
 	depends on SPS
@@ -1680,16 +1667,6 @@
 
 	  If in doubt, say yes.
 
-config MSM_SDIO_TTY
-	bool "SDIO TTY Driver"
-	depends on MSM_SDIO_AL
-	default n
-	help
-	  Provides a TTY driver SDIO TTY
-	  This driver can be used by user space
-	  applications for passing data through the
-	  SDIO interface.
-
 config MSM_SMD_TTY
 	bool "SMD TTY Driver"
 	depends on MSM_SMD
@@ -1717,13 +1694,6 @@
 
 	  If in doubt, say yes.
 
-config MSM_SDIO_CMUX
-	bool "SDIO CMUX Driver"
-	depends on MSM_SDIO_AL
-	default n
-	help
-	  Provides a Muxed port interface over SDIO QMI
-
 config MSM_DSPS
 	bool "Sensors DSPS driver"
 	depends on (MSM_PIL && (ARCH_MSM8X60 || ARCH_MSM8960))
@@ -1736,13 +1706,6 @@
 	  The number of clocks and their name may vary between targets.
 	  It also triggers the PIL to load the DSPS firmware.
 
-config MSM_SDIO_CTL
-	bool "SDIO CTL Driver"
-	depends on MSM_SDIO_CMUX
-	default n
-	help
-	  Provides a binary SDIO control port interface.
-
 config MSM_ONCRPCROUTER
 	depends on MSM_SMD
 	default n
@@ -1891,15 +1854,6 @@
 	  Collects performance statistics and shows this information
 	  through a debugfs file rmt_storage_stats.
 
-config MSM_SDIO_SMEM
-        depends on MSM_SDIO_AL
-        default n
-        bool "SDIO SMEM for remote storage"
-        help
-          Copies data from remote MDM9K memory to local MSM8x60
-	  memory. Used by remote storage client to shadow
-	  MDM9K filesystem.
-
 config MSM_DALRPC
 	bool "DAL RPC support"
 	default n
@@ -1934,6 +1888,20 @@
 
 endif # CPU_FREQ_MSM
 
+config MSM_DEVFREQ_CPUBW
+	bool "Devfreq device for CPU<->DDR IB/AB BW voting"
+	depends on PM_DEVFREQ
+	select DEVFREQ_GOV_PERFORMANCE
+	select DEVFREQ_GOV_POWERSAVE
+	select DEVFREQ_GOV_USERSPACE
+	select DEVFREQ_GOV_MSM_CPUFREQ
+	default n
+	help
+	  Different devfreq governors use this devfreq device to make CPU to
+	  DDR IB/AB bandwidth votes. This driver provides a SoC topology
+	  agnostic interface to so that some of the devfreq governors can be
+	  shared across SoCs.
+
 config MSM_AVS_HW
 	bool "Enable Adaptive Voltage Scaling (AVS)"
 	default n
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4e60414..9c9fffc 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -98,10 +98,6 @@
 obj-$(CONFIG_ARCH_FSM9XXX) += sirc-fsm9xxx.o
 obj-$(CONFIG_MSM_FIQ_SUPPORT) += fiq_glue.o
 obj-$(CONFIG_MACH_TROUT) += board-trout-rfkill.o
-obj-$(CONFIG_MSM_SDIO_AL) += sdio_al.o
-obj-$(CONFIG_MSM_SDIO_AL) += sdio_al_test.o
-obj-$(CONFIG_MSM_SDIO_AL) += sdio_al_dloader.o
-obj-$(CONFIG_MSM_SDIO_DMUX) += sdio_dmux.o
 obj-$(CONFIG_MSM_BAM_DMUX) += bam_dmux.o
 obj-$(CONFIG_MSM_SMD_LOGGING) += smem_log.o
 obj-$(CONFIG_MSM_IPC_LOGGING) += ipc_logging.o
@@ -118,13 +114,10 @@
 obj-$(CONFIG_ARCH_MSM9615) += nand_partitions.o
 obj-$(CONFIG_ARCH_MSM8625) += nand_partitions.o
 obj-$(CONFIG_ARCH_MSM7X27A) += nand_partitions.o
-obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
 obj-$(CONFIG_MSM_SMD_PKT) += smd_pkt.o
-obj-$(CONFIG_MSM_SDIO_CMUX) += sdio_cmux.o
 obj-$(CONFIG_MSM_DSPS) += msm_dsps.o
-obj-$(CONFIG_MSM_SDIO_CTL) += sdio_ctl.o
 obj-$(CONFIG_MSM_SMD_NMEA) += smd_nmea.o
 obj-$(CONFIG_MSM_RESET_MODEM) += reset_modem.o
 obj-$(CONFIG_MSM_IPC_ROUTER_SMD_XPRT) += ipc_router_smd_xprt.o
@@ -141,7 +134,6 @@
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_clients.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_xdr.o
 obj-$(CONFIG_MSM_ONCRPCROUTER) += rpcrouter_smd_xprt.o
-obj-$(CONFIG_MSM_RPC_SDIO_XPRT) += rpcrouter_sdio_xprt.o
 obj-$(CONFIG_MSM_RPC_PING) += ping_mdm_rpc_client.o
 obj-$(CONFIG_MSM_RPC_PROC_COMM_TEST) += proc_comm_test.o
 obj-$(CONFIG_MSM_RPC_PING) += ping_mdm_rpc_client.o ping_apps_server.o
@@ -322,7 +314,6 @@
 obj-$(CONFIG_HTC_PWRSINK) += htc_pwrsink.o
 obj-$(CONFIG_HTC_HEADSET) += htc_headset.o
 obj-$(CONFIG_MSM_RMT_STORAGE_CLIENT) += rmt_storage_client.o
-obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o
 obj-$(CONFIG_MSM_RPM) += rpm.o rpm_resources.o
 obj-$(CONFIG_MSM_LPM_TEST) += test-lpm.o
 obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o lpm_levels.o
@@ -422,9 +413,9 @@
 obj-$(CONFIG_ARCH_MSM8974) += msm_mpmctr.o
 obj-$(CONFIG_MSM_CPR_REGULATOR) += cpr-regulator.o
 obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
+obj-$(CONFIG_MSM_DEVFREQ_CPUBW) += devfreq_cpubw.o
 
 obj-$(CONFIG_WALL_CLK) += wallclk.o
 obj-$(CONFIG_WALL_CLK_SYSFS) += wallclk_sysfs.o
 obj-$(CONFIG_ARCH_RANDOM) += early_random.o
 obj-$(CONFIG_PERFMAP) += perfmap.o
-obj-$(CONFIG_ARCH_MSM8974) += cpubw-krait.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 83c1d4c..c0e9efc 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -69,6 +69,7 @@
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974-v2.2-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974pro-ab-pm8941-cdp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974pro-ab-pm8941-fluid.dtb
+        dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974pro-ab-pm8941-fluid-hbtp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974pro-ab-pm8941-liquid.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974pro-ab-pm8941-mtp.dtb
         dtb-$(CONFIG_ARCH_MSM8974)	+= msm8974pro-ac-pm8941-cdp.dtb
@@ -111,12 +112,22 @@
 	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-1080p-mtp.dtb
 	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-evt.dtb
 	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-dvt.dtb
-	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-720p-cdp.dtb
-	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-1080p-cdp.dtb
-	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-720p-mtp.dtb
-	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-1080p-mtp.dtb
-	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd.dtb
-	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-qrd-skug.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-720p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-1080p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-720p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-1080p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-qrd.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-qrd-skug.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v1-qrd-skug-pvt.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-720p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-1080p-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-1080p-ext-buck-cdp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-720p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-1080p-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-1080p-ext-buck-mtp.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-qrd.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-qrd-skug.dtb
+	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8926-v2-qrd-skug-pvt.dtb
 	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v1-qrd-skuf.dtb
 	dtb-$(CONFIG_ARCH_MSM8226)	+= msm8226-v2-qrd-skuf.dtb
 	dtb-$(CONFIG_ARCH_MSM8226)	+= apq8026-v1-xpm.dtb
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 6281395..b618cd4 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -28,6 +28,7 @@
 #include <linux/wakelock.h>
 #include <linux/kfifo.h>
 #include <linux/of.h>
+#include <linux/srcu.h>
 #include <mach/msm_ipc_logging.h>
 #include <mach/sps.h>
 #include <mach/bam_dmux.h>
@@ -36,19 +37,12 @@
 #include <mach/socinfo.h>
 #include <mach/subsystem_restart.h>
 
+#include "bam_dmux_private.h"
+
 #define BAM_CH_LOCAL_OPEN       0x1
 #define BAM_CH_REMOTE_OPEN      0x2
 #define BAM_CH_IN_RESET         0x4
 
-#define BAM_MUX_HDR_MAGIC_NO    0x33fc
-
-#define BAM_MUX_HDR_CMD_DATA		0
-#define BAM_MUX_HDR_CMD_OPEN		1
-#define BAM_MUX_HDR_CMD_CLOSE		2
-#define BAM_MUX_HDR_CMD_STATUS		3 /* unused */
-#define BAM_MUX_HDR_CMD_OPEN_NO_A2_PC	4
-
-
 #define LOW_WATERMARK		2
 #define HIGH_WATERMARK		4
 #define DEFAULT_POLLING_MIN_SLEEP (950)
@@ -58,20 +52,47 @@
 static int msm_bam_dmux_debug_enable;
 module_param_named(debug_enable, msm_bam_dmux_debug_enable,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-static int POLLING_MIN_SLEEP = 950;
+static int POLLING_MIN_SLEEP = 2950;
 module_param_named(min_sleep, POLLING_MIN_SLEEP,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-static int POLLING_MAX_SLEEP = 1050;
+static int POLLING_MAX_SLEEP = 3050;
 module_param_named(max_sleep, POLLING_MAX_SLEEP,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-static int POLLING_INACTIVITY = 40;
+static int POLLING_INACTIVITY = 1;
 module_param_named(inactivity, POLLING_INACTIVITY,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-static int bam_adaptive_timer_enabled = 1;
+static int bam_adaptive_timer_enabled;
 module_param_named(adaptive_timer_enabled,
 			bam_adaptive_timer_enabled,
 		   int, S_IRUGO | S_IWUSR | S_IWGRP);
 
+static struct bam_ops_if bam_default_ops = {
+	/* smsm */
+	.smsm_change_state_ptr = &smsm_change_state,
+	.smsm_get_state_ptr = &smsm_get_state,
+	.smsm_state_cb_register_ptr = &smsm_state_cb_register,
+	.smsm_state_cb_deregister_ptr = &smsm_state_cb_deregister,
+
+	/* sps */
+	.sps_connect_ptr = &sps_connect,
+	.sps_disconnect_ptr = &sps_disconnect,
+	.sps_register_bam_device_ptr = &sps_register_bam_device,
+	.sps_deregister_bam_device_ptr = &sps_deregister_bam_device,
+	.sps_alloc_endpoint_ptr = &sps_alloc_endpoint,
+	.sps_free_endpoint_ptr = &sps_free_endpoint,
+	.sps_set_config_ptr = &sps_set_config,
+	.sps_get_config_ptr = &sps_get_config,
+	.sps_device_reset_ptr = &sps_device_reset,
+	.sps_register_event_ptr = &sps_register_event,
+	.sps_transfer_one_ptr = &sps_transfer_one,
+	.sps_get_iovec_ptr = &sps_get_iovec,
+	.sps_get_unused_desc_num_ptr = &sps_get_unused_desc_num,
+
+	.dma_to = DMA_TO_DEVICE,
+	.dma_from = DMA_FROM_DEVICE,
+};
+static struct bam_ops_if *bam_ops = &bam_default_ops;
+
 #if defined(DEBUG)
 static uint32_t bam_dmux_read_cnt;
 static uint32_t bam_dmux_write_cnt;
@@ -151,29 +172,10 @@
 	int use_wm;
 };
 
-struct tx_pkt_info {
-	struct sk_buff *skb;
-	dma_addr_t dma_address;
-	char is_cmd;
-	uint32_t len;
-	struct work_struct work;
-	struct list_head list_node;
-	unsigned ts_sec;
-	unsigned long ts_nsec;
-};
-
-struct rx_pkt_info {
-	struct sk_buff *skb;
-	dma_addr_t dma_address;
-	struct work_struct work;
-	struct list_head list_node;
-};
-
 #define A2_NUM_PIPES		6
 #define A2_SUMMING_THRESHOLD	4096
 #define A2_PHYS_BASE		0x124C2000
 #define A2_PHYS_SIZE		0x2000
-#define BUFFER_SIZE		2048
 #define DEFAULT_NUM_BUFFERS	32
 
 #ifndef A2_BAM_IRQ
@@ -210,26 +212,20 @@
 static DEFINE_SPINLOCK(bam_tx_pool_spinlock);
 static DEFINE_MUTEX(bam_pdev_mutexlock);
 
-struct bam_mux_hdr {
-	uint16_t magic_num;
-	uint8_t reserved;
-	uint8_t cmd;
-	uint8_t pad_len;
-	uint8_t ch_id;
-	uint16_t pkt_len;
-};
-
 static void notify_all(int event, unsigned long data);
 static void bam_mux_write_done(struct work_struct *work);
 static void handle_bam_mux_cmd(struct work_struct *work);
 static void rx_timer_work_func(struct work_struct *work);
+static void queue_rx_work_func(struct work_struct *work);
 
 static DECLARE_WORK(rx_timer_work, rx_timer_work_func);
-static struct delayed_work queue_rx_work;
+static DECLARE_WORK(queue_rx_work, queue_rx_work_func);
 
 static struct workqueue_struct *bam_mux_rx_workqueue;
 static struct workqueue_struct *bam_mux_tx_workqueue;
 
+static struct srcu_struct bam_dmux_srcu;
+
 /* A2 power collaspe */
 #define UL_TIMEOUT_DELAY 1000	/* in ms */
 #define ENABLE_DISCONNECT_ACK	0x1
@@ -390,7 +386,7 @@
 	spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 }
 
-static void queue_rx(void)
+static void __queue_rx(gfp_t alloc_flags)
 {
 	void *ptr;
 	struct rx_pkt_info *info;
@@ -405,29 +401,29 @@
 		if (in_global_reset)
 			goto fail;
 
-		info = kmalloc(sizeof(struct rx_pkt_info),
-						GFP_NOWAIT | __GFP_NOWARN);
+		info = kmalloc(sizeof(struct rx_pkt_info), alloc_flags);
 		if (!info) {
 			DMUX_LOG_KERR(
-			"%s: unable to alloc rx_pkt_info, will retry later\n",
-								__func__);
+			"%s: unable to alloc rx_pkt_info w/ flags %x, will retry later\n",
+								__func__,
+								alloc_flags);
 			goto fail;
 		}
 
 		INIT_WORK(&info->work, handle_bam_mux_cmd);
 
-		info->skb = __dev_alloc_skb(BUFFER_SIZE,
-						GFP_NOWAIT | __GFP_NOWARN);
+		info->skb = __dev_alloc_skb(BUFFER_SIZE, alloc_flags);
 		if (info->skb == NULL) {
 			DMUX_LOG_KERR(
-				"%s: unable to alloc skb, will retry later\n",
-								__func__);
+				"%s: unable to alloc skb w/ flags %x, will retry later\n",
+								__func__,
+								alloc_flags);
 			goto fail_info;
 		}
 		ptr = skb_put(info->skb, BUFFER_SIZE);
 
 		info->dma_address = dma_map_single(NULL, ptr, BUFFER_SIZE,
-							DMA_FROM_DEVICE);
+							bam_ops->dma_from);
 		if (info->dma_address == 0 || info->dma_address == ~0) {
 			DMUX_LOG_KERR("%s: dma_map_single failure %p for %p\n",
 				__func__, (void *)info->dma_address, ptr);
@@ -437,8 +433,8 @@
 		mutex_lock(&bam_rx_pool_mutexlock);
 		list_add_tail(&info->list_node, &bam_rx_pool);
 		rx_len_cached = ++bam_rx_pool_len;
-		ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
-			BUFFER_SIZE, info, 0);
+		ret = bam_ops->sps_transfer_one_ptr(bam_rx_pipe,
+				info->dma_address, BUFFER_SIZE, info, 0);
 		if (ret) {
 			list_del(&info->list_node);
 			rx_len_cached = --bam_rx_pool_len;
@@ -447,7 +443,7 @@
 				__func__, ret);
 
 			dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
-						DMA_FROM_DEVICE);
+						bam_ops->dma_from);
 
 			goto fail_skb;
 		}
@@ -463,15 +459,30 @@
 	kfree(info);
 
 fail:
-	if (rx_len_cached == 0 && !in_global_reset) {
+	if (!in_global_reset) {
 		DMUX_LOG_KERR("%s: rescheduling\n", __func__);
-		schedule_delayed_work(&queue_rx_work, msecs_to_jiffies(100));
+		schedule_work(&queue_rx_work);
 	}
 }
 
+static void queue_rx(void)
+{
+	/*
+	 * Hot path.  Delays waiting for the allocation to find memory if its
+	 * not immediately available, and delays from logging allocation
+	 * failures which cannot be tolerated at this time.
+	 */
+	__queue_rx(GFP_NOWAIT | __GFP_NOWARN);
+}
+
 static void queue_rx_work_func(struct work_struct *work)
 {
-	queue_rx();
+	/*
+	 * Cold path.  Delays can be tolerated.  Use of GFP_KERNEL should
+	 * guarentee the requested memory will be found, after some ammount of
+	 * delay.
+	 */
+	__queue_rx(GFP_KERNEL);
 }
 
 static void bam_mux_process_data(struct sk_buff *rx_skb)
@@ -535,7 +546,8 @@
 
 	info = container_of(work, struct rx_pkt_info, work);
 	rx_skb = info->skb;
-	dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE, DMA_FROM_DEVICE);
+	dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
+			bam_ops->dma_from);
 	kfree(info);
 
 	rx_hdr = (struct bam_mux_hdr *)rx_skb->data;
@@ -644,7 +656,7 @@
 	}
 
 	dma_address = dma_map_single(NULL, data, len,
-					DMA_TO_DEVICE);
+					bam_ops->dma_to);
 	if (!dma_address) {
 		pr_err("%s: dma_map_single() failed\n", __func__);
 		kfree(pkt);
@@ -659,7 +671,7 @@
 	INIT_WORK(&pkt->work, bam_mux_write_done);
 	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
 	list_add_tail(&pkt->list_node, &bam_tx_pool);
-	rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
+	rc = bam_ops->sps_transfer_one_ptr(bam_tx_pipe, dma_address, len,
 				pkt, SPS_IOVEC_FLAG_EOT);
 	if (rc) {
 		DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
@@ -669,7 +681,7 @@
 		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 		dma_unmap_single(NULL, pkt->dma_address,
 					pkt->len,
-					DMA_TO_DEVICE);
+					bam_ops->dma_to);
 		kfree(pkt);
 	} else {
 		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
@@ -746,6 +758,7 @@
 	struct sk_buff *new_skb = NULL;
 	dma_addr_t dma_address;
 	struct tx_pkt_info *pkt;
+	int rcu_id;
 
 	if (id >= BAM_DMUX_NUM_CHANNELS)
 		return -EINVAL;
@@ -754,11 +767,19 @@
 	if (!bam_mux_initialized)
 		return -ENODEV;
 
+	rcu_id = srcu_read_lock(&bam_dmux_srcu);
+	if (in_global_reset) {
+		BAM_DMUX_LOG("%s: In SSR... ch_id[%d]\n", __func__, id);
+		srcu_read_unlock(&bam_dmux_srcu, rcu_id);
+		return -EFAULT;
+	}
+
 	DBG("%s: writing to ch %d len %d\n", __func__, id, skb->len);
 	spin_lock_irqsave(&bam_ch[id].lock, flags);
 	if (!bam_ch_is_open(id)) {
 		spin_unlock_irqrestore(&bam_ch[id].lock, flags);
 		pr_err("%s: port not open: %d\n", __func__, bam_ch[id].status);
+		srcu_read_unlock(&bam_dmux_srcu, rcu_id);
 		return -ENODEV;
 	}
 
@@ -766,6 +787,7 @@
 	    (bam_ch[id].num_tx_pkts >= HIGH_WATERMARK)) {
 		spin_unlock_irqrestore(&bam_ch[id].lock, flags);
 		pr_err("%s: watermark exceeded: %d\n", __func__, id);
+		srcu_read_unlock(&bam_dmux_srcu, rcu_id);
 		return -EAGAIN;
 	}
 	spin_unlock_irqrestore(&bam_ch[id].lock, flags);
@@ -774,8 +796,10 @@
 	if (!bam_is_connected) {
 		read_unlock(&ul_wakeup_lock);
 		ul_wakeup();
-		if (unlikely(in_global_reset == 1))
+		if (unlikely(in_global_reset == 1)) {
+			srcu_read_unlock(&bam_dmux_srcu, rcu_id);
 			return -EFAULT;
+		}
 		read_lock(&ul_wakeup_lock);
 		notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
 	}
@@ -820,7 +844,7 @@
 	}
 
 	dma_address = dma_map_single(NULL, skb->data, skb->len,
-					DMA_TO_DEVICE);
+					bam_ops->dma_to);
 	if (!dma_address) {
 		pr_err("%s: dma_map_single() failed\n", __func__);
 		goto write_fail3;
@@ -832,7 +856,7 @@
 	INIT_WORK(&pkt->work, bam_mux_write_done);
 	spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
 	list_add_tail(&pkt->list_node, &bam_tx_pool);
-	rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
+	rc = bam_ops->sps_transfer_one_ptr(bam_tx_pipe, dma_address, skb->len,
 				pkt, SPS_IOVEC_FLAG_EOT);
 	if (rc) {
 		DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
@@ -841,7 +865,7 @@
 		DBG_INC_TX_SPS_FAILURE_CNT();
 		spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
 		dma_unmap_single(NULL, pkt->dma_address,
-					pkt->skb->len,	DMA_TO_DEVICE);
+					pkt->skb->len,	bam_ops->dma_to);
 		kfree(pkt);
 		if (new_skb)
 			dev_kfree_skb_any(new_skb);
@@ -853,6 +877,7 @@
 	}
 	ul_packet_written = 1;
 	read_unlock(&ul_wakeup_lock);
+	srcu_read_unlock(&bam_dmux_srcu, rcu_id);
 	return rc;
 
 write_fail3:
@@ -863,6 +888,7 @@
 		dev_kfree_skb_any(new_skb);
 write_fail:
 	read_unlock(&ul_wakeup_lock);
+	srcu_read_unlock(&bam_dmux_srcu, rcu_id);
 	return -ENOMEM;
 }
 
@@ -1049,14 +1075,14 @@
 	 * Attempt to enable interrupts - if this fails,
 	 * continue polling and we will retry later.
 	 */
-	ret = sps_get_config(bam_rx_pipe, &cur_rx_conn);
+	ret = bam_ops->sps_get_config_ptr(bam_rx_pipe, &cur_rx_conn);
 	if (ret) {
 		pr_err("%s: sps_get_config() failed %d\n", __func__, ret);
 		goto fail;
 	}
 
 	rx_register_event.options = SPS_O_EOT;
-	ret = sps_register_event(bam_rx_pipe, &rx_register_event);
+	ret = bam_ops->sps_register_event_ptr(bam_rx_pipe, &rx_register_event);
 	if (ret) {
 		pr_err("%s: sps_register_event() failed %d\n", __func__, ret);
 		goto fail;
@@ -1064,7 +1090,7 @@
 
 	cur_rx_conn.options = SPS_O_AUTO_ENABLE |
 		SPS_O_EOT | SPS_O_ACK_TRANSFERS;
-	ret = sps_set_config(bam_rx_pipe, &cur_rx_conn);
+	ret = bam_ops->sps_set_config_ptr(bam_rx_pipe, &cur_rx_conn);
 	if (ret) {
 		pr_err("%s: sps_set_config() failed %d\n", __func__, ret);
 		goto fail;
@@ -1075,7 +1101,7 @@
 
 	/* handle any rx packets before interrupt was enabled */
 	while (bam_connection_is_active && !polling_mode) {
-		ret = sps_get_iovec(bam_rx_pipe, &iov);
+		ret = bam_ops->sps_get_iovec_ptr(bam_rx_pipe, &iov);
 		if (ret) {
 			pr_err("%s: sps_get_iovec failed %d\n",
 					__func__, ret);
@@ -1160,7 +1186,7 @@
 				return;
 			}
 
-			ret = sps_get_iovec(bam_rx_pipe, &iov);
+			ret = bam_ops->sps_get_iovec_ptr(bam_rx_pipe, &iov);
 			if (ret) {
 				DMUX_LOG_KERR("%s: sps_get_iovec failed %d\n",
 						__func__, ret);
@@ -1209,7 +1235,7 @@
 		if (bam_adaptive_timer_enabled) {
 			usleep_range(rx_timer_interval, rx_timer_interval + 50);
 
-			ret = sps_get_unused_desc_num(bam_rx_pipe,
+			ret = bam_ops->sps_get_unused_desc_num_ptr(bam_rx_pipe,
 						&buffs_unused);
 
 			if (ret) {
@@ -1261,11 +1287,11 @@
 		if (!pkt->is_cmd)
 			dma_unmap_single(NULL, pkt->dma_address,
 						pkt->skb->len,
-						DMA_TO_DEVICE);
+						bam_ops->dma_to);
 		else
 			dma_unmap_single(NULL, pkt->dma_address,
 						pkt->len,
-						DMA_TO_DEVICE);
+						bam_ops->dma_to);
 		queue_work(bam_mux_tx_workqueue, &pkt->work);
 		break;
 	default:
@@ -1288,7 +1314,8 @@
 	case SPS_EVENT_EOT:
 		/* attempt to disable interrupts in this pipe */
 		if (!polling_mode) {
-			ret = sps_get_config(bam_rx_pipe, &cur_rx_conn);
+			ret = bam_ops->sps_get_config_ptr(bam_rx_pipe,
+					&cur_rx_conn);
 			if (ret) {
 				pr_err("%s: sps_get_config() failed %d, interrupts"
 					" not disabled\n", __func__, ret);
@@ -1296,7 +1323,8 @@
 			}
 			cur_rx_conn.options = SPS_O_AUTO_ENABLE |
 				SPS_O_ACK_TRANSFERS | SPS_O_POLL;
-			ret = sps_set_config(bam_rx_pipe, &cur_rx_conn);
+			ret = bam_ops->sps_set_config_ptr(bam_rx_pipe,
+					&cur_rx_conn);
 			if (ret) {
 				pr_err("%s: sps_set_config() failed %d, interrupts"
 					" not disabled\n", __func__, ret);
@@ -1476,9 +1504,11 @@
 
 	bam_dmux_uplink_vote = vote;
 	if (vote)
-		smsm_change_state(SMSM_APPS_STATE, 0, SMSM_A2_POWER_CONTROL);
+		bam_ops->smsm_change_state_ptr(SMSM_APPS_STATE,
+			0, SMSM_A2_POWER_CONTROL);
 	else
-		smsm_change_state(SMSM_APPS_STATE, SMSM_A2_POWER_CONTROL, 0);
+		bam_ops->smsm_change_state_ptr(SMSM_APPS_STATE,
+			SMSM_A2_POWER_CONTROL, 0);
 }
 
 /*
@@ -1747,29 +1777,31 @@
 	if (!power_management_only_mode) {
 		if (ssr_skipped_disconnect) {
 			/* delayed to here to prevent bus stall */
-			sps_disconnect(bam_tx_pipe);
-			sps_disconnect(bam_rx_pipe);
+			bam_ops->sps_disconnect_ptr(bam_tx_pipe);
+			bam_ops->sps_disconnect_ptr(bam_rx_pipe);
 			__memzero(rx_desc_mem_buf.base, rx_desc_mem_buf.size);
 			__memzero(tx_desc_mem_buf.base, tx_desc_mem_buf.size);
 		}
 		ssr_skipped_disconnect = 0;
-		i = sps_device_reset(a2_device_handle);
+		i = bam_ops->sps_device_reset_ptr(a2_device_handle);
 		if (i)
 			pr_err("%s: device reset failed rc = %d\n", __func__,
 									i);
-		i = sps_connect(bam_tx_pipe, &tx_connection);
+		i = bam_ops->sps_connect_ptr(bam_tx_pipe, &tx_connection);
 		if (i)
 			pr_err("%s: tx connection failed rc = %d\n", __func__,
 									i);
-		i = sps_connect(bam_rx_pipe, &rx_connection);
+		i = bam_ops->sps_connect_ptr(bam_rx_pipe, &rx_connection);
 		if (i)
 			pr_err("%s: rx connection failed rc = %d\n", __func__,
 									i);
-		i = sps_register_event(bam_tx_pipe, &tx_register_event);
+		i = bam_ops->sps_register_event_ptr(bam_tx_pipe,
+				&tx_register_event);
 		if (i)
 			pr_err("%s: tx event reg failed rc = %d\n", __func__,
 									i);
-		i = sps_register_event(bam_rx_pipe, &rx_register_event);
+		i = bam_ops->sps_register_event_ptr(bam_rx_pipe,
+				&rx_register_event);
 		if (i)
 			pr_err("%s: rx event reg failed rc = %d\n", __func__,
 									i);
@@ -1823,9 +1855,9 @@
 	if (!power_management_only_mode) {
 		if (likely(!in_ssr)) {
 			BAM_DMUX_LOG("%s: disconnect tx\n", __func__);
-			sps_disconnect(bam_tx_pipe);
+			bam_ops->sps_disconnect_ptr(bam_tx_pipe);
 			BAM_DMUX_LOG("%s: disconnect rx\n", __func__);
-			sps_disconnect(bam_rx_pipe);
+			bam_ops->sps_disconnect_ptr(bam_rx_pipe);
 			__memzero(rx_desc_mem_buf.base, rx_desc_mem_buf.size);
 			__memzero(tx_desc_mem_buf.base, tx_desc_mem_buf.size);
 			BAM_DMUX_LOG("%s: device reset\n", __func__);
@@ -1842,7 +1874,7 @@
 		list_del(node);
 		info = container_of(node, struct rx_pkt_info, list_node);
 		dma_unmap_single(NULL, info->dma_address, BUFFER_SIZE,
-							DMA_FROM_DEVICE);
+							bam_ops->dma_from);
 		dev_kfree_skb_any(info->skb);
 		kfree(info);
 	}
@@ -1957,9 +1989,12 @@
 	 * because a watchdog crash from a bus stall would likely occur.
 	 */
 	if (code == SUBSYS_BEFORE_SHUTDOWN) {
+		BAM_DMUX_LOG("%s: begin\n", __func__);
 		in_global_reset = 1;
 		in_ssr = 1;
-		BAM_DMUX_LOG("%s: begin\n", __func__);
+		/* wait till all bam_dmux writes completes */
+		synchronize_srcu(&bam_dmux_srcu);
+		BAM_DMUX_LOG("%s: ssr signaling complete\n", __func__);
 		flush_workqueue(bam_mux_rx_workqueue);
 	}
 	if (code != SUBSYS_AFTER_SHUTDOWN)
@@ -2008,12 +2043,12 @@
 		if (!info->is_cmd) {
 			dma_unmap_single(NULL, info->dma_address,
 						info->skb->len,
-						DMA_TO_DEVICE);
+						bam_ops->dma_to);
 			dev_kfree_skb_any(info->skb);
 		} else {
 			dma_unmap_single(NULL, info->dma_address,
 						info->len,
-						DMA_TO_DEVICE);
+						bam_ops->dma_to);
 			kfree(info->skb);
 		}
 		kfree(info);
@@ -2053,20 +2088,20 @@
 	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	/* need to free on tear down */
-	ret = sps_register_bam_device(&a2_props, &h);
+	ret = bam_ops->sps_register_bam_device_ptr(&a2_props, &h);
 	if (ret < 0) {
 		pr_err("%s: register bam error %d\n", __func__, ret);
 		goto register_bam_failed;
 	}
 	a2_device_handle = h;
 
-	bam_tx_pipe = sps_alloc_endpoint();
+	bam_tx_pipe = bam_ops->sps_alloc_endpoint_ptr();
 	if (bam_tx_pipe == NULL) {
 		pr_err("%s: tx alloc endpoint failed\n", __func__);
 		ret = -ENOMEM;
 		goto tx_alloc_endpoint_failed;
 	}
-	ret = sps_get_config(bam_tx_pipe, &tx_connection);
+	ret = bam_ops->sps_get_config_ptr(bam_tx_pipe, &tx_connection);
 	if (ret) {
 		pr_err("%s: tx get config failed %d\n", __func__, ret);
 		goto tx_get_config_failed;
@@ -2091,19 +2126,19 @@
 	tx_connection.desc = tx_desc_mem_buf;
 	tx_connection.event_thresh = 0x10;
 
-	ret = sps_connect(bam_tx_pipe, &tx_connection);
+	ret = bam_ops->sps_connect_ptr(bam_tx_pipe, &tx_connection);
 	if (ret < 0) {
 		pr_err("%s: tx connect error %d\n", __func__, ret);
 		goto tx_connect_failed;
 	}
 
-	bam_rx_pipe = sps_alloc_endpoint();
+	bam_rx_pipe = bam_ops->sps_alloc_endpoint_ptr();
 	if (bam_rx_pipe == NULL) {
 		pr_err("%s: rx alloc endpoint failed\n", __func__);
 		ret = -ENOMEM;
 		goto rx_alloc_endpoint_failed;
 	}
-	ret = sps_get_config(bam_rx_pipe, &rx_connection);
+	ret = bam_ops->sps_get_config_ptr(bam_rx_pipe, &rx_connection);
 	if (ret) {
 		pr_err("%s: rx get config failed %d\n", __func__, ret);
 		goto rx_get_config_failed;
@@ -2129,7 +2164,7 @@
 	rx_connection.desc = rx_desc_mem_buf;
 	rx_connection.event_thresh = 0x10;
 
-	ret = sps_connect(bam_rx_pipe, &rx_connection);
+	ret = bam_ops->sps_connect_ptr(bam_rx_pipe, &rx_connection);
 	if (ret < 0) {
 		pr_err("%s: rx connect error %d\n", __func__, ret);
 		goto rx_connect_failed;
@@ -2140,7 +2175,7 @@
 	tx_register_event.xfer_done = NULL;
 	tx_register_event.callback = bam_mux_tx_notify;
 	tx_register_event.user = NULL;
-	ret = sps_register_event(bam_tx_pipe, &tx_register_event);
+	ret = bam_ops->sps_register_event_ptr(bam_tx_pipe, &tx_register_event);
 	if (ret < 0) {
 		pr_err("%s: tx register event error %d\n", __func__, ret);
 		goto rx_event_reg_failed;
@@ -2151,7 +2186,7 @@
 	rx_register_event.xfer_done = NULL;
 	rx_register_event.callback = bam_mux_rx_notify;
 	rx_register_event.user = NULL;
-	ret = sps_register_event(bam_rx_pipe, &rx_register_event);
+	ret = bam_ops->sps_register_event_ptr(bam_rx_pipe, &rx_register_event);
 	if (ret < 0) {
 		pr_err("%s: tx register event error %d\n", __func__, ret);
 		goto rx_event_reg_failed;
@@ -2171,22 +2206,22 @@
 	return 0;
 
 rx_event_reg_failed:
-	sps_disconnect(bam_rx_pipe);
+	bam_ops->sps_disconnect_ptr(bam_rx_pipe);
 rx_connect_failed:
 	dma_free_coherent(NULL, rx_desc_mem_buf.size, rx_desc_mem_buf.base,
 				rx_desc_mem_buf.phys_base);
 rx_mem_failed:
 rx_get_config_failed:
-	sps_free_endpoint(bam_rx_pipe);
+	bam_ops->sps_free_endpoint_ptr(bam_rx_pipe);
 rx_alloc_endpoint_failed:
-	sps_disconnect(bam_tx_pipe);
+	bam_ops->sps_disconnect_ptr(bam_tx_pipe);
 tx_connect_failed:
 	dma_free_coherent(NULL, tx_desc_mem_buf.size, tx_desc_mem_buf.base,
 				tx_desc_mem_buf.phys_base);
 tx_get_config_failed:
-	sps_free_endpoint(bam_tx_pipe);
+	bam_ops->sps_free_endpoint_ptr(bam_tx_pipe);
 tx_alloc_endpoint_failed:
-	sps_deregister_bam_device(h);
+	bam_ops->sps_deregister_bam_device_ptr(h);
 	/*
 	 * sps_deregister_bam_device() calls iounmap.  calling iounmap on the
 	 * same handle below will cause a crash, so skip it if we've freed
@@ -2224,7 +2259,7 @@
 	a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
 	if (cpu_is_msm9615() || satellite_mode)
 		a2_props.manage = SPS_BAM_MGR_DEVICE_REMOTE;
-	ret = sps_register_bam_device(&a2_props, &h);
+	ret = bam_ops->sps_register_bam_device_ptr(&a2_props, &h);
 	if (ret < 0) {
 		pr_err("%s: register bam error %d\n", __func__, ret);
 		goto register_bam_failed;
@@ -2276,7 +2311,7 @@
 
 	BAM_DMUX_LOG("%s: apps ack %d->%d\n", __func__,
 			clear_bit & 0x1, ~clear_bit & 0x1);
-	smsm_change_state(SMSM_APPS_STATE,
+	bam_ops->smsm_change_state_ptr(SMSM_APPS_STATE,
 				clear_bit & SMSM_A2_POWER_CONTROL_ACK,
 				~clear_bit & SMSM_A2_POWER_CONTROL_ACK);
 	clear_bit = ~clear_bit;
@@ -2333,6 +2368,51 @@
 	complete_all(&ul_wakeup_ack_completion);
 }
 
+/**
+ * msm_bam_dmux_set_bam_ops() - sets the bam_ops
+ * @ops: bam_ops_if to set
+ *
+ * Sets bam_ops to allow switching of runtime behavior. Preconditon, bam dmux
+ * must be in an idle state. If input ops is NULL, then bam_ops will be
+ * restored to their default state.
+ */
+void msm_bam_dmux_set_bam_ops(struct bam_ops_if *ops)
+{
+	if (ops != NULL)
+		bam_ops = ops;
+	else
+		bam_ops = &bam_default_ops;
+}
+EXPORT_SYMBOL(msm_bam_dmux_set_bam_ops);
+
+/**
+ * msm_bam_dmux_deinit() - puts bam dmux into a deinited state
+ *
+ * Puts bam dmux into a deinitialized state by simulating an ssr.
+ */
+void msm_bam_dmux_deinit(void)
+{
+	restart_notifier_cb(NULL, SUBSYS_BEFORE_SHUTDOWN, NULL);
+	restart_notifier_cb(NULL, SUBSYS_AFTER_SHUTDOWN, NULL);
+}
+EXPORT_SYMBOL(msm_bam_dmux_deinit);
+
+/**
+ * msm_bam_dmux_reinit() - reinitializes bam dmux
+ */
+void msm_bam_dmux_reinit(void)
+{
+	bam_ops->smsm_state_cb_register_ptr(SMSM_MODEM_STATE,
+			SMSM_A2_POWER_CONTROL,
+			bam_dmux_smsm_cb, NULL);
+	bam_ops->smsm_state_cb_register_ptr(SMSM_MODEM_STATE,
+			SMSM_A2_POWER_CONTROL_ACK,
+			bam_dmux_smsm_ack_cb, NULL);
+	bam_mux_initialized = 0;
+	bam_init();
+}
+EXPORT_SYMBOL(msm_bam_dmux_reinit);
+
 static int bam_dmux_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -2432,11 +2512,12 @@
 	init_completion(&shutdown_completion);
 	complete_all(&shutdown_completion);
 	INIT_DELAYED_WORK(&ul_timeout_work, ul_timeout);
-	INIT_DELAYED_WORK(&queue_rx_work, queue_rx_work_func);
 	wake_lock_init(&bam_wakelock, WAKE_LOCK_SUSPEND, "bam_dmux_wakelock");
+	init_srcu_struct(&bam_dmux_srcu);
 
-	rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL,
-					bam_dmux_smsm_cb, NULL);
+	rc = bam_ops->smsm_state_cb_register_ptr(SMSM_MODEM_STATE,
+			SMSM_A2_POWER_CONTROL,
+			bam_dmux_smsm_cb, NULL);
 
 	if (rc) {
 		destroy_workqueue(bam_mux_rx_workqueue);
@@ -2445,13 +2526,14 @@
 		return -ENOMEM;
 	}
 
-	rc = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_A2_POWER_CONTROL_ACK,
-					bam_dmux_smsm_ack_cb, NULL);
+	rc = bam_ops->smsm_state_cb_register_ptr(SMSM_MODEM_STATE,
+			SMSM_A2_POWER_CONTROL_ACK,
+			bam_dmux_smsm_ack_cb, NULL);
 
 	if (rc) {
 		destroy_workqueue(bam_mux_rx_workqueue);
 		destroy_workqueue(bam_mux_tx_workqueue);
-		smsm_state_cb_deregister(SMSM_MODEM_STATE,
+		bam_ops->smsm_state_cb_deregister_ptr(SMSM_MODEM_STATE,
 					SMSM_A2_POWER_CONTROL,
 					bam_dmux_smsm_cb, NULL);
 		pr_err("%s: smsm ack cb register failed, rc: %d\n", __func__,
@@ -2461,8 +2543,10 @@
 		return -ENOMEM;
 	}
 
-	if (smsm_get_state(SMSM_MODEM_STATE) & SMSM_A2_POWER_CONTROL)
-		bam_dmux_smsm_cb(NULL, 0, smsm_get_state(SMSM_MODEM_STATE));
+	if (bam_ops->smsm_get_state_ptr(SMSM_MODEM_STATE) &
+			SMSM_A2_POWER_CONTROL)
+		bam_dmux_smsm_cb(NULL, 0,
+			bam_ops->smsm_get_state_ptr(SMSM_MODEM_STATE));
 
 	return 0;
 }
diff --git a/arch/arm/mach-msm/bam_dmux_private.h b/arch/arm/mach-msm/bam_dmux_private.h
new file mode 100644
index 0000000..871dd64
--- /dev/null
+++ b/arch/arm/mach-msm/bam_dmux_private.h
@@ -0,0 +1,173 @@
+/* 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.
+ */
+
+#ifndef _BAM_DMUX_PRIVATE_H
+#define _BAM_DMUX_PRIVATE_H
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/sps.h>
+
+#define BAM_MUX_HDR_MAGIC_NO			0x33fc
+#define BAM_MUX_HDR_CMD_DATA			0
+#define BAM_MUX_HDR_CMD_OPEN			1
+#define BAM_MUX_HDR_CMD_CLOSE			2
+#define BAM_MUX_HDR_CMD_STATUS			3 /* unused */
+#define BAM_MUX_HDR_CMD_OPEN_NO_A2_PC		4
+#define BUFFER_SIZE				2048
+
+/**
+ * struct bam_ops_if - collection of function pointers to allow swappable
+ * runtime functionality
+ * @smsm_change_state_ptr: pointer to smsm_change_state function
+ * @smsm_get_state_ptr: pointer to smsm_get_state function
+ * @smsm_state_cb_register_ptr: pointer to smsm_state_cb_register function
+ * @smsm_state_cb_deregister_ptr: pointer to smsm_state_cb_deregister function
+ * @sps_connect_ptr: pointer to sps_connect function
+ * @sps_disconnect_ptr: pointer to sps_disconnect function
+ * @sps_register_bam_device_ptr: pointer to sps_register_bam_device
+ * @sps_deregister_bam_device_ptr: pointer to sps_deregister_bam_device
+ * function
+ * @sps_alloc_endpoint_ptr: pointer to sps_alloc_endpoint function
+ * @sps_free_endpoint_ptr: pointer to sps_free_endpoint function
+ * @sps_set_config_ptr: pointer to sps_set_config function
+ * @sps_get_config_ptr: pointer to sps_get_config function
+ * @sps_device_reset_ptr: pointer to sps_device_reset function
+ * @sps_register_event_ptr: pointer to sps_register_event function
+ * @sps_transfer_one_ptr: pointer to sps_transfer_one function
+ * @sps_get_iovec_ptr: pointer to sps_get_iovec function
+ * @sps_get_unused_desc_num_ptr: pointer to sps_get_unused_desc_num function
+ * @dma_to: enum for the direction of dma operations to device
+ * @dma_from: enum for the direction of dma operations from device
+ *
+ * This struct contains the interface from bam_dmux to smsm and sps. The
+ * pointers can be swapped out at run time to provide different functionality.
+ */
+struct bam_ops_if {
+	/* smsm */
+	int (*smsm_change_state_ptr)(uint32_t smsm_entry,
+		uint32_t clear_mask, uint32_t set_mask);
+
+	uint32_t (*smsm_get_state_ptr)(uint32_t smsm_entry);
+
+	int (*smsm_state_cb_register_ptr)(uint32_t smsm_entry, uint32_t mask,
+		void (*notify)(void *, uint32_t old_state, uint32_t new_state),
+		void *data);
+
+	int (*smsm_state_cb_deregister_ptr)(uint32_t smsm_entry, uint32_t mask,
+		void (*notify)(void *, uint32_t, uint32_t), void *data);
+
+	/* sps */
+	int (*sps_connect_ptr)(struct sps_pipe *h, struct sps_connect *connect);
+
+	int (*sps_disconnect_ptr)(struct sps_pipe *h);
+
+	int (*sps_register_bam_device_ptr)(
+		const struct sps_bam_props *bam_props,
+		u32 *dev_handle);
+
+	int (*sps_deregister_bam_device_ptr)(u32 dev_handle);
+
+	struct sps_pipe *(*sps_alloc_endpoint_ptr)(void);
+
+	int (*sps_free_endpoint_ptr)(struct sps_pipe *h);
+
+	int (*sps_set_config_ptr)(struct sps_pipe *h,
+		struct sps_connect *config);
+
+	int (*sps_get_config_ptr)(struct sps_pipe *h,
+		struct sps_connect *config);
+
+	int (*sps_device_reset_ptr)(u32 dev);
+
+	int (*sps_register_event_ptr)(struct sps_pipe *h,
+		struct sps_register_event *reg);
+
+	int (*sps_transfer_one_ptr)(struct sps_pipe *h,
+		u32 addr, u32 size,
+		void *user, u32 flags);
+
+	int (*sps_get_iovec_ptr)(struct sps_pipe *h,
+		struct sps_iovec *iovec);
+
+	int (*sps_get_unused_desc_num_ptr)(struct sps_pipe *h,
+		u32 *desc_num);
+
+	enum dma_data_direction dma_to;
+
+	enum dma_data_direction dma_from;
+};
+
+/**
+ * struct bam_mux_hdr - struct which contains bam dmux header info
+ * @magic_num: magic number placed at start to ensure that it is actually a
+ * valid bam dmux header
+ * @reserved: for later use
+ * @cmd: the command
+ * @pad_len: the length of padding
+ * @ch_id: the id of the bam dmux channel that this is sent on
+ * @pkt_len: the length of the packet that this is the header of
+ */
+struct bam_mux_hdr {
+	uint16_t magic_num;
+	uint8_t reserved;
+	uint8_t cmd;
+	uint8_t pad_len;
+	uint8_t ch_id;
+	uint16_t pkt_len;
+};
+
+/**
+ * struct rx_pkt_info - struct describing an rx packet
+ * @skb: socket buffer containing the packet
+ * @dma_address: dma mapped address of the packet
+ * @work: work_struct for processing the packet
+ * @list_node: list_head for placing this on a list
+ */
+struct rx_pkt_info {
+	struct sk_buff *skb;
+	dma_addr_t dma_address;
+	struct work_struct work;
+	struct list_head list_node;
+};
+
+/**
+ * struct tx_pkt_info - struct describing a tx packet
+ * @skb: socket buffer containing the packet
+ * @dma_address: dma mapped address of the packet
+ * @is_cmd: signifies whether this is a command or data packet
+ * @len: length og the packet
+ * @work: work_struct for processing this packet
+ * @list_node: list_head for placing this on a list
+ * @ts_sec: seconds portion of the timestamp
+ * @ts_nsec: nanoseconds portion of the timestamp
+ *
+ */
+struct tx_pkt_info {
+	struct sk_buff *skb;
+	dma_addr_t dma_address;
+	char is_cmd;
+	uint32_t len;
+	struct work_struct work;
+	struct list_head list_node;
+	unsigned ts_sec;
+	unsigned long ts_nsec;
+};
+
+void msm_bam_dmux_set_bam_ops(struct bam_ops_if *ops);
+
+void msm_bam_dmux_deinit(void);
+
+void msm_bam_dmux_reinit(void);
+
+#endif /* _BAM_DMUX_PRIVATE_H */
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 9767746..5882ebc 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -216,13 +216,6 @@
 		},
 	},
 	{
-		.gpio      = 2,		/* BLSP1 QUP1 SPI_CS1 */
-		.settings = {
-			[GPIOMUX_ACTIVE] = &gpio_spi_cs_act_config,
-			[GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
-		},
-	},
-	{
 		.gpio      = 3,		/* BLSP1 QUP1 SPI_CLK */
 		.settings = {
 			[GPIOMUX_ACTIVE] = &gpio_spi_act_config,
@@ -279,6 +272,16 @@
 	},
 };
 
+static struct msm_gpiomux_config msm_blsp_spi_cs_config[] __initdata = {
+	{
+		.gpio      = 2,		/* BLSP1 QUP1 SPI_CS1 */
+		.settings = {
+			[GPIOMUX_ACTIVE] = &gpio_spi_cs_act_config,
+			[GPIOMUX_SUSPENDED] = &gpio_spi_susp_config,
+		},
+	},
+};
+
 static struct msm_gpiomux_config msm_synaptics_configs[] __initdata = {
 	{
 		.gpio = 16,
@@ -827,9 +830,13 @@
 	if (of_board_is_skuf())
 		msm_gpiomux_install(msm_skuf_blsp_configs,
 			ARRAY_SIZE(msm_skuf_blsp_configs));
-	else
+	else {
 		msm_gpiomux_install(msm_blsp_configs,
 			ARRAY_SIZE(msm_blsp_configs));
+		if (machine_is_msm8226())
+			msm_gpiomux_install(msm_blsp_spi_cs_config,
+				ARRAY_SIZE(msm_blsp_spi_cs_config));
+	}
 
 	msm_gpiomux_install(wcnss_5wire_interface,
 				ARRAY_SIZE(wcnss_5wire_interface));
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 5244918..3539ad3 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/i2c/i2c-qup.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -24,6 +25,9 @@
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
 #include <linux/memory.h>
+#include <linux/regulator/cpr-regulator.h>
+#include <linux/regulator/fan53555.h>
+#include <linux/regulator/onsemi-ncp6335d.h>
 #include <linux/regulator/qpnp-regulator.h>
 #include <linux/msm_tsens.h>
 #include <asm/mach/map.h>
@@ -31,6 +35,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/board.h>
+#include <mach/msm_bus.h>
 #include <mach/gpiomux.h>
 #include <mach/msm_iomap.h>
 #include <mach/restart.h>
@@ -52,6 +57,7 @@
 #include "spm.h"
 #include "pm.h"
 #include "modem_notifier.h"
+#include "spm-regulator.h"
 
 static struct memtype_reserve msm8226_reserve_table[] __initdata = {
 	[MEMTYPE_SMI] = {
@@ -121,10 +127,16 @@
 	msm_pm_sleep_status_init();
 	rpm_regulator_smd_driver_init();
 	qpnp_regulator_init();
+	spm_regulator_init();
 	if (of_board_is_rumi())
 		msm_clock_init(&msm8226_rumi_clock_init_data);
 	else
 		msm_clock_init(&msm8226_clock_init_data);
+	msm_bus_fabric_init_driver();
+	qup_i2c_init_driver();
+	ncp6335d_regulator_init();
+	fan53555_regulator_init();
+	cpr_regulator_init();
 	tsens_tm_init_driver();
 	msm_thermal_device_init();
 }
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index affe6bd..2e12fc2 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -451,6 +451,12 @@
 	},
 };
 
+static struct gpiomux_setting accel_interrupt_config = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_6MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct msm_gpiomux_config msm_non_qrd_configs[] __initdata = {
 	{
 		.gpio = 8, /* CAM1_STANDBY_N */
@@ -459,6 +465,13 @@
 			[GPIOMUX_SUSPENDED] = &gpio_suspend_config[1],
 		},
 	},
+	{
+		.gpio = 81,	/*ACCEL_INT1 */
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &accel_interrupt_config,
+			[GPIOMUX_SUSPENDED] = &accel_interrupt_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm_sensor_configs[] __initdata = {
@@ -602,6 +615,13 @@
 
 static struct msm_gpiomux_config msm_interrupt_configs[] __initdata = {
 	{
+		.gpio = 75,	/* NFC_CLK_REQ_IRQ*/
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &interrupt_gpio_active,
+			[GPIOMUX_SUSPENDED] = &interrupt_gpio_suspend_pullup,
+		},
+	},
+	{
 		.gpio = 77,	/* NFC_IRQ */
 		.settings = {
 			[GPIOMUX_ACTIVE]    = &interrupt_gpio_active,
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 8ab916c..cec1a8f 100755
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -22,27 +22,28 @@
 
 static struct gpiomux_setting ap2mdm_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting mdm2ap_status_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_IN,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting mdm2ap_errfatal_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_DOWN,
-	.dir = GPIOMUX_IN,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting mdm2ap_pblrdy = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
 	.dir = GPIOMUX_IN,
 };
@@ -50,14 +51,16 @@
 
 static struct gpiomux_setting ap2mdm_soft_reset_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
+	.drv = GPIOMUX_DRV_2MA,
 	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct gpiomux_setting ap2mdm_wakeup = {
 	.func = GPIOMUX_FUNC_GPIO,
-	.drv = GPIOMUX_DRV_8MA,
-	.pull = GPIOMUX_PULL_DOWN,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
 };
 
 static struct msm_gpiomux_config mdm_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 3a0c152..1336ec3 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -1555,6 +1555,8 @@
 	},
 };
 
+static DEFINE_CLK_MEASURE(wcnss_m_clk);
+
 #ifdef CONFIG_DEBUG_FS
 struct measure_mux_entry {
 	struct clk *c;
@@ -1610,6 +1612,7 @@
 	{ &pnoc_clk.c, GCC_BASE, 0x010},
 	{ &snoc_clk.c, GCC_BASE, 0x000},
 	{ &cnoc_clk.c, GCC_BASE, 0x008},
+	{ &wcnss_m_clk, GCC_BASE, 0x0198},
 	/*
 	 * measure the gcc_bimc_kpss_axi_clk instead to account for the DDR
 	 * rate being gcc_bimc_clk/2.
@@ -3134,6 +3137,10 @@
 	CLK_LOOKUP("apc3_m_clk", apc3_m_clk, ""),
 	CLK_LOOKUP("l2_m_clk", l2_m_clk, ""),
 
+	/* Measure clocks for WCNSS */
+	CLK_LOOKUP("measure",   measure_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("wcnss_debug", wcnss_m_clk, "fb000000.qcom,wcnss-wlan"),
+
 	/* LPM Resources */
 	CLK_LOOKUP("xo",          cxo_lpm_clk.c, "fc4281d0.qcom,mpm"),
 
@@ -3150,7 +3157,7 @@
 	CLK_LOOKUP("iface_clk",   gcc_mss_cfg_ahb_clk.c, "fc880000.qcom,mss"),
 	CLK_LOOKUP("mem_clk",    gcc_boot_rom_ahb_clk.c, "fc880000.qcom,mss"),
 	/* NFC */
-	CLK_LOOKUP("ref_clk",            cxo_d1_pin.c, "2-000e"),
+	CLK_LOOKUP("ref_clk",            cxo_d1_a_pin.c, "2-000e"),
 	/* PIL-PRONTO */
 	CLK_LOOKUP("xo", cxo_pil_pronto_clk.c, "fb21b000.qcom,pronto"),
 
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index c7bf92c..d68762a 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -527,6 +527,7 @@
 static DEFINE_CLK_MEASURE(apc2_m_clk);
 static DEFINE_CLK_MEASURE(apc3_m_clk);
 static DEFINE_CLK_MEASURE(l2_m_clk);
+static DEFINE_CLK_MEASURE(wcnss_m_clk);
 
 #define APCS_SH_PLL_MODE        0x000
 #define APCS_SH_PLL_L_VAL       0x004
@@ -2509,6 +2510,7 @@
 	{                   &bimc_clk.c, GCC_BASE, 0x0155},
 	{          &gcc_bimc_smmu_clk.c, GCC_BASE, 0x015e},
 	{       &gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
+	{                  &wcnss_m_clk, GCC_BASE, 0x0198},
 
 	{     &mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
 	{   &mmss_misc_ahb_clk.c, MMSS_BASE, 0x0003},
@@ -3111,6 +3113,8 @@
 	CLK_LOOKUP("xo",        cxo_acpu_clk.c, "f9011050.qcom,acpuclk"),
 	CLK_LOOKUP("gpll0", gpll0_ao_clk_src.c, "f9011050.qcom,acpuclk"),
 	CLK_LOOKUP("a7sspll",        a7sspll.c, "f9011050.qcom,acpuclk"),
+	CLK_LOOKUP("clk-4",  gpll0_ao_clk_src.c, "f9011050.qcom,clock-a7"),
+	CLK_LOOKUP("clk-5", a7sspll.c, "f9011050.qcom,clock-a7"),
 
 	CLK_LOOKUP("measure_clk", apc0_m_clk, ""),
 	CLK_LOOKUP("measure_clk", apc1_m_clk, ""),
@@ -3118,6 +3122,9 @@
 	CLK_LOOKUP("measure_clk", apc3_m_clk, ""),
 	CLK_LOOKUP("measure_clk",   l2_m_clk, ""),
 
+	CLK_LOOKUP("measure",   measure_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("wcnss_debug", wcnss_m_clk, "fb000000.qcom,wcnss-wlan"),
+
 	CLK_LOOKUP("xo",     cxo_wlan_clk.c, "fb000000.qcom,wcnss-wlan"),
 	CLK_LOOKUP("rf_clk",       cxo_a1.c, "fb000000.qcom,wcnss-wlan"),
 
@@ -3143,6 +3150,12 @@
 	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,  "scm"),
 	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,      "scm"),
 
+	/* GUD Clocks */
+	CLK_LOOKUP("core_clk",     gcc_ce1_clk.c,      "mcd"),
+	CLK_LOOKUP("iface_clk",    gcc_ce1_ahb_clk.c,  "mcd"),
+	CLK_LOOKUP("bus_clk",      gcc_ce1_axi_clk.c,  "mcd"),
+	CLK_LOOKUP("core_clk_src", ce1_clk_src.c,      "mcd"),
+
 	/* 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"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 6ae909b..d51e6f7 100755
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4438,6 +4438,7 @@
 static DEFINE_CLK_MEASURE(krait1_m_clk);
 static DEFINE_CLK_MEASURE(krait2_m_clk);
 static DEFINE_CLK_MEASURE(krait3_m_clk);
+static DEFINE_CLK_MEASURE(wcnss_m_clk);
 
 #ifdef CONFIG_DEBUG_FS
 
@@ -4538,6 +4539,7 @@
 	{&pnoc_clk.c,                           GCC_BASE, 0x0010},
 	{&snoc_clk.c,                           GCC_BASE, 0x0000},
 	{&bimc_clk.c,                           GCC_BASE, 0x0155},
+	{&wcnss_m_clk,                          GCC_BASE, 0x0198},
 	{&mmss_mmssnoc_axi_clk.c,		MMSS_BASE, 0x0004},
 	{&ocmemnoc_clk.c,			MMSS_BASE, 0x0007},
 	{&ocmemcx_ocmemnoc_clk.c,		MMSS_BASE, 0x0009},
@@ -5054,6 +5056,9 @@
 	CLK_LOOKUP("sleep_clk", gcc_usb2b_phy_sleep_clk.c, "msm_ehci_host"),
 	CLK_LOOKUP("pwm_clk", div_clk2.c, "0-0048"),
 
+	CLK_LOOKUP("measure",   measure_clk.c, "fb000000.qcom,wcnss-wlan"),
+	CLK_LOOKUP("wcnss_debug", wcnss_m_clk, "fb000000.qcom,wcnss-wlan"),
+
 	/* Multimedia clocks */
 	CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
 	CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
@@ -5061,6 +5066,7 @@
 	CLK_LOOKUP("core_clk", mdss_edpaux_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("pixel_clk", mdss_edppixel_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("link_clk", mdss_edplink_clk.c, "fd923400.qcom,mdss_edp"),
+	CLK_LOOKUP("mdp_core_clk", mdss_mdp_clk.c, "fd923400.qcom,mdss_edp"),
 	CLK_LOOKUP("byte_clk", mdss_byte0_clk.c, "fd922800.qcom,mdss_dsi"),
 	CLK_LOOKUP("byte_clk", mdss_byte1_clk.c, "fd922e00.qcom,mdss_dsi"),
 	CLK_LOOKUP("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi"),
diff --git a/arch/arm/mach-msm/clock-a7.c b/arch/arm/mach-msm/clock-a7.c
index 5b8dc4e..d09e4b6 100644
--- a/arch/arm/mach-msm/clock-a7.c
+++ b/arch/arm/mach-msm/clock-a7.c
@@ -193,7 +193,8 @@
 	if (!c->fmax)
 		return -ENOMEM;
 
-	array = devm_kzalloc(&pdev->dev, prop_len * sizeof(u32), GFP_KERNEL);
+	array = devm_kzalloc(&pdev->dev,
+			prop_len * sizeof(u32) * 2, GFP_KERNEL);
 	if (!array)
 		return -ENOMEM;
 
diff --git a/arch/arm/mach-msm/clock-krait-8974.c b/arch/arm/mach-msm/clock-krait-8974.c
index 24fe303..4f133fc 100644
--- a/arch/arm/mach-msm/clock-krait-8974.c
+++ b/arch/arm/mach-msm/clock-krait-8974.c
@@ -414,7 +414,7 @@
 };
 
 static void get_krait_bin_format_b(struct platform_device *pdev,
-					int *speed, int *pvs, int *ver)
+					int *speed, int *pvs, int *pvs_ver)
 {
 	u32 pte_efuse, redundant_sel;
 	struct resource *res;
@@ -422,7 +422,7 @@
 
 	*speed = 0;
 	*pvs = 0;
-	*ver = 0;
+	*pvs_ver = 0;
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse");
 	if (!res) {
@@ -443,7 +443,7 @@
 	*speed = pte_efuse & 0x7;
 	/* 4 bits of PVS are in efuse register bits 31, 8-6. */
 	*pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
-	*ver = (pte_efuse >> 4) & 0x3;
+	*pvs_ver = (pte_efuse >> 4) & 0x3;
 
 	switch (redundant_sel) {
 	case 1:
@@ -471,7 +471,7 @@
 		*pvs = 0;
 	}
 
-	dev_info(&pdev->dev, "PVS version: %d\n", *ver);
+	dev_info(&pdev->dev, "PVS version: %d\n", *pvs_ver);
 
 	devm_iounmap(&pdev->dev, base);
 }
@@ -585,12 +585,16 @@
 	}
 }
 
+static char table_name[] = "qcom,speedXX-pvsXX-bin-vXX";
+module_param_string(table_name, table_name, sizeof(table_name), S_IRUGO);
+static unsigned int pvs_config_ver;
+module_param(pvs_config_ver, uint, S_IRUGO);
+
 static int clock_krait_8974_driver_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct clk *c;
-	int speed, pvs, ver, rows, cpu;
-	char prop_name[] = "qcom,speedXX-pvsXX-bin-vXX";
+	int speed, pvs, pvs_ver, config_ver, rows, cpu;
 	unsigned long *freq, cur_rate, aux_rate;
 	int *uv, *ua;
 	u32 *dscr, vco_mask, config_val;
@@ -673,15 +677,22 @@
 	if (!ret)
 		hdata.user_vco_mask = vco_mask;
 
-	get_krait_bin_format_b(pdev, &speed, &pvs, &ver);
-	snprintf(prop_name, ARRAY_SIZE(prop_name),
-			"qcom,speed%d-pvs%d-bin-v%d", speed, pvs, ver);
+	ret = of_property_read_u32(dev->of_node, "qcom,pvs-config-ver",
+			&config_ver);
+	if (!ret) {
+		pvs_config_ver = config_ver;
+		dev_info(&pdev->dev, "PVS config version: %d\n", config_ver);
+	}
 
-	rows = parse_tbl(dev, prop_name, 3,
+	get_krait_bin_format_b(pdev, &speed, &pvs, &pvs_ver);
+	snprintf(table_name, ARRAY_SIZE(table_name),
+			"qcom,speed%d-pvs%d-bin-v%d", speed, pvs, pvs_ver);
+
+	rows = parse_tbl(dev, table_name, 3,
 			(u32 **) &freq, (u32 **) &uv, (u32 **) &ua);
 	if (rows < 0) {
 		/* Fall back to most conservative PVS table */
-		dev_err(dev, "Unable to load voltage plan %s!\n", prop_name);
+		dev_err(dev, "Unable to load voltage plan %s!\n", table_name);
 		ret = parse_tbl(dev, "qcom,speed0-pvs0-bin-v0", 3,
 				(u32 **) &freq, (u32 **) &uv, (u32 **) &ua);
 		if (ret < 0) {
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index d1b1885..1fc7f1d 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -151,6 +151,7 @@
 
 #define PLL_POLL_MAX_READS	10
 #define PLL_POLL_TIMEOUT_US	50
+#define SEQ_M_MAX_COUNTER	7
 
 static long vco_cached_rate;
 static unsigned char *mdss_dsi_base;
@@ -1034,12 +1035,12 @@
 static void dsi_pll_toggle_lock_detect(void)
 {
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x05);
+		0x0d);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x04);
+		0x0c);
 	udelay(1);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-		0x05);
+		0x0d);
 }
 
 static int dsi_pll_lock_status(void)
@@ -1076,9 +1077,9 @@
 	 * reset bit off and back on.
 	 */
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x01);
-	udelay(1000);
+	udelay(1);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_TEST_CFG, 0x00);
-	udelay(1000);
+	udelay(1);
 }
 
 static int dsi_pll_enable_seq_m(void)
@@ -1093,24 +1094,25 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
-	for (i = 0; (i < 4) && !pll_locked; i++) {
+	for (i = 0; (i < SEQ_M_MAX_COUNTER) && !pll_locked; i++) {
+		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG,
+			0x00);
+		udelay(50);
 		DSS_REG_W(mdss_dsi_base,
-			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
-		if (i != 0)
-			DSS_REG_W(mdss_dsi_base,
-				DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG1, 0x34);
-		udelay(1);
+			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
+		udelay(100);
 		DSS_REG_W(mdss_dsi_base,
 			DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-		udelay(1000);
+		udelay(600);
 		pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	}
 
@@ -1134,6 +1136,8 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
@@ -1145,7 +1149,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1165,6 +1169,8 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
@@ -1174,7 +1180,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1194,12 +1200,14 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1219,6 +1227,8 @@
 	 * the updates to take effect. These delays are necessary for the
 	 * PLL to successfully lock
 	 */
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_PWRGEN_CFG, 0x00);
+	udelay(50);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
 	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
@@ -1226,7 +1236,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0d);
 	udelay(1);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(600);
 
 	pll_locked = dsi_pll_toggle_lock_detect_and_check_status();
 	pr_debug("%s: PLL status = %s\n", __func__,
@@ -1247,22 +1257,22 @@
 	 * Add necessary delays recommeded by hardware.
 	 */
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x01);
-	udelay(1000);
+	udelay(1);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x05);
-	udelay(1000);
+	udelay(200);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x07);
-	udelay(1000);
+	udelay(500);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x0f);
-	udelay(1000);
+	udelay(500);
 
-	for (i = 0; i < 3; i++) {
+	for (i = 0; i < 2; i++) {
+		udelay(100);
 		/* DSI Uniphy lock detect setting */
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-			0x04);
+			0x0c);
 		udelay(100);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2,
-			0x05);
-		udelay(500);
+			0x0d);
 		/* poll for PLL ready status */
 		max_reads = 5;
 		timeout_us = 100;
@@ -1285,17 +1295,17 @@
 		 * Add necessary delays recommeded by hardware.
 		 */
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x1);
-		udelay(1000);
+		udelay(1);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x5);
-		udelay(1000);
+		udelay(200);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x7);
-		udelay(1000);
+		udelay(250);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x5);
-		udelay(1000);
+		udelay(200);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0x7);
-		udelay(1000);
+		udelay(500);
 		DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_GLB_CFG, 0xf);
-		udelay(2000);
+		udelay(500);
 
 	}
 
@@ -1459,7 +1469,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CHGPUMP_CFG, 0x02);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG3, 0x2b);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG4, 0x66);
-	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x05);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_LKDET_CFG2, 0x0d);
 
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG1,
 		(u32)(sdm_cfg1 & 0xff));
@@ -1470,7 +1480,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG4, 0x00);
 
 	/* Add hardware recommended delay for correct PLL configuration */
-	udelay(1000);
+	udelay(1);
 
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_REFCLK_CFG,
 		(u32)refclk_cfg);
@@ -1478,7 +1488,7 @@
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_VCOLPF_CFG, 0x71);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_SDM_CFG0,
 		(u32)sdm_cfg0);
-	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x0a);
+	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG0, 0x12);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG6, 0x30);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG7, 0x00);
 	DSS_REG_W(mdss_dsi_base, DSI_0_PHY_PLL_UNIPHY_PLL_CAL_CFG8, 0x60);
@@ -1640,13 +1650,14 @@
 	.ref_clk_rate = 19200000,
 	.min_rate = 350000000,
 	.max_rate = 750000000,
-	.pll_en_seq_cnt = 6,
+	.pll_en_seq_cnt = 7,
 	.pll_enable_seqs[0] = dsi_pll_enable_seq_m,
-	.pll_enable_seqs[1] = dsi_pll_enable_seq_d,
+	.pll_enable_seqs[1] = dsi_pll_enable_seq_m,
 	.pll_enable_seqs[2] = dsi_pll_enable_seq_d,
-	.pll_enable_seqs[3] = dsi_pll_enable_seq_f1,
-	.pll_enable_seqs[4] = dsi_pll_enable_seq_c,
-	.pll_enable_seqs[5] = dsi_pll_enable_seq_e,
+	.pll_enable_seqs[3] = dsi_pll_enable_seq_d,
+	.pll_enable_seqs[4] = dsi_pll_enable_seq_f1,
+	.pll_enable_seqs[5] = dsi_pll_enable_seq_c,
+	.pll_enable_seqs[6] = dsi_pll_enable_seq_e,
 	.lpfr_lut_size = 10,
 	.lpfr_lut = (struct lpfr_cfg[]){
 		{479500000, 8},
@@ -1999,7 +2010,6 @@
 	if (status)
 		return 1;
 
-	pr_err("%s: PLL NOT ready\n", __func__);
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/cpr-regulator.c b/arch/arm/mach-msm/cpr-regulator.c
index fa132fa..08285aa 100644
--- a/arch/arm/mach-msm/cpr-regulator.c
+++ b/arch/arm/mach-msm/cpr-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -144,6 +144,10 @@
 	int quot_adjust;
 };
 
+static const char * const vdd_apc_name[] =	{"vdd-apc-optional-prim",
+						"vdd-apc-optional-sec",
+						"vdd-apc"};
+
 enum voltage_change_dir {
 	NO_CHANGE,
 	DOWN,
@@ -596,6 +600,10 @@
 					RBCPR_CTL_UP_THRESHOLD_SHIFT;
 			reg_val = reg_mask;
 			cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
+
+			/* Disable UP interrupt */
+			cpr_irq_set(cpr_vreg, CPR_INT_DEFAULT & ~CPR_INT_UP);
+
 			return;
 		}
 
@@ -622,13 +630,9 @@
 		}
 		cpr_vreg->last_volt[corner] = new_volt;
 
-		/* Restore default threshold for DOWN */
-		reg_mask = RBCPR_CTL_DN_THRESHOLD_MASK <<
-				RBCPR_CTL_DN_THRESHOLD_SHIFT;
-		reg_val = cpr_vreg->down_threshold <<
-				RBCPR_CTL_DN_THRESHOLD_SHIFT;
-		/* and disable auto nack down */
-		reg_mask |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+		/* Disable auto nack down */
+		reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+		reg_val = 0;
 
 		cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
 
@@ -652,16 +656,12 @@
 				cpr_vreg->floor_volt[fuse_corner]);
 			cpr_irq_clr_nack(cpr_vreg);
 
-			/* Maximize the DOWN threshold */
-			reg_mask = RBCPR_CTL_DN_THRESHOLD_MASK <<
-					RBCPR_CTL_DN_THRESHOLD_SHIFT;
-			reg_val = reg_mask;
 			cpr_debug_irq("gcnt = 0x%08x (quot = %d)\n", gcnt,
 					quot);
 
 			/* Enable auto nack down */
-			reg_mask |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
-			reg_val |= RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+			reg_mask = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
+			reg_val = RBCPR_CTL_SW_AUTO_CONT_NACK_DN_EN;
 
 			cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
 
@@ -700,6 +700,9 @@
 				RBCPR_CTL_UP_THRESHOLD_SHIFT;
 		cpr_ctl_modify(cpr_vreg, reg_mask, reg_val);
 
+		/* Re-enable default interrupts */
+		cpr_irq_set(cpr_vreg, CPR_INT_DEFAULT);
+
 		/* Ack */
 		cpr_irq_clr_ack(cpr_vreg);
 
@@ -1063,13 +1066,13 @@
 	int rc, i;
 
 	rc = of_property_read_u32(of_node,
-		"qti,cpr-uplift-voltage", &uplift_voltage);
+		"qcom,cpr-uplift-voltage", &uplift_voltage);
 	if (rc < 0) {
 		pr_err("cpr-uplift-voltage is missing, rc = %d", rc);
 		return rc;
 	}
 	rc = of_property_read_u32(of_node,
-		"qti,cpr-uplift-max-volt", &uplift_max_volt);
+		"qcom,cpr-uplift-max-volt", &uplift_max_volt);
 	if (rc < 0) {
 		pr_err("cpr-uplift-max-volt is missing, rc = %d", rc);
 		return rc;
@@ -1095,7 +1098,7 @@
 	bool redundant;
 	size_t pvs_bins;
 
-	rc = of_property_read_u32_array(of_node, "qti,pvs-fuse-redun-sel",
+	rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun-sel",
 					pvs_fuse_redun_sel, 5);
 	if (rc < 0) {
 		pr_err("pvs-fuse-redun-sel missing: rc=%d\n", rc);
@@ -1105,14 +1108,14 @@
 	redundant = cpr_fuse_is_setting_expected(cpr_vreg, pvs_fuse_redun_sel);
 
 	if (redundant) {
-		rc = of_property_read_u32_array(of_node, "qti,pvs-fuse-redun",
+		rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse-redun",
 						pvs_fuse, 4);
 		if (rc < 0) {
 			pr_err("pvs-fuse-redun missing: rc=%d\n", rc);
 			return rc;
 		}
 	} else {
-		rc = of_property_read_u32_array(of_node, "qti,pvs-fuse",
+		rc = of_property_read_u32_array(of_node, "qcom,pvs-fuse",
 						pvs_fuse, 4);
 		if (rc < 0) {
 			pr_err("pvs-fuse missing: rc=%d\n", rc);
@@ -1128,7 +1131,7 @@
 
 	pvs_bins = 1 << pvs_fuse[2];
 
-	rc = of_property_read_u32_array(of_node, "qti,pvs-init-voltage",
+	rc = of_property_read_u32_array(of_node, "qcom,pvs-init-voltage",
 					cpr_vreg->pvs_init_v, pvs_bins);
 	if (rc < 0) {
 		pr_err("pvs-init-voltage missing: rc=%d\n", rc);
@@ -1175,7 +1178,7 @@
 do {									\
 	if (!rc) {							\
 		rc = of_property_read_u32(of_node,			\
-				"qti," cpr_property,			\
+				"qcom," cpr_property,			\
 				cpr_config);				\
 		if (rc) {						\
 			pr_err("Missing " #cpr_property			\
@@ -1188,11 +1191,17 @@
 			       struct cpr_regulator *cpr_vreg)
 {
 	struct device_node *of_node = pdev->dev.of_node;
-	int rc;
+	int i, rc = 0;
 
-	cpr_vreg->vdd_apc = devm_regulator_get(&pdev->dev, "vdd-apc");
-	if (IS_ERR_OR_NULL(cpr_vreg->vdd_apc)) {
+	for (i = 0; i < ARRAY_SIZE(vdd_apc_name); i++) {
+		cpr_vreg->vdd_apc = devm_regulator_get(&pdev->dev,
+					vdd_apc_name[i]);
 		rc = PTR_RET(cpr_vreg->vdd_apc);
+		if (!IS_ERR_OR_NULL(cpr_vreg->vdd_apc))
+			break;
+	}
+
+	if (rc) {
 		if (rc != -EPROBE_DEFER)
 			pr_err("devm_regulator_get: rc=%d\n", rc);
 		return rc;
@@ -1212,14 +1221,14 @@
 
 	/* Parse dependency parameters */
 	if (cpr_vreg->vdd_mx) {
-		rc = of_property_read_u32(of_node, "qti,vdd-mx-vmax",
+		rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmax",
 				 &cpr_vreg->vdd_mx_vmax);
 		if (rc < 0) {
 			pr_err("vdd-mx-vmax missing: rc=%d\n", rc);
 			return rc;
 		}
 
-		rc = of_property_read_u32(of_node, "qti,vdd-mx-vmin-method",
+		rc = of_property_read_u32(of_node, "qcom,vdd-mx-vmin-method",
 				 &cpr_vreg->vdd_mx_vmin_method);
 		if (rc < 0) {
 			pr_err("vdd-mx-vmin-method missing: rc=%d\n", rc);
@@ -1252,7 +1261,7 @@
 	int rc, i;
 
 	rc = of_property_read_u32_array(of_node,
-			"qti,cpr-uplift-quotient", delta_quot, 3);
+			"qcom,cpr-uplift-quotient", delta_quot, 3);
 	if (rc < 0) {
 		pr_err("cpr-uplift-quotient is missing: %d", rc);
 		return rc;
@@ -1271,7 +1280,7 @@
 	u32 *tmp;
 	bool corners_mapped;
 
-	prop = of_find_property(dev->of_node, "qti,cpr-corner-map", NULL);
+	prop = of_find_property(dev->of_node, "qcom,cpr-corner-map", NULL);
 
 	if (prop) {
 		size = prop->length / sizeof(u32);
@@ -1294,10 +1303,10 @@
 			cpr_vreg->corner_map[i] = i;
 	} else {
 		rc = of_property_read_u32_array(dev->of_node,
-			"qti,cpr-corner-map", &cpr_vreg->corner_map[1], size);
+			"qcom,cpr-corner-map", &cpr_vreg->corner_map[1], size);
 
 		if (rc) {
-			pr_err("qti,cpr-corner-map missing, rc = %d", rc);
+			pr_err("qcom,cpr-corner-map missing, rc = %d", rc);
 			return rc;
 		}
 	}
@@ -1310,12 +1319,12 @@
 		return -ENOMEM;
 	}
 
-	prop = of_find_property(dev->of_node, "qti,cpr-quot-adjust-table",
+	prop = of_find_property(dev->of_node, "qcom,cpr-quot-adjust-table",
 				NULL);
 
 	if (prop) {
 		if (!corners_mapped) {
-			pr_err("qti,cpr-corner-map missing\n");
+			pr_err("qcom,cpr-corner-map missing\n");
 			return -EINVAL;
 		}
 
@@ -1325,9 +1334,9 @@
 			return -ENOMEM;
 
 		rc = of_property_read_u32_array(dev->of_node,
-				"qti,cpr-quot-adjust-table", tmp, size);
+				"qcom,cpr-quot-adjust-table", tmp, size);
 		if (rc) {
-			pr_err("qti,cpr-quot-adjust-table missing, rc = %d",
+			pr_err("qcom,cpr-quot-adjust-table missing, rc = %d",
 				rc);
 			kfree(tmp);
 			return rc;
@@ -1336,7 +1345,7 @@
 		stripe_size = sizeof(struct quot_adjust_info) / sizeof(int);
 
 		if ((size % stripe_size) != 0) {
-			pr_err("qti,cpr-quot-adjust-table data is not correct");
+			pr_err("qcom,cpr-quot-adjust-table data is not correct");
 			kfree(tmp);
 			return -EINVAL;
 		}
@@ -1349,7 +1358,7 @@
 					cpr_vreg->quot_adjust[tmp[i + 1]] =
 					tmp[i + 2];
 				} else {
-					pr_err("qti,cpr-quot-adjust-table data is not correct");
+					pr_err("qcom,cpr-quot-adjust-table data is not correct");
 					kfree(tmp);
 					return -EINVAL;
 				}
@@ -1376,8 +1385,9 @@
 	int bp_ro_sel[CPR_FUSE_CORNER_MAX];
 	u32 ro_sel, val;
 	u64 fuse_bits, fuse_bits_2;
+	u32 quot_adjust[CPR_FUSE_CORNER_MAX];
 
-	rc = of_property_read_u32_array(of_node, "qti,cpr-fuse-redun-sel",
+	rc = of_property_read_u32_array(of_node, "qcom,cpr-fuse-redun-sel",
 					cpr_fuse_redun_sel, 5);
 	if (rc < 0) {
 		pr_err("cpr-fuse-redun-sel missing: rc=%d\n", rc);
@@ -1388,16 +1398,16 @@
 
 	if (redundant) {
 		rc = of_property_read_u32_array(of_node,
-				"qti,cpr-fuse-redun-row",
+				"qcom,cpr-fuse-redun-row",
 				cpr_fuse_row, 2);
-		targ_quot_str = "qti,cpr-fuse-redun-target-quot";
-		ro_sel_str = "qti,cpr-fuse-redun-ro-sel";
+		targ_quot_str = "qcom,cpr-fuse-redun-target-quot";
+		ro_sel_str = "qcom,cpr-fuse-redun-ro-sel";
 	} else {
 		rc = of_property_read_u32_array(of_node,
-				"qti,cpr-fuse-row",
+				"qcom,cpr-fuse-row",
 				cpr_fuse_row, 2);
-		targ_quot_str = "qti,cpr-fuse-target-quot";
-		ro_sel_str = "qti,cpr-fuse-ro-sel";
+		targ_quot_str = "qcom,cpr-fuse-target-quot";
+		ro_sel_str = "qcom,cpr-fuse-ro-sel";
 	}
 	if (rc)
 		return rc;
@@ -1427,7 +1437,7 @@
 
 	if (redundant) {
 		if (of_property_read_bool(of_node,
-				"qti,cpr-fuse-redun-bp-cpr-disable")) {
+				"qcom,cpr-fuse-redun-bp-cpr-disable")) {
 			CPR_PROP_READ_U32(of_node,
 					  "cpr-fuse-redun-bp-cpr-disable",
 					  &bp_cpr_disable, rc);
@@ -1446,7 +1456,7 @@
 			CPR_PROP_READ_U32(of_node, "cpr-fuse-bp-scheme",
 					  &bp_scheme, rc);
 			rc = of_property_read_u32_array(of_node,
-					"qti,cpr-fuse-row",
+					"qcom,cpr-fuse-row",
 					temp_row, 2);
 			if (rc)
 				return rc;
@@ -1483,6 +1493,16 @@
 			i, ro_sel, val);
 	}
 
+	rc = of_property_read_u32_array(of_node, "qcom,cpr-quotient-adjustment",
+				&quot_adjust[1], CPR_FUSE_CORNER_MAX - 1);
+	if (!rc) {
+		for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) {
+			cpr_vreg->cpr_fuse_target_quot[i] += quot_adjust[i];
+			pr_info("Corner[%d]: adjusted target quot = %d\n",
+				i, cpr_vreg->cpr_fuse_target_quot[i]);
+		}
+	}
+
 	if (cpr_vreg->flags & FLAGS_UPLIFT_QUOT_VOLT) {
 		cpr_voltage_uplift_wa_inc_quot(cpr_vreg, of_node);
 		for (i = CPR_FUSE_CORNER_SVS; i < CPR_FUSE_CORNER_MAX; i++) {
@@ -1611,7 +1631,7 @@
 		return rc;
 
 	/* Init module parameter with the DT value */
-	cpr_vreg->enable = of_property_read_bool(of_node, "qti,cpr-enable");
+	cpr_vreg->enable = of_property_read_bool(of_node, "qcom,cpr-enable");
 	cpr_enable = (int) cpr_vreg->enable;
 	pr_info("CPR is %s by default.\n",
 		cpr_vreg->enable ? "enabled" : "disabled");
@@ -1716,12 +1736,12 @@
 	u32 fuse_sel[5];
 	/*
 	 * Restrict all pvs corner voltages to a minimum value of
-	 * qti,cpr-cond-min-voltage if the fuse defined in
-	 * qti,cpr-fuse-cond-min-volt-sel does not read back with
+	 * qcom,cpr-cond-min-voltage if the fuse defined in
+	 * qcom,cpr-fuse-cond-min-volt-sel does not read back with
 	 * the expected value.
 	 */
 	rc = of_property_read_u32_array(of_node,
-			"qti,cpr-fuse-cond-min-volt-sel", fuse_sel, 5);
+			"qcom,cpr-fuse-cond-min-volt-sel", fuse_sel, 5);
 	if (!rc) {
 		if (!cpr_fuse_is_setting_expected(cpr_vreg, fuse_sel))
 			cpr_vreg->flags |= FLAGS_SET_MIN_VOLTAGE;
@@ -1737,7 +1757,7 @@
 	u32 speed_bits;
 
 	rc = of_property_read_u32_array(of_node,
-			"qti,speed-bin-fuse-sel", fuse_sel, 4);
+			"qcom,speed-bin-fuse-sel", fuse_sel, 4);
 
 	if (!rc) {
 		fuse_bits = cpr_read_efuse_row(cpr_vreg,
@@ -1760,13 +1780,13 @@
 	u32 uplift_speed_bin;
 
 	rc = of_property_read_u32_array(of_node,
-			"qti,cpr-fuse-uplift-sel", fuse_sel, 5);
+			"qcom,cpr-fuse-uplift-sel", fuse_sel, 5);
 	if (!rc) {
 		rc = of_property_read_u32(of_node,
-				"qti,cpr-uplift-speed-bin",
+				"qcom,cpr-uplift-speed-bin",
 				&uplift_speed_bin);
 		if (rc < 0) {
-			pr_err("qti,cpr-uplift-speed-bin missing\n");
+			pr_err("qcom,cpr-uplift-speed-bin missing\n");
 			return rc;
 		}
 		if (cpr_fuse_is_setting_expected(cpr_vreg, fuse_sel)
@@ -1786,7 +1806,7 @@
 	u32 min_uv = 0;
 
 	rc = of_property_read_u32_array(of_node,
-		"qti,pvs-corner-ceiling-slow",
+		"qcom,pvs-corner-ceiling-slow",
 		&cpr_vreg->pvs_corner_v[APC_PVS_SLOW][CPR_FUSE_CORNER_SVS],
 		CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
 	if (rc < 0) {
@@ -1795,7 +1815,7 @@
 	}
 
 	rc = of_property_read_u32_array(of_node,
-		"qti,pvs-corner-ceiling-nom",
+		"qcom,pvs-corner-ceiling-nom",
 		&cpr_vreg->pvs_corner_v[APC_PVS_NOM][CPR_FUSE_CORNER_SVS],
 		CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
 	if (rc < 0) {
@@ -1804,7 +1824,7 @@
 	}
 
 	rc = of_property_read_u32_array(of_node,
-		"qti,pvs-corner-ceiling-fast",
+		"qcom,pvs-corner-ceiling-fast",
 		&cpr_vreg->pvs_corner_v[APC_PVS_FAST][CPR_FUSE_CORNER_SVS],
 		CPR_FUSE_CORNER_MAX - CPR_FUSE_CORNER_SVS);
 	if (rc < 0) {
@@ -1820,7 +1840,7 @@
 		return rc;
 	}
 	if (cpr_vreg->flags & FLAGS_SET_MIN_VOLTAGE) {
-		of_property_read_u32(of_node, "qti,cpr-cond-min-voltage",
+		of_property_read_u32(of_node, "qcom,cpr-cond-min-voltage",
 					&min_uv);
 		for (i = APC_PVS_SLOW; i < NUM_APC_PVS; i++)
 			for (j = CPR_FUSE_CORNER_SVS; j < CPR_FUSE_CORNER_MAX;
diff --git a/arch/arm/mach-msm/cpubw-krait.c b/arch/arm/mach-msm/cpubw-krait.c
deleted file mode 100644
index 4108754..0000000
--- a/arch/arm/mach-msm/cpubw-krait.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * 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.
- */
-
-#define pr_fmt(fmt) "cpubw-krait: " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/ktime.h>
-#include <linux/time.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <trace/events/power.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
-
-#include <mach/msm-krait-l2-accessors.h>
-
-#define L2PMRESR2		0x412
-#define L2PMCR			0x400
-#define L2PMCNTENCLR		0x402
-#define L2PMCNTENSET		0x403
-#define L2PMINTENCLR		0x404
-#define L2PMINTENSET		0x405
-#define L2PMOVSR		0x406
-#define L2PMOVSSET		0x407
-#define L2PMnEVCNTCR(n)		(0x420 + n * 0x10)
-#define L2PMnEVCNTR(n)		(0x421 + n * 0x10)
-#define L2PMnEVCNTSR(n)		(0x422 + n * 0x10)
-#define L2PMnEVFILTER(n)	(0x423 + n * 0x10)
-#define L2PMnEVTYPER(n)		(0x424 + n * 0x10)
-#define MON_INT			33
-
-#define MBYTE			(1 << 20)
-
-#define BW(_bw) \
-	{ \
-		.vectors = (struct msm_bus_vectors[]){ \
-			{\
-				.src = MSM_BUS_MASTER_AMPSS_M0, \
-				.dst = MSM_BUS_SLAVE_EBI_CH0, \
-			}, \
-			{ \
-				.src = MSM_BUS_MASTER_AMPSS_M1, \
-				.dst = MSM_BUS_SLAVE_EBI_CH0, \
-			}, \
-		}, \
-		.num_paths = 2, \
-	}
-
-/* Has to be a power of 2 to work correctly */
-static unsigned int bytes_per_beat = 8;
-module_param(bytes_per_beat, uint, 0644);
-
-static unsigned int sample_ms = 50;
-module_param(sample_ms, uint, 0644);
-
-static unsigned int tolerance_percent = 10;
-module_param(tolerance_percent, uint, 0644);
-
-static unsigned int guard_band_mbps = 100;
-module_param(guard_band_mbps, uint, 0644);
-
-static unsigned int decay_rate = 90;
-module_param(decay_rate, uint, 0644);
-
-static unsigned int io_percent = 15;
-module_param(io_percent, uint, 0644);
-
-static unsigned int bw_step = 200;
-module_param(bw_step, uint, 0644);
-
-static struct kernel_param_ops enable_ops;
-static bool enable;
-module_param_cb(enable, &enable_ops, &enable, S_IRUGO | S_IWUSR);
-
-static void mon_init(void)
-{
-	/* Set up counters 0/1 to count write/read beats */
-	set_l2_indirect_reg(L2PMRESR2, 0x8B0B0000);
-	set_l2_indirect_reg(L2PMnEVCNTCR(0), 0x0);
-	set_l2_indirect_reg(L2PMnEVCNTCR(1), 0x0);
-	set_l2_indirect_reg(L2PMnEVCNTR(0), 0xFFFFFFFF);
-	set_l2_indirect_reg(L2PMnEVCNTR(1), 0xFFFFFFFF);
-	set_l2_indirect_reg(L2PMnEVFILTER(0), 0xF003F);
-	set_l2_indirect_reg(L2PMnEVFILTER(1), 0xF003F);
-	set_l2_indirect_reg(L2PMnEVTYPER(0), 0xA);
-	set_l2_indirect_reg(L2PMnEVTYPER(1), 0xB);
-}
-
-static void global_mon_enable(bool en)
-{
-	u32 regval;
-
-	/* Global counter enable */
-	regval = get_l2_indirect_reg(L2PMCR);
-	if (en)
-		regval |= BIT(0);
-	else
-		regval &= ~BIT(0);
-	set_l2_indirect_reg(L2PMCR, regval);
-}
-
-static void mon_enable(int n)
-{
-	/* Clear previous overflow state for event counter n */
-	set_l2_indirect_reg(L2PMOVSR, BIT(n));
-
-	/* Enable event counter n */
-	set_l2_indirect_reg(L2PMCNTENSET, BIT(n));
-}
-
-static void mon_disable(int n)
-{
-	/* Disable event counter n */
-	set_l2_indirect_reg(L2PMCNTENCLR, BIT(n));
-}
-
-/* Returns start counter value to be used with mon_get_mbps() */
-static u32 mon_set_limit_mbyte(int n, unsigned int mbytes)
-{
-	u32 regval, beats;
-
-	beats = mult_frac(mbytes, MBYTE, bytes_per_beat);
-	regval = 0xFFFFFFFF - beats;
-	set_l2_indirect_reg(L2PMnEVCNTR(n), regval);
-	pr_debug("EV%d MB: %d, start val: %x\n", n, mbytes, regval);
-
-	return regval;
-}
-
-/* Returns MBps of read/writes for the sampling window. */
-static int mon_get_mbps(int n, u32 start_val, unsigned int us)
-{
-	u32 overflow, count;
-	long long beats;
-
-	count = get_l2_indirect_reg(L2PMnEVCNTR(n));
-	overflow = get_l2_indirect_reg(L2PMOVSR);
-
-	if (overflow & BIT(n))
-		beats = 0xFFFFFFFF - start_val + count;
-	else
-		beats = count - start_val;
-
-	beats *= USEC_PER_SEC;
-	beats *= bytes_per_beat;
-	do_div(beats, us);
-	beats = DIV_ROUND_UP_ULL(beats, MBYTE);
-
-	pr_debug("EV%d ov: %x, cnt: %x\n", n, overflow, count);
-
-	return beats;
-}
-
-static void do_bw_sample(struct work_struct *work);
-static DECLARE_DEFERRED_WORK(bw_sample, do_bw_sample);
-static struct workqueue_struct *bw_sample_wq;
-
-static DEFINE_MUTEX(bw_lock);
-static ktime_t prev_ts;
-static u32 prev_r_start_val;
-static u32 prev_w_start_val;
-
-static struct msm_bus_paths bw_levels[] = {
-	BW(0), BW(200),
-};
-static struct msm_bus_scale_pdata bw_data = {
-	.usecase = bw_levels,
-	.num_usecases = ARRAY_SIZE(bw_levels),
-	.name = "cpubw-krait",
-	.active_only = 1,
-};
-static u32 bus_client;
-static void compute_bw(int mbps);
-static irqreturn_t mon_intr_handler(int irq, void *dev_id);
-
-#define START_LIMIT	100 /* MBps */
-static int start_monitoring(void)
-{
-	int mb_limit;
-	int ret;
-
-	ret = request_threaded_irq(MON_INT, NULL, mon_intr_handler,
-			  IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_RISING,
-			  "cpubw_krait", mon_intr_handler);
-	if (ret) {
-		pr_err("Unable to register interrupt handler\n");
-		return ret;
-	}
-
-	bw_sample_wq = alloc_workqueue("cpubw-krait", WQ_HIGHPRI, 0);
-	if (!bw_sample_wq) {
-		pr_err("Unable to alloc workqueue\n");
-		ret = -ENOMEM;
-		goto alloc_wq_fail;
-	}
-
-	bus_client = msm_bus_scale_register_client(&bw_data);
-	if (!bus_client) {
-		pr_err("Unable to register bus client\n");
-		ret = -ENODEV;
-		goto bus_reg_fail;
-	}
-
-	compute_bw(START_LIMIT);
-
-	mon_init();
-	mon_disable(0);
-	mon_disable(1);
-
-	mb_limit = mult_frac(START_LIMIT, sample_ms, MSEC_PER_SEC);
-	mb_limit /= 2;
-
-	prev_r_start_val = mon_set_limit_mbyte(0, mb_limit);
-	prev_w_start_val = mon_set_limit_mbyte(1, mb_limit);
-
-	prev_ts = ktime_get();
-
-	set_l2_indirect_reg(L2PMINTENSET, BIT(0));
-	set_l2_indirect_reg(L2PMINTENSET, BIT(1));
-	mon_enable(0);
-	mon_enable(1);
-	global_mon_enable(true);
-
-	queue_delayed_work(bw_sample_wq, &bw_sample,
-				msecs_to_jiffies(sample_ms));
-
-	return 0;
-
-bus_reg_fail:
-	destroy_workqueue(bw_sample_wq);
-alloc_wq_fail:
-	disable_irq(MON_INT);
-	free_irq(MON_INT, mon_intr_handler);
-	return ret;
-}
-
-static void stop_monitoring(void)
-{
-	global_mon_enable(false);
-	mon_disable(0);
-	mon_disable(1);
-	set_l2_indirect_reg(L2PMINTENCLR, BIT(0));
-	set_l2_indirect_reg(L2PMINTENCLR, BIT(1));
-
-	disable_irq(MON_INT);
-	free_irq(MON_INT, mon_intr_handler);
-
-	cancel_delayed_work_sync(&bw_sample);
-	destroy_workqueue(bw_sample_wq);
-
-	bw_levels[0].vectors[0].ib = 0;
-	bw_levels[0].vectors[0].ab = 0;
-	bw_levels[0].vectors[1].ib = 0;
-	bw_levels[0].vectors[1].ab = 0;
-
-	bw_levels[1].vectors[0].ib = 0;
-	bw_levels[1].vectors[0].ab = 0;
-	bw_levels[1].vectors[1].ib = 0;
-	bw_levels[1].vectors[1].ab = 0;
-	msm_bus_scale_unregister_client(bus_client);
-}
-
-static void set_bw(int mbps)
-{
-	static int cur_idx, cur_ab, cur_ib;
-	int new_ab, new_ib;
-	int i, ret;
-
-	if (!io_percent)
-		io_percent = 1;
-	new_ab = roundup(mbps, bw_step);
-	new_ib = mbps * 100 / io_percent;
-	new_ib = roundup(new_ib, bw_step);
-
-	if (cur_ib == new_ib && cur_ab == new_ab)
-		return;
-
-	i = (cur_idx + 1) % ARRAY_SIZE(bw_levels);
-
-	bw_levels[i].vectors[0].ib = new_ib * 1000000ULL;
-	bw_levels[i].vectors[0].ab = new_ab * 1000000ULL;
-	bw_levels[i].vectors[1].ib = new_ib * 1000000ULL;
-	bw_levels[i].vectors[1].ab = new_ab * 1000000ULL;
-
-	pr_debug("BW MBps: Req: %d AB: %d IB: %d\n", mbps, new_ab, new_ib);
-
-	ret = msm_bus_scale_client_update_request(bus_client, i);
-	if (ret)
-		pr_err("bandwidth request failed (%d)\n", ret);
-	else {
-		cur_idx = i;
-		cur_ib = new_ib;
-		cur_ab = new_ab;
-	}
-}
-
-static void compute_bw(int mbps)
-{
-	static int cur_bw;
-	int new_bw;
-
-	mbps += guard_band_mbps;
-
-	if (mbps > cur_bw) {
-		new_bw = mbps;
-	} else {
-		new_bw = mbps * decay_rate + cur_bw * (100 - decay_rate);
-		new_bw /= 100;
-	}
-
-	if (new_bw == cur_bw)
-		return;
-
-	set_bw(new_bw);
-	cur_bw = new_bw;
-}
-
-static int to_limit(int mbps)
-{
-	mbps *= (100 + tolerance_percent) * sample_ms;
-	mbps /= 100;
-	mbps = DIV_ROUND_UP(mbps, MSEC_PER_SEC);
-	return mbps;
-}
-
-static void measure_bw(void)
-{
-	int r_mbps, w_mbps, mbps;
-	ktime_t ts;
-	unsigned int us;
-
-	mutex_lock(&bw_lock);
-
-	/*
-	 * Since we are stopping the counters, we don't want this short work
-	 * to be interrupted by other tasks and cause the measurements to be
-	 * wrong. Not blocking interrupts to avoid affecting interrupt
-	 * latency and since they should be short anyway because they run in
-	 * atomic context.
-	 */
-	preempt_disable();
-
-	ts = ktime_get();
-	us = ktime_to_us(ktime_sub(ts, prev_ts));
-	if (!us)
-		us = 1;
-
-	mon_disable(0);
-	mon_disable(1);
-
-	r_mbps = mon_get_mbps(0, prev_r_start_val, us);
-	w_mbps = mon_get_mbps(1, prev_w_start_val, us);
-
-	prev_r_start_val = mon_set_limit_mbyte(0, to_limit(r_mbps));
-	prev_w_start_val = mon_set_limit_mbyte(1, to_limit(w_mbps));
-
-	mon_enable(0);
-	mon_enable(1);
-
-	preempt_enable();
-
-	mbps = r_mbps + w_mbps;
-	pr_debug("R/W/BW/us = %d/%d/%d/%d\n", r_mbps, w_mbps, mbps, us);
-	compute_bw(mbps);
-
-	prev_ts = ts;
-	mutex_unlock(&bw_lock);
-}
-
-static void do_bw_sample(struct work_struct *work)
-{
-	measure_bw();
-	queue_delayed_work(bw_sample_wq, &bw_sample,
-				msecs_to_jiffies(sample_ms));
-}
-
-static irqreturn_t mon_intr_handler(int irq, void *dev_id)
-{
-	bool pending;
-	u32 regval;
-
-	regval = get_l2_indirect_reg(L2PMOVSR);
-	pr_debug("Got interrupt: %x\n", regval);
-
-	pending = cancel_delayed_work_sync(&bw_sample);
-
-	/*
-	 * Don't recalc bandwidth if the interrupt came just after the end
-	 * of the sample period (!pending). This is done for two reasons:
-	 *
-	 * 1. Sampling the BW during a very short duration can result in a
-	 *    very inaccurate measurement due to very short bursts.
-	 * 2. If the limit was hit very close to the sample period, then the
-	 *    current BW estimate is not very off and can stay as such.
-	 */
-	if (pending)
-		measure_bw();
-
-	queue_delayed_work(bw_sample_wq, &bw_sample,
-				msecs_to_jiffies(sample_ms));
-
-	return IRQ_HANDLED;
-}
-
-static int set_enable(const char *arg, const struct kernel_param *kp)
-{
-	int ret;
-	bool old_val = *((bool *) kp->arg);
-	bool new_val;
-
-	if (!arg)
-		arg = "1";
-	ret = strtobool(arg, &new_val);
-	if (ret)
-		return ret;
-
-	if (!old_val && new_val) {
-		if (start_monitoring()) {
-			pr_err("L2PM counters already in use.\n");
-			return ret;
-		} else {
-			pr_info("Enabling CPU BW monitoring\n");
-		}
-	} else if (old_val && !new_val) {
-		pr_info("Disabling CPU BW monitoring\n");
-		stop_monitoring();
-	}
-
-	*(bool *) kp->arg = new_val;
-	return 0;
-}
-
-static struct kernel_param_ops enable_ops = {
-	.set = set_enable,
-	.get = param_get_bool,
-};
-
-static int cpubw_krait_init(void)
-{
-	bw_sample_wq = alloc_workqueue("cpubw-krait", WQ_HIGHPRI, 0);
-	if (!bw_sample_wq)
-		return -ENOMEM;
-
-	bus_client = msm_bus_scale_register_client(&bw_data);
-	if (!bus_client) {
-		pr_err("Unable to register bus client\n");
-		destroy_workqueue(bw_sample_wq);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-late_initcall(cpubw_krait_init);
-
-MODULE_DESCRIPTION("CPU DDR bandwidth voting driver for Krait CPUs");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c
index 60856c2..46505e0 100644
--- a/arch/arm/mach-msm/cpufreq.c
+++ b/arch/arm/mach-msm/cpufreq.c
@@ -32,7 +32,7 @@
 #include <linux/platform_device.h>
 #include <trace/events/power.h>
 #include <mach/socinfo.h>
-#include <mach/msm_bus.h>
+#include <mach/cpufreq.h>
 
 #include "acpuclock.h"
 
@@ -47,16 +47,12 @@
 static struct clk *cpu_clk[NR_CPUS];
 static struct clk *l2_clk;
 static unsigned int freq_index[NR_CPUS];
+static unsigned int max_freq_index;
 static struct cpufreq_frequency_table *freq_table;
 static unsigned int *l2_khz;
 static bool is_clk;
 static bool is_sync;
-static struct msm_bus_vectors *bus_vec_lst;
-static struct msm_bus_scale_pdata bus_bw = {
-	.name = "msm-cpufreq",
-	.active_only = 1,
-};
-static u32 bus_client;
+static unsigned long *mem_bw;
 
 struct cpufreq_work_struct {
 	struct work_struct work;
@@ -77,6 +73,11 @@
 
 static DEFINE_PER_CPU(struct cpufreq_suspend_t, cpufreq_suspend);
 
+unsigned long msm_cpufreq_get_bw(void)
+{
+	return mem_bw[max_freq_index];
+}
+
 static void update_l2_bw(int *also_cpu)
 {
 	int rc = 0, cpu;
@@ -98,10 +99,10 @@
 		goto out;
 	}
 
-	if (bus_client)
-		rc = msm_bus_scale_client_update_request(bus_client, index);
+	max_freq_index = index;
+	rc = devfreq_msm_cpufreq_update_bw();
 	if (rc)
-		pr_err("Bandwidth req failed (%d)\n", rc);
+		pr_err("Unable to update BW (%d)\n", rc);
 
 out:
 	mutex_unlock(&l2bw_lock);
@@ -253,6 +254,14 @@
 		|| cpu_is_msm8610() || (is_clk && is_sync))
 		cpumask_setall(policy->cpus);
 
+	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
+	INIT_WORK(&cpu_work->work, set_cpu_work);
+	init_completion(&cpu_work->complete);
+
+	/* synchronous cpus share the same policy */
+	if (!cpu_clk[policy->cpu])
+		return 0;
+
 	if (cpufreq_frequency_table_cpuinfo(policy, table)) {
 #ifdef CONFIG_MSM_CPU_FREQ_SET_MIN_MAX
 		policy->cpuinfo.min_freq = CONFIG_MSM_CPU_FREQ_MIN;
@@ -291,10 +300,6 @@
 	policy->cpuinfo.transition_latency =
 		acpuclk_get_switch_time() * NSEC_PER_USEC;
 
-	cpu_work = &per_cpu(cpufreq_work, policy->cpu);
-	INIT_WORK(&cpu_work->work, set_cpu_work);
-	init_completion(&cpu_work->complete);
-
 	return 0;
 }
 
@@ -397,33 +402,14 @@
 };
 
 #define PROP_TBL "qcom,cpufreq-table"
-#define PROP_PORTS "qcom,cpu-mem-ports"
 static int cpufreq_parse_dt(struct device *dev)
 {
-	int ret, len, nf, num_cols = 1, num_paths = 0, i, j, k;
-	u32 *data, *ports = NULL;
-	struct msm_bus_vectors *v = NULL;
+	int ret, len, nf, num_cols = 2, i, j;
+	u32 *data;
 
 	if (l2_clk)
 		num_cols++;
 
-	/* Parse optional bus ports parameter */
-	if (of_find_property(dev->of_node, PROP_PORTS, &len)) {
-		len /= sizeof(*ports);
-		if (len % 2)
-			return -EINVAL;
-
-		ports = devm_kzalloc(dev, len * sizeof(*ports), GFP_KERNEL);
-		if (!ports)
-			return -ENOMEM;
-		ret = of_property_read_u32_array(dev->of_node, PROP_PORTS,
-						 ports, len);
-		if (ret)
-			return ret;
-		num_paths = len / 2;
-		num_cols++;
-	}
-
 	/* Parse CPU freq -> L2/Mem BW map table. */
 	if (!of_find_property(dev->of_node, PROP_TBL, &len))
 		return -EINVAL;
@@ -444,7 +430,9 @@
 	/* Allocate all data structures. */
 	freq_table = devm_kzalloc(dev, (nf + 1) * sizeof(*freq_table),
 				  GFP_KERNEL);
-	if (!freq_table)
+	mem_bw = devm_kzalloc(dev, nf * sizeof(*mem_bw), GFP_KERNEL);
+
+	if (!freq_table || !mem_bw)
 		return -ENOMEM;
 
 	if (l2_clk) {
@@ -453,15 +441,6 @@
 			return -ENOMEM;
 	}
 
-	if (num_paths) {
-		int sz_u = nf * sizeof(*bus_bw.usecase);
-		int sz_v = nf * num_paths * sizeof(*bus_vec_lst);
-		bus_bw.usecase = devm_kzalloc(dev, sz_u, GFP_KERNEL);
-		v = bus_vec_lst = devm_kzalloc(dev, sz_v, GFP_KERNEL);
-		if (!bus_bw.usecase || !bus_vec_lst)
-			return -ENOMEM;
-	}
-
 	j = 0;
 	for (i = 0; i < nf; i++) {
 		unsigned long f;
@@ -504,25 +483,12 @@
 			}
 		}
 
-		if (num_paths) {
-			unsigned int bw_mbps = data[j++];
-			bus_bw.usecase[i].num_paths = num_paths;
-			bus_bw.usecase[i].vectors = v;
-			for (k = 0; k < num_paths; k++) {
-				v->src = ports[k * 2];
-				v->dst = ports[k * 2 + 1];
-				v->ib = bw_mbps * 1000000ULL;
-				v++;
-			}
-		}
+		mem_bw[i] = data[j++];
 	}
 
-	bus_bw.num_usecases = i;
 	freq_table[i].index = i;
 	freq_table[i].frequency = CPUFREQ_TABLE_END;
 
-	if (ports)
-		devm_kfree(dev, ports);
 	devm_kfree(dev, data);
 
 	return 0;
@@ -532,15 +498,12 @@
 static int msm_cpufreq_show(struct seq_file *m, void *unused)
 {
 	unsigned int i, cpu_freq;
-	uint64_t ib;
 
 	if (!freq_table)
 		return 0;
 
 	seq_printf(m, "%10s%10s", "CPU (KHz)", "L2 (KHz)");
-	if (bus_bw.usecase)
-		seq_printf(m, "%12s", "Mem (MBps)");
-	seq_printf(m, "\n");
+	seq_printf(m, "%12s\n", "Mem (MBps)");
 
 	for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
 		cpu_freq = freq_table[i].frequency;
@@ -548,11 +511,7 @@
 			continue;
 		seq_printf(m, "%10d", cpu_freq);
 		seq_printf(m, "%10d", l2_khz ? l2_khz[i] : cpu_freq);
-		if (bus_bw.usecase) {
-			ib = bus_bw.usecase[i].vectors[0].ib;
-			do_div(ib, 1000000);
-			seq_printf(m, "%12llu", ib);
-		}
+		seq_printf(m, "%12lu", mem_bw[i]);
 		seq_printf(m, "\n");
 	}
 	return 0;
@@ -602,10 +561,10 @@
 		cpufreq_frequency_table_get_attr(freq_table, cpu);
 	}
 
-	if (bus_bw.usecase) {
-		bus_client = msm_bus_scale_register_client(&bus_bw);
-		if (!bus_client)
-			dev_warn(dev, "Unable to register bus client\n");
+	ret = register_devfreq_msm_cpufreq();
+	if (ret) {
+		pr_err("devfreq governor registration failed\n");
+		return ret;
 	}
 
 	is_clk = true;
diff --git a/arch/arm/mach-msm/devfreq_cpubw.c b/arch/arm/mach-msm/devfreq_cpubw.c
new file mode 100644
index 0000000..20cabc2
--- /dev/null
+++ b/arch/arm/mach-msm/devfreq_cpubw.c
@@ -0,0 +1,221 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt) "cpubw: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#include <linux/time.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/devfreq.h>
+#include <linux/of.h>
+#include <trace/events/power.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
+
+/* Has to be ULL to prevent overflow where this macro is used. */
+#define MBYTE (1ULL << 20)
+#define MAX_PATHS	2
+
+static struct msm_bus_vectors vectors[MAX_PATHS * 2];
+static struct msm_bus_paths bw_levels[] = {
+	{ .vectors = &vectors[0] },
+	{ .vectors = &vectors[MAX_PATHS] },
+};
+static struct msm_bus_scale_pdata bw_data = {
+	.usecase = bw_levels,
+	.num_usecases = ARRAY_SIZE(bw_levels),
+	.name = "devfreq_cpubw",
+	.active_only = 1,
+};
+static int num_paths;
+static u32 bus_client;
+
+static int set_bw(int new_ib, int new_ab)
+{
+	static int cur_idx, cur_ab, cur_ib;
+	int i, ret;
+
+	if (cur_ib == new_ib && cur_ab == new_ab)
+		return 0;
+
+	i = (cur_idx + 1) % ARRAY_SIZE(bw_levels);
+
+	bw_levels[i].vectors[0].ib = new_ib * MBYTE;
+	bw_levels[i].vectors[0].ab = new_ab / num_paths * MBYTE;
+	bw_levels[i].vectors[1].ib = new_ib * MBYTE;
+	bw_levels[i].vectors[1].ab = new_ab / num_paths * MBYTE;
+
+	pr_debug("BW MBps: AB: %d IB: %d\n", new_ab, new_ib);
+
+	ret = msm_bus_scale_client_update_request(bus_client, i);
+	if (ret) {
+		pr_err("bandwidth request failed (%d)\n", ret);
+	} else {
+		cur_idx = i;
+		cur_ib = new_ib;
+		cur_ab = new_ab;
+	}
+
+	return ret;
+}
+
+static void find_freq(struct devfreq_dev_profile *p, unsigned long *freq,
+			u32 flags)
+{
+	int i;
+	unsigned long atmost, atleast, f;
+
+	atmost = p->freq_table[0];
+	atleast = p->freq_table[p->max_state-1];
+	for (i = 0; i < p->max_state; i++) {
+		f = p->freq_table[i];
+		if (f <= *freq)
+			atmost = max(f, atmost);
+		if (f >= *freq)
+			atleast = min(f, atleast);
+	}
+
+	if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND)
+		*freq = atmost;
+	else
+		*freq = atleast;
+}
+
+struct devfreq_dev_profile cpubw_profile;
+static long gov_ab;
+
+int cpubw_target(struct device *dev, unsigned long *freq, u32 flags)
+{
+	find_freq(&cpubw_profile, freq, flags);
+	return set_bw(*freq, gov_ab);
+}
+
+static struct devfreq_governor_data gov_data[] = {
+	{ .name = "performance" },
+	{ .name = "powersave" },
+	{ .name = "userspace" },
+	{ .name = "msm_cpufreq" },
+	{ .name = "cpubw_hwmon", .data = &gov_ab },
+};
+
+struct devfreq_dev_profile cpubw_profile = {
+	.polling_ms = 50,
+	.target = cpubw_target,
+	.governor_data = gov_data,
+	.num_governor_data = ARRAY_SIZE(gov_data),
+};
+
+#define PROP_PORTS "qcom,cpu-mem-ports"
+#define PROP_TBL "qcom,bw-tbl"
+
+static int __init cpubw_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct devfreq_dev_profile *p = &cpubw_profile;
+	struct devfreq *df;
+	u32 *data, ports[MAX_PATHS * 2];
+	int ret, len, i;
+
+	if (of_find_property(dev->of_node, PROP_PORTS, &len)) {
+		len /= sizeof(ports[0]);
+		if (len % 2 || len > ARRAY_SIZE(ports)) {
+			dev_err(dev, "Unexpected number of ports\n");
+			return -EINVAL;
+		}
+
+		ret = of_property_read_u32_array(dev->of_node, PROP_PORTS,
+						 ports, len);
+		if (ret)
+			return ret;
+
+		num_paths = len / 2;
+	} else {
+		return -EINVAL;
+	}
+
+	for (i = 0; i < num_paths; i++) {
+		bw_levels[0].vectors[i].src = ports[2 * i];
+		bw_levels[0].vectors[i].dst = ports[2 * i + 1];
+		bw_levels[1].vectors[i].src = ports[2 * i];
+		bw_levels[1].vectors[i].dst = ports[2 * i + 1];
+	}
+	bw_levels[0].num_paths = num_paths;
+	bw_levels[1].num_paths = num_paths;
+
+	if (of_find_property(dev->of_node, PROP_TBL, &len)) {
+		len /= sizeof(*data);
+		data = devm_kzalloc(dev, len * sizeof(*data), GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+
+		p->freq_table = devm_kzalloc(dev,
+					     len * sizeof(*p->freq_table),
+					     GFP_KERNEL);
+		if (!p->freq_table)
+			return -ENOMEM;
+
+		ret = of_property_read_u32_array(dev->of_node, PROP_TBL,
+						 data, len);
+		if (ret)
+			return ret;
+
+		for (i = 0; i < len; i++)
+			p->freq_table[i] = data[i];
+		p->max_state = len;
+	}
+
+	bus_client = msm_bus_scale_register_client(&bw_data);
+	if (!bus_client) {
+		dev_err(dev, "Unable to register bus client\n");
+		return -ENODEV;
+	}
+
+	df = devfreq_add_device(dev, &cpubw_profile, "msm_cpufreq", NULL);
+	if (IS_ERR(df)) {
+		msm_bus_scale_unregister_client(bus_client);
+		return PTR_ERR(df);
+	}
+
+	return 0;
+}
+
+static struct of_device_id match_table[] = {
+	{ .compatible = "qcom,cpubw" },
+	{}
+};
+
+static struct platform_driver cpubw_driver = {
+	.driver = {
+		.name = "cpubw",
+		.of_match_table = match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init cpubw_init(void)
+{
+	platform_driver_probe(&cpubw_driver, cpubw_probe);
+	return 0;
+}
+device_initcall(cpubw_init);
+
+MODULE_DESCRIPTION("CPU DDR bandwidth voting driver MSM CPUs");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 1f7d56a..06eb6dc 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010,2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010,2013-2014, 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
@@ -123,6 +123,11 @@
 }
 EXPORT_SYMBOL(msm_gpiomux_put);
 
+int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg)
+{
+	return readl_relaxed(MSM_TLMM_BASE + misc_reg);
+}
+
 void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val)
 {
 	writel_relaxed(val, MSM_TLMM_BASE + misc_reg);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 6370bd4..47c07ff 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -513,6 +513,10 @@
 /**
  * msm_i2c_platform_data: i2c-qup driver configuration data
  *
+ * @clk_ctl_xfer : When true, the clocks's state (prepare_enable/
+ *       unprepare_disable) is controlled by i2c-transaction's begining and
+ *       ending. When false, the clock's state is controlled by runtime-pm
+ *       events.
  * @active_only when set, votes when system active and removes the vote when
  *       system goes idle (optimises for performance). When unset, voting using
  *       runtime pm (optimizes for power).
@@ -521,6 +525,7 @@
  */
 struct msm_i2c_platform_data {
 	int clk_freq;
+	bool clk_ctl_xfer;
 	uint32_t rmutex;
 	const char *rsl_id;
 	uint32_t pm_lat;
diff --git a/arch/arm/mach-msm/include/mach/cpufreq.h b/arch/arm/mach-msm/include/mach/cpufreq.h
new file mode 100644
index 0000000..46872d7
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/cpufreq.h
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+#ifndef __MACH_CPUFREQ_H
+#define __MACH_CPUFREQ_H
+
+#if defined(CONFIG_DEVFREQ_GOV_MSM_CPUFREQ)
+extern int devfreq_msm_cpufreq_update_bw(void);
+extern int register_devfreq_msm_cpufreq(void);
+#else
+static int devfreq_msm_cpufreq_update_bw(void)
+{
+	return 0;
+}
+static int register_devfreq_msm_cpufreq(void)
+{
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_CPU_FREQ_MSM)
+extern unsigned long msm_cpufreq_get_bw(void);
+#else
+extern unsigned long msm_cpufreq_get_bw(void)
+{
+	return ULONG_MAX;
+}
+#endif
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/ecm_ipa.h b/arch/arm/mach-msm/include/mach/ecm_ipa.h
index f6afb2a..cdcb8d8 100644
--- a/arch/arm/mach-msm/include/mach/ecm_ipa.h
+++ b/arch/arm/mach-msm/include/mach/ecm_ipa.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -40,6 +40,8 @@
  * with ecm_ipa APIs
  * @host_ethaddr: host Ethernet address in network order
  * @device_ethaddr: device Ethernet address in network order
+ * @skip_ep_cfg: boolean field that determines if Apps-processor
+ *  should or should not configure this end-point.
  */
 struct ecm_ipa_params {
 	ecm_ipa_callback ecm_ipa_rx_dp_notify;
@@ -47,6 +49,7 @@
 	u8 host_ethaddr[ETH_ALEN];
 	u8 device_ethaddr[ETH_ALEN];
 	void *private;
+	bool skip_ep_cfg;
 };
 
 
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index 122ffaa..2278677 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011,2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2011,2013-2014, 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
@@ -118,8 +118,6 @@
 	TLMM_CDC_HDRV_PULL_CTL = 0x2058,
 };
 
-void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
-
 #ifdef CONFIG_MSM_GPIOMUX
 
 /* Before using gpiomux, initialize the subsystem by telling it how many
@@ -170,6 +168,14 @@
  * should use msm_gpiomux_write.
  */
 void __msm_gpiomux_write(unsigned gpio, struct gpiomux_setting val);
+
+/* Functions that provide an API for drivers to read from and write to
+ * miscellaneous TLMM registers.
+ */
+int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg);
+
+void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
+
 #else
 static inline int msm_gpiomux_init(size_t ngpio)
 {
@@ -195,5 +201,16 @@
 {
 	return -ENOSYS;
 }
+
+static inline int msm_tlmm_misc_reg_read(enum msm_tlmm_misc_reg misc_reg)
+{
+	return -ENOSYS;
+}
+
+static inline void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg,
+						int val)
+{
+}
+
 #endif
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
index a35ff4d..45d000b 100644
--- a/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
+++ b/arch/arm/mach-msm/include/mach/msm-krait-l2-accessors.h
@@ -2,7 +2,7 @@
 #define __ASM_ARCH_MSM_MSM_KRAIT_L2_ACCESSORS_H
 
 /*
- * Copyright (c) 2011,2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,55 @@
  * GNU General Public License for more details.
  */
 
+#define MAX_L2_PERIOD		((1ULL << 32) - 1)
+#define MAX_KRAIT_L2_CTRS	10
+
+#define PMCR_NUM_EV_SHIFT	11
+#define PMCR_NUM_EV_MASK	0x1f
+
+#define L2_EVT_MASK		0xfffff
+
+#define L2_SLAVE_EV_PREFIX	4
+#define L2_TRACECTR_PREFIX	5
+
+#define L2PMCCNTR		0x409
+#define L2PMCCNTCR		0x408
+#define L2PMCCNTSR		0x40A
+#define L2CYCLE_CTR_BIT		31
+#define L2CYCLE_CTR_RAW_CODE	0xfe
+
+#define L2PMOVSR	0x406
+
+#define L2PMCR			0x400
+#define L2PMCR_RESET_ALL	0x6
+#define L2PMCR_GLOBAL_ENABLE	0x1
+#define L2PMCR_GLOBAL_DISABLE	0x0
+
+#define L2PMCNTENSET	0x403
+#define L2PMCNTENCLR	0x402
+
+#define L2PMINTENSET	0x405
+#define L2PMINTENCLR	0x404
+
+#define IA_L2PMXEVCNTCR_BASE	0x420
+#define IA_L2PMXEVTYPER_BASE	0x424
+#define IA_L2PMRESX_BASE	0x410
+#define IA_L2PMXEVFILTER_BASE	0x423
+#define IA_L2PMXEVCNTR_BASE	0x421
+
+/* event format is -e rsRCCG See get_event_desc() */
+
+#define EVENT_PREFIX_MASK	0xf0000
+#define EVENT_REG_MASK		0x0f000
+#define EVENT_GROUPSEL_MASK	0x0000f
+#define EVENT_GROUPCODE_MASK	0x00ff0
+
+#define EVENT_PREFIX_SHIFT		16
+#define EVENT_REG_SHIFT			12
+#define EVENT_GROUPCODE_SHIFT		4
+
+#define RESRX_VALUE_EN	0x80000000
+
 #ifdef CONFIG_ARCH_MSM_KRAIT
 extern void set_l2_indirect_reg(u32 reg_addr, u32 val);
 extern u32 get_l2_indirect_reg(u32 reg_addr);
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h
index ebc43da..57f781f 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -75,6 +75,7 @@
  */
 
 #ifdef CONFIG_MSM_BUS_SCALING
+int __init msm_bus_fabric_init_driver(void);
 uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata);
 int msm_bus_scale_client_update_request(uint32_t cl, unsigned int index);
 void msm_bus_scale_unregister_client(uint32_t cl);
@@ -83,6 +84,8 @@
 int msm_bus_axi_portunhalt(int master_port);
 
 #else
+static inline int __init msm_bus_fabric_init_driver(void) { return 0; }
+
 static inline uint32_t
 msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata)
 {
diff --git a/arch/arm/mach-msm/include/mach/msm_bus_board.h b/arch/arm/mach-msm/include/mach/msm_bus_board.h
index ef835b8..bc22517 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus_board.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus_board.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -41,6 +41,7 @@
 	int hw_sel;
 	void *hw_data;
 	uint32_t qos_freq;
+	uint32_t qos_baseoffset;
 	bool virt;
 };
 
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
index 9a27fd2..faf50d2 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -132,13 +132,6 @@
 	uint8_t *params_data;
 };
 
-/* Input events sources */
-enum us_input_event_src_type {
-	US_INPUT_SRC_PEN,
-	US_INPUT_SRC_FINGER,
-	US_INPUT_SRC_UNDEF
-};
-
 struct us_input_info_type {
 	/* Touch screen dimensions: min & max;for input module */
 	int tsc_x_dim[MIN_MAX_DIM];
@@ -149,12 +142,10 @@
 	int tsc_y_tilt[MIN_MAX_DIM];
 	/* Touch screen pressure limits: min & max; for input module */
 	int tsc_pressure[MIN_MAX_DIM];
-	/* The requested side buttons bitmap */
-	uint16_t req_side_buttons_bitmap;
+	/* The requested buttons bitmap */
+	uint16_t req_buttons_bitmap;
 	/* Bitmap of types of events (USF_X_EVENT), produced by calculator */
 	uint16_t event_types;
-	/* Input event source */
-	enum us_input_event_src_type event_src;
 	/* Bitmap of types of events from devs, conflicting with USF */
 	uint16_t conflicting_event_types;
 };
@@ -179,8 +170,8 @@
 	int inclinations[TILTS_DIM];
 /* [0-1023] (10bits); 0 - pen up */
 	uint32_t pressure;
-/* Bitmap for side button state. 1 - down, 0 - up */
-	uint16_t side_buttons_state_bitmap;
+/* Bitmap for button state. 1 - down, 0 - up */
+	uint16_t buttons_state_bitmap;
 };
 
 /* Mouse buttons, supported by USF */
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 688dea0..222a171 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -18,13 +18,15 @@
 
 #define QSEECOM_KEY_ID_SIZE   32
 
-#define	QSEOS_RESULT_FAIL_LOAD_KS         -57
-#define	QSEOS_RESULT_FAIL_SAVE_KS         -58
-#define	QSEOS_RESULT_FAIL_MAX_KEYS        -59
-#define	QSEOS_RESULT_FAIL_KEY_ID_EXISTS   -60
-#define	QSEOS_RESULT_FAIL_KEY_ID_DNE      -61
-#define	QSEOS_RESULT_FAIL_KS_OP           -62
-#define	QSEOS_RESULT_FAIL_CE_PIPE_INVALID -63
+#define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
+#define QSEOS_RESULT_FAIL_KS_OP               -64
+#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS       -65
+#define QSEOS_RESULT_FAIL_MAX_KEYS            -66
+#define QSEOS_RESULT_FAIL_SAVE_KS             -67
+#define QSEOS_RESULT_FAIL_LOAD_KS             -68
+#define QSEOS_RESULT_FAIL_KS_ALREADY_DONE     -69
+#define QSEOS_RESULT_FAIL_KEY_ID_DNE          -70
+#define QSEOS_RESULT_FAIL_INCORRECT_PSWD      -71
 
 enum qseecom_command_scm_resp_type {
 	QSEOS_APP_ID = 0xEE01,
@@ -52,6 +54,7 @@
 	QSEOS_DELETE_KEY,
 	QSEOS_MAX_KEY_COUNT,
 	QSEOS_SET_KEY,
+	QSEOS_UPDATE_KEY_USERINFO,
 	QSEOS_CMD_MAX     = 0xEFFFFFFF
 };
 
@@ -166,6 +169,7 @@
 	uint32_t qsee_command_id;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_select_ireq {
@@ -175,13 +179,23 @@
 	uint32_t pipe_type;
 	uint32_t flags;
 	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
-	unsigned char hash[QSEECOM_HASH_SIZE];
+	uint8_t hash32[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];
+	uint8_t hash32[QSEECOM_HASH_SIZE];
+
+};
+
+__packed struct qseecom_key_userinfo_update_ireq {
+	uint32_t qsee_command_id;
+	uint32_t flags;
+	uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+	uint8_t current_hash32[QSEECOM_HASH_SIZE];
+	uint8_t new_hash32[QSEECOM_HASH_SIZE];
 };
 
 __packed struct qseecom_key_max_count_query_ireq {
@@ -192,10 +206,5 @@
 	uint32_t max_key_count;
 };
 
-struct key_id_info {
-	uint32_t	ce_hw;
-	uint32_t	pipe;
-	bool		flags;
-};
 
 #endif /* __QSEECOMI_H_ */
diff --git a/arch/arm/mach-msm/include/mach/remote_spinlock.h b/arch/arm/mach-msm/include/mach/remote_spinlock.h
index 8c8b821..8ec68a1 100644
--- a/arch/arm/mach-msm/include/mach/remote_spinlock.h
+++ b/arch/arm/mach-msm/include/mach/remote_spinlock.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2009, 2011, 2013 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009, 2011, 2013-2014 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
@@ -22,6 +23,9 @@
 #include <linux/io.h>
 #include <linux/types.h>
 
+#define REMOTE_SPINLOCK_NUM_PID 128
+#define REMOTE_SPINLOCK_TID_START REMOTE_SPINLOCK_NUM_PID
+
 /* Remote spinlock definitions. */
 
 struct dek_spinlock {
@@ -48,6 +52,8 @@
 int _remote_spin_trylock(_remote_spinlock_t *lock);
 int _remote_spin_release(_remote_spinlock_t *lock, uint32_t pid);
 int _remote_spin_owner(_remote_spinlock_t *lock);
+void _remote_spin_lock_rlock_id(_remote_spinlock_t *lock, uint32_t tid);
+void _remote_spin_unlock_rlock(_remote_spinlock_t *lock);
 #else
 static inline
 int _remote_spin_lock_init(remote_spinlock_id_t id, _remote_spinlock_t *lock)
@@ -69,6 +75,9 @@
 {
 	return -ENODEV;
 }
+static inline void _remote_spin_lock_rlock_id(_remote_spinlock_t *lock,
+					      uint32_t tid) {}
+static inline void _remote_spin_unlock_rlock(_remote_spinlock_t *lock) {}
 #endif
 
 
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 6b3d590..aeb32f8 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -44,6 +44,7 @@
 #define of_board_is_qrd()	of_machine_is_compatible("qcom,qrd")
 #define of_board_is_xpm()	of_machine_is_compatible("qcom,xpm")
 #define of_board_is_skuf()	of_machine_is_compatible("qcom,skuf")
+#define of_board_is_sbc()	of_machine_is_compatible("qcom,sbc")
 
 #define machine_is_msm8974()	of_machine_is_compatible("qcom,msm8974")
 #define machine_is_msm9625()	of_machine_is_compatible("qcom,msm9625")
@@ -75,6 +76,7 @@
 #define of_board_is_qrd()		0
 #define of_board_is_xpm()		0
 #define of_board_is_skuf()		0
+#define of_board_is_sbc()		0
 
 #define machine_is_msm8974()		0
 #define machine_is_msm9625()		0
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 06160f7..7553f82 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -271,7 +271,7 @@
 {
 	int best_level = -1;
 	int i;
-	uint32_t best_level_pwr = ~0UL;
+	uint32_t best_level_pwr = ~0U;
 	uint32_t pwr;
 	uint32_t latency_us = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
 
@@ -490,7 +490,7 @@
 static noinline int lpm_cpu_power_select(struct cpuidle_device *dev, int *index)
 {
 	int best_level = -1;
-	uint32_t best_level_pwr = ~0UL;
+	uint32_t best_level_pwr = ~0U;
 	uint32_t latency_us = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
 	uint32_t sleep_us =
 		(uint32_t)(ktime_to_us(tick_nohz_get_sleep_length()));
@@ -720,8 +720,6 @@
 	int idx;
 	struct lpm_cpu_level *cpu_level = &system_state->cpu_level[cpu_index];
 
-	cpu_level = &system_state->cpu_level[cpu_index];
-
 	lpm_cpu_prepare(system_state, cpu_index, from_idle);
 
 	idx = lpm_system_select(system_state, cpu_index, from_idle);
diff --git a/arch/arm/mach-msm/msm-pm.c b/arch/arm/mach-msm/msm-pm.c
index fab86d3..865cd0a 100644
--- a/arch/arm/mach-msm/msm-pm.c
+++ b/arch/arm/mach-msm/msm-pm.c
@@ -777,7 +777,7 @@
 		return 0;
 	if (!msm_pm_slp_sts[cpu].base_addr)
 		return 0;
-	while (timeout--) {
+	while (1) {
 		/*
 		 * Check for the SPM of the core being hotplugged to set
 		 * its sleep state.The SPM sleep state indicates that the
@@ -788,10 +788,9 @@
 		if (acc_sts & msm_pm_slp_sts[cpu].mask)
 			return 0;
 		udelay(100);
+		WARN(++timeout == 20, "CPU%u didn't collapse in 2 ms\n", cpu);
 	}
 
-	pr_info("%s(): Timed out waiting for CPU %u SPM to enter sleep state",
-		__func__, cpu);
 	return -EBUSY;
 }
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 058e409..72e3ec3 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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,21 @@
 	return CREATE_PNODE_ID(src, pnode_num);
 }
 
+static uint64_t get_node_maxib(struct msm_bus_inode_info *info)
+{
+	int i, ctx;
+	uint64_t maxib = 0;
+
+	for (i = 0; i <= info->num_pnodes; i++) {
+		for (ctx = 0; ctx < NUM_CTX; ctx++)
+			maxib = max(info->pnode[i].clk[ctx], maxib);
+	}
+
+	MSM_BUS_DBG("%s: Node %d numpnodes %d maxib %llu", __func__,
+		info->num_pnodes, info->node_info->id, maxib);
+	return maxib;
+}
+
 /**
  * update_path() - Update the path with the bandwidth and clock values, as
  * requested by the client.
@@ -344,15 +359,6 @@
 		return -ENXIO;
 	}
 
-	/**
-	 * If master supports dual configuration, check if
-	 * the configuration needs to be changed based on
-	 * incoming requests
-	 */
-	if (info->node_info->dual_conf)
-		fabdev->algo->config_master(fabdev, info,
-			req_clk, req_bw);
-
 	info->link_info.sel_bw = &info->link_info.bw[ctx];
 	info->link_info.sel_clk = &info->link_info.clk[ctx];
 	*info->link_info.sel_bw += add_bw;
@@ -366,6 +372,19 @@
 	info->pnode[index].sel_clk = &info->pnode[index].clk[ctx &
 		cl_active_flag];
 	*info->pnode[index].sel_bw += add_bw;
+	*info->pnode[index].sel_clk = req_clk;
+
+	/**
+	 * If master supports dual configuration, check if
+	 * the configuration needs to be changed based on
+	 * incoming requests
+	 */
+	if (info->node_info->dual_conf) {
+		uint64_t node_maxib = 0;
+		node_maxib = get_node_maxib(info);
+		fabdev->algo->config_master(fabdev, info,
+			node_maxib, req_bw);
+	}
 
 	info->link_info.num_tiers = info->node_info->num_tiers;
 	info->link_info.tier = info->node_info->tier;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
index c745f92..a76c29b 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_bimc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -1919,10 +1919,12 @@
 			qbw.thh = div_s64((110 * bw), 100);
 			/* Check if info is a shared master.
 			 * If it is, mark it dirty
-			 * If it isn't, then set QOS Bandwidth
+			 * If it isn't, then set QOS Bandwidth.
+			 * Also if dual-conf is set, don't program bw regs.
 			 **/
-			msm_bus_bimc_set_qos_bw(binfo,
-				info->node_info->qport[i], &qbw);
+			if (!info->node_info->dual_conf)
+				msm_bus_bimc_set_qos_bw(binfo,
+					info->node_info->qport[i], &qbw);
 		}
 	}
 
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 7c694a7..626c5e8 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -896,9 +896,17 @@
 	},
 };
 
-static int __init msm_bus_fabric_init_driver(void)
+int __init msm_bus_fabric_init_driver(void)
 {
+	static bool initialized;
+
+	if (initialized)
+		return 0;
+	else
+		initialized = true;
+
 	MSM_BUS_ERR("msm_bus_fabric_init_driver\n");
 	return platform_driver_register(&msm_bus_fabric_driver);
 }
+EXPORT_SYMBOL(msm_bus_fabric_init_driver);
 subsys_initcall(msm_bus_fabric_init_driver);
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
index 8f7b7f2..479826e 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -22,12 +22,14 @@
 #define __CLZ(x) ((8 * sizeof(uint32_t)) - 1 - __fls(x))
 #define SAT_SCALE 16	/* 16 bytes minimum for saturation */
 #define BW_SCALE  256	/* 1/256 byte per cycle unit */
+#define QOS_DEFAULT_BASEOFFSET		0x00003000
 #define MAX_BW_FIELD (NOC_QOS_BWn_BW_BMSK >> NOC_QOS_BWn_BW_SHFT)
 #define MAX_SAT_FIELD (NOC_QOS_SATn_SAT_BMSK >> NOC_QOS_SATn_SAT_SHFT)
 
-#define NOC_QOS_REG_BASE(b)		((b) + 0x00003000)
+#define NOC_QOS_REG_BASE(b, o)		((b) + (o))
 
-#define NOC_QOS_ID_COREIDn_ADDR(b, n)	(NOC_QOS_REG_BASE(b) + 0x80 * (n))
+#define NOC_QOS_ID_COREIDn_ADDR(b, o, n) \
+	(NOC_QOS_REG_BASE(b, o) + 0x80 * (n))
 enum noc_qos_id_coreidn {
 	NOC_QOS_ID_COREIDn_RMSK			= 0xffffffff,
 	NOC_QOS_ID_COREIDn_MAXn			= 32,
@@ -37,8 +39,8 @@
 	NOC_QOS_ID_COREIDn_CORETYPEID_SHFT	= 0x0,
 };
 
-#define NOC_QOS_ID_REVISIONIDn_ADDR(b, n) \
-	(NOC_QOS_REG_BASE(b) + 0x4 + 0x80 * (n))
+#define NOC_QOS_ID_REVISIONIDn_ADDR(b, o, n) \
+	(NOC_QOS_REG_BASE(b, o) + 0x4 + 0x80 * (n))
 enum noc_qos_id_revisionidn {
 	NOC_QOS_ID_REVISIONIDn_RMSK		= 0xffffffff,
 	NOC_QOS_ID_REVISIONIDn_MAXn		= 32,
@@ -48,8 +50,8 @@
 	NOC_QOS_ID_REVISIONIDn_USERID_SHFT	= 0x0,
 };
 
-#define NOC_QOS_PRIORITYn_ADDR(b, n)	\
-	(NOC_QOS_REG_BASE(b) + 0x8 + 0x80 * (n))
+#define NOC_QOS_PRIORITYn_ADDR(b, o, n)	\
+	(NOC_QOS_REG_BASE(b, o) + 0x8 + 0x80 * (n))
 enum noc_qos_id_priorityn {
 	NOC_QOS_PRIORITYn_RMSK		= 0x0000000f,
 	NOC_QOS_PRIORITYn_MAXn		= 32,
@@ -59,8 +61,8 @@
 	NOC_QOS_PRIORITYn_P0_SHFT	= 0x0,
 };
 
-#define NOC_QOS_MODEn_ADDR(b, n) \
-	(NOC_QOS_REG_BASE(b) + 0xC + 0x80 * (n))
+#define NOC_QOS_MODEn_ADDR(b, o, n) \
+	(NOC_QOS_REG_BASE(b, o) + 0xC + 0x80 * (n))
 enum noc_qos_id_moden_rmsk {
 	NOC_QOS_MODEn_RMSK		= 0x00000003,
 	NOC_QOS_MODEn_MAXn		= 32,
@@ -68,8 +70,8 @@
 	NOC_QOS_MODEn_MODE_SHFT		= 0x0,
 };
 
-#define NOC_QOS_BWn_ADDR(b, n) \
-	(NOC_QOS_REG_BASE(b) + 0x10 + 0x80 * (n))
+#define NOC_QOS_BWn_ADDR(b, o, n) \
+	(NOC_QOS_REG_BASE(b, o) + 0x10 + 0x80 * (n))
 enum noc_qos_id_bwn {
 	NOC_QOS_BWn_RMSK		= 0x0000ffff,
 	NOC_QOS_BWn_MAXn		= 32,
@@ -78,8 +80,8 @@
 };
 
 /* QOS Saturation registers */
-#define NOC_QOS_SATn_ADDR(b, n) \
-	(NOC_QOS_REG_BASE(b) + 0x14 + 0x80 * (n))
+#define NOC_QOS_SATn_ADDR(b, o, n) \
+	(NOC_QOS_REG_BASE(b, o) + 0x14 + 0x80 * (n))
 enum noc_qos_id_saturationn {
 	NOC_QOS_SATn_RMSK		= 0x000003ff,
 	NOC_QOS_SATn_MAXn		= 32,
@@ -196,10 +198,11 @@
 		uint32_t reg_val;
 
 		reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
-			mport)) & NOC_QOS_MODEn_RMSK;
+			ninfo->qos_baseoffset, mport)) & NOC_QOS_MODEn_RMSK;
 		writel_relaxed(((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK))) |
 			(mode & NOC_QOS_MODEn_MODE_BMSK)),
-			NOC_QOS_MODEn_ADDR(ninfo->base, mport));
+			NOC_QOS_MODEn_ADDR(ninfo->base, ninfo->qos_baseoffset,
+						mport));
 	}
 	/* Ensure qos mode is set before exiting */
 	wmb();
@@ -210,18 +213,23 @@
 {
 	uint32_t reg_val, val;
 
-	reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport))
-		& NOC_QOS_PRIORITYn_RMSK;
+	reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base,
+						ninfo->qos_baseoffset, mport))
+				& NOC_QOS_PRIORITYn_RMSK;
 	val = priority->p1 << NOC_QOS_PRIORITYn_P1_SHFT;
 	writel_relaxed(((reg_val & (~(NOC_QOS_PRIORITYn_P1_BMSK))) |
 		(val & NOC_QOS_PRIORITYn_P1_BMSK)),
-		NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport));
+		NOC_QOS_PRIORITYn_ADDR(ninfo->base, ninfo->qos_baseoffset,
+								mport));
 
-	reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport))
-		& NOC_QOS_PRIORITYn_RMSK;
+	reg_val = readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base,
+							ninfo->qos_baseoffset,
+							mport))
+				& NOC_QOS_PRIORITYn_RMSK;
 	writel_relaxed(((reg_val & (~(NOC_QOS_PRIORITYn_P0_BMSK))) |
 		(priority->p0 & NOC_QOS_PRIORITYn_P0_BMSK)),
-		NOC_QOS_PRIORITYn_ADDR(ninfo->base, mport));
+		NOC_QOS_PRIORITYn_ADDR(ninfo->base, ninfo->qos_baseoffset,
+						mport));
 	/* Ensure qos priority is set before exiting */
 	wmb();
 }
@@ -251,33 +259,38 @@
 		 * Clear QoS accumulator
 		 **/
 		mode = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
-			mport)) & NOC_QOS_MODEn_MODE_BMSK;
+			ninfo->qos_baseoffset, mport))
+					& NOC_QOS_MODEn_MODE_BMSK;
 		if (mode == NOC_QOS_MODE_REGULATOR || mode ==
 			NOC_QOS_MODE_LIMITER) {
 			reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->
-				base, mport));
+				base, ninfo->qos_baseoffset, mport));
 			val = NOC_QOS_MODE_FIXED;
 			writel_relaxed((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK)))
 				| (val & NOC_QOS_MODEn_MODE_BMSK),
-				NOC_QOS_MODEn_ADDR(ninfo->base, mport));
+				NOC_QOS_MODEn_ADDR(ninfo->base,
+						ninfo->qos_baseoffset, mport));
 		}
 
-		reg_val = readl_relaxed(NOC_QOS_BWn_ADDR(ninfo->base, mport));
+		reg_val = readl_relaxed(NOC_QOS_BWn_ADDR(ninfo->base,
+						ninfo->qos_baseoffset, mport));
 		val = bw_val << NOC_QOS_BWn_BW_SHFT;
 		writel_relaxed(((reg_val & (~(NOC_QOS_BWn_BW_BMSK))) |
 			(val & NOC_QOS_BWn_BW_BMSK)),
-			NOC_QOS_BWn_ADDR(ninfo->base, mport));
+			NOC_QOS_BWn_ADDR(ninfo->base, ninfo->qos_baseoffset,
+								mport));
 
 		MSM_BUS_DBG("NOC: BW: Wrote value: 0x%x\n", ((reg_val &
 			(~NOC_QOS_BWn_BW_BMSK)) | (val &
 			NOC_QOS_BWn_BW_BMSK)));
 
 		reg_val = readl_relaxed(NOC_QOS_SATn_ADDR(ninfo->base,
-			mport));
+			ninfo->qos_baseoffset, mport));
 		val = sat_val << NOC_QOS_SATn_SAT_SHFT;
 		writel_relaxed(((reg_val & (~(NOC_QOS_SATn_SAT_BMSK))) |
 			(val & NOC_QOS_SATn_SAT_BMSK)),
-			NOC_QOS_SATn_ADDR(ninfo->base, mport));
+			NOC_QOS_SATn_ADDR(ninfo->base, ninfo->qos_baseoffset,
+									mport));
 
 		MSM_BUS_DBG("NOC: SAT: Wrote value: 0x%x\n", ((reg_val &
 			(~NOC_QOS_SATn_SAT_BMSK)) | (val &
@@ -285,10 +298,11 @@
 
 		/* Set mode back to what it was initially */
 		reg_val = readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
-			mport));
+				ninfo->qos_baseoffset, mport));
 		writel_relaxed((reg_val & (~(NOC_QOS_MODEn_MODE_BMSK)))
 			| (mode & NOC_QOS_MODEn_MODE_BMSK),
-			NOC_QOS_MODEn_ADDR(ninfo->base, mport));
+			NOC_QOS_MODEn_ADDR(ninfo->base, ninfo->qos_baseoffset,
+							mport));
 		/* Ensure that all writes for bandwidth registers have
 		 * completed before returning
 		 */
@@ -301,7 +315,8 @@
 {
 	if (NOC_QOS_MODES_ALL_PERM == perm_mode)
 		return readl_relaxed(NOC_QOS_MODEn_ADDR(ninfo->base,
-			mport)) & NOC_QOS_MODEn_MODE_BMSK;
+			ninfo->qos_baseoffset, mport)) &
+						NOC_QOS_MODEn_MODE_BMSK;
 	else
 		return 31 - __CLZ(mode &
 			NOC_QOS_MODES_ALL_PERM);
@@ -311,11 +326,11 @@
 	uint32_t mport, struct msm_bus_noc_qos_priority *priority)
 {
 	priority->p1 = (readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base,
-		mport)) & NOC_QOS_PRIORITYn_P1_BMSK) >>
+		ninfo->qos_baseoffset, mport)) & NOC_QOS_PRIORITYn_P1_BMSK) >>
 		NOC_QOS_PRIORITYn_P1_SHFT;
 
 	priority->p0 = (readl_relaxed(NOC_QOS_PRIORITYn_ADDR(ninfo->base,
-		mport)) & NOC_QOS_PRIORITYn_P0_BMSK) >>
+		ninfo->qos_baseoffset, mport)) & NOC_QOS_PRIORITYn_P0_BMSK) >>
 		NOC_QOS_PRIORITYn_P0_SHFT;
 }
 
@@ -325,9 +340,11 @@
 	if (perm_mode & (NOC_QOS_PERM_MODE_LIMITER |
 		NOC_QOS_PERM_MODE_REGULATOR)) {
 		uint32_t bw_val = readl_relaxed(NOC_QOS_BWn_ADDR(ninfo->
-			base, mport)) & NOC_QOS_BWn_BW_BMSK;
+			base, ninfo->qos_baseoffset, mport)) &
+							NOC_QOS_BWn_BW_BMSK;
 		uint32_t sat = readl_relaxed(NOC_QOS_SATn_ADDR(ninfo->
-			base, mport)) & NOC_QOS_SATn_SAT_BMSK;
+			base, ninfo->qos_baseoffset, mport)) &
+						NOC_QOS_SATn_SAT_BMSK;
 
 		qbw->bw = noc_bw(bw_val, ninfo->qos_freq);
 		qbw->ws = noc_ws(qbw->bw, sat, ninfo->qos_freq);
@@ -431,6 +448,12 @@
 	ninfo->nqos_masters = fab_pdata->nmasters;
 	ninfo->nslaves = fab_pdata->nslaves;
 	ninfo->qos_freq = fab_pdata->qos_freq;
+
+	if (!fab_pdata->qos_baseoffset)
+		ninfo->qos_baseoffset = QOS_DEFAULT_BASEOFFSET;
+	else
+		ninfo->qos_baseoffset = fab_pdata->qos_baseoffset;
+
 	ninfo->mas_modes = kzalloc(sizeof(uint32_t) * fab_pdata->nmasters,
 		GFP_KERNEL);
 	if (!ninfo->mas_modes) {
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.h b/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
index 00479c6..6ba3a24 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -44,6 +44,7 @@
 	uint32_t nqos_masters;
 	uint32_t nslaves;
 	uint32_t qos_freq; /* QOS Clock in KHz */
+	uint32_t qos_baseoffset;
 	uint32_t *mas_modes;
 	struct msm_bus_noc_commit cdata[NUM_CTX];
 };
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index 06894c6..52195c7 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -173,7 +173,7 @@
 	of_node = pdev->dev.of_node;
 	pdata = get_pdata(pdev, of_node);
 	if (!pdata) {
-		pr_err("Error getting bus pdata!\n");
+		pr_err("client has to provide missing entry for successful registration\n");
 		return NULL;
 	}
 
@@ -214,7 +214,7 @@
 
 	pdata = get_pdata(pdev, of_node);
 	if (!pdata) {
-		pr_err("Error getting bus pdata!\n");
+		pr_err("client has to provide missing entry for successful registration\n");
 		return NULL;
 	}
 
@@ -552,6 +552,11 @@
 	if (of_property_read_bool(of_node, "qcom,virt"))
 		pdata->virt = true;
 
+	ret = of_property_read_u32(of_node, "qcom,qos-baseoffset",
+						&pdata->qos_baseoffset);
+	if (ret)
+		pr_debug("%s:qos_baseoffset not available\n", __func__);
+
 	if (of_property_read_bool(of_node, "qcom,rpm-en"))
 		pdata->rpm_enabled = 1;
 
diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c
index f70022e..c99f0ec 100644
--- a/arch/arm/mach-msm/msm_rq_stats.c
+++ b/arch/arm/mach-msm/msm_rq_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -376,11 +376,12 @@
 	int ret;
 	int i;
 	struct cpufreq_policy cpu_policy;
+
+#ifndef CONFIG_SMP
 	/* Bail out if this is not an SMP Target */
-	if (!is_smp()) {
-		rq_info.init = 0;
-		return -ENOSYS;
-	}
+	rq_info.init = 0;
+	return -ENOSYS;
+#endif
 
 	rq_wq = create_singlethread_workqueue("rq_stats");
 	BUG_ON(!rq_wq);
@@ -416,11 +417,11 @@
 
 static int __init msm_rq_stats_early_init(void)
 {
+#ifndef CONFIG_SMP
 	/* Bail out if this is not an SMP Target */
-	if (!is_smp()) {
-		rq_info.init = 0;
-		return -ENOSYS;
-	}
+	rq_info.init = 0;
+	return -ENOSYS;
+#endif
 
 	pm_notifier(system_suspend_handler, 0);
 	return 0;
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index ead2e95..979c5bb 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -478,8 +478,9 @@
 	wdog_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	pdata->size = resource_size(wdog_resource);
 	pdata->phys_base = wdog_resource->start;
-	if (unlikely(!(devm_request_region(&pdev->dev, pdata->phys_base,
-					pdata->size, "msm-watchdog")))) {
+	if (unlikely(!(devm_request_mem_region(&pdev->dev, pdata->phys_base,
+					       pdata->size, "msm-watchdog")))) {
+
 		dev_err(&pdev->dev, "%s cannot reserve watchdog region\n",
 								__func__);
 		return -ENXIO;
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 28d8e42..05d3cef 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -35,6 +35,17 @@
 	"10 Perf: Fix counts across power collapse\n"
 	"11 ARM: dts: msm: add perf-events support for msm8x10, msm8x12\n"
 	"12 Perf: Make per-process counters configurable\n"
+	"13 msm: perf: Add L2 support for tracecounters\n"
+	"14 Perf: keep events across hotplug\n"
+	"15 Perf: bring CPU online if needed when disabling irq\n"
+	"16 Perf: Support sw events across hotplug\n"
+	"17 msm: perf: initialise krait perf L2 counter enables\n"
+	"18 msm: perf: clean up duplicate constraint events\n"
+	"19 Perf: Make per-process counters cumulative\n"
+	"20 Perf: Fix PID for tracepoints\n"
+	"21 Perf: preserve registers across hotplug\n"
+	"22 msm: perf: fix formatting of trace entry\n"
+	"23 msm: perf: Fix cpu id logic in tracectr notifier\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index ad34457..c9e2b8f 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -18,54 +18,6 @@
 
 #include <mach/msm-krait-l2-accessors.h>
 
-#define MAX_L2_PERIOD	((1ULL << 32) - 1)
-#define MAX_KRAIT_L2_CTRS 10
-
-#define PMCR_NUM_EV_SHIFT 11
-#define PMCR_NUM_EV_MASK 0x1f
-
-#define L2_EVT_MASK 0xfffff
-
-#define L2_SLAVE_EV_PREFIX 4
-
-#define L2PMCCNTR 0x409
-#define L2PMCCNTCR 0x408
-#define L2PMCCNTSR 0x40A
-#define L2CYCLE_CTR_BIT 31
-#define L2CYCLE_CTR_RAW_CODE 0xfe
-
-#define L2PMOVSR	0x406
-
-#define L2PMCR	0x400
-#define L2PMCR_RESET_ALL	0x6
-#define L2PMCR_GLOBAL_ENABLE	0x1
-#define L2PMCR_GLOBAL_DISABLE	0x0
-
-#define L2PMCNTENSET	0x403
-#define L2PMCNTENCLR	0x402
-
-#define L2PMINTENSET	0x405
-#define L2PMINTENCLR	0x404
-
-#define IA_L2PMXEVCNTCR_BASE	0x420
-#define IA_L2PMXEVTYPER_BASE	0x424
-#define IA_L2PMRESX_BASE	0x410
-#define IA_L2PMXEVFILTER_BASE	0x423
-#define IA_L2PMXEVCNTR_BASE	0x421
-
-/* event format is -e rsRCCG See get_event_desc() */
-
-#define EVENT_PREFIX_MASK	0xf0000
-#define EVENT_REG_MASK		0x0f000
-#define EVENT_GROUPSEL_MASK	0x0000f
-#define	EVENT_GROUPCODE_MASK	0x00ff0
-
-#define EVENT_PREFIX_SHIFT	16
-#define EVENT_REG_SHIFT		12
-#define EVENT_GROUPCODE_SHIFT	4
-
-#define	RESRX_VALUE_EN	0x80000000
-
 /*
  * The L2 PMU is shared between all CPU's, so protect
  * its bitmap access.
@@ -197,13 +149,16 @@
 	set_l2_indirect_reg(filter_reg, filter_val);
 }
 
-static void set_evfilter_sys_mode(int ctr, unsigned int is_slv)
+static void set_evfilter_sys_mode(int ctr, unsigned int is_slv, int cpu,
+		unsigned int is_tracectr)
 {
 	u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
 	u32 filter_val = l2_orig_filter_prefix | 0xf;
 
-	if (is_slv)
+	if (is_slv == 1)
 		filter_val = l2_slv_filter_prefix;
+	if (is_tracectr == 1)
+		filter_val = l2_orig_filter_prefix | 1 << cpu;
 
 	set_l2_indirect_reg(filter_reg, filter_val);
 }
@@ -277,6 +232,7 @@
 	struct event_desc evdesc;
 	unsigned long iflags;
 	unsigned int is_slv = 0;
+	unsigned int is_tracectr = 0;
 	unsigned int evt_prefix;
 
 	raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
@@ -290,6 +246,8 @@
 
 	if (evt_prefix == L2_SLAVE_EV_PREFIX)
 		is_slv = 1;
+	else if (evt_prefix == L2_TRACECTR_PREFIX)
+		is_tracectr = 1;
 
 	set_evcntcr(idx);
 
@@ -305,7 +263,7 @@
 	if (cpu < 0)
 		set_evfilter_task_mode(idx, is_slv);
 	else
-		set_evfilter_sys_mode(idx, is_slv);
+		set_evfilter_sys_mode(idx, is_slv, cpu, is_tracectr);
 
 out:
 	enable_intenset(idx);
@@ -456,6 +414,7 @@
 static int msm_l2_test_set_ev_constraint(struct perf_event *event)
 {
 	u32 evt_type = event->attr.config & L2_EVT_MASK;
+	u8 evt_prefix = (evt_type & EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
 	u8 reg   = (evt_type & 0x0F000) >> 12;
 	u8 group = evt_type & 0x0000F;
 	u8 code = (evt_type & 0x00FF0) >> 4;
@@ -464,6 +423,8 @@
 	u64 bitmap_t;
 	u32 shift_idx;
 
+	if (evt_prefix == L2_TRACECTR_PREFIX)
+		return err;
 	/*
 	 * Cycle counter collision is detected in
 	 * get_event_idx().
@@ -496,8 +457,10 @@
 			 * This sets the event OFF on all but one
 			 * CPU.
 			 */
-			if (!(event->cpu < 0))
+			if (!(event->cpu < 0)) {
 				event->state = PERF_EVENT_STATE_OFF;
+				event->attr.constraint_duplicate = 1;
+			}
 	}
 out:
 	raw_spin_unlock_irqrestore(&l2_pmu_constraints.lock, flags);
@@ -507,12 +470,15 @@
 static int msm_l2_clear_ev_constraint(struct perf_event *event)
 {
 	u32 evt_type = event->attr.config & L2_EVT_MASK;
+	u8 evt_prefix = (evt_type & EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
 	u8 reg   = (evt_type & 0x0F000) >> 12;
 	u8 group =  evt_type & 0x0000F;
 	unsigned long flags;
 	u64 bitmap_t;
 	u32 shift_idx;
 
+	if (evt_prefix == L2_TRACECTR_PREFIX)
+		return 1;
 	raw_spin_lock_irqsave(&l2_pmu_constraints.lock, flags);
 
 	shift_idx = ((reg * 4) + group);
@@ -592,6 +558,8 @@
 
 static int __init register_krait_l2_pmu_driver(void)
 {
+	int i;
+
 	/* Reset all ctrs */
 	set_l2_indirect_reg(L2PMCR, L2PMCR_RESET_ALL);
 
@@ -613,6 +581,11 @@
 	/* Avoid spurious interrupt if any */
 	get_reset_pmovsr();
 
+	/* Clear counter enables */
+	disable_counter(l2_cycle_ctr_idx);
+	for (i = 0; i < total_l2_ctrs; i++)
+		disable_counter(i);
+
 	return platform_driver_register(&krait_l2_pmu_driver);
 }
 device_initcall(register_krait_l2_pmu_driver);
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
index 8fa73ae..0a679b1 100644
--- a/arch/arm/mach-msm/perf_trace_counters.c
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -17,21 +17,48 @@
 
 static unsigned int tp_pid_state;
 
+DEFINE_PER_CPU(u32, previous_ccnt);
+DEFINE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
+DEFINE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
+DEFINE_PER_CPU(u32, old_pid);
+/* Reset per_cpu variables that store counter values uppn CPU hotplug */
+static int tracectr_cpu_hotplug_notifier(struct notifier_block *self,
+				    unsigned long action, void *hcpu)
+{
+	int ret = NOTIFY_OK;
+	int cpu = (int)hcpu;
+	int i;
+
+	if ((action & (~CPU_TASKS_FROZEN)) == CPU_UP_PREPARE) {
+		per_cpu(previous_ccnt, cpu) = 0;
+		for (i = 0; i < NUM_L1_CTRS; i++)
+			per_cpu(previous_l1_cnts[i], cpu) = 0;
+		for (i = 0; i < NUM_L2_PERCPU; i++)
+			per_cpu(previous_l2_cnts[i], cpu) = 0;
+	}
+	return ret;
+}
+
+static struct notifier_block tracectr_cpu_hotplug_notifier_block = {
+	.notifier_call = tracectr_cpu_hotplug_notifier,
+};
+
 static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
 		void *v)
 {
-	static int old_pid = -1;
 	struct thread_info *thread = v;
 	int current_pid;
+	u32 cpu = thread->cpu;
 
 	if (cmd != THREAD_NOTIFY_SWITCH)
-		return old_pid;
+		return -EFAULT;
 
 	current_pid = thread->task->pid;
-	if (old_pid != -1)
-		trace_sched_switch_with_ctrs(old_pid, current_pid);
-	old_pid = current_pid;
-	return old_pid;
+	if (per_cpu(old_pid, cpu) != -1)
+		trace_sched_switch_with_ctrs(per_cpu(old_pid, cpu),
+						current_pid);
+	per_cpu(old_pid, cpu) = current_pid;
+	return NOTIFY_OK;
 }
 
 static struct notifier_block tracectr_notifier_block = {
@@ -102,6 +129,7 @@
 	struct dentry *dir;
 	struct dentry *file;
 	unsigned int value = 1;
+	int cpu;
 
 	dir = debugfs_create_dir("perf_debug_tp", NULL);
 	if (!dir)
@@ -112,6 +140,15 @@
 		debugfs_remove(dir);
 		return -ENOMEM;
 	}
+	register_cpu_notifier(&tracectr_cpu_hotplug_notifier_block);
+	for_each_possible_cpu(cpu)
+		per_cpu(old_pid, cpu) = -1;
+	return 0;
+}
+
+int __exit exit_tracecounters(void)
+{
+	unregister_cpu_notifier(&tracectr_cpu_hotplug_notifier_block);
 	return 0;
 }
 late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/perf_trace_counters.h b/arch/arm/mach-msm/perf_trace_counters.h
index 8f77bad..fce176e 100644
--- a/arch/arm/mach-msm/perf_trace_counters.h
+++ b/arch/arm/mach-msm/perf_trace_counters.h
@@ -19,14 +19,21 @@
 /* Ctr index for PMCNTENSET/CLR */
 #define CC 0x80000000
 #define C0 0x1
-#define C1 0x10
-#define C2 0x100
-#define C3 0x1000
-
+#define C1 0x2
+#define C2 0x4
+#define C3 0x8
+#define C_ALL (CC | C0 | C1 | C2 | C3)
+#define NUM_L1_CTRS 4
+#define NUM_L2_PERCPU 2
 
 #include <linux/sched.h>
+#include <linux/cpumask.h>
 #include <linux/tracepoint.h>
+#include <mach/msm-krait-l2-accessors.h>
 
+DECLARE_PER_CPU(u32, previous_ccnt);
+DECLARE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
+DECLARE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
 TRACE_EVENT(sched_switch_with_ctrs,
 
 		TP_PROTO(pid_t prev, pid_t next),
@@ -41,82 +48,112 @@
 			__field(u32, ctr1)
 			__field(u32, ctr2)
 			__field(u32, ctr3)
+			__field(u32, lctr0)
+			__field(u32, lctr1)
 		),
 
 		TP_fast_assign(
+			u32 cpu = smp_processor_id();
+			u32 idx;
+			u32 i;
+			u32 counter_reg;
+			u32 val;
+			u32 cnten_val;
+			u32 num_l2ctrs;
+			u32 num_cores = nr_cpu_ids;
+			u32 total_ccnt = 0;
+			u32 total_cnt = 0;
+			u32 delta_l1_cnts[NUM_L1_CTRS];
+			u32 delta_l2_cnts[NUM_L2_PERCPU];
 			__entry->old_pid	= prev;
 			__entry->new_pid	= next;
 
-			/* cycle counter */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(CC));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 0"
-				: "=r"(__entry->cctr));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(CC));
+			val = get_l2_indirect_reg(L2PMCR);
+			num_l2ctrs = ((val >> 11) & 0x1f) + 1;
 
-			/* ctr 0 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C0));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(0));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr0));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C0));
+			/* Read PMCNTENSET */
+			asm volatile("mrc p15, 0, %0, c9, c12, 1"
+						: "=r"(cnten_val));
+			/* Disable all the counters that were enabled */
+			asm volatile("mcr p15, 0, %0, c9, c12, 2"
+					: : "r"(cnten_val));
+			if (cnten_val & CC) {
+				/* Read value */
+				asm volatile("mrc p15, 0, %0, c9, c13, 0"
+					: "=r"(total_ccnt));
+				__entry->cctr = total_ccnt -
+					per_cpu(previous_ccnt, cpu);
+				per_cpu(previous_ccnt, cpu) = total_ccnt;
+			}
+			for (i = 0; i < NUM_L1_CTRS; i++) {
+				if (cnten_val & (1 << i)) {
+					/* Select */
+					asm volatile(
+						"mcr p15, 0, %0, c9, c12, 5"
+						: : "r"(i));
+					/* Read value */
+					asm volatile(
+						"mrc p15, 0, %0, c9, c13, 2"
+						: "=r"(total_cnt));
 
-			/* ctr 1 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C1));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(1));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr1));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C1));
+					delta_l1_cnts[i] = total_cnt -
+					  per_cpu(previous_l1_cnts[i], cpu);
+					per_cpu(previous_l1_cnts[i], cpu) =
+						total_cnt;
+				} else
+					delta_l1_cnts[i] = 0;
+			}
+			/* Enable all the counters that were disabled */
+			asm volatile("mcr p15, 0, %0, c9, c12, 1"
+					: : "r"(cnten_val));
 
-			/* ctr 2 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C2));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(2));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr2));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C2));
-
-			/* ctr 3 */
-			/* Disable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C3));
-			/* Select */
-			asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(3));
-			/* Read value */
-			asm volatile("mrc p15, 0, %0, c9, c13, 2"
-					: "=r"(__entry->ctr3));
-			/* Reset */
-			asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
-			/* Enable */
-			asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C3));
-
+			/* L2 counters */
+			/* Assign L2 counters to cores sequentially starting
+			 * from zero. A core could have multiple L2 counters
+			 * allocated if # L2 counters is more than the # cores
+			 */
+			cnten_val = get_l2_indirect_reg(L2PMCNTENSET);
+			for (i = 0; i < NUM_L2_PERCPU; i++) {
+				idx = cpu + (num_cores * i);
+				if (idx < num_l2ctrs &&
+						(cnten_val & (1 << idx))) {
+					/* Disable */
+					set_l2_indirect_reg(L2PMCNTENCLR,
+						(1 << idx));
+					/* L2PMEVCNTR values go from 0x421,
+					 * 0x431..
+					 * So we multiply idx by 16 to get the
+					 * counter reg value
+					 */
+					counter_reg = (idx * 16) +
+						IA_L2PMXEVCNTR_BASE;
+					total_cnt =
+					  get_l2_indirect_reg(counter_reg);
+					/* Enable */
+					set_l2_indirect_reg(L2PMCNTENSET,
+						(1 << idx));
+					delta_l2_cnts[i] = total_cnt -
+					  per_cpu(previous_l2_cnts[i], cpu);
+					per_cpu(previous_l2_cnts[i], cpu) =
+						total_cnt;
+				} else
+					delta_l2_cnts[i] = 0;
+			}
+			__entry->ctr0 = delta_l1_cnts[0];
+			__entry->ctr1 = delta_l1_cnts[1];
+			__entry->ctr2 = delta_l1_cnts[2];
+			__entry->ctr3 = delta_l1_cnts[3];
+			__entry->lctr0 = delta_l2_cnts[0];
+			__entry->lctr1 = delta_l2_cnts[1];
 		),
 
 		TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u," \
-				" CTR1: %u, CTR2: %u, CTR3: %u",
+				" CTR1: %u, CTR2: %u, CTR3: %u," \
+				" L2CTR0: %u, L2CTR1: %u",
 				__entry->old_pid, __entry->new_pid,
 				__entry->cctr, __entry->ctr0, __entry->ctr1,
-				__entry->ctr2, __entry->ctr3)
+				__entry->ctr2, __entry->ctr3,
+				__entry->lctr0, __entry->lctr1)
 );
 
 #endif
diff --git a/arch/arm/mach-msm/qdsp6v2/apr_tal.c b/arch/arm/mach-msm/qdsp6v2/apr_tal.c
index 8826a35..e917f31 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr_tal.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr_tal.c
@@ -190,6 +190,9 @@
 		apr_tal_close(&apr_svc_ch[dl][dest][svc]);
 		return NULL;
 	}
+
+	smd_disable_read_intr(apr_svc_ch[dl][dest][svc].ch);
+
 	if (!apr_svc_ch[dl][dest][svc].dest_state) {
 		apr_svc_ch[dl][dest][svc].dest_state = 1;
 		pr_debug("apr_tal:Waiting for apr svc init\n");
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
index 2f1ff3e..109e120 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -23,6 +23,11 @@
 #include <asm/ioctls.h>
 #include "audio_utils.h"
 
+#define MIN_FRAME_SIZE  1536
+#define NUM_FRAMES      5
+#define META_SIZE       (sizeof(struct meta_out_dsp))
+#define FRAME_SIZE      (1 + ((MIN_FRAME_SIZE + META_SIZE) * NUM_FRAMES))
+
 static int audio_in_pause(struct q6audio_in  *audio)
 {
 	int rc;
@@ -258,6 +263,11 @@
 			rc = -EINVAL;
 			break;
 		}
+		if ((cfg.buffer_size > FRAME_SIZE) ||
+			(cfg.buffer_count != FRAME_NUM)) {
+			rc = -EINVAL;
+			break;
+		}
 		audio->str_cfg.buffer_size = cfg.buffer_size;
 		audio->str_cfg.buffer_count = cfg.buffer_count;
 		if(audio->opened){
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
index a18d0f3..cf69e17 100644
--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -27,8 +27,8 @@
 #include "usfcdev.h"
 
 /* The driver version*/
-#define DRV_VERSION "1.5.1"
-#define USF_VERSION_ID 0x0151
+#define DRV_VERSION "1.6.1"
+#define USF_VERSION_ID 0x0161
 
 /* Standard timeout in the asynchronous ops */
 #define USF_TIMEOUT_JIFFIES (1*HZ) /* 1 sec */
@@ -118,14 +118,12 @@
 	uint16_t event_types;
 	/*  The input devices are "input" module registered clients */
 	struct input_dev *input_ifs[USF_MAX_EVENT_IND];
-	/*  The event source */
-	int event_src;
 	/* Bitmap of types of events, conflicting to USF's ones */
 	uint16_t conflicting_event_types;
 	/* Bitmap of types of events from devs, conflicting with USF */
 	uint16_t conflicting_event_filters;
-	/* The requested side buttons bitmap */
-	uint16_t req_side_buttons_bitmap;
+	/* The requested buttons bitmap */
+	uint16_t req_buttons_bitmap;
 };
 
 struct usf_input_dev_type {
@@ -148,17 +146,22 @@
 /* The MAX number of the supported devices */
 #define MAX_DEVS_NUMBER	1
 
-/* The opened devices container */
-static const int s_event_src_map[] = {
-	BTN_TOOL_PEN, /* US_INPUT_SRC_PEN*/
-	0,            /* US_INPUT_SRC_FINGER */
-	0,            /* US_INPUT_SRC_UNDEF */
-};
+/*
+ * code for a special button that is used to show/hide a
+ * hovering cursor in the input framework. Must be in
+ * sync with the button code definition in the framework
+ * (EventHub.h)
+ */
+#define BTN_USF_HOVERING_CURSOR         0x230
 
 /* Supported buttons container */
 static const int s_button_map[] = {
 	BTN_STYLUS,
-	BTN_STYLUS2
+	BTN_STYLUS2,
+	BTN_TOOL_PEN,
+	BTN_TOOL_RUBBER,
+	BTN_TOOL_FINGER,
+	BTN_USF_HOVERING_CURSOR
 };
 
 /* The opened devices container */
@@ -192,31 +195,32 @@
 				const char *name)
 {
 	int i = 0;
-	int num_side_buttons = min(ARRAY_SIZE(s_button_map),
-		sizeof(input_info->req_side_buttons_bitmap) *
+
+	int num_buttons = min(ARRAY_SIZE(s_button_map),
+		sizeof(input_info->req_buttons_bitmap) *
 		BITS_IN_BYTE);
-	uint16_t max_side_button_bitmap = ((1 << ARRAY_SIZE(s_button_map)) - 1);
+	uint16_t max_buttons_bitmap = ((1 << ARRAY_SIZE(s_button_map)) - 1);
+
 	struct input_dev *in_dev = allocate_dev(ind, name);
 	if (in_dev == NULL)
 		return -ENOMEM;
 
-	if (input_info->req_side_buttons_bitmap > max_side_button_bitmap) {
-		pr_err("%s: Requested side buttons[%d] exceeds max side buttons available[%d]\n",
+	if (input_info->req_buttons_bitmap > max_buttons_bitmap) {
+		pr_err("%s: Requested buttons[%d] exceeds max buttons available[%d]\n",
 		__func__,
-		input_info->req_side_buttons_bitmap,
-		max_side_button_bitmap);
+		input_info->req_buttons_bitmap,
+		max_buttons_bitmap);
 		return -EINVAL;
 	}
 
 	usf_info->input_ifs[ind] = in_dev;
-	usf_info->req_side_buttons_bitmap =
-		input_info->req_side_buttons_bitmap;
+	usf_info->req_buttons_bitmap =
+		input_info->req_buttons_bitmap;
 	in_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	in_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
-
-	for (i = 0; i < num_side_buttons; i++)
-		if (input_info->req_side_buttons_bitmap & (1 << i))
+	for (i = 0; i < num_buttons; i++)
+		if (input_info->req_buttons_bitmap & (1 << i))
 			in_dev->keybit[BIT_WORD(s_button_map[i])] |=
 			BIT_MASK(s_button_map[i]);
 
@@ -297,8 +301,8 @@
 
 {
 	int i = 0;
-	int num_side_buttons = min(ARRAY_SIZE(s_button_map),
-		sizeof(usf_info->req_side_buttons_bitmap) *
+	int num_buttons = min(ARRAY_SIZE(s_button_map),
+		sizeof(usf_info->req_buttons_bitmap) *
 		BITS_IN_BYTE);
 
 	struct input_dev *input_if = usf_info->input_ifs[if_ind];
@@ -314,19 +318,16 @@
 	input_report_abs(input_if, ABS_PRESSURE, pe->pressure);
 	input_report_key(input_if, BTN_TOUCH, !!(pe->pressure));
 
-	for (i = 0; i < num_side_buttons; i++) {
+	for (i = 0; i < num_buttons; i++) {
 		uint16_t mask = (1 << i),
-		btn_state = !!(pe->side_buttons_state_bitmap & mask);
-		if (usf_info->req_side_buttons_bitmap & mask)
+		btn_state = !!(pe->buttons_state_bitmap & mask);
+		if (usf_info->req_buttons_bitmap & mask)
 			input_report_key(input_if, s_button_map[i], btn_state);
 	}
 
-	if (usf_info->event_src)
-		input_report_key(input_if, usf_info->event_src, 1);
-
 	input_sync(input_if);
 
-	pr_debug("%s: TSC event: xyz[%d;%d;%d], incl[%d;%d], pressure[%d], side_buttons[%d]\n",
+	pr_debug("%s: TSC event: xyz[%d;%d;%d], incl[%d;%d], pressure[%d], buttons[%d]\n",
 		 __func__,
 		 pe->coordinates[X_IND],
 		 pe->coordinates[Y_IND],
@@ -334,7 +335,7 @@
 		 pe->inclinations[X_IND],
 		 pe->inclinations[Y_IND],
 		 pe->pressure,
-		 pe->side_buttons_state_bitmap);
+		 pe->buttons_state_bitmap);
 }
 
 static void notify_mouse_event(struct usf_type *usf_info,
@@ -663,12 +664,6 @@
 		return -EINVAL;
 	}
 
-	if (input_info->event_src < ARRAY_SIZE(s_event_src_map))
-		usf_info->event_src =
-			s_event_src_map[input_info->event_src];
-	else
-		usf_info->event_src = 0;
-
 	for (ind = 0; ind < USF_MAX_EVENT_IND; ++ind) {
 		if (usf_info->input_ifs[ind] != NULL) {
 			pr_err("%s: input_if[%d] is already allocated\n",
@@ -686,12 +681,6 @@
 			if (rc)
 				return rc;
 
-
-			if (usf_info->event_src)
-				input_set_capability(usf_info->input_ifs[ind],
-						     EV_KEY,
-						     usf_info->event_src);
-
 			rc = input_register_device(usf_info->input_ifs[ind]);
 			if (rc) {
 				pr_err("%s: input_reg_dev() failed; rc=%d\n",
diff --git a/arch/arm/mach-msm/remote_spinlock.c b/arch/arm/mach-msm/remote_spinlock.c
index a9ebd7c..0a953ac 100644
--- a/arch/arm/mach-msm/remote_spinlock.c
+++ b/arch/arm/mach-msm/remote_spinlock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, 2011-2013 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2009, 2011-2014 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,8 @@
 	int (*trylock)(raw_remote_spinlock_t *lock);
 	int (*release)(raw_remote_spinlock_t *lock, uint32_t pid);
 	int (*owner)(raw_remote_spinlock_t *lock);
+	void (*lock_rlock_id)(raw_remote_spinlock_t *lock, uint32_t tid);
+	void (*unlock_rlock)(raw_remote_spinlock_t *lock);
 };
 
 static struct spinlock_ops current_ops;
@@ -364,6 +366,27 @@
 	writel_relaxed(0, lock);
 	smp_mb();
 }
+
+static void __raw_remote_sfpb_spin_lock_rlock_id(raw_remote_spinlock_t *lock,
+						 uint32_t tid)
+{
+	if (unlikely(!tid)) {
+		pr_err("%s: unsupported rlock tid=0\n", __func__);
+		BUG();
+	}
+
+	do {
+		writel_relaxed(tid, lock);
+		smp_mb();
+	} while (readl_relaxed(lock) != tid);
+}
+
+static void __raw_remote_sfpb_spin_unlock_rlock(raw_remote_spinlock_t *lock)
+{
+	writel_relaxed(0, lock);
+	smp_mb();
+}
+
 /* end sfpb implementation -------------------------------------------------- */
 
 /* common spinlock API ------------------------------------------------------ */
@@ -458,6 +481,9 @@
 		current_ops.trylock = __raw_remote_sfpb_spin_trylock;
 		current_ops.release = __raw_remote_gen_spin_release;
 		current_ops.owner = __raw_remote_gen_spin_owner;
+		current_ops.lock_rlock_id =
+				__raw_remote_sfpb_spin_lock_rlock_id;
+		current_ops.unlock_rlock = __raw_remote_sfpb_spin_unlock_rlock;
 		is_hw_lock_type = 1;
 		break;
 	case AUTO_MODE:
@@ -474,6 +500,10 @@
 			current_ops.trylock = __raw_remote_sfpb_spin_trylock;
 			current_ops.release = __raw_remote_gen_spin_release;
 			current_ops.owner = __raw_remote_gen_spin_owner;
+			current_ops.lock_rlock_id =
+					__raw_remote_sfpb_spin_lock_rlock_id;
+			current_ops.unlock_rlock =
+					__raw_remote_sfpb_spin_unlock_rlock;
 			is_hw_lock_type = 1;
 			break;
 		}
@@ -517,6 +547,11 @@
 	int n;
 	 _remote_spinlock_t lock;
 
+	if (pid >= REMOTE_SPINLOCK_NUM_PID) {
+		pr_err("%s: unsupported PID %d\n", __func__, pid);
+		return;
+	}
+
 	for (n = 0; n < count; ++n) {
 		if (remote_spinlock_init_address(n, &lock) == 0)
 			_remote_spin_release(&lock, pid);
@@ -671,6 +706,23 @@
 	return current_ops.owner((raw_remote_spinlock_t *)(*lock));
 }
 EXPORT_SYMBOL(_remote_spin_owner);
+
+void _remote_spin_lock_rlock_id(_remote_spinlock_t *lock, uint32_t tid)
+{
+	if (unlikely(!current_ops.lock_rlock_id))
+		BUG();
+	current_ops.lock_rlock_id((raw_remote_spinlock_t *)(*lock), tid);
+}
+EXPORT_SYMBOL(_remote_spin_lock_rlock_id);
+
+void _remote_spin_unlock_rlock(_remote_spinlock_t *lock)
+{
+	if (unlikely(!current_ops.unlock_rlock))
+		BUG();
+	current_ops.unlock_rlock((raw_remote_spinlock_t *)(*lock));
+}
+EXPORT_SYMBOL(_remote_spin_unlock_rlock);
+
 /* end common spinlock API -------------------------------------------------- */
 
 /* remote mutex implementation ---------------------------------------------- */
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 37fd650..a96b02f 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -115,6 +115,10 @@
 		__raw_writel(EMERGENCY_DLOAD_MAGIC3,
 				emergency_dload_mode_addr +
 				(2 * sizeof(unsigned int)));
+
+		/* Need disable the pmic wdt, then the emergency dload mode
+		 * will not auto reset. */
+		qpnp_pon_wd_config(0);
 		mb();
 	}
 }
@@ -276,6 +280,8 @@
 			__raw_writel(0x77665500, restart_reason);
 		} else if (!strncmp(cmd, "recovery", 8)) {
 			__raw_writel(0x77665502, restart_reason);
+		} else if (!strcmp(cmd, "rtc")) {
+			__raw_writel(0x77665503, restart_reason);
 		} else if (!strncmp(cmd, "oem-", 4)) {
 			unsigned long code;
 			code = simple_strtoul(cmd + 4, NULL, 16) & 0xff;
diff --git a/arch/arm/mach-msm/rpcrouter_sdio_xprt.c b/arch/arm/mach-msm/rpcrouter_sdio_xprt.c
deleted file mode 100644
index e9818e5..0000000
--- a/arch/arm/mach-msm/rpcrouter_sdio_xprt.c
+++ /dev/null
@@ -1,655 +0,0 @@
-/* Copyright (c) 2010-2011, 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.
- */
-
-/*
- * RPCROUTER SDIO XPRT module.
- */
-
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/err.h>
-#include <linux/sched.h>
-#include <linux/poll.h>
-#include <linux/wakelock.h>
-#include <asm/uaccess.h>
-#include <linux/slab.h>
-
-#include <mach/sdio_al.h>
-#include "smd_rpcrouter.h"
-
-enum {
-	MSM_SDIO_XPRT_DEBUG = 1U << 0,
-	MSM_SDIO_XPRT_INFO = 1U << 1,
-};
-
-static int msm_sdio_xprt_debug_mask;
-module_param_named(debug_mask, msm_sdio_xprt_debug_mask,
-		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-
-#if defined(CONFIG_MSM_RPC_SDIO_DEBUG)
-#define SDIO_XPRT_DBG(x...) do {                \
-	if (msm_sdio_xprt_debug_mask & MSM_SDIO_XPRT_DEBUG)     \
-		printk(KERN_DEBUG x);           \
-	} while (0)
-
-#define SDIO_XPRT_INFO(x...) do {               \
-	if (msm_sdio_xprt_debug_mask & MSM_SDIO_XPRT_INFO)      \
-		printk(KERN_INFO x);            \
-	} while (0)
-#else
-#define SDIO_XPRT_DBG(x...) do { } while (0)
-#define SDIO_XPRT_INFO(x...) do { } while (0)
-#endif
-
-#define MAX_SDIO_WRITE_RETRY 5
-#define SDIO_BUF_SIZE (RPCROUTER_MSGSIZE_MAX + sizeof(struct rr_header) - 8)
-#define NUM_SDIO_BUFS 20
-#define MAX_TX_BUFS 10
-#define MAX_RX_BUFS 10
-
-struct sdio_xprt {
-	struct sdio_channel *handle;
-
-	struct list_head write_list;
-	spinlock_t write_list_lock;
-
-	struct list_head read_list;
-	spinlock_t read_list_lock;
-
-	struct list_head free_list;
-	spinlock_t free_list_lock;
-
-	struct wake_lock read_wakelock;
-};
-
-struct rpcrouter_sdio_xprt {
-	struct rpcrouter_xprt xprt;
-	struct sdio_xprt *channel;
-};
-
-static struct rpcrouter_sdio_xprt sdio_remote_xprt;
-
-static void sdio_xprt_read_data(struct work_struct *work);
-static DECLARE_DELAYED_WORK(work_read_data, sdio_xprt_read_data);
-static struct workqueue_struct *sdio_xprt_read_workqueue;
-
-struct sdio_buf_struct {
-	struct list_head list;
-	uint32_t size;
-	uint32_t read_index;
-	uint32_t write_index;
-	unsigned char data[SDIO_BUF_SIZE];
-};
-
-static void sdio_xprt_write_data(struct work_struct *work);
-static DECLARE_WORK(work_write_data, sdio_xprt_write_data);
-static wait_queue_head_t write_avail_wait_q;
-static uint32_t num_free_bufs;
-static uint32_t num_tx_bufs;
-static uint32_t num_rx_bufs;
-
-static DEFINE_MUTEX(modem_reset_lock);
-static uint32_t modem_reset;
-
-static void free_sdio_xprt(struct sdio_xprt *chnl)
-{
-	struct sdio_buf_struct *buf;
-	unsigned long flags;
-
-	if (!chnl) {
-		printk(KERN_ERR "Invalid chnl to free\n");
-		return;
-	}
-
-	spin_lock_irqsave(&chnl->free_list_lock, flags);
-	while (!list_empty(&chnl->free_list)) {
-		buf = list_first_entry(&chnl->free_list,
-					struct sdio_buf_struct, list);
-		list_del(&buf->list);
-		kfree(buf);
-	}
-	num_free_bufs = 0;
-	spin_unlock_irqrestore(&chnl->free_list_lock, flags);
-
-	spin_lock_irqsave(&chnl->write_list_lock, flags);
-	while (!list_empty(&chnl->write_list)) {
-		buf = list_first_entry(&chnl->write_list,
-					struct sdio_buf_struct, list);
-		list_del(&buf->list);
-		kfree(buf);
-	}
-	num_tx_bufs = 0;
-	spin_unlock_irqrestore(&chnl->write_list_lock, flags);
-
-	spin_lock_irqsave(&chnl->read_list_lock, flags);
-	while (!list_empty(&chnl->read_list)) {
-		buf = list_first_entry(&chnl->read_list,
-					struct sdio_buf_struct, list);
-		list_del(&buf->list);
-		kfree(buf);
-	}
-	num_rx_bufs = 0;
-	spin_unlock_irqrestore(&chnl->read_list_lock, flags);
-	wake_unlock(&chnl->read_wakelock);
-}
-
-static struct sdio_buf_struct *alloc_from_free_list(struct sdio_xprt *chnl)
-{
-	struct sdio_buf_struct *buf;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chnl->free_list_lock, flags);
-	if (list_empty(&chnl->free_list)) {
-		spin_unlock_irqrestore(&chnl->free_list_lock, flags);
-		SDIO_XPRT_DBG("%s: Free list empty\n", __func__);
-		return NULL;
-	}
-	buf = list_first_entry(&chnl->free_list, struct sdio_buf_struct, list);
-	list_del(&buf->list);
-	num_free_bufs--;
-	spin_unlock_irqrestore(&chnl->free_list_lock, flags);
-
-	buf->size = 0;
-	buf->read_index = 0;
-	buf->write_index = 0;
-
-	return buf;
-}
-
-static void return_to_free_list(struct sdio_xprt *chnl,
-				struct sdio_buf_struct *buf)
-{
-	unsigned long flags;
-
-	if (!chnl || !buf) {
-		pr_err("%s: Invalid chnl or buf\n", __func__);
-		return;
-	}
-
-	buf->size = 0;
-	buf->read_index = 0;
-	buf->write_index = 0;
-
-	spin_lock_irqsave(&chnl->free_list_lock, flags);
-	list_add_tail(&buf->list, &chnl->free_list);
-	num_free_bufs++;
-	spin_unlock_irqrestore(&chnl->free_list_lock, flags);
-
-}
-
-static int rpcrouter_sdio_remote_read_avail(void)
-{
-	int read_avail = 0;
-	unsigned long flags;
-	struct sdio_buf_struct *buf;
-
-	spin_lock_irqsave(&sdio_remote_xprt.channel->read_list_lock, flags);
-	list_for_each_entry(buf, &sdio_remote_xprt.channel->read_list, list) {
-		read_avail += buf->size;
-	}
-	spin_unlock_irqrestore(&sdio_remote_xprt.channel->read_list_lock,
-				flags);
-	return read_avail;
-}
-
-static int rpcrouter_sdio_remote_read(void *data, uint32_t len)
-{
-	struct sdio_buf_struct *buf;
-	unsigned char *buf_data;
-	unsigned long flags;
-
-	SDIO_XPRT_DBG("sdio_xprt Called %s\n", __func__);
-	if (len < 0 || !data)
-		return -EINVAL;
-	else if (len == 0)
-		return 0;
-
-	spin_lock_irqsave(&sdio_remote_xprt.channel->read_list_lock, flags);
-	if (list_empty(&sdio_remote_xprt.channel->read_list)) {
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->read_list_lock, flags);
-		return -EINVAL;
-	}
-
-	buf = list_first_entry(&sdio_remote_xprt.channel->read_list,
-				struct sdio_buf_struct, list);
-	if (buf->size < len) {
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->read_list_lock, flags);
-		return -EINVAL;
-	}
-
-	buf_data = buf->data + buf->read_index;
-	memcpy(data, buf_data, len);
-	buf->read_index += len;
-	buf->size -= len;
-	if (buf->size == 0) {
-		list_del(&buf->list);
-		num_rx_bufs--;
-		return_to_free_list(sdio_remote_xprt.channel, buf);
-	}
-
-	if (list_empty(&sdio_remote_xprt.channel->read_list))
-		wake_unlock(&sdio_remote_xprt.channel->read_wakelock);
-	spin_unlock_irqrestore(&sdio_remote_xprt.channel->read_list_lock,
-				flags);
-	return len;
-}
-
-static int rpcrouter_sdio_remote_write_avail(void)
-{
-	uint32_t write_avail = 0;
-	unsigned long flags;
-
-	SDIO_XPRT_DBG("sdio_xprt Called %s\n", __func__);
-	spin_lock_irqsave(&sdio_remote_xprt.channel->write_list_lock, flags);
-	write_avail = (MAX_TX_BUFS - num_tx_bufs) * SDIO_BUF_SIZE;
-	spin_unlock_irqrestore(&sdio_remote_xprt.channel->write_list_lock,
-				flags);
-	return write_avail;
-}
-
-static int rpcrouter_sdio_remote_write(void *data, uint32_t len,
-					enum write_data_type type)
-{
-	unsigned long flags;
-	static struct sdio_buf_struct *buf;
-	unsigned char *buf_data;
-
-	switch (type) {
-	case HEADER:
-		spin_lock_irqsave(&sdio_remote_xprt.channel->write_list_lock,
-				  flags);
-		if (num_tx_bufs == MAX_TX_BUFS) {
-			spin_unlock_irqrestore(
-				&sdio_remote_xprt.channel->write_list_lock,
-				flags);
-			return -ENOMEM;
-		}
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->write_list_lock, flags);
-
-		SDIO_XPRT_DBG("sdio_xprt WRITE HEADER %s\n", __func__);
-		buf = alloc_from_free_list(sdio_remote_xprt.channel);
-		if (!buf) {
-			pr_err("%s: alloc_from_free_list failed\n", __func__);
-			return -ENOMEM;
-		}
-		buf_data = buf->data + buf->write_index;
-		memcpy(buf_data, data, len);
-		buf->write_index += len;
-		buf->size += len;
-		return len;
-	case PACKMARK:
-		SDIO_XPRT_DBG("sdio_xprt WRITE PACKMARK %s\n",	__func__);
-		if (!buf) {
-			pr_err("%s: HEADER not written or alloc failed\n",
-				__func__);
-			return -ENOMEM;
-		}
-		buf_data = buf->data + buf->write_index;
-		memcpy(buf_data, data, len);
-		buf->write_index += len;
-		buf->size += len;
-		return len;
-	case PAYLOAD:
-		SDIO_XPRT_DBG("sdio_xprt WRITE PAYLOAD %s\n",	__func__);
-		if (!buf) {
-			pr_err("%s: HEADER not written or alloc failed\n",
-				__func__);
-			return -ENOMEM;
-		}
-		buf_data = buf->data + buf->write_index;
-		memcpy(buf_data, data, len);
-		buf->write_index += len;
-		buf->size += len;
-
-		SDIO_XPRT_DBG("sdio_xprt flush %d bytes\n", buf->size);
-		spin_lock_irqsave(&sdio_remote_xprt.channel->write_list_lock,
-				   flags);
-		list_add_tail(&buf->list,
-			      &sdio_remote_xprt.channel->write_list);
-		num_tx_bufs++;
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->write_list_lock, flags);
-		queue_work(sdio_xprt_read_workqueue, &work_write_data);
-		buf = NULL;
-		return len;
-	default:
-		return -EINVAL;
-	}
-}
-
-static void sdio_xprt_write_data(struct work_struct *work)
-{
-	int rc = 0, sdio_write_retry = 0;
-	unsigned long flags;
-	struct sdio_buf_struct *buf;
-
-	mutex_lock(&modem_reset_lock);
-	if (modem_reset) {
-		mutex_unlock(&modem_reset_lock);
-		return;
-	}
-
-	spin_lock_irqsave(&sdio_remote_xprt.channel->write_list_lock, flags);
-	while (!list_empty(&sdio_remote_xprt.channel->write_list)) {
-		buf = list_first_entry(&sdio_remote_xprt.channel->write_list,
-					struct sdio_buf_struct, list);
-		list_del(&buf->list);
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->write_list_lock, flags);
-		mutex_unlock(&modem_reset_lock);
-
-		wait_event(write_avail_wait_q,
-			   (!(modem_reset) && (sdio_write_avail(
-			   sdio_remote_xprt.channel->handle) >=
-			   buf->size)));
-
-		mutex_lock(&modem_reset_lock);
-		while (!(modem_reset) &&
-			((rc = sdio_write(sdio_remote_xprt.channel->handle,
-					buf->data, buf->size)) < 0) &&
-			(sdio_write_retry++ < MAX_SDIO_WRITE_RETRY)) {
-			printk(KERN_ERR "sdio_write failed with RC %d\n", rc);
-			mutex_unlock(&modem_reset_lock);
-			msleep(250);
-			mutex_lock(&modem_reset_lock);
-		}
-		if (modem_reset) {
-			mutex_unlock(&modem_reset_lock);
-			kfree(buf);
-			return;
-		} else {
-			return_to_free_list(sdio_remote_xprt.channel, buf);
-		}
-
-		if (!rc)
-			SDIO_XPRT_DBG("sdio_write %d bytes completed\n",
-					buf->size);
-
-		spin_lock_irqsave(&sdio_remote_xprt.channel->write_list_lock,
-				   flags);
-		num_tx_bufs--;
-	}
-	spin_unlock_irqrestore(&sdio_remote_xprt.channel->write_list_lock,
-				flags);
-	mutex_unlock(&modem_reset_lock);
-}
-
-static int rpcrouter_sdio_remote_close(void)
-{
-	SDIO_XPRT_DBG("sdio_xprt Called %s\n", __func__);
-	flush_workqueue(sdio_xprt_read_workqueue);
-	sdio_close(sdio_remote_xprt.channel->handle);
-	free_sdio_xprt(sdio_remote_xprt.channel);
-	return 0;
-}
-
-static void sdio_xprt_read_data(struct work_struct *work)
-{
-	int size = 0, read_avail;
-	unsigned long flags;
-	struct sdio_buf_struct *buf;
-	SDIO_XPRT_DBG("sdio_xprt Called %s\n", __func__);
-
-	mutex_lock(&modem_reset_lock);
-	while (!(modem_reset) &&
-		((read_avail =
-		sdio_read_avail(sdio_remote_xprt.channel->handle)) > 0)) {
-		spin_lock_irqsave(&sdio_remote_xprt.channel->read_list_lock,
-				  flags);
-		if (num_rx_bufs == MAX_RX_BUFS) {
-			spin_unlock_irqrestore(
-				&sdio_remote_xprt.channel->read_list_lock,
-				flags);
-			queue_delayed_work(sdio_xprt_read_workqueue,
-					   &work_read_data,
-					   msecs_to_jiffies(100));
-			break;
-		}
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->read_list_lock, flags);
-
-		buf = alloc_from_free_list(sdio_remote_xprt.channel);
-		if (!buf) {
-			SDIO_XPRT_DBG("%s: Failed to alloc_from_free_list"
-				      " Try again later\n", __func__);
-			queue_delayed_work(sdio_xprt_read_workqueue,
-					   &work_read_data,
-					   msecs_to_jiffies(100));
-			break;
-		}
-
-		size = sdio_read(sdio_remote_xprt.channel->handle,
-				 buf->data, read_avail);
-		if (size < 0) {
-			printk(KERN_ERR "sdio_read failed,"
-					" read %d bytes, expected %d\n",
-					size, read_avail);
-			return_to_free_list(sdio_remote_xprt.channel, buf);
-			queue_delayed_work(sdio_xprt_read_workqueue,
-					   &work_read_data,
-					   msecs_to_jiffies(100));
-			break;
-		}
-
-		if (size == 0)
-			size = read_avail;
-
-		buf->size = size;
-		buf->write_index = size;
-		spin_lock_irqsave(&sdio_remote_xprt.channel->read_list_lock,
-				   flags);
-		list_add_tail(&buf->list,
-			      &sdio_remote_xprt.channel->read_list);
-		num_rx_bufs++;
-		spin_unlock_irqrestore(
-			&sdio_remote_xprt.channel->read_list_lock, flags);
-		wake_lock(&sdio_remote_xprt.channel->read_wakelock);
-	}
-
-	if (!modem_reset && !list_empty(&sdio_remote_xprt.channel->read_list))
-		msm_rpcrouter_xprt_notify(&sdio_remote_xprt.xprt,
-				  RPCROUTER_XPRT_EVENT_DATA);
-	mutex_unlock(&modem_reset_lock);
-}
-
-static void rpcrouter_sdio_remote_notify(void *_dev, unsigned event)
-{
-	if (event == SDIO_EVENT_DATA_READ_AVAIL) {
-		SDIO_XPRT_DBG("%s Received Notify"
-			      "SDIO_EVENT_DATA_READ_AVAIL\n", __func__);
-		queue_delayed_work(sdio_xprt_read_workqueue,
-				   &work_read_data, 0);
-	}
-	if (event == SDIO_EVENT_DATA_WRITE_AVAIL) {
-		SDIO_XPRT_DBG("%s Received Notify"
-			      "SDIO_EVENT_DATA_WRITE_AVAIL\n", __func__);
-		wake_up(&write_avail_wait_q);
-	}
-}
-
-static int allocate_sdio_xprt(struct sdio_xprt **sdio_xprt_chnl)
-{
-	struct sdio_buf_struct *buf;
-	struct sdio_xprt *chnl;
-	int i;
-	unsigned long flags;
-	int rc = -ENOMEM;
-
-	if (!(*sdio_xprt_chnl)) {
-		chnl = kmalloc(sizeof(struct sdio_xprt), GFP_KERNEL);
-		if (!chnl) {
-			printk(KERN_ERR "sdio_xprt channel"
-					" allocation failed\n");
-			return rc;
-		}
-
-		spin_lock_init(&chnl->write_list_lock);
-		spin_lock_init(&chnl->read_list_lock);
-		spin_lock_init(&chnl->free_list_lock);
-
-		INIT_LIST_HEAD(&chnl->write_list);
-		INIT_LIST_HEAD(&chnl->read_list);
-		INIT_LIST_HEAD(&chnl->free_list);
-		wake_lock_init(&chnl->read_wakelock,
-				WAKE_LOCK_SUSPEND, "rpc_sdio_xprt_read");
-	} else {
-		chnl = *sdio_xprt_chnl;
-	}
-
-	for (i = 0; i < NUM_SDIO_BUFS; i++) {
-		buf = kzalloc(sizeof(struct sdio_buf_struct), GFP_KERNEL);
-		if (!buf) {
-			printk(KERN_ERR "sdio_buf_struct alloc failed\n");
-			goto alloc_failure;
-		}
-		spin_lock_irqsave(&chnl->free_list_lock, flags);
-		list_add_tail(&buf->list, &chnl->free_list);
-		spin_unlock_irqrestore(&chnl->free_list_lock, flags);
-	}
-	num_free_bufs = NUM_SDIO_BUFS;
-
-	*sdio_xprt_chnl = chnl;
-	return 0;
-
-alloc_failure:
-	spin_lock_irqsave(&chnl->free_list_lock, flags);
-	while (!list_empty(&chnl->free_list)) {
-		buf = list_first_entry(&chnl->free_list,
-					struct sdio_buf_struct,
-					list);
-		list_del(&buf->list);
-		kfree(buf);
-	}
-	spin_unlock_irqrestore(&chnl->free_list_lock, flags);
-	wake_lock_destroy(&chnl->read_wakelock);
-
-	kfree(chnl);
-	*sdio_xprt_chnl = NULL;
-	return rc;
-}
-
-static int rpcrouter_sdio_remote_probe(struct platform_device *pdev)
-{
-	int rc;
-
-	SDIO_XPRT_INFO("%s Called\n", __func__);
-
-	mutex_lock(&modem_reset_lock);
-	if (!modem_reset) {
-		sdio_xprt_read_workqueue =
-			create_singlethread_workqueue("sdio_xprt");
-		if (!sdio_xprt_read_workqueue) {
-			mutex_unlock(&modem_reset_lock);
-			return -ENOMEM;
-		}
-
-		sdio_remote_xprt.xprt.name = "rpcrotuer_sdio_xprt";
-		sdio_remote_xprt.xprt.read_avail =
-			rpcrouter_sdio_remote_read_avail;
-		sdio_remote_xprt.xprt.read = rpcrouter_sdio_remote_read;
-		sdio_remote_xprt.xprt.write_avail =
-			rpcrouter_sdio_remote_write_avail;
-		sdio_remote_xprt.xprt.write = rpcrouter_sdio_remote_write;
-		sdio_remote_xprt.xprt.close = rpcrouter_sdio_remote_close;
-		sdio_remote_xprt.xprt.priv = NULL;
-
-		init_waitqueue_head(&write_avail_wait_q);
-	}
-	modem_reset = 0;
-
-	rc = allocate_sdio_xprt(&sdio_remote_xprt.channel);
-	if (rc) {
-		destroy_workqueue(sdio_xprt_read_workqueue);
-		mutex_unlock(&modem_reset_lock);
-		return rc;
-	}
-
-	/* Open up SDIO channel */
-	rc = sdio_open("SDIO_RPC", &sdio_remote_xprt.channel->handle, NULL,
-		      rpcrouter_sdio_remote_notify);
-
-	if (rc < 0) {
-		free_sdio_xprt(sdio_remote_xprt.channel);
-		destroy_workqueue(sdio_xprt_read_workqueue);
-		mutex_unlock(&modem_reset_lock);
-		return rc;
-	}
-	mutex_unlock(&modem_reset_lock);
-
-	msm_rpcrouter_xprt_notify(&sdio_remote_xprt.xprt,
-				  RPCROUTER_XPRT_EVENT_OPEN);
-
-	SDIO_XPRT_INFO("%s Completed\n", __func__);
-
-	return 0;
-}
-
-static int rpcrouter_sdio_remote_remove(struct platform_device *pdev)
-{
-	SDIO_XPRT_INFO("%s Called\n", __func__);
-
-	mutex_lock(&modem_reset_lock);
-	modem_reset = 1;
-	wake_up(&write_avail_wait_q);
-	free_sdio_xprt(sdio_remote_xprt.channel);
-	mutex_unlock(&modem_reset_lock);
-
-	msm_rpcrouter_xprt_notify(&sdio_remote_xprt.xprt,
-				  RPCROUTER_XPRT_EVENT_CLOSE);
-
-	SDIO_XPRT_INFO("%s Completed\n", __func__);
-
-	return 0;
-}
-
-/*Remove this platform driver after mainline of SDIO_AL update*/
-static struct platform_driver rpcrouter_sdio_remote_driver = {
-	.probe		= rpcrouter_sdio_remote_probe,
-	.driver		= {
-			.name	= "SDIO_AL",
-			.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver rpcrouter_sdio_driver = {
-	.probe		= rpcrouter_sdio_remote_probe,
-	.remove		= rpcrouter_sdio_remote_remove,
-	.driver		= {
-			.name	= "SDIO_RPC",
-			.owner	= THIS_MODULE,
-	},
-};
-
-static int __init rpcrouter_sdio_init(void)
-{
-	int rc;
-	msm_sdio_xprt_debug_mask = 0x2;
-	rc = platform_driver_register(&rpcrouter_sdio_remote_driver);
-	if (rc < 0)
-		return rc;
-	return platform_driver_register(&rpcrouter_sdio_driver);
-}
-
-module_init(rpcrouter_sdio_init);
-MODULE_DESCRIPTION("RPC Router SDIO XPRT");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 7995e9a..c7e9e75 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -163,6 +163,7 @@
 	struct mutex		mlock;
 	unsigned long		flags;
 	bool			sleep_request_sent;
+	bool			apps_only;
 	struct msm_rpm_request	*handle_active;
 	struct msm_rpm_request	*handle_sleep;
 };
@@ -241,6 +242,16 @@
 					& BIT(RPM_REGULATOR_PARAM_ENABLE)));
 }
 
+static inline bool rpm_vreg_shared_active_or_sleep_enabled_valid
+						(struct rpm_vreg *rpm_vreg)
+{
+	return !rpm_vreg->apps_only &&
+		((rpm_vreg->aggr_req_active.valid
+					& BIT(RPM_REGULATOR_PARAM_ENABLE))
+		 || (rpm_vreg->aggr_req_sleep.valid
+					& BIT(RPM_REGULATOR_PARAM_ENABLE)));
+}
+
 /*
  * This is used when voting for LPM or HPM by subtracting or adding to the
  * hpm_min_load of a regulator.  It has units of uA.
@@ -660,7 +671,8 @@
 	 * if the regulator has been configured to always send voltage updates.
 	 */
 	if (reg->always_send_voltage
-	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
+	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -719,7 +731,8 @@
 	 * updates.
 	 */
 	if (reg->always_send_voltage
-	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
+	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -774,7 +787,8 @@
 	 * voltage updates.
 	 */
 	if (reg->always_send_voltage
-	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
+	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -829,7 +843,8 @@
 	 * current updates.
 	 */
 	if (reg->always_send_current
-	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg))
+	    || rpm_vreg_active_or_sleep_enabled(reg->rpm_vreg)
+	    || rpm_vreg_shared_active_or_sleep_enabled_valid(reg->rpm_vreg))
 		rc = rpm_vreg_aggregate_requests(reg);
 
 	if (rc) {
@@ -1579,6 +1594,7 @@
 	of_property_read_u32(node, "qcom,enable-time", &rpm_vreg->enable_time);
 	of_property_read_u32(node, "qcom,hpm-min-load",
 		&rpm_vreg->hpm_min_load);
+	rpm_vreg->apps_only = of_property_read_bool(node, "qcom,apps-only");
 
 	rpm_vreg->handle_active = msm_rpm_create_request(RPM_SET_ACTIVE,
 		resource_type, rpm_vreg->resource_id, RPM_REGULATOR_PARAM_MAX);
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 54576a9..2a01a36 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -130,8 +130,7 @@
 	bool valid;
 };
 static struct rb_root tr_root = RB_ROOT;
-
-static int msm_rpm_send_smd_buffer(char *buf, int size, bool noirq);
+static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq);
 static uint32_t msm_rpm_get_next_msg_id(void);
 
 static inline unsigned int get_rsc_type(char *buf)
@@ -187,7 +186,8 @@
 static void delete_kvp(char *msg, struct kvp *d)
 {
 	struct kvp *n;
-	int dec, size;
+	int dec;
+	uint32_t size;
 
 	n = get_next_kvp(d);
 	dec = (void *)n - (void *)d;
@@ -206,7 +206,7 @@
 
 static void add_kvp(char *buf, struct kvp *n)
 {
-	int inc = sizeof(*n) + n->s;
+	uint32_t inc = sizeof(*n) + n->s;
 	BUG_ON((get_req_len(buf) + inc) > MAX_SLEEP_BUFFER);
 
 	memcpy(buf + get_buf_len(buf), n, inc);
@@ -311,7 +311,7 @@
 	}
 }
 
-int msm_rpm_smd_buffer_request(char *buf, int size, gfp_t flag)
+int msm_rpm_smd_buffer_request(char *buf, uint32_t size, gfp_t flag)
 {
 	struct slp_buf *slp;
 	static DEFINE_SPINLOCK(slp_buffer_lock);
@@ -367,7 +367,7 @@
 	pos += scnprintf(buf + pos, buflen - pos, " id = 0%x",
 			get_rsc_id(s->buf));
 	for_each_kvp(s->buf, e) {
-		int i;
+		uint32_t i;
 		char *data = get_data(e);
 
 		memcpy(ch, &e->k, sizeof(u32));
@@ -482,14 +482,17 @@
 static int msm_rpm_add_kvp_data_common(struct msm_rpm_request *handle,
 		uint32_t key, const uint8_t *data, int size, bool noirq)
 {
-	int i;
-	int data_size, msg_size;
+	uint32_t i;
+	uint32_t data_size, msg_size;
 
 	if (!handle) {
 		pr_err("%s(): Invalid handle\n", __func__);
 		return -EINVAL;
 	}
 
+	if (size < 0)
+		return  -EINVAL;
+
 	data_size = ALIGN(size, SZ_4);
 	msg_size = data_size + sizeof(struct rpm_request_header);
 
@@ -813,7 +816,7 @@
 
 static int msm_rpm_read_smd_data(char *buf)
 {
-	int pkt_sz;
+	uint32_t pkt_sz;
 	int bytes_read = 0;
 
 	pkt_sz = smd_cur_packet_size(msm_rpm_data.ch_info);
@@ -867,7 +870,8 @@
 	size_t buflen = DEBUG_PRINT_BUFFER_SIZE;
 	char name[5];
 	u32 value;
-	int i, j, prev_valid;
+	uint32_t i;
+	int j, prev_valid;
 	int valid_count = 0;
 	int pos = 0;
 
@@ -992,7 +996,7 @@
 	pos += scnprintf(buf + pos, buflen - pos, "\n");
 	printk(buf);
 }
-static int msm_rpm_send_smd_buffer(char *buf, int size, bool noirq)
+static int msm_rpm_send_smd_buffer(char *buf, uint32_t size, bool noirq)
 {
 	unsigned long flags;
 	int ret;
@@ -1027,8 +1031,9 @@
 		int msg_type, bool noirq)
 {
 	uint8_t *tmpbuff;
-	int i, ret, msg_size;
-
+	int ret;
+	uint32_t i;
+	uint32_t msg_size;
 	int req_hdr_sz, msg_hdr_sz;
 
 	if (!cdata->msg_hdr.data_len)
diff --git a/arch/arm/mach-msm/sdio_al.c b/arch/arm/mach-msm/sdio_al.c
deleted file mode 100644
index bcfc556..0000000
--- a/arch/arm/mach-msm/sdio_al.c
+++ /dev/null
@@ -1,4365 +0,0 @@
-/* Copyright (c) 2010-2011, 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.
- */
-
-/*
- * SDIO-Abstraction-Layer Module.
- *
- * To be used with Qualcomm's SDIO-Client connected to this host.
- */
-#include "sdio_al_private.h"
-
-#include <linux/module.h>
-#include <linux/scatterlist.h>
-#include <linux/workqueue.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/wakelock.h>
-#include <linux/mmc/core.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/mmc.h>
-#include <linux/mmc/sdio.h>
-#include <linux/mmc/sdio_func.h>
-#include <linux/mmc/sdio_ids.h>
-#include <linux/gpio.h>
-#include <linux/dma-mapping.h>
-#include <linux/earlysuspend.h>
-#include <linux/debugfs.h>
-#include <linux/uaccess.h>
-#include <linux/syscalls.h>
-#include <linux/time.h>
-#include <linux/spinlock.h>
-
-#include <mach/dma.h>
-#include <mach/gpio.h>
-#include <mach/subsystem_notif.h>
-
-#include "../../../drivers/mmc/host/msm_sdcc.h"
-
-/**
- *  Func#0 has SDIO standard registers
- *  Func#1 is for Mailbox.
- *  Functions 2..7 are for channels.
- *  Currently only functions 2..5 are active due to SDIO-Client
- *  number of pipes.
- *
- */
-#define SDIO_AL_MAX_CHANNELS 6
-
-/** Func 1..5 */
-#define SDIO_AL_MAX_FUNCS    (SDIO_AL_MAX_CHANNELS+1)
-#define SDIO_AL_WAKEUP_FUNC  6
-
-/** Number of SDIO-Client pipes */
-#define SDIO_AL_MAX_PIPES    16
-#define SDIO_AL_ACTIVE_PIPES 8
-
-/** CMD53/CMD54 Block size */
-#define SDIO_AL_BLOCK_SIZE   256
-
-/** Func#1 hardware Mailbox base address	 */
-#define HW_MAILBOX_ADDR			0x1000
-
-/** Func#1 peer sdioc software version.
- *  The header is duplicated also to the mailbox of the other
- *  functions. It can be used before other functions are enabled. */
-#define SDIOC_SW_HEADER_ADDR		0x0400
-
-/** Func#2..7 software Mailbox base address at 16K */
-#define SDIOC_SW_MAILBOX_ADDR			0x4000
-
-/** Some Mailbox registers address, written by host for
- control */
-#define PIPES_THRESHOLD_ADDR		0x01000
-
-#define PIPES_0_7_IRQ_MASK_ADDR 	0x01048
-
-#define PIPES_8_15_IRQ_MASK_ADDR	0x0104C
-
-#define FUNC_1_4_MASK_IRQ_ADDR		0x01040
-#define FUNC_5_7_MASK_IRQ_ADDR		0x01044
-#define FUNC_1_4_USER_IRQ_ADDR		0x01050
-#define FUNC_5_7_USER_IRQ_ADDR		0x01054
-
-#define EOT_PIPES_ENABLE		0x00
-
-/** Maximum read/write data available is SDIO-Client limitation */
-#define MAX_DATA_AVAILABLE   		(16*1024)
-#define INVALID_DATA_AVAILABLE  	(0x8000)
-
-/** SDIO-Client HW threshold to generate interrupt to the
- *  SDIO-Host on write available bytes.
- */
-#define DEFAULT_WRITE_THRESHOLD 	(1024)
-
-/** SDIO-Client HW threshold to generate interrupt to the
- *  SDIO-Host on read available bytes, for streaming (non
- *  packet) rx data.
- */
-#define DEFAULT_READ_THRESHOLD  	(1024)
-#define LOW_LATENCY_THRESHOLD		(1)
-
-/* Extra bytes to ensure getting the rx threshold interrupt on stream channels
-   when restoring the threshold after sleep */
-#define THRESHOLD_CHANGE_EXTRA_BYTES (100)
-
-/** SW threshold to trigger reading the mailbox. */
-#define DEFAULT_MIN_WRITE_THRESHOLD 	(1024)
-#define DEFAULT_MIN_WRITE_THRESHOLD_STREAMING	(1600)
-
-#define THRESHOLD_DISABLE_VAL  		(0xFFFFFFFF)
-
-/** Mailbox polling time for packet channels */
-#define DEFAULT_POLL_DELAY_MSEC		10
-/** Mailbox polling time for streaming channels */
-#define DEFAULT_POLL_DELAY_NOPACKET_MSEC 30
-
-/** The SDIO-Client prepares N buffers of size X per Tx pipe.
- *  Even when the transfer fills a partial buffer,
- *  that buffer becomes unusable for the next transfer. */
-#define DEFAULT_PEER_TX_BUF_SIZE	(128)
-
-#define ROUND_UP(x, n) (((x + n - 1) / n) * n)
-
-/** Func#2..7 FIFOs are r/w via
- sdio_readsb() & sdio_writesb(),when inc_addr=0 */
-#define PIPE_RX_FIFO_ADDR   0x00
-#define PIPE_TX_FIFO_ADDR   0x00
-
-/** Inactivity time to go to sleep in mseconds */
-#define INACTIVITY_TIME_MSEC 30
-#define INITIAL_INACTIVITY_TIME_MSEC 5000
-
-/** Context validity check */
-#define SDIO_AL_SIGNATURE 0xAABBCCDD
-
-/* Vendor Specific Command */
-#define SD_IO_RW_EXTENDED_QCOM 54
-
-#define TIME_TO_WAIT_US 500
-#define SDIO_CLOSE_FLUSH_TIMEOUT_MSEC   (10000)
-#define RX_FLUSH_BUFFER_SIZE (16*1024)
-
-#define SDIO_TEST_POSTFIX "_TEST"
-
-#define DATA_DEBUG(x, y...)						\
-	do {								\
-		if (sdio_al->debug.debug_data_on)			\
-			pr_info(y);					\
-		sdio_al_log(x, y);					\
-	} while (0)
-
-#define LPM_DEBUG(x, y...)						\
-	do {								\
-		if (sdio_al->debug.debug_lpm_on)			\
-			pr_info(y);					\
-		sdio_al_log(x, y);					\
-	} while (0)
-
-#define sdio_al_loge(x, y...)						\
-	do {								\
-		pr_err(y);						\
-		sdio_al_log(x, y);					\
-	} while (0)
-
-#define sdio_al_logi(x, y...)						\
-	do {								\
-		pr_info(y);						\
-		sdio_al_log(x, y);					\
-	} while (0)
-
-#define CLOSE_DEBUG(x, y...)						\
-	do {								\
-		if (sdio_al->debug.debug_close_on)			\
-			pr_info(y);					\
-		sdio_al_log(x, y);					\
-	} while (0)
-
-/* The index of the SDIO card used for the sdio_al_dloader */
-#define SDIO_BOOTLOADER_CARD_INDEX 1
-
-
-/* SDIO card state machine */
-enum sdio_al_device_state {
-	CARD_INSERTED,
-	CARD_REMOVED,
-	MODEM_RESTART
-};
-
-struct sdio_al_debug {
-	u8 debug_lpm_on;
-	u8 debug_data_on;
-	u8 debug_close_on;
-	struct dentry *sdio_al_debug_root;
-	struct dentry *sdio_al_debug_lpm_on;
-	struct dentry *sdio_al_debug_data_on;
-	struct dentry *sdio_al_debug_close_on;
-	struct dentry *sdio_al_debug_info;
-	struct dentry *sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES + 1];
-};
-
-/* Polling time for the inactivity timer for devices that doesn't have
- * a streaming channel
- */
-#define SDIO_AL_POLL_TIME_NO_STREAMING 30
-
-#define CHAN_TO_FUNC(x) ((x) + 2 - 1)
-
-/**
- *  Mailbox structure.
- *  The Mailbox is located on the SDIO-Client Function#1.
- *  The mailbox size is 128 bytes, which is one block.
- *  The mailbox allows the host ton:
- *  1. Get the number of available bytes on the pipes.
- *  2. Enable/Disable SDIO-Client interrupt, related to pipes.
- *  3. Set the Threshold for generating interrupt.
- *
- */
-struct sdio_mailbox {
-	u32 pipe_bytes_threshold[SDIO_AL_MAX_PIPES]; /* Addr 0x1000 */
-
-	/* Mask USER interrupts generated towards host - Addr 0x1040 */
-	u32 mask_irq_func_1:8; /* LSB */
-	u32 mask_irq_func_2:8;
-	u32 mask_irq_func_3:8;
-	u32 mask_irq_func_4:8;
-
-	u32 mask_irq_func_5:8;
-	u32 mask_irq_func_6:8;
-	u32 mask_irq_func_7:8;
-	u32 mask_mutex_irq:8;
-
-	/* Mask PIPE interrupts generated towards host - Addr 0x1048 */
-	u32 mask_eot_pipe_0_7:8;
-	u32 mask_thresh_above_limit_pipe_0_7:8;
-	u32 mask_overflow_pipe_0_7:8;
-	u32 mask_underflow_pipe_0_7:8;
-
-	u32 mask_eot_pipe_8_15:8;
-	u32 mask_thresh_above_limit_pipe_8_15:8;
-	u32 mask_overflow_pipe_8_15:8;
-	u32 mask_underflow_pipe_8_15:8;
-
-	/* Status of User interrupts generated towards host - Addr 0x1050 */
-	u32 user_irq_func_1:8;
-	u32 user_irq_func_2:8;
-	u32 user_irq_func_3:8;
-	u32 user_irq_func_4:8;
-
-	u32 user_irq_func_5:8;
-	u32 user_irq_func_6:8;
-	u32 user_irq_func_7:8;
-	u32 user_mutex_irq:8;
-
-	/* Status of PIPE interrupts generated towards host */
-	/* Note: All sources are cleared once they read. - Addr 0x1058 */
-	u32 eot_pipe_0_7:8;
-	u32 thresh_above_limit_pipe_0_7:8;
-	u32 overflow_pipe_0_7:8;
-	u32 underflow_pipe_0_7:8;
-
-	u32 eot_pipe_8_15:8;
-	u32 thresh_above_limit_pipe_8_15:8;
-	u32 overflow_pipe_8_15:8;
-	u32 underflow_pipe_8_15:8;
-
-	u16 pipe_bytes_avail[SDIO_AL_MAX_PIPES];
-};
-
-/** Track pending Rx Packet size */
-struct rx_packet_size {
-	u32 size; /* in bytes */
-	struct list_head	list;
-};
-
-#define PEER_SDIOC_SW_MAILBOX_SIGNATURE 0xFACECAFE
-#define PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE 0x5D107E57
-#define PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE 0xDEADBEEF
-
-/* Allow support in old sdio version */
-#define PEER_SDIOC_OLD_VERSION_MAJOR	0x0002
-#define INVALID_SDIO_CHAN		0xFF
-
-/**
- * Peer SDIO-Client software header.
- */
-struct peer_sdioc_sw_header {
-	u32 signature;
-	u32 version;
-	u32 max_channels;
-	char channel_names[SDIO_AL_MAX_CHANNELS][PEER_CHANNEL_NAME_SIZE];
-	u32 reserved[23];
-};
-
-struct peer_sdioc_boot_sw_header {
-	u32 signature;
-	u32 version;
-	u32 boot_ch_num;
-	u32 reserved[29]; /* 32 - previous fields */
-};
-
-/**
- * Peer SDIO-Client software mailbox.
- */
-struct peer_sdioc_sw_mailbox {
-	struct peer_sdioc_sw_header sw_header;
-	struct peer_sdioc_channel_config ch_config[SDIO_AL_MAX_CHANNELS];
-};
-
-#define SDIO_AL_DEBUG_LOG_SIZE 3000
-struct sdio_al_local_log {
-	char buffer[SDIO_AL_DEBUG_LOG_SIZE];
-	unsigned int buf_cur_pos;
-	spinlock_t log_lock;
-};
-
-#define SDIO_AL_DEBUG_TMP_LOG_SIZE 250
-static int sdio_al_log(struct sdio_al_local_log *, const char *fmt, ...);
-
-/**
- *  SDIO Abstraction Layer driver context.
- *
- *  @pdata -
- *  @debug -
- *  @devices - an array of the the devices claimed by sdio_al
- *  @unittest_mode - a flag to indicate if sdio_al is in
- *		   unittest mode
- *  @bootloader_dev - the device which is used for the
- *                 bootloader
- *  @subsys_notif_handle - handle for modem restart
- *                 notifications
- *
- */
-struct sdio_al {
-	struct sdio_al_local_log gen_log;
-	struct sdio_al_local_log device_log[MAX_NUM_OF_SDIO_DEVICES];
-	struct sdio_al_platform_data *pdata;
-	struct sdio_al_debug debug;
-	struct sdio_al_device *devices[MAX_NUM_OF_SDIO_DEVICES];
-	int unittest_mode;
-	struct sdio_al_device *bootloader_dev;
-	void *subsys_notif_handle;
-	int sdioc_major;
-	int skip_print_info;
-};
-
-struct sdio_al_work {
-	struct work_struct work;
-	struct sdio_al_device *sdio_al_dev;
-};
-
-
-/**
- *  SDIO Abstraction Layer device context.
- *
- *  @card - card claimed.
- *
- *  @mailbox - A shadow of the SDIO-Client mailbox.
- *
- *  @channel - Channels context.
- *
- *  @workqueue - workqueue to read the mailbox and handle
- *     pending requests. Reading the mailbox should not happen
- *     in interrupt context.
- *
- *  @work - work to submit to workqueue.
- *
- *  @is_ready - driver is ready.
- *
- *  @ask_mbox - Flag to request reading the mailbox,
- *					  for different reasons.
- *
- *  @wake_lock - Lock when can't sleep.
- *
- *  @lpm_chan - Channel to use for LPM (low power mode)
- *            communication.
- *
- *  @is_ok_to_sleep - Mark if driver is OK with going to sleep
- * 			(no pending transactions).
- *
- *  @inactivity_time - time allowed to be in inactivity before
- * 		going to sleep
- *
- *  @timer - timer to use for polling the mailbox.
- *
- *  @poll_delay_msec - timer delay for polling the mailbox.
- *
- *  @is_err - error detected.
- *
- *  @signature - Context Validity Check.
- *
- *  @flashless_boot_on - flag to indicate if sdio_al is in
- *    flshless boot mode
- *
- */
-struct sdio_al_device {
-	struct sdio_al_local_log *dev_log;
-	struct mmc_card *card;
-	struct mmc_host *host;
-	struct sdio_mailbox *mailbox;
-	struct sdio_channel channel[SDIO_AL_MAX_CHANNELS];
-
-	struct peer_sdioc_sw_header *sdioc_sw_header;
-	struct peer_sdioc_boot_sw_header *sdioc_boot_sw_header;
-
-	struct workqueue_struct *workqueue;
-	struct sdio_al_work sdio_al_work;
-	struct sdio_al_work boot_work;
-
-	int is_ready;
-
-	wait_queue_head_t   wait_mbox;
-	int ask_mbox;
-	int bootloader_done;
-
-	struct wake_lock wake_lock;
-	int lpm_chan;
-	int is_ok_to_sleep;
-	unsigned long inactivity_time;
-
-	struct timer_list timer;
-	u32 poll_delay_msec;
-	int is_timer_initialized;
-
-	int is_err;
-
-	u32 signature;
-
-	unsigned int is_suspended;
-
-	int flashless_boot_on;
-	int ch_close_supported;
-	int state;
-	int (*lpm_callback)(void *, int);
-
-	int print_after_interrupt;
-
-	u8 *rx_flush_buf;
-};
-
-/*
- * Host operation:
- *   lower 16bits are operation code
- *   upper 16bits are operation state
- */
-#define PEER_OPERATION(op_code , op_state) ((op_code) | ((op_state) << 16))
-#define GET_PEER_OPERATION_CODE(op) ((op) & 0xffff)
-#define GET_PEER_OPERATION_STATE(op) ((op) >> 16)
-
-enum peer_op_code {
-	PEER_OP_CODE_CLOSE = 1
-};
-
-enum peer_op_state {
-	PEER_OP_STATE_INIT = 0,
-	PEER_OP_STATE_START = 1
-};
-
-
-/*
- * On the kernel command line specify
- * sdio_al.debug_lpm_on=1 to enable the LPM debug messages
- * By default the LPM debug messages are turned off
- */
-static int debug_lpm_on;
-module_param(debug_lpm_on, int, 0);
-
-/*
- * On the kernel command line specify
- * sdio_al.debug_data_on=1 to enable the DATA debug messages
- * By default the DATA debug messages are turned off
- */
-static int debug_data_on;
-module_param(debug_data_on, int, 0);
-
-/*
- * Enables / disables open close debug messages
- */
-static int debug_close_on = 1;
-module_param(debug_close_on, int, 0);
-
-/** The driver context */
-static struct sdio_al *sdio_al;
-
-/* Static functions declaration */
-static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
-				int pipe_index, int enable);
-static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
-				      int pipe_index, int enable);
-static void sdio_func_irq(struct sdio_func *func);
-static void sdio_al_timer_handler(unsigned long data);
-static int get_min_poll_time_msec(struct sdio_al_device *sdio_al_dev);
-static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot);
-static u32 remove_handled_rx_packet(struct sdio_channel *ch);
-static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
-			      int pipe_index, int threshold);
-static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
-			   u32 not_from_int, struct sdio_channel *ch);
-static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev);
-static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
-			   int func_num, int enable, u8 bit_offset);
-static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name);
-static void sdio_al_print_info(void);
-static int sdio_read_internal(struct sdio_channel *ch, void *data, int len);
-static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len);
-static void stop_and_del_timer(struct sdio_al_device *sdio_al_dev);
-
-#define SDIO_AL_ERR(func)					\
-	do {							\
-		printk_once(KERN_ERR MODULE_NAME		\
-			":In Error state, ignore %s\n",		\
-			func);					\
-		sdio_al_print_info();				\
-	} while (0)
-
-#ifdef CONFIG_DEBUG_FS
-static int debug_info_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t debug_info_write(struct file *file,
-		const char __user *buf, size_t count, loff_t *ppos)
-{
-	sdio_al_print_info();
-	return 1;
-}
-
-const struct file_operations debug_info_ops = {
-	.open = debug_info_open,
-	.write = debug_info_write,
-};
-
-struct debugfs_blob_wrapper sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES + 1];
-
-/*
-*
-* Trigger on/off for debug messages
-* for trigger off the data messages debug level use:
-* echo 0 > /sys/kernel/debugfs/sdio_al/debug_data_on
-* for trigger on the data messages debug level use:
-* echo 1 > /sys/kernel/debugfs/sdio_al/debug_data_on
-* for trigger off the lpm messages debug level use:
-* echo 0 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
-* for trigger on the lpm messages debug level use:
-* echo 1 > /sys/kernel/debugfs/sdio_al/debug_lpm_on
-*/
-static int sdio_al_debugfs_init(void)
-{
-	int i, blob_errs = 0;
-
-	sdio_al->debug.sdio_al_debug_root = debugfs_create_dir("sdio_al", NULL);
-	if (!sdio_al->debug.sdio_al_debug_root)
-		return -ENOENT;
-
-	sdio_al->debug.sdio_al_debug_lpm_on = debugfs_create_u8("debug_lpm_on",
-					S_IRUGO | S_IWUGO,
-					sdio_al->debug.sdio_al_debug_root,
-					&sdio_al->debug.debug_lpm_on);
-
-	sdio_al->debug.sdio_al_debug_data_on = debugfs_create_u8(
-					"debug_data_on",
-					S_IRUGO | S_IWUGO,
-					sdio_al->debug.sdio_al_debug_root,
-					&sdio_al->debug.debug_data_on);
-
-	sdio_al->debug.sdio_al_debug_close_on = debugfs_create_u8(
-					"debug_close_on",
-					S_IRUGO | S_IWUGO,
-					sdio_al->debug.sdio_al_debug_root,
-					&sdio_al->debug.debug_close_on);
-
-	sdio_al->debug.sdio_al_debug_info = debugfs_create_file(
-					"sdio_debug_info",
-					S_IRUGO | S_IWUGO,
-					sdio_al->debug.sdio_al_debug_root,
-					NULL,
-					&debug_info_ops);
-
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
-		char temp[18];
-
-		scnprintf(temp, 18, "sdio_al_log_dev_%d", i + 1);
-		sdio_al->debug.sdio_al_debug_log_buffers[i] =
-			debugfs_create_blob(temp,
-					S_IRUGO | S_IWUGO,
-					sdio_al->debug.sdio_al_debug_root,
-					&sdio_al_dbgfs_log[i]);
-	}
-
-	sdio_al->debug.sdio_al_debug_log_buffers[MAX_NUM_OF_SDIO_DEVICES] =
-			debugfs_create_blob("sdio_al_gen_log",
-				S_IRUGO | S_IWUGO,
-				sdio_al->debug.sdio_al_debug_root,
-				&sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES]);
-
-	for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i) {
-		if (!sdio_al->debug.sdio_al_debug_log_buffers[i]) {
-			pr_err(MODULE_NAME ": Failed to create debugfs buffer"
-				   " entry for "
-				   "sdio_al->debug.sdio_al_debug_log_buffers[%d]",
-				   i);
-			blob_errs = 1;
-		}
-	}
-
-	if (blob_errs) {
-		for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
-			if (sdio_al->debug.sdio_al_debug_log_buffers[i])
-				debugfs_remove(
-					sdio_al->
-					debug.sdio_al_debug_log_buffers[i]);
-	}
-
-
-	if ((!sdio_al->debug.sdio_al_debug_data_on) &&
-	    (!sdio_al->debug.sdio_al_debug_lpm_on) &&
-	    (!sdio_al->debug.sdio_al_debug_close_on) &&
-	    (!sdio_al->debug.sdio_al_debug_info) &&
-		blob_errs) {
-		debugfs_remove(sdio_al->debug.sdio_al_debug_root);
-		sdio_al->debug.sdio_al_debug_root = NULL;
-		return -ENOENT;
-	}
-
-	sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].data =
-						sdio_al->gen_log.buffer;
-	sdio_al_dbgfs_log[MAX_NUM_OF_SDIO_DEVICES].size =
-						SDIO_AL_DEBUG_LOG_SIZE;
-
-	return 0;
-}
-
-static void sdio_al_debugfs_cleanup(void)
-{
-	int i;
-
-	debugfs_remove(sdio_al->debug.sdio_al_debug_lpm_on);
-	debugfs_remove(sdio_al->debug.sdio_al_debug_data_on);
-	debugfs_remove(sdio_al->debug.sdio_al_debug_close_on);
-	debugfs_remove(sdio_al->debug.sdio_al_debug_info);
-
-	for (i = 0; i < (MAX_NUM_OF_SDIO_DEVICES + 1); ++i)
-		debugfs_remove(sdio_al->debug.sdio_al_debug_log_buffers[i]);
-
-	debugfs_remove(sdio_al->debug.sdio_al_debug_root);
-}
-#endif
-
-static int sdio_al_log(struct sdio_al_local_log *log, const char *fmt, ...)
-{
-	va_list args;
-	int r;
-	char *tp, *log_buf;
-	unsigned int *log_cur_pos;
-	struct timeval kt;
-	unsigned long flags;
-	static char sdio_al_log_tmp[SDIO_AL_DEBUG_TMP_LOG_SIZE];
-
-	spin_lock_irqsave(&log->log_lock, flags);
-
-	kt = ktime_to_timeval(ktime_get());
-	r = scnprintf(sdio_al_log_tmp, SDIO_AL_DEBUG_TMP_LOG_SIZE,
-			"[%8ld.%6ld] ", kt.tv_sec, kt.tv_usec);
-
-	va_start(args, fmt);
-	r += vscnprintf(&sdio_al_log_tmp[r], (SDIO_AL_DEBUG_TMP_LOG_SIZE - r),
-			fmt, args);
-	va_end(args);
-
-	log_buf = log->buffer;
-	log_cur_pos = &(log->buf_cur_pos);
-
-	for (tp = sdio_al_log_tmp; tp < (sdio_al_log_tmp + r); tp++) {
-		log_buf[(*log_cur_pos)++] = *tp;
-		if ((*log_cur_pos) == SDIO_AL_DEBUG_LOG_SIZE)
-			*log_cur_pos = 0;
-	}
-
-	spin_unlock_irqrestore(&log->log_lock, flags);
-
-	return r;
-}
-
-static int sdio_al_verify_func1(struct sdio_al_device *sdio_al_dev,
-				char const *func)
-{
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-				"sdio_al_dev\n", func);
-		return -ENODEV;
-	}
-
-	if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
-				"signature\n", func);
-		return -ENODEV;
-	}
-
-	if (!sdio_al_dev->card) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
-				"card\n", func);
-		return -ENODEV;
-	}
-	if (!sdio_al_dev->card->sdio_func[0]) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
-				"func1\n", func);
-		return -ENODEV;
-	}
-	return 0;
-}
-
-static int sdio_al_claim_mutex(struct sdio_al_device *sdio_al_dev,
-			       char const *func)
-{
-	if (!sdio_al_dev) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-					"device\n", func);
-		return -ENODEV;
-	}
-
-	if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
-					"device signature\n", func);
-		return -ENODEV;
-	}
-
-	if (!sdio_al_dev->host) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
-					"host\n", func);
-		return -ENODEV;
-	}
-
-	mmc_claim_host(sdio_al_dev->host);
-
-	return 0;
-}
-
-static int sdio_al_release_mutex(struct sdio_al_device *sdio_al_dev,
-			       char const *func)
-{
-	if (!sdio_al_dev) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-					"device\n", func);
-		return -ENODEV;
-	}
-
-	if (sdio_al_dev->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
-					"device signature\n", func);
-		return -ENODEV;
-	}
-
-	if (!sdio_al_dev->host) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: NULL "
-					"host\n", func);
-		return -ENODEV;
-	}
-
-	mmc_release_host(sdio_al_dev->host);
-
-	return 0;
-}
-
-static int sdio_al_claim_mutex_and_verify_dev(
-	struct sdio_al_device *sdio_al_dev,
-	char const *func)
-{
-	if (sdio_al_claim_mutex(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	if (sdio_al_dev->state != CARD_INSERTED) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": %s: Invalid "
-				"device state %d\n", func, sdio_al_dev->state);
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-static void sdio_al_get_into_err_state(struct sdio_al_device *sdio_al_dev)
-{
-	if ((!sdio_al) || (!sdio_al_dev))
-		return;
-
-	sdio_al_dev->is_err = true;
-	sdio_al->debug.debug_data_on = 0;
-	sdio_al->debug.debug_lpm_on = 0;
-	sdio_al_print_info();
-}
-
-void sdio_al_register_lpm_cb(void *device_handle,
-				       int(*lpm_callback)(void *, int))
-{
-	struct sdio_al_device *sdio_al_dev =
-		(struct sdio_al_device *) device_handle;
-
-	if (!sdio_al_dev) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
-				"device_handle is NULL\n", __func__);
-		return;
-	}
-
-	if (lpm_callback) {
-		sdio_al_dev->lpm_callback = lpm_callback;
-		lpm_callback((void *)sdio_al_dev,
-					   sdio_al_dev->is_ok_to_sleep);
-	}
-
-	LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
-			"registered for wakeup callback\n", __func__,
-			sdio_al_dev->host->index);
-}
-
-void sdio_al_unregister_lpm_cb(void *device_handle)
-{
-	struct sdio_al_device *sdio_al_dev =
-		(struct sdio_al_device *) device_handle;
-
-	if (!sdio_al_dev) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - "
-				"device_handle is NULL\n", __func__);
-		return;
-	}
-
-	sdio_al_dev->lpm_callback = NULL;
-	LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - device %d "
-		"unregister for wakeup callback\n", __func__,
-		sdio_al_dev->host->index);
-}
-
-static void sdio_al_vote_for_sleep(struct sdio_al_device *sdio_al_dev,
-				   int is_vote_for_sleep)
-{
-	pr_debug(MODULE_NAME ": %s()", __func__);
-
-	if (!sdio_al_dev) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - sdio_al_dev"
-				" is NULL\n", __func__);
-		return;
-	}
-
-	if (is_vote_for_sleep) {
-		pr_debug(MODULE_NAME ": %s - sdio vote for Sleep", __func__);
-		wake_unlock(&sdio_al_dev->wake_lock);
-	} else {
-		pr_debug(MODULE_NAME ": %s - sdio vote against sleep",
-			  __func__);
-		wake_lock(&sdio_al_dev->wake_lock);
-	}
-
-	if (sdio_al_dev->lpm_callback != NULL) {
-		LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": %s - "
-				"is_vote_for_sleep=%d for card#%d, "
-				"calling callback...", __func__,
-				is_vote_for_sleep,
-				sdio_al_dev->host->index);
-		sdio_al_dev->lpm_callback((void *)sdio_al_dev,
-					   is_vote_for_sleep);
-	}
-}
-
-/**
- *  Write SDIO-Client lpm information
- *  Should only be called with host claimed.
- */
-static int write_lpm_info(struct sdio_al_device *sdio_al_dev)
-{
-	struct sdio_func *lpm_func = NULL;
-	int offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
-		sizeof(struct peer_sdioc_channel_config) *
-		sdio_al_dev->lpm_chan+
-		offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
-	int ret;
-
-	if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
-				"lpm_chan for card %d\n",
-				sdio_al_dev->host->index);
-		return -EINVAL;
-	}
-
-	if (!sdio_al_dev->card ||
-		!sdio_al_dev->card->sdio_func[sdio_al_dev->lpm_chan+1]) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": NULL card or lpm_func\n");
-		return -ENODEV;
-	}
-	lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->lpm_chan+1];
-
-	pr_debug(MODULE_NAME ":write_lpm_info is_ok_to_sleep=%d, device %d\n",
-		 sdio_al_dev->is_ok_to_sleep,
-		 sdio_al_dev->host->index);
-
-	ret = sdio_memcpy_toio(lpm_func, SDIOC_SW_MAILBOX_ADDR+offset,
-				&sdio_al_dev->is_ok_to_sleep, sizeof(u32));
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
-				"write lpm info for card %d\n",
-				sdio_al_dev->host->index);
-		return ret;
-	}
-
-	return 0;
-}
-
-/* Set inactivity counter to intial value to allow clients come up */
-static inline void start_inactive_time(struct sdio_al_device *sdio_al_dev)
-{
-	sdio_al_dev->inactivity_time = jiffies +
-		msecs_to_jiffies(INITIAL_INACTIVITY_TIME_MSEC);
-}
-
-static inline void restart_inactive_time(struct sdio_al_device *sdio_al_dev)
-{
-	sdio_al_dev->inactivity_time = jiffies +
-		msecs_to_jiffies(INACTIVITY_TIME_MSEC);
-}
-
-static inline int is_inactive_time_expired(struct sdio_al_device *sdio_al_dev)
-{
-	return time_after(jiffies, sdio_al_dev->inactivity_time);
-}
-
-
-static int is_user_irq_enabled(struct sdio_al_device *sdio_al_dev,
-			       int func_num)
-{
-	int ret = 0;
-	struct sdio_func *func1;
-	u32 user_irq = 0;
-	u32 addr = 0;
-	u32 offset = 0;
-	u32 masked_user_irq = 0;
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return 0;
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	if (func_num < 4) {
-		addr = FUNC_1_4_USER_IRQ_ADDR;
-		offset = func_num * 8;
-	} else {
-		addr = FUNC_5_7_USER_IRQ_ADDR;
-		offset = (func_num - 4) * 8;
-	}
-
-	user_irq = sdio_readl(func1, addr, &ret);
-	if (ret) {
-		pr_debug(MODULE_NAME ":read_user_irq fail\n");
-		return 0;
-	}
-
-	masked_user_irq = (user_irq >> offset) && 0xFF;
-	if (masked_user_irq == 0x1) {
-		sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":user_irq "
-				"enabled\n");
-		return 1;
-	}
-
-	return 0;
-}
-
-static void sdio_al_sleep(struct sdio_al_device *sdio_al_dev,
-			  struct mmc_host *host)
-{
-	int i;
-
-	/* Go to sleep */
-	pr_debug(MODULE_NAME  ":Inactivity timer expired."
-		" Going to sleep\n");
-	/* Stop mailbox timer */
-	stop_and_del_timer(sdio_al_dev);
-	/* Make sure we get interrupt for non-packet-mode right away */
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		struct sdio_channel *ch = &sdio_al_dev->channel[i];
-		if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
-		    (ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
-			pr_debug(MODULE_NAME  ":continue for channel %s in"
-					" state %d\n", ch->name, ch->state);
-			continue;
-		}
-		if (ch->is_packet_mode == false) {
-			ch->read_threshold = LOW_LATENCY_THRESHOLD;
-			set_pipe_threshold(sdio_al_dev,
-					   ch->rx_pipe_index,
-					   ch->read_threshold);
-		}
-	}
-	/* Prevent modem to go to sleep until we get the PROG_DONE on
-	   the dummy CMD52 */
-	msmsdcc_set_pwrsave(sdio_al_dev->host, 0);
-	/* Mark HOST_OK_TOSLEEP */
-	sdio_al_dev->is_ok_to_sleep = 1;
-	write_lpm_info(sdio_al_dev);
-
-	msmsdcc_lpm_enable(host);
-	LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Finished sleep sequence"
-			" for card %d. Sleep now.\n",
-		sdio_al_dev->host->index);
-	/* Release wakelock */
-	sdio_al_vote_for_sleep(sdio_al_dev, 1);
-}
-
-
-/**
- *  Read SDIO-Client Mailbox from Function#1.thresh_pipe
- *
- *  The mailbox contain the bytes available per pipe,
- *  and the End-Of-Transfer indication per pipe (if available).
- *
- * WARNING: Each time the Mailbox is read from the client, the
- * read_bytes_avail is incremented with another pending
- * transfer. Therefore, a pending rx-packet should be added to a
- * list before the next read of the mailbox.
- *
- * This function should run from a workqueue context since it
- * notifies the clients.
- *
- * This function assumes that sdio_al_claim_mutex was called before
- * calling it.
- *
- */
-static int read_mailbox(struct sdio_al_device *sdio_al_dev, int from_isr)
-{
-	int ret;
-	struct sdio_func *func1 = NULL;
-	struct sdio_mailbox *mailbox = sdio_al_dev->mailbox;
-	struct mmc_host *host = sdio_al_dev->host;
-	u32 new_write_avail = 0;
-	u32 old_write_avail = 0;
-	u32 any_read_avail = 0;
-	u32 any_write_pending = 0;
-	int i;
-	u32 rx_notify_bitmask = 0;
-	u32 tx_notify_bitmask = 0;
-	u32 eot_pipe = 0;
-	u32 thresh_pipe = 0;
-	u32 overflow_pipe = 0;
-	u32 underflow_pipe = 0;
-	u32 thresh_intr_mask = 0;
-	int is_closing = 0;
-
-	if (sdio_al_dev->is_err) {
-		SDIO_AL_ERR(__func__);
-		return 0;
-	}
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	pr_debug(MODULE_NAME ":start %s from_isr = %d for card %d.\n"
-		 , __func__, from_isr, sdio_al_dev->host->index);
-
-	pr_debug(MODULE_NAME ":before sdio_memcpy_fromio.\n");
-	memset(mailbox, 0, sizeof(struct sdio_mailbox));
-	ret = sdio_memcpy_fromio(func1, mailbox,
-			HW_MAILBOX_ADDR, sizeof(*mailbox));
-	pr_debug(MODULE_NAME ":after sdio_memcpy_fromio.\n");
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to read "
-				"Mailbox for card %d, goto error state\n",
-				sdio_al_dev->host->index);
-		sdio_al_get_into_err_state(sdio_al_dev);
-		goto exit_err;
-	}
-
-	eot_pipe =	(mailbox->eot_pipe_0_7) |
-			(mailbox->eot_pipe_8_15<<8);
-	thresh_pipe = 	(mailbox->thresh_above_limit_pipe_0_7) |
-			(mailbox->thresh_above_limit_pipe_8_15<<8);
-
-	overflow_pipe = (mailbox->overflow_pipe_0_7) |
-			(mailbox->overflow_pipe_8_15<<8);
-	underflow_pipe = mailbox->underflow_pipe_0_7 |
-			(mailbox->underflow_pipe_8_15<<8);
-	thresh_intr_mask =
-		(mailbox->mask_thresh_above_limit_pipe_0_7) |
-		(mailbox->mask_thresh_above_limit_pipe_8_15<<8);
-
-	if (overflow_pipe || underflow_pipe)
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Mailbox ERROR "
-				"overflow=0x%x, underflow=0x%x\n",
-				overflow_pipe, underflow_pipe);
-
-	/* In case of modem reset we would like to read the daya from the modem
-	   to clear the interrupts but do not process it */
-	if (sdio_al_dev->state != CARD_INSERTED) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_device"
-				" (card %d) is in invalid state %d\n",
-				sdio_al_dev->host->index,
-				sdio_al_dev->state);
-		return -ENODEV;
-	}
-
-	pr_debug(MODULE_NAME ":card %d: eot=0x%x, thresh=0x%x\n",
-			sdio_al_dev->host->index,
-			eot_pipe, thresh_pipe);
-
-	/* Scan for Rx Packets available and update read available bytes */
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		struct sdio_channel *ch = &sdio_al_dev->channel[i];
-		u32 old_read_avail;
-		u32 read_avail;
-		u32 new_packet_size = 0;
-
-		if (ch->state == SDIO_CHANNEL_STATE_CLOSING)
-			is_closing = true; /* used to prevent sleep */
-
-		old_read_avail = ch->read_avail;
-		read_avail = mailbox->pipe_bytes_avail[ch->rx_pipe_index];
-
-		if ((ch->state == SDIO_CHANNEL_STATE_CLOSED) &&
-			(read_avail > 0)) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				 ":%s: Invalid read_avail 0x%x, for CLOSED ch %s\n",
-				 __func__, read_avail, ch->name);
-			sdio_read_from_closed_ch(ch, read_avail);
-		}
-		if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
-		    (ch->state != SDIO_CHANNEL_STATE_CLOSING))
-			continue;
-
-		if (read_avail > INVALID_DATA_AVAILABLE) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				 ":Invalid read_avail 0x%x for pipe %d\n",
-				 read_avail, ch->rx_pipe_index);
-			continue;
-		}
-		any_read_avail |= read_avail | old_read_avail;
-		ch->statistics.last_any_read_avail = any_read_avail;
-		ch->statistics.last_read_avail = read_avail;
-		ch->statistics.last_old_read_avail = old_read_avail;
-
-		if (ch->is_packet_mode) {
-			if ((eot_pipe & (1<<ch->rx_pipe_index)) &&
-			    sdio_al_dev->print_after_interrupt) {
-				LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
-					":Interrupt on ch %s, "
-					"card %d", ch->name,
-					sdio_al_dev->host->index);
-			}
-			new_packet_size = check_pending_rx_packet(ch, eot_pipe);
-		} else {
-			if ((thresh_pipe & (1<<ch->rx_pipe_index)) &&
-			    sdio_al_dev->print_after_interrupt) {
-				LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME
-					":Interrupt on ch %s, "
-					"card %d", ch->name,
-					sdio_al_dev->host->index);
-			}
-			ch->read_avail = read_avail;
-
-			/*
-			 * Restore default thresh for non packet channels.
-			 * in case it IS low latency channel then read_threshold
-			 * and def_read_threshold are both
-			 * LOW_LATENCY_THRESHOLD
-			 */
-			if ((ch->read_threshold != ch->def_read_threshold) &&
-			    (read_avail >= ch->threshold_change_cnt)) {
-				if (!ch->is_low_latency_ch) {
-					ch->read_threshold =
-						ch->def_read_threshold;
-					set_pipe_threshold(sdio_al_dev,
-							   ch->rx_pipe_index,
-							   ch->read_threshold);
-				}
-			}
-		}
-
-		if ((ch->is_packet_mode) && (new_packet_size > 0)) {
-			rx_notify_bitmask |= (1<<ch->num);
-			ch->statistics.total_notifs++;
-		}
-
-		if ((!ch->is_packet_mode) && (ch->read_avail > 0) &&
-		    (old_read_avail == 0)) {
-			rx_notify_bitmask |= (1<<ch->num);
-			ch->statistics.total_notifs++;
-		}
-	}
-	sdio_al_dev->print_after_interrupt = 0;
-
-	/* Update Write available */
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		struct sdio_channel *ch = &sdio_al_dev->channel[i];
-
-		if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
-		    (ch->state != SDIO_CHANNEL_STATE_CLOSING))
-			continue;
-
-		new_write_avail = mailbox->pipe_bytes_avail[ch->tx_pipe_index];
-
-		if (new_write_avail > INVALID_DATA_AVAILABLE) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				 ":Invalid write_avail 0x%x for pipe %d\n",
-				 new_write_avail, ch->tx_pipe_index);
-			continue;
-		}
-
-		old_write_avail = ch->write_avail;
-		ch->write_avail = new_write_avail;
-
-		if ((old_write_avail <= ch->min_write_avail) &&
-			(new_write_avail >= ch->min_write_avail))
-			tx_notify_bitmask |= (1<<ch->num);
-
-		/* There is not enough write avail for this channel.
-		   We need to keep reading mailbox to wait for the appropriate
-		   write avail and cannot sleep. Ignore SMEM channel that has
-		   only one direction. */
-		if (strncmp(ch->name, "SDIO_SMEM", CHANNEL_NAME_SIZE))
-			any_write_pending |=
-			(new_write_avail < ch->ch_config.max_tx_threshold);
-	}
-	/* notify clients */
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		struct sdio_channel *ch = &sdio_al_dev->channel[i];
-
-		if ((ch->state != SDIO_CHANNEL_STATE_OPEN) ||
-				(ch->notify == NULL))
-			continue;
-
-		if (rx_notify_bitmask & (1<<ch->num))
-			ch->notify(ch->priv,
-					   SDIO_EVENT_DATA_READ_AVAIL);
-
-		if (tx_notify_bitmask & (1<<ch->num))
-			ch->notify(ch->priv,
-					   SDIO_EVENT_DATA_WRITE_AVAIL);
-	}
-
-
-	if ((rx_notify_bitmask == 0) && (tx_notify_bitmask == 0) &&
-	    !any_read_avail && !any_write_pending) {
-		DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Nothing to "
-				"Notify for card %d, is_closing=%d\n",
-				sdio_al_dev->host->index, is_closing);
-		if (is_closing)
-			restart_inactive_time(sdio_al_dev);
-		else if (is_inactive_time_expired(sdio_al_dev))
-			sdio_al_sleep(sdio_al_dev, host);
-	} else {
-		DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":Notify bitmask"
-				" for card %d rx=0x%x, tx=0x%x.\n",
-				sdio_al_dev->host->index,
-				rx_notify_bitmask, tx_notify_bitmask);
-		/* Restart inactivity timer if any activity on the channel */
-		restart_inactive_time(sdio_al_dev);
-	}
-
-	pr_debug(MODULE_NAME ":end %s.\n", __func__);
-
-exit_err:
-	return ret;
-}
-
-/**
- *  Check pending rx packet when reading the mailbox.
- */
-static u32 check_pending_rx_packet(struct sdio_channel *ch, u32 eot)
-{
-	u32 rx_pending;
-	u32 rx_avail;
-	u32 new_packet_size = 0;
-	struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
-
-
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
-				" for channel %s\n", ch->name);
-		return -EINVAL;
-	}
-
-	mutex_lock(&ch->ch_lock);
-
-	rx_pending = ch->rx_pending_bytes;
-	rx_avail = sdio_al_dev->mailbox->pipe_bytes_avail[ch->rx_pipe_index];
-
-	pr_debug(MODULE_NAME ":pipe %d of card %d rx_avail=0x%x, "
-			     "rx_pending=0x%x\n",
-	   ch->rx_pipe_index, sdio_al_dev->host->index, rx_avail,
-		 rx_pending);
-
-
-	/* new packet detected */
-	if (eot & (1<<ch->rx_pipe_index)) {
-		struct rx_packet_size *p = NULL;
-		new_packet_size = rx_avail - rx_pending;
-
-		if ((rx_avail <= rx_pending)) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": Invalid new packet size."
-					" rx_avail=%d.\n", rx_avail);
-			new_packet_size = 0;
-			goto exit_err;
-		}
-
-		p = kzalloc(sizeof(*p), GFP_KERNEL);
-		if (p == NULL) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": failed to allocate item for "
-					"rx_pending list. rx_avail=%d, "
-					"rx_pending=%d.\n",
-					rx_avail, rx_pending);
-			new_packet_size = 0;
-			goto exit_err;
-		}
-		p->size = new_packet_size;
-		/* Add new packet as last */
-		list_add_tail(&p->list, &ch->rx_size_list_head);
-		ch->rx_pending_bytes += new_packet_size;
-
-		if (ch->read_avail == 0)
-			ch->read_avail = new_packet_size;
-	}
-
-exit_err:
-	mutex_unlock(&ch->ch_lock);
-
-	return new_packet_size;
-}
-
-
-
-/**
- *  Remove first pending packet from the list.
- */
-static u32 remove_handled_rx_packet(struct sdio_channel *ch)
-{
-	struct rx_packet_size *p = NULL;
-
-	mutex_lock(&ch->ch_lock);
-
-	ch->rx_pending_bytes -= ch->read_avail;
-
-	if (!list_empty(&ch->rx_size_list_head)) {
-		p = list_first_entry(&ch->rx_size_list_head,
-			struct rx_packet_size, list);
-		list_del(&p->list);
-		kfree(p);
-	} else {
-		sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: ch "
-				"%s: unexpected empty list!!\n",
-				__func__, ch->name);
-	}
-
-	if (list_empty(&ch->rx_size_list_head))	{
-		ch->read_avail = 0;
-	} else {
-		p = list_first_entry(&ch->rx_size_list_head,
-			struct rx_packet_size, list);
-		ch->read_avail = p->size;
-	}
-
-	mutex_unlock(&ch->ch_lock);
-
-	return ch->read_avail;
-}
-
-
-/**
- *  Bootloader worker function.
- *
- *  @note: clear the bootloader_done flag only after reading the
- *  mailbox, to ignore more requests while reading the mailbox.
- */
-static void boot_worker(struct work_struct *work)
-{
-	int ret = 0;
-	int func_num = 0;
-	int i;
-	struct sdio_al_device *sdio_al_dev = NULL;
-	struct sdio_al_work *sdio_al_work = container_of(work,
-							 struct sdio_al_work,
-							 work);
-
-	if (sdio_al_work == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-				"sdio_al_work\n", __func__);
-		return;
-	}
-
-	sdio_al_dev = sdio_al_work->sdio_al_dev;
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-				"sdio_al_dev\n", __func__);
-		return;
-	}
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Bootloader Worker Started"
-			", wait for bootloader_done event..\n");
-	wait_event(sdio_al_dev->wait_mbox,
-		   sdio_al_dev->bootloader_done);
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":Got bootloader_done "
-			"event..\n");
-	/* Do polling until MDM is up */
-	for (i = 0; i < 5000; ++i) {
-		if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-			return;
-		if (is_user_irq_enabled(sdio_al_dev, func_num)) {
-			sdio_al_release_mutex(sdio_al_dev, __func__);
-			sdio_al_dev->bootloader_done = 0;
-			ret = sdio_al_client_setup(sdio_al_dev);
-			if (ret) {
-				sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": sdio_al_client_setup failed, "
-					"for card %d ret=%d\n",
-					sdio_al_dev->host->index, ret);
-				sdio_al_get_into_err_state(sdio_al_dev);
-			}
-			goto done;
-		}
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		msleep(100);
-	}
-	sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Timeout waiting for "
-			"user_irq for card %d\n",
-			sdio_al_dev->host->index);
-	sdio_al_get_into_err_state(sdio_al_dev);
-
-done:
-	pr_debug(MODULE_NAME ":Boot Worker for card %d Exit!\n",
-		sdio_al_dev->host->index);
-}
-
-/**
- *  Worker function.
- *
- *  @note: clear the ask_mbox flag only after
- *  	 reading the mailbox, to ignore more requests while
- *  	 reading the mailbox.
- */
-static void worker(struct work_struct *work)
-{
-	int ret = 0;
-	struct sdio_al_device *sdio_al_dev = NULL;
-	struct sdio_al_work *sdio_al_work = container_of(work,
-							 struct sdio_al_work,
-							 work);
-	if (sdio_al_work == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
-				"sdio_al_work\n");
-		return;
-	}
-
-	sdio_al_dev = sdio_al_work->sdio_al_dev;
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": worker: NULL "
-				"sdio_al_dev\n");
-		return;
-	}
-	pr_debug(MODULE_NAME ":Worker Started..\n");
-	while ((sdio_al_dev->is_ready) && (ret == 0)) {
-		pr_debug(MODULE_NAME ":Wait for read mailbox request..\n");
-		wait_event(sdio_al_dev->wait_mbox, sdio_al_dev->ask_mbox);
-		if (!sdio_al_dev->is_ready)
-			break;
-		if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-			break;
-		if (sdio_al_dev->is_ok_to_sleep) {
-			ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
-			if (ret) {
-				sdio_al_release_mutex(sdio_al_dev, __func__);
-				return;
-			}
-		}
-		ret = read_mailbox(sdio_al_dev, false);
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		sdio_al_dev->ask_mbox = false;
-	}
-
-	pr_debug(MODULE_NAME ":Worker Exit!\n");
-}
-
-/**
- *  Write command using CMD54 rather than CMD53.
- *  Writing with CMD54 generate EOT interrupt at the
- *  SDIO-Client.
- *  Based on mmc_io_rw_extended()
- */
-static int sdio_write_cmd54(struct mmc_card *card, unsigned fn,
-	unsigned addr, const u8 *buf,
-	unsigned blocks, unsigned blksz)
-{
-	struct mmc_request mrq;
-	struct mmc_command cmd;
-	struct mmc_data data;
-	struct scatterlist sg;
-	int incr_addr = 1; /* MUST */
-	int write = 1;
-
-	BUG_ON(!card);
-	BUG_ON(fn > 7);
-	BUG_ON(blocks == 1 && blksz > 512);
-	WARN_ON(blocks == 0);
-	WARN_ON(blksz == 0);
-
-	write = true;
-	pr_debug(MODULE_NAME ":sdio_write_cmd54()"
-		"fn=%d,buf=0x%x,blocks=%d,blksz=%d\n",
-		fn, (u32) buf, blocks, blksz);
-
-	memset(&mrq, 0, sizeof(struct mmc_request));
-	memset(&cmd, 0, sizeof(struct mmc_command));
-	memset(&data, 0, sizeof(struct mmc_data));
-
-	mrq.cmd = &cmd;
-	mrq.data = &data;
-
-	cmd.opcode = SD_IO_RW_EXTENDED_QCOM;
-
-	cmd.arg = write ? 0x80000000 : 0x00000000;
-	cmd.arg |= fn << 28;
-	cmd.arg |= incr_addr ? 0x04000000 : 0x00000000;
-	cmd.arg |= addr << 9;
-	if (blocks == 1 && blksz <= 512)
-		cmd.arg |= (blksz == 512) ? 0 : blksz;  /* byte mode */
-	else
-		cmd.arg |= 0x08000000 | blocks; 	/* block mode */
-	cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
-
-	data.blksz = blksz;
-	data.blocks = blocks;
-	data.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
-	data.sg = &sg;
-	data.sg_len = 1;
-
-	sg_init_one(&sg, buf, blksz * blocks);
-
-	mmc_set_data_timeout(&data, card);
-
-	mmc_wait_for_req(card->host, &mrq);
-
-	if (cmd.error)
-		return cmd.error;
-	if (data.error)
-		return data.error;
-
-	if (mmc_host_is_spi(card->host)) {
-		/* host driver already reported errors */
-	} else {
-		if (cmd.resp[0] & R5_ERROR) {
-			sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
-						":%s: R5_ERROR for card %d",
-						__func__, card->host->index);
-			return -EIO;
-		}
-		if (cmd.resp[0] & R5_FUNCTION_NUMBER) {
-			sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
-						":%s: R5_FUNCTION_NUMBER for card %d",
-						__func__, card->host->index);
-			return -EINVAL;
-		}
-		if (cmd.resp[0] & R5_OUT_OF_RANGE) {
-			sdio_al_loge(&sdio_al->gen_log, MODULE_NAME
-						":%s: R5_OUT_OF_RANGE for card %d",
-						__func__, card->host->index);
-			return -ERANGE;
-		}
-	}
-
-	return 0;
-}
-
-
-/**
- *  Write data to channel.
- *  Handle different data size types.
- *
- */
-static int sdio_ch_write(struct sdio_channel *ch, const u8 *buf, u32 len)
-{
-	int ret = 0;
-	unsigned blksz = ch->func->cur_blksize;
-	int blocks = len / blksz;
-	int remain_bytes = len % blksz;
-	struct mmc_card *card = NULL;
-	u32 fn = ch->func->num;
-
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-				"channel\n", __func__);
-		return -ENODEV;
-	}
-
-	if (!ch->sdio_al_dev) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-				"sdio_al_dev\n", __func__);
-		return -ENODEV;
-	}
-
-	if (len == 0) {
-		sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":channel "
-				"%s trying to write 0 bytes\n", ch->name);
-		return -EINVAL;
-	}
-
-	card = ch->func->card;
-
-	if (remain_bytes) {
-		/* CMD53 */
-		if (blocks) {
-			ret = sdio_memcpy_toio(ch->func, PIPE_TX_FIFO_ADDR,
-					       (void *) buf, blocks*blksz);
-			if (ret != 0) {
-				sdio_al_loge(ch->sdio_al_dev->dev_log,
-					MODULE_NAME ":%s: sdio_memcpy_toio "
-					"failed for channel %s\n",
-					__func__, ch->name);
-				sdio_al_get_into_err_state(ch->sdio_al_dev);
-				return ret;
-			}
-		}
-
-		buf += (blocks*blksz);
-
-		ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
-				buf, 1, remain_bytes);
-	} else {
-		ret = sdio_write_cmd54(card, fn, PIPE_TX_FIFO_ADDR,
-				buf, blocks, blksz);
-	}
-
-	if (ret != 0) {
-		sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
-				"sdio_write_cmd54 failed for channel %s\n",
-				__func__, ch->name);
-		ch->sdio_al_dev->is_err = true;
-		return ret;
-	}
-
-	return ret;
-}
-
-static int sdio_al_bootloader_completed(void)
-{
-	int i;
-
-	pr_debug(MODULE_NAME ":sdio_al_bootloader_completed was called\n");
-
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
-		struct sdio_al_device *dev = NULL;
-		if (sdio_al->devices[i] == NULL)
-			continue;
-		dev = sdio_al->devices[i];
-		dev->bootloader_done = 1;
-		wake_up(&dev->wait_mbox);
-	}
-
-	return 0;
-}
-
-static int sdio_al_wait_for_bootloader_comp(struct sdio_al_device *sdio_al_dev)
-{
-	int ret = 0;
-
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	/*
-	 * Enable function 0 interrupt mask to allow 9k to raise this interrupt
-	 * in power-up. When sdio_downloader will notify its completion
-	 * we will poll on this interrupt to wait for 9k power-up
-	 */
-	ret = enable_mask_irq(sdio_al_dev, 0, 1, 0);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": Enable_mask_irq for card %d failed, "
-				"ret=%d\n",
-				sdio_al_dev->host->index, ret);
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		return ret;
-	}
-
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-
-	/*
-	 * Start bootloader worker that will wait for the bootloader
-	 * completion
-	 */
-	sdio_al_dev->boot_work.sdio_al_dev = sdio_al_dev;
-	INIT_WORK(&sdio_al_dev->boot_work.work, boot_worker);
-	sdio_al_dev->bootloader_done = 0;
-	queue_work(sdio_al_dev->workqueue, &sdio_al_dev->boot_work.work);
-
-	return 0;
-}
-
-static int sdio_al_bootloader_setup(void)
-{
-	int ret = 0;
-	struct sdio_al_device *bootloader_dev = sdio_al->bootloader_dev;
-	struct sdio_func *func1 = NULL;
-
-	if (sdio_al_claim_mutex_and_verify_dev(bootloader_dev, __func__))
-		return -ENODEV;
-
-	if (bootloader_dev->flashless_boot_on) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":Already "
-			"in boot process.\n");
-		sdio_al_release_mutex(bootloader_dev, __func__);
-		return 0;
-	}
-
-	bootloader_dev->sdioc_boot_sw_header
-		= kzalloc(sizeof(*bootloader_dev->sdioc_boot_sw_header),
-			  GFP_KERNEL);
-	if (bootloader_dev->sdioc_boot_sw_header == NULL) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
-			"allocate sdioc boot sw header.\n");
-		sdio_al_release_mutex(bootloader_dev, __func__);
-		return -ENOMEM;
-	}
-
-	if (sdio_al_verify_func1(bootloader_dev, __func__)) {
-		sdio_al_release_mutex(bootloader_dev, __func__);
-		goto exit_err;
-	}
-	func1 = bootloader_dev->card->sdio_func[0];
-
-	ret = sdio_memcpy_fromio(func1,
-				 bootloader_dev->sdioc_boot_sw_header,
-				 SDIOC_SW_HEADER_ADDR,
-				 sizeof(struct peer_sdioc_boot_sw_header));
-	if (ret) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":fail to "
-			"read sdioc boot sw header.\n");
-		sdio_al_release_mutex(bootloader_dev, __func__);
-		goto exit_err;
-	}
-
-	if (bootloader_dev->sdioc_boot_sw_header->signature !=
-	    (u32) PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ":invalid "
-			"mailbox signature 0x%x.\n",
-			bootloader_dev->sdioc_boot_sw_header->signature);
-		sdio_al_release_mutex(bootloader_dev, __func__);
-		ret = -EINVAL;
-		goto exit_err;
-	}
-
-	/* Upper byte has to be equal - no backward compatibility for unequal */
-	if ((bootloader_dev->sdioc_boot_sw_header->version >> 16) !=
-	    (sdio_al->pdata->peer_sdioc_boot_version_major)) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME ": HOST(0x%x)"
-			" and CLIENT(0x%x) SDIO_AL BOOT VERSION don't match\n",
-			((sdio_al->pdata->peer_sdioc_boot_version_major<<16)+
-			sdio_al->pdata->peer_sdioc_boot_version_minor),
-			bootloader_dev->sdioc_boot_sw_header->version);
-		sdio_al_release_mutex(bootloader_dev, __func__);
-		ret = -EIO;
-		goto exit_err;
-	}
-
-	sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ": SDIOC BOOT SW "
-			"version 0x%x\n",
-			bootloader_dev->sdioc_boot_sw_header->version);
-
-	bootloader_dev->flashless_boot_on = true;
-
-	sdio_al_release_mutex(bootloader_dev, __func__);
-
-	ret = sdio_al_wait_for_bootloader_comp(bootloader_dev);
-	if (ret) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
-				": sdio_al_wait_for_bootloader_comp failed, "
-				"err=%d\n", ret);
-		goto exit_err;
-	}
-
-	ret = sdio_downloader_setup(bootloader_dev->card, 1,
-			bootloader_dev->sdioc_boot_sw_header->boot_ch_num,
-			sdio_al_bootloader_completed);
-
-	if (ret) {
-		sdio_al_loge(bootloader_dev->dev_log, MODULE_NAME
-			": sdio_downloader_setup failed, err=%d\n", ret);
-		goto exit_err;
-	}
-
-	sdio_al_logi(bootloader_dev->dev_log, MODULE_NAME ":In Flashless boot,"
-		" waiting for its completion\n");
-
-
-exit_err:
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":free "
-			"sdioc_boot_sw_header.\n");
-	kfree(bootloader_dev->sdioc_boot_sw_header);
-	bootloader_dev->sdioc_boot_sw_header = NULL;
-	bootloader_dev = NULL;
-
-	return ret;
-}
-
-
-/**
- *  Read SDIO-Client software header
- *
- */
-static int read_sdioc_software_header(struct sdio_al_device *sdio_al_dev,
-				      struct peer_sdioc_sw_header *header)
-{
-	int ret;
-	int i;
-	int test_version = 0;
-	int sdioc_test_version = 0;
-	struct sdio_func *func1 = NULL;
-
-	pr_debug(MODULE_NAME ":reading sdioc sw header.\n");
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	ret = sdio_memcpy_fromio(func1, header,
-			SDIOC_SW_HEADER_ADDR, sizeof(*header));
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
-				"sdioc sw header.\n");
-		goto exit_err;
-	}
-
-	if (header->signature == (u32)PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE) {
-		sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
-				"unittest signature. 0x%x\n",
-				header->signature);
-		sdio_al->unittest_mode = true;
-		/* Verify test code compatibility with the modem */
-		sdioc_test_version = (header->version & 0xFF00) >> 8;
-		test_version = sdio_al->pdata->peer_sdioc_version_minor >> 8;
-		if (test_version != sdioc_test_version) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": HOST(0x%x) and CLIENT(0x%x) "
-				"testing VERSION don't match\n",
-				test_version,
-				sdioc_test_version);
-			msleep(500);
-			BUG();
-		}
-	}
-
-	if ((header->signature != (u32) PEER_SDIOC_SW_MAILBOX_SIGNATURE) &&
-	    (header->signature != (u32) PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE)) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW "
-				"invalid signature. 0x%x\n", header->signature);
-		goto exit_err;
-	}
-	/* Upper byte has to be equal - no backward compatibility for unequal */
-	sdio_al->sdioc_major = header->version >> 16;
-	if (sdio_al->pdata->allow_sdioc_version_major_2) {
-		if ((sdio_al->sdioc_major !=
-		    sdio_al->pdata->peer_sdioc_version_major) &&
-		    (sdio_al->sdioc_major != PEER_SDIOC_OLD_VERSION_MAJOR)) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": HOST(0x%x) and CLIENT(0x%x) "
-				"SDIO_AL VERSION don't match\n",
-				((sdio_al->pdata->peer_sdioc_version_major<<16)+
-				sdio_al->pdata->peer_sdioc_version_minor),
-				header->version);
-			goto exit_err;
-		}
-	} else {
-		if (sdio_al->sdioc_major !=
-		    sdio_al->pdata->peer_sdioc_version_major) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": HOST(0x%x) and CLIENT(0x%x) "
-				"SDIO_AL VERSION don't match\n",
-				((sdio_al->pdata->peer_sdioc_version_major<<16)+
-				sdio_al->pdata->peer_sdioc_version_minor),
-				header->version);
-			goto exit_err;
-		}
-	}
-	sdio_al_dev->ch_close_supported = (header->version & 0x000F) >=
-		(sdio_al->pdata->peer_sdioc_version_minor & 0xF);
-
-	sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":SDIOC SW version 0x%x,"
-			" sdio_al major 0x%x minor 0x%x\n", header->version,
-			sdio_al->sdioc_major,
-			sdio_al->pdata->peer_sdioc_version_minor);
-
-	sdio_al_dev->flashless_boot_on = false;
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		struct sdio_channel *ch = &sdio_al_dev->channel[i];
-
-		/* Set default values */
-		ch->read_threshold  = DEFAULT_READ_THRESHOLD;
-		ch->write_threshold = DEFAULT_WRITE_THRESHOLD;
-		ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD;
-		ch->is_packet_mode = true;
-		ch->peer_tx_buf_size = DEFAULT_PEER_TX_BUF_SIZE;
-		ch->poll_delay_msec = 0;
-
-		ch->num = i;
-		ch->func = NULL;
-		ch->rx_pipe_index = ch->num*2;
-		ch->tx_pipe_index = ch->num*2+1;
-
-		memset(ch->name, 0, sizeof(ch->name));
-
-		if (header->channel_names[i][0]) {
-			memcpy(ch->name, SDIO_PREFIX,
-			       strlen(SDIO_PREFIX));
-			memcpy(ch->name + strlen(SDIO_PREFIX),
-			       header->channel_names[i],
-			       PEER_CHANNEL_NAME_SIZE);
-
-			ch->state = SDIO_CHANNEL_STATE_IDLE;
-			ch->sdio_al_dev = sdio_al_dev;
-			if (sdio_al_dev->card->sdio_func[ch->num+1]) {
-				ch->func =
-				sdio_al_dev->card->sdio_func[ch->num+1];
-			} else {
-				sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": NULL func for channel %s\n",
-					ch->name);
-				goto exit_err;
-			}
-		} else {
-			ch->state = SDIO_CHANNEL_STATE_INVALID;
-		}
-
-		sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Channel=%s, "
-				"state=%d\n", ch->name,	ch->state);
-	}
-
-	return 0;
-
-exit_err:
-	sdio_al_get_into_err_state(sdio_al_dev);
-	memset(header, 0, sizeof(*header));
-
-	return -EIO;
-}
-
-/**
- *  Read SDIO-Client channel configuration
- *
- */
-static int read_sdioc_channel_config(struct sdio_channel *ch)
-{
-	int ret;
-	struct peer_sdioc_sw_mailbox *sw_mailbox = NULL;
-	struct peer_sdioc_channel_config *ch_config = NULL;
-	struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
-
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL sdio_al_dev"
-				" for channel %s\n", ch->name);
-		return -EINVAL;
-	}
-
-	if (sdio_al_dev->sdioc_sw_header->version == 0)
-		return -1;
-
-	pr_debug(MODULE_NAME ":reading sw mailbox %s channel.\n", ch->name);
-
-	sw_mailbox = kzalloc(sizeof(*sw_mailbox), GFP_KERNEL);
-	if (sw_mailbox == NULL)
-		return -ENOMEM;
-
-	ret = sdio_memcpy_fromio(ch->func, sw_mailbox,
-			SDIOC_SW_MAILBOX_ADDR, sizeof(*sw_mailbox));
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
-				"sw mailbox.\n");
-		goto exit_err;
-	}
-
-	ch_config = &sw_mailbox->ch_config[ch->num];
-	memcpy(&ch->ch_config, ch_config,
-		sizeof(struct peer_sdioc_channel_config));
-
-	if (!ch_config->is_ready) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sw mailbox "
-				"channel not ready.\n");
-		goto exit_err;
-	}
-
-	ch->read_threshold = LOW_LATENCY_THRESHOLD;
-	ch->is_low_latency_ch = ch_config->is_low_latency_ch;
-	/* Threshold on 50% of the maximum size , sdioc uses double-buffer */
-	ch->write_threshold = (ch_config->max_tx_threshold * 5) / 10;
-	ch->threshold_change_cnt = ch->ch_config.max_rx_threshold -
-			ch->read_threshold + THRESHOLD_CHANGE_EXTRA_BYTES;
-
-	if (ch->is_low_latency_ch)
-		ch->def_read_threshold = LOW_LATENCY_THRESHOLD;
-	else /* Aggregation up to 90% of the maximum size */
-		ch->def_read_threshold = (ch_config->max_rx_threshold * 9) / 10;
-
-	ch->is_packet_mode = ch_config->is_packet_mode;
-	if (!ch->is_packet_mode) {
-		ch->poll_delay_msec = DEFAULT_POLL_DELAY_NOPACKET_MSEC;
-		ch->min_write_avail = DEFAULT_MIN_WRITE_THRESHOLD_STREAMING;
-	}
-	/* The max_packet_size is set by the modem in version 3 and on */
-	if (sdio_al->sdioc_major > PEER_SDIOC_OLD_VERSION_MAJOR)
-		ch->min_write_avail = ch_config->max_packet_size;
-
-	if (ch->min_write_avail > ch->write_threshold)
-		ch->min_write_avail = ch->write_threshold;
-
-	CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":ch %s "
-			"read_threshold=%d, write_threshold=%d,"
-			" min_write_avail=%d, max_rx_threshold=%d,"
-			" max_tx_threshold=%d\n", ch->name, ch->read_threshold,
-			ch->write_threshold, ch->min_write_avail,
-			ch_config->max_rx_threshold,
-			ch_config->max_tx_threshold);
-
-	ch->peer_tx_buf_size = ch_config->tx_buf_size;
-
-	kfree(sw_mailbox);
-
-	return 0;
-
-exit_err:
-	sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":Reading SW Mailbox "
-			"error.\n");
-	kfree(sw_mailbox);
-
-	return -1;
-}
-
-
-/**
- *  Enable/Disable EOT interrupt of a pipe.
- *
- */
-static int enable_eot_interrupt(struct sdio_al_device *sdio_al_dev,
-				int pipe_index, int enable)
-{
-	int ret = 0;
-	struct sdio_func *func1;
-	u32 mask;
-	u32 pipe_mask;
-	u32 addr;
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	if (pipe_index < 8) {
-		addr = PIPES_0_7_IRQ_MASK_ADDR;
-		pipe_mask = (1<<pipe_index);
-	} else {
-		addr = PIPES_8_15_IRQ_MASK_ADDR;
-		pipe_mask = (1<<(pipe_index-8));
-	}
-
-	mask = sdio_readl(func1, addr, &ret);
-	if (ret) {
-		pr_debug(MODULE_NAME ":enable_eot_interrupt fail\n");
-		goto exit_err;
-	}
-
-	if (enable)
-		mask &= (~pipe_mask); /* 0 = enable */
-	else
-		mask |= (pipe_mask);  /* 1 = disable */
-
-	sdio_writel(func1, mask, addr, &ret);
-
-exit_err:
-	return ret;
-}
-
-
-/**
- *  Enable/Disable mask interrupt of a function.
- *
- */
-static int enable_mask_irq(struct sdio_al_device *sdio_al_dev,
-			   int func_num, int enable, u8 bit_offset)
-{
-	int ret = 0;
-	struct sdio_func *func1 = NULL;
-	u32 mask = 0;
-	u32 func_mask = 0;
-	u32 addr = 0;
-	u32 offset = 0;
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	if (func_num < 4) {
-		addr = FUNC_1_4_MASK_IRQ_ADDR;
-		offset = func_num * 8 + bit_offset;
-	} else {
-		addr = FUNC_5_7_MASK_IRQ_ADDR;
-		offset = (func_num - 4) * 8 + bit_offset;
-	}
-
-	func_mask = 1<<offset;
-
-	mask = sdio_readl(func1, addr, &ret);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"enable_mask_irq fail\n");
-		goto exit_err;
-	}
-
-	if (enable)
-		mask &= (~func_mask); /* 0 = enable */
-	else
-		mask |= (func_mask);  /* 1 = disable */
-
-	pr_debug(MODULE_NAME ":enable_mask_irq,  writing mask = 0x%x\n", mask);
-
-	sdio_writel(func1, mask, addr, &ret);
-
-exit_err:
-	return ret;
-}
-
-/**
- *  Enable/Disable Threshold interrupt of a pipe.
- *
- */
-static int enable_threshold_interrupt(struct sdio_al_device *sdio_al_dev,
-				      int pipe_index, int enable)
-{
-	int ret = 0;
-	struct sdio_func *func1;
-	u32 mask;
-	u32 pipe_mask;
-	u32 addr;
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	if (pipe_index < 8) {
-		addr = PIPES_0_7_IRQ_MASK_ADDR;
-		pipe_mask = (1<<pipe_index);
-	} else {
-		addr = PIPES_8_15_IRQ_MASK_ADDR;
-		pipe_mask = (1<<(pipe_index-8));
-	}
-
-	mask = sdio_readl(func1, addr, &ret);
-	if (ret) {
-		pr_debug(MODULE_NAME ":enable_threshold_interrupt fail\n");
-		goto exit_err;
-	}
-
-	pipe_mask = pipe_mask<<8; /* Threshold bits 8..15 */
-	if (enable)
-		mask &= (~pipe_mask); /* 0 = enable */
-	else
-		mask |= (pipe_mask);  /* 1 = disable */
-
-	sdio_writel(func1, mask, addr, &ret);
-
-exit_err:
-	return ret;
-}
-
-/**
- *  Set the threshold to trigger interrupt from SDIO-Card on
- *  pipe available bytes.
- *
- */
-static int set_pipe_threshold(struct sdio_al_device *sdio_al_dev,
-			      int pipe_index, int threshold)
-{
-	int ret = 0;
-	struct sdio_func *func1;
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	sdio_writel(func1, threshold,
-			PIPES_THRESHOLD_ADDR+pipe_index*4, &ret);
-	if (ret)
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"set_pipe_threshold err=%d\n", -ret);
-
-	return ret;
-}
-
-/**
- *  Enable func w/ retries
- *
- */
-static int sdio_al_enable_func_retry(struct sdio_func *func, const char *name)
-{
-	int ret, i;
-	for (i = 0; i < 200; i++) {
-		ret = sdio_enable_func(func);
-		if (ret) {
-			pr_debug(MODULE_NAME ":retry enable %s func#%d "
-					     "ret=%d\n",
-					 name, func->num, ret);
-			msleep(10);
-		} else
-			break;
-	}
-
-	return ret;
-}
-
-/**
- *  Open Channel
- *
- *  1. Init Channel Context.
- *  2. Init the Channel SDIO-Function.
- *  3. Init the Channel Pipes on Mailbox.
- */
-static int open_channel(struct sdio_channel *ch)
-{
-	int ret = 0;
-	struct sdio_al_device *sdio_al_dev = ch->sdio_al_dev;
-
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL "
-				"sdio_al_dev for channel %s\n", ch->name);
-		return -EINVAL;
-	}
-
-	/* Init channel Context */
-	/** Func#1 is reserved for mailbox */
-	ch->func = sdio_al_dev->card->sdio_func[ch->num+1];
-	ch->rx_pipe_index = ch->num*2;
-	ch->tx_pipe_index = ch->num*2+1;
-	ch->signature = SDIO_AL_SIGNATURE;
-
-	ch->total_rx_bytes = 0;
-	ch->total_tx_bytes = 0;
-
-	ch->write_avail = 0;
-	ch->read_avail = 0;
-	ch->rx_pending_bytes = 0;
-
-	mutex_init(&ch->ch_lock);
-
-	pr_debug(MODULE_NAME ":open_channel %s func#%d\n",
-			 ch->name, ch->func->num);
-
-	INIT_LIST_HEAD(&(ch->rx_size_list_head));
-
-	/* Init SDIO Function */
-	ret = sdio_al_enable_func_retry(ch->func, ch->name);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"sdio_enable_func() err=%d\n", -ret);
-		goto exit_err;
-	}
-
-	/* Note: Patch Func CIS tuple issue */
-	ret = sdio_set_block_size(ch->func, SDIO_AL_BLOCK_SIZE);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"sdio_set_block_size()failed, err=%d\n", -ret);
-		goto exit_err;
-	}
-
-	ch->func->max_blksize = SDIO_AL_BLOCK_SIZE;
-
-	sdio_set_drvdata(ch->func, ch);
-
-	/* Get channel parameters from the peer SDIO-Client */
-	read_sdioc_channel_config(ch);
-
-	/* Set Pipes Threshold on Mailbox */
-	ret = set_pipe_threshold(sdio_al_dev,
-				 ch->rx_pipe_index, ch->read_threshold);
-	if (ret)
-		goto exit_err;
-	ret = set_pipe_threshold(sdio_al_dev,
-				 ch->tx_pipe_index, ch->write_threshold);
-	if (ret)
-		goto exit_err;
-
-	/* Set flag before interrupts are enabled to allow notify */
-	ch->state = SDIO_CHANNEL_STATE_OPEN;
-	pr_debug(MODULE_NAME ":channel %s is in OPEN state now\n", ch->name);
-
-	sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
-
-	/* lpm mechanism lives under the assumption there is always a timer */
-	/* Check if need to start the timer */
-	if  ((sdio_al_dev->poll_delay_msec) &&
-	     (sdio_al_dev->is_timer_initialized == false)) {
-
-		init_timer(&sdio_al_dev->timer);
-		sdio_al_dev->timer.data = (unsigned long) sdio_al_dev;
-		sdio_al_dev->timer.function = sdio_al_timer_handler;
-		sdio_al_dev->timer.expires = jiffies +
-			msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
-		add_timer(&sdio_al_dev->timer);
-		sdio_al_dev->is_timer_initialized = true;
-	}
-
-	/* Enable Pipes Interrupts */
-	enable_eot_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
-	enable_eot_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
-
-	enable_threshold_interrupt(sdio_al_dev, ch->rx_pipe_index, true);
-	enable_threshold_interrupt(sdio_al_dev, ch->tx_pipe_index, true);
-
-exit_err:
-
-	return ret;
-}
-
-/**
- *  Ask the worker to read the mailbox.
- */
-static void ask_reading_mailbox(struct sdio_al_device *sdio_al_dev)
-{
-	if (!sdio_al_dev->ask_mbox) {
-		pr_debug(MODULE_NAME ":ask_reading_mailbox for card %d\n",
-			 sdio_al_dev->host->index);
-		sdio_al_dev->ask_mbox = true;
-		wake_up(&sdio_al_dev->wait_mbox);
-	}
-}
-
-/**
- *  Start the timer
- */
-static void start_timer(struct sdio_al_device *sdio_al_dev)
-{
-	if ((sdio_al_dev->poll_delay_msec)  &&
-		(sdio_al_dev->state == CARD_INSERTED)) {
-		sdio_al_dev->timer.expires = jiffies +
-			msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
-		add_timer(&sdio_al_dev->timer);
-	}
-}
-
-/**
- *  Restart(postpone) the already working timer
- */
-static void restart_timer(struct sdio_al_device *sdio_al_dev)
-{
-	if ((sdio_al_dev->poll_delay_msec) &&
-		(sdio_al_dev->state == CARD_INSERTED)) {
-		ulong expires =	jiffies +
-			msecs_to_jiffies(sdio_al_dev->poll_delay_msec);
-		mod_timer(&sdio_al_dev->timer, expires);
-	}
-}
-
-/**
- *  Stop and delete the timer
- */
-static void stop_and_del_timer(struct sdio_al_device *sdio_al_dev)
-{
-	if (sdio_al_dev->is_timer_initialized) {
-		sdio_al_dev->poll_delay_msec = 0;
-		del_timer_sync(&sdio_al_dev->timer);
-	}
-}
-
-/**
- *  Do the wakup sequence.
- *  This function should be called after claiming the host!
- *  The caller is responsible for releasing the host.
- *
- *  Wake up sequence
- *  1. Get lock
- *  2. Enable wake up function if needed
- *  3. Mark NOT OK to sleep and write it
- *  4. Restore default thresholds
- *  5. Start the mailbox and inactivity timer again
- */
-static int sdio_al_wake_up(struct sdio_al_device *sdio_al_dev,
-			   u32 not_from_int, struct sdio_channel *ch)
-{
-	int ret = 0;
-	struct sdio_func *wk_func = NULL;
-	unsigned long time_to_wait;
-	struct mmc_host *host = sdio_al_dev->host;
-
-	if (sdio_al_dev->is_err) {
-		SDIO_AL_ERR(__func__);
-		return -ENODEV;
-	}
-
-	if (!sdio_al_dev->is_ok_to_sleep) {
-		LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":card %d "
-				"already awake, no need to wake up\n",
-				sdio_al_dev->host->index);
-		return 0;
-	}
-
-	/* Wake up sequence */
-	if (not_from_int) {
-		if (ch) {
-			LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
-					" card %d (not by interrupt), ch %s",
-					sdio_al_dev->host->index,
-					ch->name);
-		} else {
-			LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up"
-					  " card %d (not	by interrupt)",
-					  sdio_al_dev->host->index);
-		}
-	} else {
-		LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": Wake up card "
-				"%d by interrupt",
-				sdio_al_dev->host->index);
-		sdio_al_dev->print_after_interrupt = 1;
-	}
-
-	sdio_al_vote_for_sleep(sdio_al_dev, 0);
-
-	msmsdcc_lpm_disable(host);
-	msmsdcc_set_pwrsave(host, 0);
-	/* Poll the GPIO */
-	time_to_wait = jiffies + msecs_to_jiffies(1000);
-	while (time_before(jiffies, time_to_wait)) {
-		if (sdio_al->pdata->get_mdm2ap_status())
-			break;
-		udelay(TIME_TO_WAIT_US);
-	}
-
-	pr_debug(MODULE_NAME ":GPIO mdm2ap_status=%d\n",
-		       sdio_al->pdata->get_mdm2ap_status());
-
-	/* Here get_mdm2ap_status() returning 0 is not an error condition */
-	if (sdio_al->pdata->get_mdm2ap_status() == 0)
-		LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"get_mdm2ap_status() is 0\n");
-
-	/* Enable Wake up Function */
-	if (!sdio_al_dev->card ||
-	    !sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1]) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": NULL card or wk_func\n");
-		return -ENODEV;
-	}
-	wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
-	ret = sdio_al_enable_func_retry(wk_func, "wakeup func");
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"sdio_enable_func() err=%d\n", -ret);
-		goto error_exit;
-	}
-	/* Mark NOT OK_TOSLEEP */
-	sdio_al_dev->is_ok_to_sleep = 0;
-	ret = write_lpm_info(sdio_al_dev);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": "
-				"write_lpm_info() failed, err=%d\n", -ret);
-		sdio_al_dev->is_ok_to_sleep = 1;
-		sdio_disable_func(wk_func);
-		goto error_exit;
-	}
-	sdio_disable_func(wk_func);
-
-	/* Start the timer again*/
-	restart_inactive_time(sdio_al_dev);
-	sdio_al_dev->poll_delay_msec = get_min_poll_time_msec(sdio_al_dev);
-	start_timer(sdio_al_dev);
-
-	LPM_DEBUG(sdio_al_dev->dev_log, MODULE_NAME "Finished Wake up sequence"
-			" for card %d", sdio_al_dev->host->index);
-
-	msmsdcc_set_pwrsave(host, 1);
-	pr_debug(MODULE_NAME ":Turn clock off\n");
-
-	return ret;
-error_exit:
-	sdio_al_vote_for_sleep(sdio_al_dev, 1);
-	msmsdcc_set_pwrsave(host, 1);
-	WARN_ON(ret);
-	sdio_al_get_into_err_state(sdio_al_dev);
-	return ret;
-}
-
-
-/**
- *  SDIO Function Interrupt handler.
- *
- *  Interrupt shall be triggered by SDIO-Client when:
- *  1. End-Of-Transfer (EOT) detected in packet mode.
- *  2. Bytes-available reached the threshold.
- *
- *  Reading the mailbox clears the EOT/Threshold interrupt
- *  source.
- *  The interrupt source should be cleared before this ISR
- *  returns. This ISR is called from IRQ Thread and not
- *  interrupt, so it may sleep.
- *
- */
-static void sdio_func_irq(struct sdio_func *func)
-{
-	struct sdio_al_device *sdio_al_dev = sdio_get_drvdata(func);
-
-	pr_debug(MODULE_NAME ":start %s.\n", __func__);
-
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": NULL device");
-		return;
-	}
-
-	if (sdio_al_dev->is_ok_to_sleep)
-		sdio_al_wake_up(sdio_al_dev, 0, NULL);
-	else
-		restart_timer(sdio_al_dev);
-
-	read_mailbox(sdio_al_dev, true);
-
-	pr_debug(MODULE_NAME ":end %s.\n", __func__);
-}
-
-/**
- *  Timer Expire Handler
- *
- */
-static void sdio_al_timer_handler(unsigned long data)
-{
-	struct sdio_al_device *sdio_al_dev = (struct sdio_al_device *)data;
-	if (sdio_al_dev == NULL) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": NULL "
-				"sdio_al_dev for data %lu\n", data);
-		return;
-	}
-	if (sdio_al_dev->state != CARD_INSERTED) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": sdio_al_dev "
-				"is in invalid state %d\n", sdio_al_dev->state);
-		return;
-	}
-	pr_debug(MODULE_NAME " Timer Expired\n");
-
-	ask_reading_mailbox(sdio_al_dev);
-
-	restart_timer(sdio_al_dev);
-}
-
-/**
- *  Driver Setup.
- *
- */
-static int sdio_al_setup(struct sdio_al_device *sdio_al_dev)
-{
-	int ret = 0;
-	struct mmc_card *card = sdio_al_dev->card;
-	struct sdio_func *func1 = NULL;
-	int i = 0;
-	int fn = 0;
-
-	if (sdio_al_verify_func1(sdio_al_dev, __func__))
-		return -ENODEV;
-	func1 = card->sdio_func[0];
-
-	sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":sdio_al_setup for "
-			"card %d\n", sdio_al_dev->host->index);
-
-	ret = sdio_al->pdata->config_mdm2ap_status(1);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME "Could not "
-				"request GPIO\n");
-		return ret;
-	}
-
-	INIT_WORK(&sdio_al_dev->sdio_al_work.work, worker);
-	/* disable all pipes interrupts before claim irq.
-	   since all are enabled by default. */
-	for (i = 0 ; i < SDIO_AL_MAX_PIPES; i++) {
-		enable_eot_interrupt(sdio_al_dev, i, false);
-		enable_threshold_interrupt(sdio_al_dev, i, false);
-	}
-
-	/* Disable all SDIO Functions before claim irq. */
-	for (fn = 1 ; fn <= card->sdio_funcs; fn++)
-		sdio_disable_func(card->sdio_func[fn-1]);
-
-	sdio_set_drvdata(func1, sdio_al_dev);
-	sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":claim IRQ for card "
-			"%d\n",	sdio_al_dev->host->index);
-
-	ret = sdio_claim_irq(func1, sdio_func_irq);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to claim"
-				" IRQ for card %d\n",
-				sdio_al_dev->host->index);
-		return ret;
-	}
-
-	sdio_al_dev->is_ready = true;
-
-	/* Start worker before interrupt might happen */
-	queue_work(sdio_al_dev->workqueue, &sdio_al_dev->sdio_al_work.work);
-
-	start_inactive_time(sdio_al_dev);
-
-	pr_debug(MODULE_NAME ":Ready.\n");
-
-	return 0;
-}
-
-/**
- *  Driver Tear-Down.
- *
- */
-static void sdio_al_tear_down(void)
-{
-	int i, j;
-	struct sdio_al_device *sdio_al_dev = NULL;
-	struct sdio_func *func1;
-
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
-		if (sdio_al->devices[i] == NULL)
-			continue;
-		sdio_al_dev = sdio_al->devices[i];
-
-		if (sdio_al_dev->is_ready) {
-			sdio_al_dev->is_ready = false; /* Flag worker to exit */
-			sdio_al_dev->ask_mbox = false;
-			ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
-			/* allow gracefully exit of the worker thread */
-			msleep(100);
-
-			flush_workqueue(sdio_al_dev->workqueue);
-			destroy_workqueue(sdio_al_dev->workqueue);
-
-			sdio_al_vote_for_sleep(sdio_al_dev, 1);
-
-			if (!sdio_al_claim_mutex_and_verify_dev(sdio_al_dev,
-								__func__)) {
-				if (!sdio_al_dev->card ||
-				    !sdio_al_dev->card->sdio_func[0]) {
-					sdio_al_loge(sdio_al_dev->dev_log,
-						     MODULE_NAME
-							": %s: Invalid func1",
-							__func__);
-					return;
-				}
-				func1 = sdio_al_dev->card->sdio_func[0];
-				sdio_release_irq(func1);
-				sdio_disable_func(func1);
-				sdio_al_release_mutex(sdio_al_dev, __func__);
-			}
-		}
-
-		for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++)
-			sdio_al_dev->channel[j].signature = 0x0;
-		sdio_al_dev->signature = 0;
-
-		kfree(sdio_al_dev->sdioc_sw_header);
-		kfree(sdio_al_dev->mailbox);
-		kfree(sdio_al_dev->rx_flush_buf);
-		kfree(sdio_al_dev);
-	}
-
-	sdio_al->pdata->config_mdm2ap_status(0);
-}
-
-/**
- *  Find channel by name.
- *
- */
-static struct sdio_channel *find_channel_by_name(const char *name)
-{
-	struct sdio_channel *ch = NULL;
-	int i, j;
-	struct sdio_al_device *sdio_al_dev = NULL;
-
-	for (j = 0; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
-		if (sdio_al->devices[j] == NULL)
-			continue;
-		sdio_al_dev = sdio_al->devices[j];
-		for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-			if (sdio_al_dev->channel[i].state ==
-					SDIO_CHANNEL_STATE_INVALID)
-				continue;
-			if (strncmp(sdio_al_dev->channel[i].name, name,
-					CHANNEL_NAME_SIZE) == 0) {
-				ch = &sdio_al_dev->channel[i];
-				break;
-			}
-		}
-		if (ch != NULL)
-			break;
-	}
-
-	return ch;
-}
-
-/**
- *  Find the minimal poll time.
- *
- */
-static int get_min_poll_time_msec(struct sdio_al_device *sdio_sl_dev)
-{
-	int i;
-	int poll_delay_msec = 0x0FFFFFFF;
-
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++)
-		if ((sdio_sl_dev->channel[i].state ==
-					SDIO_CHANNEL_STATE_OPEN) &&
-		(sdio_sl_dev->channel[i].poll_delay_msec > 0) &&
-		(sdio_sl_dev->channel[i].poll_delay_msec < poll_delay_msec))
-			poll_delay_msec =
-				sdio_sl_dev->channel[i].poll_delay_msec;
-
-	if (poll_delay_msec == 0x0FFFFFFF)
-		poll_delay_msec = SDIO_AL_POLL_TIME_NO_STREAMING;
-
-	pr_debug(MODULE_NAME ":poll delay time is %d msec\n", poll_delay_msec);
-
-	return poll_delay_msec;
-}
-
-/**
- *  Open SDIO Channel.
- *
- *  Enable the channel.
- *  Set the channel context.
- *  Trigger reading the mailbox to check available bytes.
- *
- */
-int sdio_open(const char *name, struct sdio_channel **ret_ch, void *priv,
-		 void (*notify)(void *priv, unsigned ch_event))
-{
-	int ret = 0;
-	struct sdio_channel *ch = NULL;
-	struct sdio_al_device *sdio_al_dev = NULL;
-
-	*ret_ch = NULL; /* default */
-
-	ch = find_channel_by_name(name);
-	if (ch == NULL) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":Can't find "
-			"channel name %s\n", name);
-		return -EINVAL;
-	}
-
-	sdio_al_dev = ch->sdio_al_dev;
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	if ((ch->state != SDIO_CHANNEL_STATE_IDLE) &&
-		(ch->state != SDIO_CHANNEL_STATE_CLOSED)) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Wrong ch %s "
-				"state %d\n", name, ch->state);
-		ret = -EPERM;
-		goto exit_err;
-	}
-
-	if (sdio_al_dev->is_err) {
-		SDIO_AL_ERR(__func__);
-		ret = -ENODEV;
-		goto exit_err;
-	}
-
-	ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
-	if (ret)
-		goto exit_err;
-
-	ch->notify = notify;
-	ch->priv = priv;
-
-	/* Note: Set caller returned context before interrupts are enabled */
-	*ret_ch = ch;
-
-	ret = open_channel(ch);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
-				"err=%d\n", name, -ret);
-		goto exit_err;
-	}
-
-	CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":sdio_open %s "
-							"completed OK\n", name);
-	if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
-		if (sdio_al->sdioc_major == PEER_SDIOC_OLD_VERSION_MAJOR) {
-			if (!ch->is_packet_mode) {
-				sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
-						":setting channel %s as "
-						"lpm_chan\n", name);
-				sdio_al_dev->lpm_chan = ch->num;
-			}
-		} else {
-			sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": "
-					"setting channel %s as lpm_chan\n",
-					name);
-			sdio_al_dev->lpm_chan = ch->num;
-		}
-	}
-
-exit_err:
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-	return ret;
-}
-EXPORT_SYMBOL(sdio_open);
-
-/**
- *  Request peer operation
- *  note: sanity checks of parameters done by caller
- *        called under bus locked
- */
-static int peer_set_operation(u32 opcode,
-		struct sdio_al_device *sdio_al_dev,
-		struct sdio_channel *ch)
-{
-	int ret;
-	int offset;
-	struct sdio_func *wk_func = NULL;
-	u32 peer_operation;
-	int loop_count = 0;
-
-	if (!sdio_al_dev->card ||
-	    !sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1]) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": NULL card or wk_func\n");
-		ret = -ENODEV;
-		goto exit;
-	}
-	wk_func = sdio_al_dev->card->sdio_func[SDIO_AL_WAKEUP_FUNC-1];
-
-	/* calculate offset of peer_operation field in sw mailbox struct */
-	offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config) +
-		sizeof(struct peer_sdioc_channel_config) * ch->num +
-		offsetof(struct peer_sdioc_channel_config, peer_operation);
-
-	ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
-				"wake up\n");
-		goto exit;
-	}
-	/* request operation from MDM peer */
-	peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_INIT);
-	ret = sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
-			&peer_operation, sizeof(u32));
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
-				"request close operation\n");
-		goto exit;
-	}
-	ret = sdio_al_enable_func_retry(wk_func, "wk_func");
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to enable"
-				" Func#%d\n", wk_func->num);
-		goto exit;
-	}
-	pr_debug(MODULE_NAME ":%s: wk_func enabled on ch %s\n",
-			__func__, ch->name);
-	/* send "start" operation to MDM */
-	peer_operation = PEER_OPERATION(opcode, PEER_OP_STATE_START);
-	ret  =  sdio_memcpy_toio(ch->func, SDIOC_SW_MAILBOX_ADDR+offset,
-			&peer_operation, sizeof(u32));
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":failed to "
-				"send start close operation\n");
-		goto exit;
-	}
-	ret = sdio_disable_func(wk_func);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
-				"disable Func#%d\n", wk_func->num);
-		goto exit;
-	}
-	/* poll for peer operation ack */
-	while (peer_operation != 0) {
-		ret  =  sdio_memcpy_fromio(ch->func,
-				&peer_operation,
-				SDIOC_SW_MAILBOX_ADDR+offset,
-				sizeof(u32));
-		if (ret) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					":failed to request ack on close"
-					" operation, loop_count = %d\n",
-					loop_count);
-			goto exit;
-		}
-		loop_count++;
-		if (loop_count > 10) {
-			sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
-					"peer_operation=0x%x wait loop"
-					" %d on ch %s\n", __func__,
-					peer_operation, loop_count, ch->name);
-		}
-	}
-exit:
-	return ret;
-}
-
-static int channel_close(struct sdio_channel *ch, int flush_flag)
-{
-	int ret;
-	struct sdio_al_device *sdio_al_dev = NULL;
-	int flush_len;
-	ulong flush_expires;
-
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
-				"channel\n",  __func__);
-		return -ENODEV;
-	}
-
-	if (!ch->func) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: NULL func"
-				" on channel:%d\n", __func__, ch->num);
-		return -ENODEV;
-	}
-
-	sdio_al_dev = ch->sdio_al_dev;
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	if (!sdio_al_dev->ch_close_supported) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: Not "
-			"supported by mdm, ch %s\n",
-			__func__, ch->name);
-		ret = -ENOTSUPP;
-		goto error_exit;
-	}
-
-	if (sdio_al_dev->is_err) {
-		SDIO_AL_ERR(__func__);
-		ret = -ENODEV;
-		goto error_exit;
-	}
-	if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
-		sdio_al_loge(sdio_al_dev->dev_log,
-				MODULE_NAME ":%s: ch %s is not in "
-				"open state (%d)\n",
-				__func__, ch->name, ch->state);
-		ret = -ENODEV;
-		goto error_exit;
-	}
-	ch->state = SDIO_CHANNEL_STATE_CLOSING;
-	ret = peer_set_operation(PEER_OP_CODE_CLOSE, sdio_al_dev, ch);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: "
-				"peer_set_operation() failed: %d\n",
-				__func__, ret);
-		ret = -ENODEV;
-		goto error_exit;
-	}
-	/* udate poll time for opened channels */
-	if  (ch->poll_delay_msec > 0) {
-		sdio_al_dev->poll_delay_msec =
-			get_min_poll_time_msec(sdio_al_dev);
-	}
-	sdio_al_release_mutex(ch->sdio_al_dev, __func__);
-
-	flush_expires = jiffies +
-		msecs_to_jiffies(SDIO_CLOSE_FLUSH_TIMEOUT_MSEC);
-	/* flush rx packets of the channel */
-	if (flush_flag) {
-		do {
-			while (ch->read_avail > 0) {
-				flush_len = ch->read_avail;
-				ret = sdio_read_internal(ch,
-						sdio_al_dev->rx_flush_buf,
-						flush_len);
-				if (ret) {
-					sdio_al_loge(&sdio_al->gen_log,
-						MODULE_NAME ":%s sdio_read"
-						" failed: %d, ch %s\n",
-						__func__, ret,
-						ch->name);
-					return ret;
-				}
-
-				if (time_after(jiffies, flush_expires) != 0) {
-					sdio_al_loge(&sdio_al->gen_log,
-						MODULE_NAME ":%s flush rx "
-						"packets timeout: ch %s\n",
-						__func__, ch->name);
-					sdio_al_get_into_err_state(sdio_al_dev);
-					return -EBUSY;
-				}
-			}
-			msleep(100);
-			if (ch->signature != SDIO_AL_SIGNATURE) {
-					sdio_al_loge(&sdio_al->gen_log,
-						MODULE_NAME ":%s: after sleep,"
-						" invalid signature"
-						" 0x%x\n", __func__,
-						ch->signature);
-				return -ENODEV;
-			}
-			if (sdio_al_claim_mutex_and_verify_dev(ch->sdio_al_dev,
-							       __func__))
-				return -ENODEV;
-
-			ret = read_mailbox(sdio_al_dev, false);
-			if (ret) {
-				sdio_al_loge(&sdio_al->gen_log,
-						MODULE_NAME ":%s: failed to"
-						" read mailbox", __func__);
-				goto error_exit;
-			}
-			sdio_al_release_mutex(ch->sdio_al_dev, __func__);
-		} while (ch->read_avail > 0);
-	}
-	if (sdio_al_claim_mutex_and_verify_dev(ch->sdio_al_dev,
-					       __func__))
-		return -ENODEV;
-	/* disable function to be able to open the channel again */
-	ret = sdio_disable_func(ch->func);
-	if (ret) {
-		sdio_al_loge(&sdio_al->gen_log,
-			MODULE_NAME ":Fail to disable Func#%d\n",
-			ch->func->num);
-		goto error_exit;
-	}
-	ch->state = SDIO_CHANNEL_STATE_CLOSED;
-	CLOSE_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":%s: Ch %s closed "
-				"successfully\n", __func__, ch->name);
-
-error_exit:
-	sdio_al_release_mutex(ch->sdio_al_dev, __func__);
-
-	return ret;
-}
-
-/**
- *  Close SDIO Channel.
- *
- */
-int sdio_close(struct sdio_channel *ch)
-{
-	return channel_close(ch, true);
-}
-EXPORT_SYMBOL(sdio_close);
-
-/**
- *  Get the number of available bytes to write.
- *
- */
-int sdio_write_avail(struct sdio_channel *ch)
-{
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
-				"channel\n", __func__);
-		return -ENODEV;
-	}
-	if (ch->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
-				"Invalid signature 0x%x\n",  __func__,
-				ch->signature);
-		return -ENODEV;
-	}
-	if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
-		sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
-				"channel %s state is not open (%d)\n",
-				__func__, ch->name, ch->state);
-		return -ENODEV;
-	}
-	pr_debug(MODULE_NAME ":sdio_write_avail %s 0x%x\n",
-			 ch->name, ch->write_avail);
-
-	return ch->write_avail;
-}
-EXPORT_SYMBOL(sdio_write_avail);
-
-/**
- *  Get the number of available bytes to read.
- *
- */
-int sdio_read_avail(struct sdio_channel *ch)
-{
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
-				"channel\n", __func__);
-		return -ENODEV;
-	}
-	if (ch->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
-				"Invalid signature 0x%x\n",  __func__,
-				ch->signature);
-		return -ENODEV;
-	}
-	if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
-		sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME ":%s: "
-				"channel %s state is not open (%d)\n",
-				__func__, ch->name, ch->state);
-		return -ENODEV;
-	}
-	pr_debug(MODULE_NAME ":sdio_read_avail %s 0x%x\n",
-			 ch->name, ch->read_avail);
-
-	return ch->read_avail;
-}
-EXPORT_SYMBOL(sdio_read_avail);
-
-static int sdio_read_from_closed_ch(struct sdio_channel *ch, int len)
-{
-	int ret = 0;
-	struct sdio_al_device *sdio_al_dev = NULL;
-
-	if (!ch) {
-		sdio_al_loge(ch->sdio_al_dev->dev_log,
-			MODULE_NAME ":%s: NULL channel\n",  __func__);
-		return -ENODEV;
-	}
-
-	sdio_al_dev = ch->sdio_al_dev;
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	ret = sdio_memcpy_fromio(ch->func, sdio_al_dev->rx_flush_buf,
-				 PIPE_RX_FIFO_ADDR, len);
-
-	if (ret) {
-		sdio_al_loge(ch->sdio_al_dev->dev_log,
-				MODULE_NAME ":ch %s: %s err=%d, len=%d\n",
-				ch->name, __func__, -ret, len);
-		sdio_al_dev->is_err = true;
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		return ret;
-	}
-
-	restart_inactive_time(sdio_al_dev);
-
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-
-	return 0;
-}
-
-/**
- *  Internal read from SDIO Channel.
- *
- *  Reading from the pipe will trigger interrupt if there are
- *  other pending packets on the SDIO-Client.
- *
- */
-static int sdio_read_internal(struct sdio_channel *ch, void *data, int len)
-{
-	int ret = 0;
-	struct sdio_al_device *sdio_al_dev = NULL;
-
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
-				"channel\n",  __func__);
-		return -ENODEV;
-	}
-	if (!data) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
-				__func__);
-		return -ENODEV;
-	}
-	if (len == 0) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
-				" to read 0 bytes\n", ch->name);
-		return -EINVAL;
-	}
-
-	if (ch->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
-				"signature 0x%x\n",  __func__, ch->signature);
-		return -ENODEV;
-	}
-
-	sdio_al_dev = ch->sdio_al_dev;
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	if (sdio_al_dev->is_err) {
-		SDIO_AL_ERR(__func__);
-		ret = -ENODEV;
-		goto exit;
-	}
-
-	/* lpm policy says we can't go to sleep when we have pending rx data,
-	   so either we had rx interrupt and woken up, or we never went to
-	   sleep */
-	if (sdio_al_dev->is_ok_to_sleep) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s: called "
-				"when is_ok_to_sleep is set for ch %s, len=%d,"
-				" last_any_read_avail=%d, last_read_avail=%d, "
-				"last_old_read_avail=%d", __func__, ch->name,
-				len, ch->statistics.last_any_read_avail,
-				ch->statistics.last_read_avail,
-				ch->statistics.last_old_read_avail);
-	}
-	BUG_ON(sdio_al_dev->is_ok_to_sleep);
-
-	if ((ch->state != SDIO_CHANNEL_STATE_OPEN) &&
-			(ch->state != SDIO_CHANNEL_STATE_CLOSING)) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":%s wrong "
-				"channel %s state %d\n",
-				__func__, ch->name, ch->state);
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s read %d "
-			"avail %d.\n", ch->name, len, ch->read_avail);
-
-	restart_inactive_time(sdio_al_dev);
-
-	if ((ch->is_packet_mode) && (len != ch->read_avail)) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_read ch "
-				"%s len != read_avail\n", ch->name);
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	if (len > ch->read_avail) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
-				"reading more bytes (%d) than the avail(%d).\n",
-				ch->name, len, ch->read_avail);
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	ret = sdio_memcpy_fromio(ch->func, data, PIPE_RX_FIFO_ADDR, len);
-
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ch %s: "
-				"sdio_read err=%d, len=%d, read_avail=%d, "
-				"last_read_avail=%d, last_old_read_avail=%d\n",
-				ch->name, -ret, len, ch->read_avail,
-				ch->statistics.last_read_avail,
-				ch->statistics.last_old_read_avail);
-		sdio_al_get_into_err_state(sdio_al_dev);
-		goto exit;
-	}
-
-	ch->statistics.total_read_times++;
-
-	/* Remove handled packet from the list regardless if ret is ok */
-	if (ch->is_packet_mode)
-		remove_handled_rx_packet(ch);
-	else
-		ch->read_avail -= len;
-
-	ch->total_rx_bytes += len;
-	DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s read %d "
-			"avail %d total %d.\n", ch->name, len,
-			ch->read_avail, ch->total_rx_bytes);
-
-	if ((ch->read_avail == 0) && !(ch->is_packet_mode))
-		ask_reading_mailbox(sdio_al_dev);
-
-exit:
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-
-	return ret;
-}
-
-/**
- *  Read from SDIO Channel.
- *
- *  Reading from the pipe will trigger interrupt if there are
- *  other pending packets on the SDIO-Client.
- *
- */
-int sdio_read(struct sdio_channel *ch, void *data, int len)
-{
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
-				"channel\n", __func__);
-		return -ENODEV;
-	}
-	if (ch->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: "
-			"Invalid signature 0x%x\n",  __func__, ch->signature);
-		return -ENODEV;
-	}
-	if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
-		return sdio_read_internal(ch, data, len);
-	} else {
-		sdio_al_loge(ch->sdio_al_dev->dev_log, MODULE_NAME
-				":%s: Invalid channel %s state %d\n",
-				__func__, ch->name, ch->state);
-	}
-	return -ENODEV;
-}
-EXPORT_SYMBOL(sdio_read);
-
-/**
- *  Write to SDIO Channel.
- *
- */
-int sdio_write(struct sdio_channel *ch, const void *data, int len)
-{
-	int ret = 0;
-	struct sdio_al_device *sdio_al_dev = NULL;
-
-	if (!ch) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL "
-				"channel\n",  __func__);
-		return -ENODEV;
-	}
-	if (!data) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: NULL data\n",
-				__func__);
-		return -ENODEV;
-	}
-	if (len == 0) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":channel %s trying"
-				" to write 0 bytes\n", ch->name);
-		return -EINVAL;
-	}
-
-	if (ch->signature != SDIO_AL_SIGNATURE) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":%s: Invalid "
-				"signature 0x%x\n",  __func__, ch->signature);
-		return -ENODEV;
-	}
-
-	sdio_al_dev = ch->sdio_al_dev;
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	WARN_ON(len > ch->write_avail);
-
-	if (sdio_al_dev->is_err) {
-		SDIO_AL_ERR(__func__);
-		ret = -ENODEV;
-		goto exit;
-	}
-
-	if (ch->state != SDIO_CHANNEL_STATE_OPEN) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":writing to "
-				"closed channel %s\n", ch->name);
-		ret = -EINVAL;
-		goto exit;
-	}
-
-	if (sdio_al_dev->is_ok_to_sleep) {
-		ret = sdio_al_wake_up(sdio_al_dev, 1, ch);
-		if (ret)
-			goto exit;
-	} else {
-		restart_inactive_time(sdio_al_dev);
-	}
-
-	DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":start ch %s write %d "
-			"avail %d.\n", ch->name, len, ch->write_avail);
-
-	if (len > ch->write_avail) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":ERR ch %s: "
-				"write more bytes (%d) than  available %d.\n",
-				ch->name, len, ch->write_avail);
-		ret = -ENOMEM;
-		goto exit;
-	}
-
-	ret = sdio_ch_write(ch, data, len);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":sdio_write "
-				"on channel %s err=%d\n", ch->name, -ret);
-		goto exit;
-	}
-
-	ch->total_tx_bytes += len;
-	DATA_DEBUG(sdio_al_dev->dev_log, MODULE_NAME ":end ch %s write %d "
-			"avail %d total %d.\n", ch->name, len,
-			ch->write_avail, ch->total_tx_bytes);
-
-	/* Round up to whole buffer size */
-	len = ROUND_UP(len, ch->peer_tx_buf_size);
-	/* Protect from wraparound */
-	len = min(len, (int) ch->write_avail);
-	ch->write_avail -= len;
-
-	if (ch->write_avail < ch->min_write_avail)
-		ask_reading_mailbox(sdio_al_dev);
-
-exit:
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-
-	return ret;
-}
-EXPORT_SYMBOL(sdio_write);
-
-static int __devinit msm_sdio_al_probe(struct platform_device *pdev)
-{
-	if (!sdio_al) {
-		pr_err(MODULE_NAME ": %s: NULL sdio_al\n", __func__);
-		return -ENODEV;
-	}
-
-	sdio_al->pdata = pdev->dev.platform_data;
-	return 0;
-}
-
-static int __devexit msm_sdio_al_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static void sdio_al_close_all_channels(struct sdio_al_device *sdio_al_dev)
-{
-	int j;
-	int ret;
-	struct sdio_channel *ch = NULL;
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
-
-	if (!sdio_al_dev) {
-		sdio_al_loge(sdio_al_dev->dev_log,
-			MODULE_NAME ": %s: NULL device", __func__);
-		return;
-	}
-	for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
-		ch = &sdio_al_dev->channel[j];
-
-		if (ch->state == SDIO_CHANNEL_STATE_OPEN) {
-			sdio_al_loge(sdio_al_dev->dev_log,
-				MODULE_NAME ": %s: Call to sdio_close() for"
-				" ch %s\n", __func__, ch->name);
-			ret = channel_close(ch, false);
-			if (ret) {
-				sdio_al_loge(sdio_al_dev->dev_log,
-					MODULE_NAME ": %s: failed sdio_close()"
-					" for ch %s (%d)\n",
-					__func__, ch->name, ret);
-			}
-		} else {
-			pr_debug(MODULE_NAME ": %s: skip sdio_close() ch %s"
-					" (state=%d)\n", __func__,
-					ch->name, ch->state);
-		}
-	}
-}
-
-static void sdio_al_invalidate_sdio_clients(struct sdio_al_device *sdio_al_dev,
-					    struct platform_device **pdev_arr)
-{
-	int j;
-
-	pr_debug(MODULE_NAME ": %s: Notifying SDIO clients for card %d",
-			__func__, sdio_al_dev->host->index);
-	for (j = 0; j < SDIO_AL_MAX_CHANNELS; ++j) {
-		if (sdio_al_dev->channel[j].state ==
-			SDIO_CHANNEL_STATE_INVALID)
-			continue;
-		pdev_arr[j] = sdio_al_dev->channel[j].pdev;
-		sdio_al_dev->channel[j].signature = 0x0;
-		sdio_al_dev->channel[j].state =
-			SDIO_CHANNEL_STATE_INVALID;
-	}
-}
-
-static void sdio_al_modem_reset_operations(struct sdio_al_device
-							*sdio_al_dev)
-{
-	int ret = 0;
-	struct platform_device *pdev_arr[SDIO_AL_MAX_CHANNELS];
-	int j;
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
-
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return;
-
-	if (sdio_al_dev->state == CARD_REMOVED) {
-		sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
-			"card %d is already removed", __func__,
-			sdio_al_dev->host->index);
-		goto exit_err;
-	}
-
-	if (sdio_al_dev->state == MODEM_RESTART) {
-		sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: "
-			"card %d was already notified for modem reset",
-			__func__, sdio_al_dev->host->index);
-		goto exit_err;
-	}
-
-	sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ": %s: Set the "
-		"state to MODEM_RESTART for card %d",
-		__func__, sdio_al_dev->host->index);
-	sdio_al_dev->state = MODEM_RESTART;
-	sdio_al_dev->is_ready = false;
-
-	/* Stop mailbox timer */
-	stop_and_del_timer(sdio_al_dev);
-
-	if ((sdio_al_dev->is_ok_to_sleep) &&
-	    (!sdio_al_dev->is_err)) {
-		pr_debug(MODULE_NAME ": %s: wakeup modem for "
-				    "card %d", __func__,
-			sdio_al_dev->host->index);
-		ret = sdio_al_wake_up(sdio_al_dev, 1, NULL);
-	}
-
-	if (!ret && (!sdio_al_dev->is_err) && sdio_al_dev->card &&
-		sdio_al_dev->card->sdio_func[0]) {
-			sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME
-			": %s: sdio_release_irq for card %d",
-			__func__,
-			sdio_al_dev->host->index);
-			sdio_release_irq(sdio_al_dev->card->sdio_func[0]);
-	}
-
-	memset(pdev_arr, 0, sizeof(pdev_arr));
-	sdio_al_invalidate_sdio_clients(sdio_al_dev, pdev_arr);
-
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Notifying SDIO "
-						    "clients for card %d",
-			__func__, sdio_al_dev->host->index);
-	for (j = 0; j < SDIO_AL_MAX_CHANNELS; j++) {
-		if (!pdev_arr[j])
-			continue;
-		platform_device_unregister(pdev_arr[j]);
-	}
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Finished Notifying "
-						    "SDIO clients for card %d",
-			__func__, sdio_al_dev->host->index);
-
-	return;
-
-exit_err:
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-	return;
-}
-
-#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
-static void sdio_al_reset(void)
-{
-	int i;
-	struct sdio_al_device *sdio_al_dev;
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s", __func__);
-
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
-		if (sdio_al->devices[i] == NULL) {
-			pr_debug(MODULE_NAME ": %s: NULL device in index %d",
-					__func__, i);
-			continue;
-		}
-		sdio_al_dev = sdio_al->devices[i];
-		sdio_al_modem_reset_operations(sdio_al->devices[i]);
-	}
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s completed", __func__);
-}
-#endif
-
-static void msm_sdio_al_shutdown(struct platform_device *pdev)
-{
-	int i;
-	struct sdio_al_device *sdio_al_dev;
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME
-			"Initiating msm_sdio_al_shutdown...");
-
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; i++) {
-		if (sdio_al->devices[i] == NULL) {
-			pr_debug(MODULE_NAME ": %s: NULL device in index %d",
-					__func__, i);
-			continue;
-		}
-		sdio_al_dev = sdio_al->devices[i];
-
-		if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-			return;
-
-		if (sdio_al_dev->ch_close_supported)
-			sdio_al_close_all_channels(sdio_al_dev);
-
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-
-		sdio_al_modem_reset_operations(sdio_al_dev);
-	}
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: "
-		"msm_sdio_al_shutdown complete.", __func__);
-}
-
-static struct platform_driver msm_sdio_al_driver = {
-	.probe          = msm_sdio_al_probe,
-	.remove         = __exit_p(msm_sdio_al_remove),
-	.shutdown	= msm_sdio_al_shutdown,
-	.driver         = {
-		.name   = "msm_sdio_al",
-	},
-};
-
-/**
- *  Initialize SDIO_AL channels.
- *
- */
-static int init_channels(struct sdio_al_device *sdio_al_dev)
-{
-	int ret = 0;
-	int i;
-
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	ret = read_sdioc_software_header(sdio_al_dev,
-					 sdio_al_dev->sdioc_sw_header);
-	if (ret)
-		goto exit;
-
-	ret = sdio_al_setup(sdio_al_dev);
-	if (ret)
-		goto exit;
-
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		int ch_name_size;
-		if (sdio_al_dev->channel[i].state == SDIO_CHANNEL_STATE_INVALID)
-			continue;
-		if (sdio_al->unittest_mode) {
-			memset(sdio_al_dev->channel[i].ch_test_name, 0,
-				sizeof(sdio_al_dev->channel[i].ch_test_name));
-			ch_name_size = strnlen(sdio_al_dev->channel[i].name,
-				       CHANNEL_NAME_SIZE);
-			strncpy(sdio_al_dev->channel[i].ch_test_name,
-			       sdio_al_dev->channel[i].name,
-			       ch_name_size);
-			strncat(sdio_al_dev->channel[i].ch_test_name +
-			       ch_name_size,
-			       SDIO_TEST_POSTFIX,
-			       SDIO_TEST_POSTFIX_SIZE);
-			pr_debug(MODULE_NAME ":pdev.name = %s\n",
-				sdio_al_dev->channel[i].ch_test_name);
-			sdio_al_dev->channel[i].pdev = platform_device_alloc(
-				sdio_al_dev->channel[i].ch_test_name, -1);
-		} else {
-			pr_debug(MODULE_NAME ":pdev.name = %s\n",
-				sdio_al_dev->channel[i].name);
-			sdio_al_dev->channel[i].pdev = platform_device_alloc(
-				sdio_al_dev->channel[i].name, -1);
-		}
-		if (!sdio_al_dev->channel[i].pdev) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					":NULL platform device for ch %s",
-					sdio_al_dev->channel[i].name);
-			sdio_al_dev->channel[i].state =
-				SDIO_CHANNEL_STATE_INVALID;
-			continue;
-		}
-		ret = platform_device_add(sdio_al_dev->channel[i].pdev);
-		if (ret) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					":platform_device_add failed, "
-					"ret=%d\n", ret);
-			sdio_al_dev->channel[i].state =
-				SDIO_CHANNEL_STATE_INVALID;
-		}
-	}
-
-exit:
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-	return ret;
-}
-
-/**
- *  Initialize SDIO_AL channels according to the client setup.
- *  This function also check if the client is in boot mode and
- *  flashless boot is required to be activated or the client is
- *  up and running.
- *
- */
-static int sdio_al_client_setup(struct sdio_al_device *sdio_al_dev)
-{
-	int ret = 0;
-	struct sdio_func *func1;
-	int signature = 0;
-
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":NULL card or "
-							       "func1\n");
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		return -ENODEV;
-	}
-	func1 = sdio_al_dev->card->sdio_func[0];
-
-	/* Read the header signature to determine the status of the MDM
-	 * SDIO Client
-	 */
-	signature = sdio_readl(func1, SDIOC_SW_HEADER_ADDR, &ret);
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":fail to read "
-				"signature from sw header.\n");
-		return ret;
-	}
-
-	switch (signature) {
-	case PEER_SDIOC_SW_MAILBOX_BOOT_SIGNATURE:
-		if (sdio_al_dev == sdio_al->bootloader_dev) {
-			sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":setup "
-					"bootloader on card %d\n",
-					sdio_al_dev->host->index);
-			return sdio_al_bootloader_setup();
-		} else {
-			sdio_al_logi(sdio_al_dev->dev_log, MODULE_NAME ":wait "
-					"for bootloader completion "
-					"on card %d\n",
-					sdio_al_dev->host->index);
-			return sdio_al_wait_for_bootloader_comp(sdio_al_dev);
-		}
-	case PEER_SDIOC_SW_MAILBOX_SIGNATURE:
-	case PEER_SDIOC_SW_MAILBOX_UT_SIGNATURE:
-		return init_channels(sdio_al_dev);
-	default:
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Invalid "
-				"signature 0x%x\n", signature);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void clean_sdio_al_device_data(struct sdio_al_device *sdio_al_dev)
-{
-	sdio_al_dev->is_ready = 0;
-	sdio_al_dev->bootloader_done = 0;
-	sdio_al_dev->lpm_chan = 0;
-	sdio_al_dev->is_ok_to_sleep = 0;
-	sdio_al_dev->inactivity_time = 0;
-	sdio_al_dev->poll_delay_msec = 0;
-	sdio_al_dev->is_timer_initialized = 0;
-	sdio_al_dev->is_err = 0;
-	sdio_al_dev->is_suspended = 0;
-	sdio_al_dev->flashless_boot_on = 0;
-	sdio_al_dev->ch_close_supported = 0;
-	sdio_al_dev->print_after_interrupt = 0;
-	memset(sdio_al_dev->sdioc_sw_header, 0,
-	       sizeof(*sdio_al_dev->sdioc_sw_header));
-	memset(sdio_al_dev->mailbox, 0, sizeof(*sdio_al_dev->mailbox));
-	memset(sdio_al_dev->rx_flush_buf, 0,
-	       sizeof(*sdio_al_dev->rx_flush_buf));
-}
-
-/*
- * SDIO driver functions
- */
-static int sdio_al_sdio_probe(struct sdio_func *func,
-		const struct sdio_device_id *sdio_dev_id)
-{
-	int ret = 0;
-	struct sdio_al_device *sdio_al_dev = NULL;
-	int i;
-	struct mmc_card *card = NULL;
-
-	if (!func) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
-				__func__);
-		return -ENODEV;
-	}
-	card = func->card;
-
-	if (!card) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
-				__func__);
-		return -ENODEV;
-	}
-
-	if (!card->sdio_func[0]) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-							    "func1\n",
-				__func__);
-		return -ENODEV;
-	}
-
-	if (card->sdio_funcs < SDIO_AL_MAX_FUNCS) {
-		dev_info(&card->dev,
-			 "SDIO-functions# %d less than expected.\n",
-			 card->sdio_funcs);
-		return -ENODEV;
-	}
-
-	/* Check if there is already a device for this card */
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
-		if (sdio_al->devices[i] == NULL)
-			continue;
-		if (sdio_al->devices[i]->host == card->host) {
-			sdio_al_dev = sdio_al->devices[i];
-			if (sdio_al_dev->state == CARD_INSERTED)
-				return 0;
-			clean_sdio_al_device_data(sdio_al_dev);
-			break;
-		}
-	}
-
-	if (!sdio_al_dev) {
-		sdio_al_dev = kzalloc(sizeof(struct sdio_al_device),
-				      GFP_KERNEL);
-		if (sdio_al_dev == NULL)
-			return -ENOMEM;
-
-		for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
-			if (sdio_al->devices[i] == NULL) {
-				sdio_al->devices[i] = sdio_al_dev;
-				sdio_al_dev->dev_log = &sdio_al->device_log[i];
-				spin_lock_init(&sdio_al_dev->dev_log->log_lock);
-	#ifdef CONFIG_DEBUG_FS
-				sdio_al_dbgfs_log[i].data =
-						sdio_al_dev->dev_log->buffer;
-				sdio_al_dbgfs_log[i].size =
-					SDIO_AL_DEBUG_LOG_SIZE;
-	#endif
-				break;
-			}
-		if (i == MAX_NUM_OF_SDIO_DEVICES) {
-			sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ":No space "
-					"in devices array for the device\n");
-			return -ENOMEM;
-		}
-	}
-
-	dev_info(&card->dev, "SDIO Card claimed.\n");
-	sdio_al->skip_print_info = 0;
-
-	sdio_al_dev->state = CARD_INSERTED;
-
-	if (card->host->index == SDIO_BOOTLOADER_CARD_INDEX)
-		sdio_al->bootloader_dev = sdio_al_dev;
-
-	sdio_al_dev->is_ready = false;
-
-	sdio_al_dev->signature = SDIO_AL_SIGNATURE;
-
-	sdio_al_dev->is_suspended = 0;
-	sdio_al_dev->is_timer_initialized = false;
-
-	sdio_al_dev->lpm_chan = INVALID_SDIO_CHAN;
-
-	sdio_al_dev->card = card;
-	sdio_al_dev->host = card->host;
-
-	if (!sdio_al_dev->mailbox) {
-		sdio_al_dev->mailbox = kzalloc(sizeof(struct sdio_mailbox),
-					       GFP_KERNEL);
-		if (sdio_al_dev->mailbox == NULL)
-			return -ENOMEM;
-	}
-
-	if (!sdio_al_dev->sdioc_sw_header) {
-		sdio_al_dev->sdioc_sw_header
-			= kzalloc(sizeof(*sdio_al_dev->sdioc_sw_header),
-				  GFP_KERNEL);
-		if (sdio_al_dev->sdioc_sw_header == NULL)
-			return -ENOMEM;
-	}
-
-	if (!sdio_al_dev->rx_flush_buf) {
-		sdio_al_dev->rx_flush_buf = kzalloc(RX_FLUSH_BUFFER_SIZE,
-						    GFP_KERNEL);
-		if (sdio_al_dev->rx_flush_buf == NULL) {
-			sdio_al_loge(&sdio_al->gen_log,
-					MODULE_NAME ":Fail to allocate "
-					   "rx_flush_buf for card %d\n",
-			       card->host->index);
-			return -ENOMEM;
-		}
-	}
-
-	sdio_al_dev->timer.data = (unsigned long)sdio_al_dev;
-
-	wake_lock_init(&sdio_al_dev->wake_lock, WAKE_LOCK_SUSPEND, MODULE_NAME);
-	/* Don't allow sleep until all required clients register */
-	sdio_al_vote_for_sleep(sdio_al_dev, 0);
-
-	if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-		return -ENODEV;
-
-	/* Init Func#1 */
-	ret = sdio_al_enable_func_retry(card->sdio_func[0], "Init Func#1");
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to "
-				"enable Func#%d\n", card->sdio_func[0]->num);
-		goto exit;
-	}
-
-	/* Patch Func CIS tuple issue */
-	ret = sdio_set_block_size(card->sdio_func[0], SDIO_AL_BLOCK_SIZE);
-	if (ret) {
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ":Fail to set "
-			"block size, Func#%d\n", card->sdio_func[0]->num);
-		goto exit;
-	}
-	sdio_al_dev->card->sdio_func[0]->max_blksize = SDIO_AL_BLOCK_SIZE;
-
-	sdio_al_dev->workqueue = create_singlethread_workqueue("sdio_al_wq");
-	sdio_al_dev->sdio_al_work.sdio_al_dev = sdio_al_dev;
-	init_waitqueue_head(&sdio_al_dev->wait_mbox);
-
-	ret = sdio_al_client_setup(sdio_al_dev);
-
-exit:
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-	return ret;
-}
-
-static void sdio_al_sdio_remove(struct sdio_func *func)
-{
-	struct sdio_al_device *sdio_al_dev = NULL;
-	int i;
-	struct mmc_card *card = NULL;
-	struct platform_device *pdev_arr[SDIO_AL_MAX_CHANNELS];
-
-	if (!func) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL func\n",
-				__func__);
-		return;
-	}
-	card = func->card;
-
-	if (!card) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL card\n",
-				__func__);
-		return;
-	}
-
-	/* Find the sdio_al_device of this card */
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES; ++i) {
-		if (sdio_al->devices[i] == NULL)
-			continue;
-		if (sdio_al->devices[i]->card == card) {
-			sdio_al_dev = sdio_al->devices[i];
-			break;
-		}
-	}
-	if (sdio_al_dev == NULL) {
-		pr_debug(MODULE_NAME ":%s :NULL sdio_al_dev for card %d\n",
-				 __func__, card->host->index);
-		return;
-	}
-
-	if (sdio_al_claim_mutex(sdio_al_dev, __func__))
-		return;
-
-	if (sdio_al_dev->state == CARD_REMOVED) {
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		return;
-	}
-
-	if (!card->sdio_func[0]) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: NULL "
-						"func1\n", __func__);
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-		return;
-	}
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s for card %d\n",
-			 __func__, card->host->index);
-
-	sdio_al_dev->state = CARD_REMOVED;
-
-	memset(pdev_arr, 0, sizeof(pdev_arr));
-	sdio_al_invalidate_sdio_clients(sdio_al_dev, pdev_arr);
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: ask_reading_mailbox "
-			"for card %d\n", __func__, card->host->index);
-	sdio_al_dev->is_ready = false; /* Flag worker to exit */
-	sdio_al_dev->ask_mbox = false;
-	ask_reading_mailbox(sdio_al_dev); /* Wakeup worker */
-
-	stop_and_del_timer(sdio_al_dev);
-
-	sdio_al_release_mutex(sdio_al_dev, __func__);
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Notifying SDIO "
-						    "clients for card %d",
-			__func__, sdio_al_dev->host->index);
-	for (i = 0; i < SDIO_AL_MAX_CHANNELS; i++) {
-		if (!pdev_arr[i])
-			continue;
-		platform_device_unregister(pdev_arr[i]);
-	}
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: Finished Notifying "
-						    "SDIO clients for card %d",
-			__func__, sdio_al_dev->host->index);
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: vote for sleep for "
-			"card %d\n", __func__, card->host->index);
-	sdio_al_vote_for_sleep(sdio_al_dev, 1);
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: flush_workqueue for "
-			"card %d\n", __func__, card->host->index);
-	flush_workqueue(sdio_al_dev->workqueue);
-	destroy_workqueue(sdio_al_dev->workqueue);
-	wake_lock_destroy(&sdio_al_dev->wake_lock);
-
-	sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ":%s: sdio card %d removed."
-			"\n", __func__,	card->host->index);
-}
-
-static void sdio_print_mailbox(char *prefix_str, struct sdio_mailbox *mailbox)
-{
-	int k = 0;
-	char buf[256];
-	char buf1[10];
-
-	if (!mailbox) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": mailbox is "
-				"NULL\n");
-		return;
-	}
-
-	sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s: pipes 0_7: eot=0x%x,"
-		" thresh=0x%x, overflow=0x%x, "
-		"underflow=0x%x, mask_thresh=0x%x\n",
-		 prefix_str, mailbox->eot_pipe_0_7,
-		 mailbox->thresh_above_limit_pipe_0_7,
-		 mailbox->overflow_pipe_0_7,
-		 mailbox->underflow_pipe_0_7,
-		 mailbox->mask_thresh_above_limit_pipe_0_7);
-
-	memset(buf, 0, sizeof(buf));
-	strncat(buf, ": bytes_avail:", sizeof(buf));
-
-	for (k = 0 ; k < SDIO_AL_ACTIVE_PIPES ; ++k) {
-		snprintf(buf1, sizeof(buf1), "%d, ",
-			 mailbox->pipe_bytes_avail[k]);
-		strncat(buf, buf1, sizeof(buf));
-	}
-
-	sdio_al_loge(&sdio_al->gen_log, MODULE_NAME "%s", buf);
-}
-
-static void sdio_al_print_info(void)
-{
-	int i = 0;
-	int j = 0;
-	int ret = 0;
-	struct sdio_mailbox *mailbox = NULL;
-	struct sdio_mailbox *hw_mailbox = NULL;
-	struct peer_sdioc_channel_config *ch_config = NULL;
-	struct sdio_func *func1 = NULL;
-	struct sdio_func *lpm_func = NULL;
-	int offset = 0;
-	int is_ok_to_sleep = 0;
-	char buf[50];
-
-	if (sdio_al->skip_print_info == 1)
-		return;
-
-	sdio_al->skip_print_info = 1;
-
-	sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - SDIO DEBUG INFO\n",
-			__func__);
-
-	if (!sdio_al) {
-		sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": %s - ERROR - "
-				"sdio_al is NULL\n",  __func__);
-		return;
-	}
-
-	sdio_al_loge(&sdio_al->gen_log, MODULE_NAME ": GPIO mdm2ap_status=%d\n",
-				sdio_al->pdata->get_mdm2ap_status());
-
-	for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
-		struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
-
-		if (sdio_al_dev == NULL) {
-			continue;
-		}
-
-		if (!sdio_al_dev->host) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Host"
-					" is NULL\n);");
-			continue;
-		}
-
-		snprintf(buf, sizeof(buf), "Card#%d: Shadow HW MB",
-		       sdio_al_dev->host->index);
-
-		/* printing Shadowing HW Mailbox*/
-		mailbox = sdio_al_dev->mailbox;
-		sdio_print_mailbox(buf, mailbox);
-
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
-			"is_ok_to_sleep=%d\n",
-			sdio_al_dev->host->index,
-			sdio_al_dev->is_ok_to_sleep);
-
-
-		sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME ": Card#%d: "
-				   "Shadow channels SW MB:",
-		       sdio_al_dev->host->index);
-
-		/* printing Shadowing SW Mailbox per channel*/
-		for (i = 0 ; i < SDIO_AL_MAX_CHANNELS ; ++i) {
-			struct sdio_channel *ch = &sdio_al_dev->channel[i];
-
-			if (ch == NULL) {
-				continue;
-			}
-
-			if (ch->state == SDIO_CHANNEL_STATE_INVALID)
-				continue;
-
-			ch_config = &sdio_al_dev->channel[i].ch_config;
-
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": Ch %s: max_rx_thres=0x%x, "
-				"max_tx_thres=0x%x, tx_buf=0x%x, "
-				"is_packet_mode=%d, "
-				"max_packet=0x%x, min_write=0x%x",
-				ch->name, ch_config->max_rx_threshold,
-				ch_config->max_tx_threshold,
-				ch_config->tx_buf_size,
-				ch_config->is_packet_mode,
-				ch_config->max_packet_size,
-				ch->min_write_avail);
-
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": total_rx=0x%x, total_tx=0x%x, "
-				"read_avail=0x%x, write_avail=0x%x, "
-				"rx_pending=0x%x, num_reads=0x%x, "
-				"num_notifs=0x%x", ch->total_rx_bytes,
-				ch->total_tx_bytes, ch->read_avail,
-				ch->write_avail, ch->rx_pending_bytes,
-				ch->statistics.total_read_times,
-				ch->statistics.total_notifs);
-		} /* end loop over all channels */
-
-	} /* end loop over all devices */
-
-	/* reading from client and printing is_host_ok_to_sleep per device */
-	for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
-		struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
-
-		if (sdio_al_verify_func1(sdio_al_dev, __func__))
-			continue;
-
-		if (!sdio_al_dev->host) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": Host is NULL");
-			continue;
-		}
-
-		if (sdio_al_dev->lpm_chan == INVALID_SDIO_CHAN) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-				": %s - for Card#%d, is lpm_chan=="
-				"INVALID_SDIO_CHAN. continuing...",
-				__func__, sdio_al_dev->host->index);
-			continue;
-		}
-
-		offset = offsetof(struct peer_sdioc_sw_mailbox, ch_config)+
-		sizeof(struct peer_sdioc_channel_config) *
-		sdio_al_dev->lpm_chan+
-		offsetof(struct peer_sdioc_channel_config, is_host_ok_to_sleep);
-
-		lpm_func = sdio_al_dev->card->sdio_func[sdio_al_dev->
-								lpm_chan+1];
-		if (!lpm_func) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": %s - lpm_func is NULL for card#%d"
-					" continuing...\n", __func__,
-					sdio_al_dev->host->index);
-			continue;
-		}
-
-		if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-			return;
-		ret  =  sdio_memcpy_fromio(lpm_func,
-					    &is_ok_to_sleep,
-					    SDIOC_SW_MAILBOX_ADDR+offset,
-					    sizeof(int));
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-
-		if (ret)
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": %s - fail to read "
-				"is_HOST_ok_to_sleep from mailbox for card %d",
-				__func__, sdio_al_dev->host->index);
-		else
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": Card#%d: "
-				"is_HOST_ok_to_sleep=%d\n",
-				sdio_al_dev->host->index,
-				is_ok_to_sleep);
-	}
-
-	for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES ; ++j) {
-		struct sdio_al_device *sdio_al_dev = sdio_al->devices[j];
-
-		if (!sdio_al_dev)
-			continue;
-
-		/* Reading HW Mailbox */
-		hw_mailbox = sdio_al_dev->mailbox;
-
-		if (sdio_al_claim_mutex_and_verify_dev(sdio_al_dev, __func__))
-			return;
-
-		if (!sdio_al_dev->card || !sdio_al_dev->card->sdio_func[0]) {
-			sdio_al_release_mutex(sdio_al_dev, __func__);
-			return;
-		}
-		func1 = sdio_al_dev->card->sdio_func[0];
-		ret = sdio_memcpy_fromio(func1, hw_mailbox,
-			HW_MAILBOX_ADDR, sizeof(*hw_mailbox));
-		sdio_al_release_mutex(sdio_al_dev, __func__);
-
-		if (ret) {
-			sdio_al_loge(sdio_al_dev->dev_log, MODULE_NAME
-					": fail to read "
-			       "mailbox for card#%d. "
-			       "continuing...\n",
-			       sdio_al_dev->host->index);
-			continue;
-		}
-
-		snprintf(buf, sizeof(buf), "Card#%d: Current HW MB",
-		       sdio_al_dev->host->index);
-
-		/* Printing HW Mailbox */
-		sdio_print_mailbox(buf, hw_mailbox);
-	}
-}
-
-static struct sdio_device_id sdio_al_sdioid[] = {
-    {.class = 0, .vendor = 0x70, .device = 0x2460},
-    {.class = 0, .vendor = 0x70, .device = 0x0460},
-    {.class = 0, .vendor = 0x70, .device = 0x23F1},
-    {.class = 0, .vendor = 0x70, .device = 0x23F0},
-    {}
-};
-
-static struct sdio_driver sdio_al_sdiofn_driver = {
-    .name      = "sdio_al_sdiofn",
-    .id_table  = sdio_al_sdioid,
-    .probe     = sdio_al_sdio_probe,
-    .remove    = sdio_al_sdio_remove,
-};
-
-#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
-/*
- *  Callback for notifications from restart mudule.
- *  This function handles only the BEFORE_RESTART notification.
- *  Stop all the activity on the card and notify our clients.
- */
-static int sdio_al_subsys_notifier_cb(struct notifier_block *this,
-				  unsigned long notif_type,
-				  void *data)
-{
-	if (notif_type != SUBSYS_BEFORE_SHUTDOWN) {
-		sdio_al_logi(&sdio_al->gen_log, MODULE_NAME ": %s: got "
-				"notification %ld", __func__, notif_type);
-		return NOTIFY_DONE;
-	}
-
-	sdio_al_reset();
-	return NOTIFY_OK;
-}
-
-static struct notifier_block sdio_al_nb = {
-	.notifier_call = sdio_al_subsys_notifier_cb,
-};
-#endif
-
-/**
- *  Module Init.
- *
- *  @warn: allocate sdio_al context before registering driver.
- *
- */
-static int __init sdio_al_init(void)
-{
-	int ret = 0;
-	int i;
-
-	pr_debug(MODULE_NAME ":sdio_al_init\n");
-
-	pr_info(MODULE_NAME ":SDIO-AL SW version %s\n",
-		DRV_VERSION);
-
-	sdio_al = kzalloc(sizeof(struct sdio_al), GFP_KERNEL);
-	if (sdio_al == NULL)
-		return -ENOMEM;
-
-	for (i = 0; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
-		sdio_al->devices[i] = NULL;
-
-	sdio_al->unittest_mode = false;
-
-	sdio_al->debug.debug_lpm_on = debug_lpm_on;
-	sdio_al->debug.debug_data_on = debug_data_on;
-	sdio_al->debug.debug_close_on = debug_close_on;
-
-#ifdef CONFIG_DEBUG_FS
-	sdio_al_debugfs_init();
-#endif
-
-
-#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
-	sdio_al->subsys_notif_handle = subsys_notif_register_notifier(
-		"external_modem", &sdio_al_nb);
-#endif
-
-	ret = platform_driver_register(&msm_sdio_al_driver);
-	if (ret) {
-		pr_err(MODULE_NAME ": platform_driver_register failed: %d\n",
-		       ret);
-		goto exit;
-	}
-
-	sdio_register_driver(&sdio_al_sdiofn_driver);
-
-	spin_lock_init(&sdio_al->gen_log.log_lock);
-
-exit:
-	if (ret)
-		kfree(sdio_al);
-	return ret;
-}
-
-/**
- *  Module Exit.
- *
- *  Free allocated memory.
- *  Disable SDIO-Card.
- *  Unregister driver.
- *
- */
-static void __exit sdio_al_exit(void)
-{
-	if (sdio_al == NULL)
-		return;
-
-	pr_debug(MODULE_NAME ":sdio_al_exit\n");
-
-#ifdef CONFIG_MSM_SUBSYSTEM_RESTART
-	subsys_notif_unregister_notifier(
-		sdio_al->subsys_notif_handle, &sdio_al_nb);
-#endif
-
-	sdio_al_tear_down();
-
-	sdio_unregister_driver(&sdio_al_sdiofn_driver);
-
-	kfree(sdio_al);
-
-#ifdef CONFIG_DEBUG_FS
-	sdio_al_debugfs_cleanup();
-#endif
-
-	platform_driver_unregister(&msm_sdio_al_driver);
-
-	pr_debug(MODULE_NAME ":sdio_al_exit complete\n");
-}
-
-module_init(sdio_al_init);
-module_exit(sdio_al_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SDIO Abstraction Layer");
-MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
-MODULE_VERSION(DRV_VERSION);
-
diff --git a/arch/arm/mach-msm/sdio_al_dloader.c b/arch/arm/mach-msm/sdio_al_dloader.c
deleted file mode 100644
index f3effa8..0000000
--- a/arch/arm/mach-msm/sdio_al_dloader.c
+++ /dev/null
@@ -1,2574 +0,0 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * 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.
- */
-
-/*
- * SDIO-Downloader
- *
- * To be used with Qualcomm's SDIO-Client connected to this host.
- */
-
-/* INCLUDES */
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/wakelock.h>
-#include <linux/workqueue.h>
-#include <linux/mmc/card.h>
-#include <linux/dma-mapping.h>
-#include <mach/dma.h>
-#include <linux/mmc/sdio_func.h>
-#include "sdio_al_private.h"
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/kthread.h>
-#include <linux/version.h>
-#include <linux/errno.h>
-#include <linux/debugfs.h>
-
-/* DEFINES AND MACROS */
-#define MAX_NUM_DEVICES		1
-#define TTY_SDIO_DEV			"tty_sdio_0"
-#define TTY_SDIO_DEV_TEST		"tty_sdio_test_0"
-#define SDIOC_MAILBOX_ADDRESS		0
-#define SDIO_DL_BLOCK_SIZE		512
-#define SDIO_DL_MAIN_THREAD_NAME	"sdio_tty_main_thread"
-#define SDIOC_DL_BUFF_ADDRESS		0
-#define SDIOC_UP_BUFF_ADDRESS		0x4
-#define SDIOC_DL_BUFF_SIZE_OFFSET	0x8
-#define SDIOC_UP_BUFF_SIZE_OFFSET	0xC
-#define SDIOC_DL_WR_PTR		0x10
-#define SDIOC_DL_RD_PTR		0x14
-#define SDIOC_UL_WR_PTR		0x18
-#define SDIOC_UL_RD_PTR		0x1C
-#define SDIOC_EXIT_PTR			0x20
-#define SDIOC_OP_MODE_PTR		0x24
-#define SDIOC_PTRS_OFFSET		0x10
-#define SDIOC_PTR_REGS_SIZE		0x10
-#define SDIOC_CFG_REGS_SIZE		0x10
-#define WRITE_RETRIES			0xFFFFFFFF
-#define INPUT_SPEED			4800
-#define OUTPUT_SPEED			4800
-#define SDIOC_EXIT_CODE		0xDEADDEAD
-#define SLEEP_MS			10
-#define PRINTING_GAP			200
-#define TIMER_DURATION			10
-#define PUSH_TIMER_DURATION		5000
-#define MULTIPLE_RATIO			1
-#define MS_IN_SEC			1000
-#define BITS_IN_BYTE			8
-#define BYTES_IN_KB			1024
-#define WRITE_TILL_END_RETRIES		5
-#define SDIO_DLD_NORMAL_MODE_NAME	"SDIO DLD NORMAL MODE"
-#define SDIO_DLD_BOOT_TEST_MODE_NAME	"SDIO DLD BOOT TEST MODE"
-#define SDIO_DLD_AMSS_TEST_MODE_NAME	"SDIO DLD AMSS TEST MODE"
-#define TEST_NAME_MAX_SIZE		30
-#define PUSH_STRING
-#define SDIO_DLD_OUTGOING_BUFFER_SIZE	(48*1024*MULTIPLE_RATIO)
-
-/* FORWARD DECLARATIONS */
-static int sdio_dld_open(struct tty_struct *tty, struct file *file);
-static void sdio_dld_close(struct tty_struct *tty, struct file *file);
-static int sdio_dld_write_callback(struct tty_struct *tty,
-				   const unsigned char *buf, int count);
-static int sdio_dld_write_room(struct tty_struct *tty);
-static int sdio_dld_main_task(void *card);
-static void sdio_dld_print_info(void);
-#ifdef CONFIG_DEBUG_FS
-static int sdio_dld_debug_info_open(struct inode *inode, struct file *file);
-static ssize_t sdio_dld_debug_info_write(struct file *file,
-		const char __user *buf, size_t count, loff_t *ppos);
-#endif
-
-static void sdio_dld_tear_down(struct work_struct *work);
-DECLARE_WORK(cleanup, sdio_dld_tear_down);
-
-/* STRUCTURES AND TYPES */
-enum sdio_dld_op_mode {
-	 SDIO_DLD_NO_MODE = 0,
-	 SDIO_DLD_NORMAL_MODE = 1,
-	 SDIO_DLD_BOOT_TEST_MODE = 2,
-	 SDIO_DLD_AMSS_TEST_MODE = 3,
-	 SDIO_DLD_NUM_OF_MODES,
-};
-
-struct sdioc_reg_sequential_chunk_ptrs {
-	unsigned int dl_wr_ptr;
-	unsigned int dl_rd_ptr;
-	unsigned int up_wr_ptr;
-	unsigned int up_rd_ptr;
-};
-
-struct sdioc_reg_sequential_chunk_cfg {
-	unsigned int dl_buff_address;
-	unsigned int up_buff_address;
-	unsigned int dl_buff_size;
-	unsigned int ul_buff_size;
-};
-
-struct sdioc_reg {
-	unsigned int reg_val;
-	unsigned int reg_offset;
-};
-
-struct sdioc_reg_chunk {
-	struct sdioc_reg dl_buff_address;
-	struct sdioc_reg up_buff_address;
-	struct sdioc_reg dl_buff_size;
-	struct sdioc_reg ul_buff_size;
-	struct sdioc_reg dl_wr_ptr;
-	struct sdioc_reg dl_rd_ptr;
-	struct sdioc_reg up_wr_ptr;
-	struct sdioc_reg up_rd_ptr;
-	struct sdioc_reg good_to_exit_ptr;
-};
-
-struct sdio_data {
-	char *data;
-	int offset_read_p;
-	int offset_write_p;
-	int buffer_size;
-	int num_of_bytes_in_use;
-};
-
-struct sdio_dld_data {
-	struct sdioc_reg_chunk sdioc_reg;
-	struct sdio_data incoming_data;
-	struct sdio_data outgoing_data;
-};
-
-struct sdio_dld_wait_event {
-	wait_queue_head_t wait_event;
-	int wake_up_signal;
-};
-
-struct sdio_dld_task {
-	struct task_struct *dld_task;
-	const char *task_name;
-	struct sdio_dld_wait_event exit_wait;
-	atomic_t please_close;
-};
-
-#ifdef CONFIG_DEBUG_FS
-struct sdio_dloader_debug {
-	struct dentry *sdio_dld_debug_root;
-	struct dentry *sdio_al_dloader;
-};
-
-const struct file_operations sdio_dld_debug_info_ops = {
-	.open = sdio_dld_debug_info_open,
-	.write = sdio_dld_debug_info_write,
-};
-#endif
-
-struct sdio_downloader {
-	int sdioc_boot_func;
-	struct sdio_dld_wait_event write_callback_event;
-	struct sdio_dld_task dld_main_thread;
-	struct tty_driver *tty_drv;
-	struct tty_struct *tty_str;
-	struct sdio_dld_data sdio_dloader_data;
-	struct mmc_card *card;
-	int(*done_callback)(void);
-	struct sdio_dld_wait_event main_loop_event;
-	struct timer_list timer;
-	unsigned int poll_ms;
-	struct timer_list push_timer;
-	unsigned int push_timer_ms;
-	enum sdio_dld_op_mode op_mode;
-	char op_mode_name[TEST_NAME_MAX_SIZE];
-};
-
-struct sdio_dld_global_info {
-	int global_bytes_write_toio;
-	int global_bytes_write_tty;
-	int global_bytes_read_fromio;
-	int global_bytes_push_tty;
-	u64 start_time;
-	u64 end_time;
-	u64 delta_jiffies;
-	unsigned int time_msec;
-	unsigned int throughput;
-	int cl_dl_wr_ptr;
-	int cl_dl_rd_ptr;
-	int cl_up_wr_ptr;
-	int cl_up_rd_ptr;
-	int host_read_ptr;
-	int host_write_ptr;
-	int cl_dl_buffer_size;
-	int cl_up_buffer_size;
-	int host_outgoing_buffer_size;
-	int cl_dl_buffer_address;
-	int cl_up_buffer_address;
-};
-
-static const struct tty_operations sdio_dloader_tty_ops = {
-	.open = sdio_dld_open,
-	.close = sdio_dld_close,
-	.write = sdio_dld_write_callback,
-	.write_room = sdio_dld_write_room,
-};
-
-/* GLOBAL VARIABLES */
-struct sdio_downloader *sdio_dld;
-struct sdio_dld_global_info sdio_dld_info;
-static char outgoing_data_buffer[SDIO_DLD_OUTGOING_BUFFER_SIZE];
-
-static DEFINE_SPINLOCK(lock1);
-static unsigned long lock_flags1;
-static DEFINE_SPINLOCK(lock2);
-static unsigned long lock_flags2;
-
-static atomic_t sdio_dld_in_use = ATOMIC_INIT(0);
-static atomic_t sdio_dld_setup_done = ATOMIC_INIT(0);
-
-/*
- * sdio_op_mode sets the operation mode of the sdio_dloader -
- * it may be in NORMAL_MODE, BOOT_TEST_MODE or AMSS_TEST_MODE
- */
-static int sdio_op_mode = (int)SDIO_DLD_NORMAL_MODE;
-module_param(sdio_op_mode, int, 0);
-
-#ifdef CONFIG_DEBUG_FS
-
-struct sdio_dloader_debug sdio_dld_debug;
-
-#define ARR_SIZE 30000
-#define SDIO_DLD_DEBUGFS_INIT_VALUE	87654321
-#define SDIO_DLD_DEBUGFS_CASE_1_CODE	11111111
-#define SDIO_DLD_DEBUGFS_CASE_2_CODE	22222222
-#define SDIO_DLD_DEBUGFS_CASE_3_CODE	33333333
-#define SDIO_DLD_DEBUGFS_CASE_4_CODE	44444444
-#define SDIO_DLD_DEBUGFS_CASE_5_CODE	55555555
-#define SDIO_DLD_DEBUGFS_CASE_6_CODE	66666666
-#define SDIO_DLD_DEBUGFS_CASE_7_CODE	77777777
-#define SDIO_DLD_DEBUGFS_CASE_8_CODE	88888888
-#define SDIO_DLD_DEBUGFS_CASE_9_CODE	99999999
-#define SDIO_DLD_DEBUGFS_CASE_10_CODE	10101010
-#define SDIO_DLD_DEBUGFS_CASE_11_CODE	11001100
-#define SDIO_DLD_DEBUGFS_CASE_12_CODE	12001200
-#define SDIO_DLD_DEBUGFS_LOOP_WAIT	7
-#define SDIO_DLD_DEBUGFS_LOOP_WAKEUP	8
-#define SDIO_DLD_DEBUGFS_CB_WAIT	3
-#define SDIO_DLD_DEBUGFS_CB_WAKEUP	4
-
-static int curr_index;
-struct ptrs {
-	int h_w_ptr;
-	int h_r_ptr;
-	int c_u_w_ptr;
-	int c_u_r_ptr;
-	int code;
-	int h_has_to_send;
-	int c_has_to_receive;
-	int min_of;
-	int reserve2;
-	int tty_count;
-	int write_tty;
-	int write_toio;
-	int loop_wait_wake;
-	int cb_wait_wake;
-	int c_d_w_ptr;
-	int c_d_r_ptr;
-	int to_read;
-	int push_to_tty;
-	int global_tty_send;
-	int global_sdio_send;
-	int global_tty_received;
-	int global_sdio_received;
-	int reserve22;
-	int reserve23;
-	int reserve24;
-	int reserve25;
-	int reserve26;
-	int reserve27;
-	int reserve28;
-	int reserve29;
-	int reserve30;
-	int reserve31;
-};
-
-struct global_data {
-	int curr_i;
-	int duration_ms;
-	int global_bytes_sent;
-	int throughput_Mbs;
-	int host_outgoing_buffer_size_KB;
-	int client_up_buffer_size_KB;
-	int client_dl_buffer_size_KB;
-	int client_dl_buffer_address;
-	int client_up_buffer_address;
-	int global_bytes_received;
-	int global_bytes_pushed;
-	int reserve11;
-	int reserve12;
-	int reserve13;
-	int reserve14;
-	int reserve15;
-	int reserve16;
-	int reserve17;
-	int reserve18;
-	int reserve19;
-	int reserve20;
-	int reserve21;
-	int reserve22;
-	int reserve23;
-	int reserve24;
-	int reserve25;
-	int reserve26;
-	int reserve27;
-	int reserve28;
-	int reserve29;
-	int reserve30;
-	int reserve31;
-	struct ptrs ptr_array[ARR_SIZE];
-};
-
-static struct global_data gd;
-static struct debugfs_blob_wrapper blob;
-static struct dentry *root;
-static struct dentry *dld;
-
-struct debugfs_global {
-	int global_8k_has;
-	int global_9k_has;
-	int global_min;
-	int global_count;
-	int global_write_tty;
-	int global_write_toio;
-	int global_bytes_cb_tty;
-	int global_to_read;
-	int global_push_to_tty;
-	int global_tty_send;
-	int global_sdio_send;
-	int global_sdio_received;
-	int global_tty_push;
-};
-
-static struct debugfs_global debugfs_glob;
-
-static void update_standard_fields(int index)
-{
-
-	gd.ptr_array[index].global_tty_send =
-		sdio_dld_info.global_bytes_write_tty;
-	gd.ptr_array[index].global_sdio_send =
-		sdio_dld_info.global_bytes_write_toio;
-	gd.ptr_array[index].global_tty_received =
-		sdio_dld_info.global_bytes_push_tty;
-	gd.ptr_array[index].global_sdio_received =
-		sdio_dld_info.global_bytes_read_fromio;
-}
-
-static void update_gd(int code)
-{
-	struct sdioc_reg_chunk *reg_str =
-					&sdio_dld->sdio_dloader_data.sdioc_reg;
-	struct sdio_data *outgoing = &sdio_dld->sdio_dloader_data.outgoing_data;
-	int index = curr_index%ARR_SIZE;
-
-	gd.curr_i = curr_index;
-	gd.duration_ms = 0;
-	gd.global_bytes_sent = 0;
-	gd.throughput_Mbs = 0;
-	gd.host_outgoing_buffer_size_KB = 0;
-	gd.client_up_buffer_size_KB = 0;
-	gd.client_dl_buffer_size_KB = 0;
-	gd.client_dl_buffer_address = 0;
-	gd.client_up_buffer_address = 0;
-	gd.global_bytes_received = 0;
-	gd.global_bytes_pushed = 0;
-	gd.reserve11 = 0;
-	gd.reserve12 = 0;
-	gd.reserve13 = 0;
-	gd.reserve14 = 0;
-	gd.reserve15 = 0;
-	gd.reserve16 = 0;
-	gd.reserve17 = 0;
-	gd.reserve18 = 0;
-	gd.reserve19 = 0;
-	gd.reserve20 = 0;
-	gd.reserve21 = 0;
-	gd.reserve22 = 0;
-	gd.reserve23 = 0;
-	gd.reserve24 = 0;
-	gd.reserve25 = 0;
-	gd.reserve26 = 0;
-	gd.reserve27 = 0;
-	gd.reserve28 = 0;
-	gd.reserve29 = 0;
-	gd.reserve30 = 0;
-	gd.reserve31 = 0;
-
-	gd.ptr_array[index].h_w_ptr = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*0*/
-	gd.ptr_array[index].h_r_ptr = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*1*/
-	gd.ptr_array[index].c_u_w_ptr =	SDIO_DLD_DEBUGFS_INIT_VALUE;	/*2*/
-	gd.ptr_array[index].c_u_r_ptr =	SDIO_DLD_DEBUGFS_INIT_VALUE;	/*3*/
-	gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_INIT_VALUE;		/*4*/
-	gd.ptr_array[index].h_has_to_send = SDIO_DLD_DEBUGFS_INIT_VALUE;/*5*/
-	gd.ptr_array[index].c_has_to_receive =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;				/*6*/
-	gd.ptr_array[index].min_of = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*7*/
-	gd.ptr_array[index].reserve2 = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*8*/
-	gd.ptr_array[index].tty_count = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*9*/
-	gd.ptr_array[index].write_tty = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*A*/
-	gd.ptr_array[index].write_toio = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*B*/
-	gd.ptr_array[index].loop_wait_wake =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;				/*C*/
-	gd.ptr_array[index].cb_wait_wake = SDIO_DLD_DEBUGFS_INIT_VALUE;	/*D*/
-	gd.ptr_array[index].c_d_w_ptr =	SDIO_DLD_DEBUGFS_INIT_VALUE;	/*E*/
-	gd.ptr_array[index].c_d_r_ptr =	SDIO_DLD_DEBUGFS_INIT_VALUE;	/*F*/
-	gd.ptr_array[index].to_read =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;			/*0x10*/
-	gd.ptr_array[index].push_to_tty =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;			/*0x11*/
-	gd.ptr_array[index].global_tty_send =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;			/*0x12*/
-	gd.ptr_array[index].global_sdio_send =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;			/*0x13*/
-	gd.ptr_array[index].global_tty_received =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;			/*0x14*/
-	gd.ptr_array[index].global_sdio_received =
-		SDIO_DLD_DEBUGFS_INIT_VALUE;			/*0x15*/
-	gd.ptr_array[index].reserve22 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve23 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve24 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve25 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve26 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve27 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve28 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve29 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve30 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-	gd.ptr_array[index].reserve31 = SDIO_DLD_DEBUGFS_INIT_VALUE;
-
-	switch (code) {
-	case SDIO_DLD_DEBUGFS_CASE_1_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_1_CODE;
-		gd.ptr_array[index].h_w_ptr = outgoing->offset_write_p;
-		gd.ptr_array[index].h_r_ptr = outgoing->offset_read_p;
-		gd.ptr_array[index].c_u_w_ptr =	reg_str->up_wr_ptr.reg_val;
-		gd.ptr_array[index].c_u_r_ptr =	reg_str->up_rd_ptr.reg_val;
-		gd.ptr_array[index].c_d_w_ptr =	reg_str->dl_wr_ptr.reg_val;
-		gd.ptr_array[index].c_d_r_ptr =	reg_str->dl_rd_ptr.reg_val;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_2_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_2_CODE;
-		gd.ptr_array[index].c_u_r_ptr = reg_str->up_rd_ptr.reg_val;
-		gd.ptr_array[index].c_u_w_ptr = reg_str->up_wr_ptr.reg_val;
-		gd.ptr_array[index].h_has_to_send = debugfs_glob.global_8k_has;
-		gd.ptr_array[index].c_has_to_receive =
-			debugfs_glob.global_9k_has;
-		gd.ptr_array[index].min_of = debugfs_glob.global_min;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_3_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_3_CODE;
-		gd.ptr_array[index].h_w_ptr = outgoing->offset_write_p;
-		gd.ptr_array[index].h_r_ptr = outgoing->offset_read_p;
-		gd.ptr_array[index].write_tty = debugfs_glob.global_write_tty;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_4_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_4_CODE;
-		gd.ptr_array[index].h_w_ptr = outgoing->offset_write_p;
-		gd.ptr_array[index].h_r_ptr = outgoing->offset_read_p;
-		gd.ptr_array[index].c_u_r_ptr = reg_str->up_rd_ptr.reg_val;
-		gd.ptr_array[index].c_u_w_ptr = reg_str->up_wr_ptr.reg_val;
-		gd.ptr_array[index].write_toio =
-			debugfs_glob.global_write_toio;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_5_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_5_CODE;
-		gd.ptr_array[index].tty_count = debugfs_glob.global_count;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_6_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_6_CODE;
-		gd.ptr_array[index].loop_wait_wake = 7;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_7_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_7_CODE;
-		gd.ptr_array[index].loop_wait_wake = 8;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_8_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_8_CODE;
-		gd.ptr_array[index].cb_wait_wake = 3;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_9_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_9_CODE;
-		gd.ptr_array[index].cb_wait_wake = 4;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_10_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_10_CODE;
-		gd.ptr_array[index].cb_wait_wake =
-			debugfs_glob.global_bytes_cb_tty;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_11_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_11_CODE;
-		gd.ptr_array[index].to_read = debugfs_glob.global_to_read;
-		break;
-
-	case SDIO_DLD_DEBUGFS_CASE_12_CODE:
-		gd.ptr_array[index].code = SDIO_DLD_DEBUGFS_CASE_12_CODE;
-		gd.ptr_array[index].push_to_tty =
-			debugfs_glob.global_push_to_tty;
-		break;
-
-	default:
-		break;
-	}
-	update_standard_fields(index);
-	curr_index++;
-}
-
-static int bootloader_debugfs_init(void)
-{
-	/* /sys/kernel/debug/bootloader there will be dld_arr file */
-	root = debugfs_create_dir("bootloader", NULL);
-	if (!root) {
-		pr_info(MODULE_NAME ": %s - creating root dir "
-			"failed\n", __func__);
-		return -ENODEV;
-	}
-
-	blob.data = &gd;
-	blob.size = sizeof(struct global_data);
-	dld = debugfs_create_blob("dld_arr", S_IRUGO, root, &blob);
-	if (!dld) {
-		debugfs_remove_recursive(root);
-		pr_err(MODULE_NAME ": %s, failed to create debugfs entry\n",
-		       __func__);
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
-/*
-* for triggering the sdio_dld info use:
-* echo 1 > /sys/kernel/debug/sdio_al_dld/sdio_al_dloader_info
-*/
-static int sdio_dld_debug_init(void)
-{
-	sdio_dld_debug.sdio_dld_debug_root =
-				debugfs_create_dir("sdio_al_dld", NULL);
-	if (!sdio_dld_debug.sdio_dld_debug_root) {
-		pr_err(MODULE_NAME ": %s - Failed to create folder. "
-		       "sdio_dld_debug_root is NULL",
-		       __func__);
-		return -ENOENT;
-	}
-
-	sdio_dld_debug.sdio_al_dloader = debugfs_create_file(
-					"sdio_al_dloader_info",
-					S_IRUGO | S_IWUGO,
-					sdio_dld_debug.sdio_dld_debug_root,
-					NULL,
-					&sdio_dld_debug_info_ops);
-
-	if (!sdio_dld_debug.sdio_al_dloader) {
-		pr_err(MODULE_NAME ": %s - Failed to create a file. "
-		       "sdio_al_dloader is NULL",
-		       __func__);
-		debugfs_remove(sdio_dld_debug.sdio_dld_debug_root);
-		sdio_dld_debug.sdio_dld_debug_root = NULL;
-		return -ENOENT;
-	}
-
-	return 0;
-}
-
-static int sdio_dld_debug_info_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t sdio_dld_debug_info_write(struct file *file,
-		const char __user *buf, size_t count, loff_t *ppos)
-{
-	sdio_dld_print_info();
-	return count;
-}
-#endif /* CONFIG_DEBUG_FS */
-
-static void sdio_dld_print_info(void)
-{
-
-	sdio_dld_info.end_time = get_jiffies_64(); /* read the current time */
-	sdio_dld_info.delta_jiffies =
-		sdio_dld_info.end_time - sdio_dld_info.start_time;
-	sdio_dld_info.time_msec = jiffies_to_msecs(sdio_dld_info.delta_jiffies);
-
-	sdio_dld_info.throughput = sdio_dld_info.global_bytes_write_toio *
-		BITS_IN_BYTE / sdio_dld_info.time_msec;
-	sdio_dld_info.throughput /= MS_IN_SEC;
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - DURATION IN MSEC = %d\n",
-		__func__,
-		sdio_dld_info.time_msec);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - BYTES WRITTEN ON SDIO BUS "
-			    "= %d...BYTES SENT BY TTY = %d",
-		__func__,
-	       sdio_dld_info.global_bytes_write_toio,
-	       sdio_dld_info.global_bytes_write_tty);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - BYTES RECEIVED ON SDIO BUS "
-			    "= %d...BYTES SENT TO TTY = %d",
-		__func__,
-		sdio_dld_info.global_bytes_read_fromio,
-		sdio_dld_info.global_bytes_push_tty);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - THROUGHPUT=%d Mbit/Sec",
-		__func__, sdio_dld_info.throughput);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT DL_BUFFER_SIZE=%d"
-		" KB..CLIENT UL_BUFFER=%d KB\n",
-		__func__,
-		sdio_dld_info.cl_dl_buffer_size/BYTES_IN_KB,
-		sdio_dld_info.cl_up_buffer_size/BYTES_IN_KB);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - HOST OUTGOING BUFFER_SIZE"
-			    "=%d KB",
-		__func__,
-		sdio_dld_info.host_outgoing_buffer_size/BYTES_IN_KB);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT DL BUFFER "
-		 "ADDRESS = 0x%x", __func__,
-		sdio_dld_info.cl_dl_buffer_address);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT UP BUFFER "
-		"ADDRESS = 0x%x",
-		__func__,
-		sdio_dld_info.cl_up_buffer_address);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT - UPLINK BUFFER - "
-		"READ POINTER = %d", __func__,
-		sdio_dld_info.cl_up_rd_ptr);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT - UPLINK BUFFER - "
-		"WRITE POINTER = %d", __func__,
-		sdio_dld_info.cl_up_wr_ptr);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT - DOWNLINK BUFFER - "
-		"READ POINTER = %d", __func__,
-		sdio_dld_info.cl_dl_rd_ptr);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - CLIENT - DOWNLINK BUFFER - "
-		"WRITE POINTER = %d", __func__,
-		sdio_dld_info.cl_dl_wr_ptr);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - HOST - OUTGOING BUFFER - "
-		"READ POINTER = %d", __func__,
-		sdio_dld_info.host_read_ptr);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - HOST - OUTGOING BUFFER - "
-		"WRITE POINTER = %d", __func__,
-		sdio_dld_info.host_write_ptr);
-
-	pr_info(MODULE_NAME ": %s, FLASHLESS BOOT - END DEBUG INFO", __func__);
-}
-
-/**
-  * sdio_dld_set_op_mode
-  * sets the op_mode and the name of the op_mode. Also, in case
-  * it's invalid mode sets op_mode to SDIO_DLD_NORMAL_MODE
-  *
-  * @op_mode: the operation mode to be set
-  * @return NONE
-  */
-static void sdio_dld_set_op_mode(enum sdio_dld_op_mode op_mode)
-{
-	sdio_dld->op_mode = op_mode;
-
-	switch (op_mode) {
-	case SDIO_DLD_NORMAL_MODE:
-		memcpy(sdio_dld->op_mode_name,
-		       SDIO_DLD_NORMAL_MODE_NAME, TEST_NAME_MAX_SIZE);
-		break;
-	case SDIO_DLD_BOOT_TEST_MODE:
-		memcpy(sdio_dld->op_mode_name,
-		       SDIO_DLD_BOOT_TEST_MODE_NAME, TEST_NAME_MAX_SIZE);
-		break;
-	case SDIO_DLD_AMSS_TEST_MODE:
-		memcpy(sdio_dld->op_mode_name,
-		       SDIO_DLD_AMSS_TEST_MODE_NAME, TEST_NAME_MAX_SIZE);
-		break;
-	default:
-		sdio_dld->op_mode = SDIO_DLD_NORMAL_MODE;
-		pr_err(MODULE_NAME ": %s - Invalid Op_Mode = %d. Settings "
-		       "Op_Mode to default - NORMAL_MODE\n",
-		       __func__, op_mode);
-		memcpy(sdio_dld->op_mode_name,
-		       SDIO_DLD_NORMAL_MODE_NAME, TEST_NAME_MAX_SIZE);
-		break;
-	}
-
-	if (sdio_dld->op_mode_name != NULL) {
-		pr_info(MODULE_NAME ": %s - FLASHLESS BOOT - Op_Mode is set to "
-			"%s\n", __func__, sdio_dld->op_mode_name);
-	} else {
-		pr_info(MODULE_NAME ": %s - FLASHLESS BOOT - op_mode_name is "
-			"NULL\n", __func__);
-	}
-}
-
-/**
-  * sdio_dld_allocate_local_buffers
-  * allocates local outgoing and incoming buffers and also sets
-  * threshold for outgoing data.
-  *
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_allocate_local_buffers(void)
-{
-	struct sdioc_reg_chunk *reg_str = &sdio_dld->sdio_dloader_data.
-		sdioc_reg;
-	struct sdio_data *outgoing = &sdio_dld->sdio_dloader_data.outgoing_data;
-	struct sdio_data *incoming = &sdio_dld->sdio_dloader_data.incoming_data;
-
-	incoming->data =
-		kzalloc(reg_str->dl_buff_size.reg_val, GFP_KERNEL);
-
-	if (!incoming->data) {
-		pr_err(MODULE_NAME ": %s - param ""incoming->data"" is NULL. "
-		       "Couldn't allocate incoming_data local buffer\n",
-		       __func__);
-		return -ENOMEM;
-	}
-
-	incoming->buffer_size = reg_str->dl_buff_size.reg_val;
-
-	outgoing->data = outgoing_data_buffer;
-
-	outgoing->buffer_size = SDIO_DLD_OUTGOING_BUFFER_SIZE;
-
-	if (outgoing->buffer_size !=
-	    reg_str->ul_buff_size.reg_val*MULTIPLE_RATIO) {
-		pr_err(MODULE_NAME ": %s - HOST outgoing buffer size (%d bytes)"
-		       "must be a multiple of ClIENT uplink buffer size (%d "
-		       "bytes). HOST_SIZE == n*CLIENT_SIZE.(n=1,2,3...)\n",
-		       __func__,
-		       SDIO_DLD_OUTGOING_BUFFER_SIZE,
-		       reg_str->ul_buff_size.reg_val);
-		kfree(incoming->data);
-		return -EINVAL;
-	}
-
-	/* keep sdio_dld_info up to date */
-	sdio_dld_info.host_outgoing_buffer_size = outgoing->buffer_size;
-
-	return 0;
-}
-
-/**
-  * sdio_dld_dealloc_local_buffers frees incoming and outgoing
-  * buffers.
-  *
-  * @return None.
-  */
-static void sdio_dld_dealloc_local_buffers(void)
-{
-	kfree((void *)sdio_dld->sdio_dloader_data.incoming_data.data);
-}
-
-/**
-  * mailbox_to_seq_chunk_read_cfg
-  * reads 4 configuration registers of mailbox from str_func, as
-  * a sequentail chunk in memory, and updates global struct
-  * accordingly.
-  *
-  * @str_func: a pointer to func struct.
-  * @return 0 on success or negative value on error.
-  */
-static int mailbox_to_seq_chunk_read_cfg(struct sdio_func *str_func)
-{
-	struct sdioc_reg_sequential_chunk_cfg seq_chunk;
-	struct sdioc_reg_chunk *reg = &sdio_dld->sdio_dloader_data.sdioc_reg;
-	int status = 0;
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	sdio_claim_host(str_func);
-
-	/* reading SDIOC_MAILBOX_SIZE bytes from SDIOC_MAILBOX_ADDRESS */
-	status = sdio_memcpy_fromio(str_func,
-				    (void *)&seq_chunk,
-				    SDIOC_MAILBOX_ADDRESS,
-				    SDIOC_CFG_REGS_SIZE);
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_fromio()"
-		       " READING CFG MAILBOX failed. status=%d.\n",
-		       __func__, status);
-	}
-
-	sdio_release_host(str_func);
-
-	reg->dl_buff_address.reg_val = seq_chunk.dl_buff_address;
-	reg->up_buff_address.reg_val = seq_chunk.up_buff_address;
-	reg->dl_buff_size.reg_val = seq_chunk.dl_buff_size;
-	reg->ul_buff_size.reg_val = seq_chunk.ul_buff_size;
-
-	/* keep sdio_dld_info up to date */
-	sdio_dld_info.cl_dl_buffer_size = seq_chunk.dl_buff_size;
-	sdio_dld_info.cl_up_buffer_size = seq_chunk.ul_buff_size;
-	sdio_dld_info.cl_dl_buffer_address = seq_chunk.dl_buff_address;
-	sdio_dld_info.cl_up_buffer_address = seq_chunk.up_buff_address;
-
-	return status;
-}
-
-/**
-  * mailbox_to_seq_chunk_read_ptrs
-  * reads 4 pointers registers of mailbox from str_func, as a
-  * sequentail chunk in memory, and updates global struct
-  * accordingly.
-  *
-  * @str_func: a pointer to func struct.
-  * @return 0 on success or negative value on error.
-  */
-static int mailbox_to_seq_chunk_read_ptrs(struct sdio_func *str_func)
-{
-	struct sdioc_reg_sequential_chunk_ptrs seq_chunk;
-	struct sdioc_reg_chunk *reg = &sdio_dld->sdio_dloader_data.sdioc_reg;
-	int status = 0;
-
-	struct sdio_data *outgoing = &sdio_dld->sdio_dloader_data.outgoing_data;
-	static int counter = 1;
-	static int offset_write_p;
-	static int offset_read_p;
-	static int up_wr_ptr;
-	static int up_rd_ptr;
-	static int dl_wr_ptr;
-	static int dl_rd_ptr;
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	sdio_claim_host(str_func);
-
-	/* reading SDIOC_MAILBOX_SIZE bytes from SDIOC_MAILBOX_ADDRESS */
-	status = sdio_memcpy_fromio(str_func,
-				    (void *)&seq_chunk,
-				    SDIOC_PTRS_OFFSET,
-				    SDIOC_PTR_REGS_SIZE);
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_fromio()"
-		       " READING PTRS MAILBOX failed. status=%d.\n",
-		       __func__, status);
-	}
-
-	sdio_release_host(str_func);
-
-	reg->dl_rd_ptr.reg_val = seq_chunk.dl_rd_ptr;
-	reg->dl_wr_ptr.reg_val = seq_chunk.dl_wr_ptr;
-	reg->up_rd_ptr.reg_val = seq_chunk.up_rd_ptr;
-	reg->up_wr_ptr.reg_val = seq_chunk.up_wr_ptr;
-
-	/* keeping sdio_dld_info up to date */
-	sdio_dld_info.cl_dl_rd_ptr = seq_chunk.dl_rd_ptr;
-	sdio_dld_info.cl_dl_wr_ptr = seq_chunk.dl_wr_ptr;
-	sdio_dld_info.cl_up_rd_ptr = seq_chunk.up_rd_ptr;
-	sdio_dld_info.cl_up_wr_ptr = seq_chunk.up_wr_ptr;
-
-
-	/* DEBUG - if there was a change in value */
-	if ((offset_write_p != outgoing->offset_write_p) ||
-	    (offset_read_p != outgoing->offset_read_p) ||
-	    (up_wr_ptr != reg->up_wr_ptr.reg_val) ||
-	    (up_rd_ptr != reg->up_rd_ptr.reg_val) ||
-	    (dl_wr_ptr != reg->dl_wr_ptr.reg_val) ||
-	    (dl_rd_ptr != reg->dl_rd_ptr.reg_val) ||
-	    (counter % PRINTING_GAP == 0)) {
-		counter = 1;
-		pr_debug(MODULE_NAME ": %s MailBox pointers: BLOCK_SIZE=%d, "
-			 "hw=%d, hr=%d, cuw=%d, cur=%d, cdw=%d, cdr=%d\n",
-			 __func__,
-			 SDIO_DL_BLOCK_SIZE,
-			 outgoing->offset_write_p,
-			 outgoing->offset_read_p,
-			 reg->up_wr_ptr.reg_val,
-			 reg->up_rd_ptr.reg_val,
-			 reg->dl_wr_ptr.reg_val,
-			 reg->dl_rd_ptr.reg_val);
-
-#ifdef CONFIG_DEBUG_FS
-		update_gd(SDIO_DLD_DEBUGFS_CASE_1_CODE);
-#endif
-		/* update static variables */
-		offset_write_p = outgoing->offset_write_p;
-		offset_read_p =	outgoing->offset_read_p;
-		up_wr_ptr = reg->up_wr_ptr.reg_val;
-		up_rd_ptr = reg->up_rd_ptr.reg_val;
-		dl_wr_ptr = reg->dl_wr_ptr.reg_val;
-		dl_rd_ptr = reg->dl_rd_ptr.reg_val;
-	} else {
-		counter++;
-	}
-	return status;
-}
-
-/**
-  * sdio_dld_init_func
-  * enables the sdio func, and sets the func block size.
-  *
-  * @str_func: a pointer to func struct.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_init_func(struct sdio_func *str_func)
-{
-	int status1 = 0;
-	int status2 = 0;
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	sdio_claim_host(str_func);
-
-	status1 = sdio_enable_func(str_func);
-	if (status1) {
-		sdio_release_host(str_func);
-		pr_err(MODULE_NAME ": %s - sdio_enable_func() failed. "
-		       "status=%d\n", __func__, status1);
-		return status1;
-	}
-
-	status2 = sdio_set_block_size(str_func, SDIO_DL_BLOCK_SIZE);
-	if (status2) {
-		pr_err(MODULE_NAME ": %s - sdio_set_block_size() failed. "
-		       "status=%d\n", __func__, status2);
-		status1 = sdio_disable_func(str_func);
-		if (status1) {
-			pr_err(MODULE_NAME ": %s - sdio_disable_func() "
-		       "failed. status=%d\n", __func__, status1);
-		}
-		sdio_release_host(str_func);
-		return status2;
-	}
-
-	sdio_release_host(str_func);
-	str_func->max_blksize = SDIO_DL_BLOCK_SIZE;
-	return 0;
-}
-
-/**
-  * sdio_dld_allocate_buffers
-  * initializes the sdio func, and then reads the mailbox, in
-  * order to allocate incoming and outgoing buffers according to
-  * the size that was read from the mailbox.
-  *
-  * @str_func: a pointer to func struct.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_allocate_buffers(struct sdio_func *str_func)
-{
-	int status = 0;
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	status = mailbox_to_seq_chunk_read_cfg(str_func);
-	if (status) {
-		pr_err(MODULE_NAME ": %s - Failure in Function "
-		       "mailbox_to_seq_chunk_read_cfg(). status=%d\n",
-		       __func__, status);
-		return status;
-	}
-
-	status = sdio_dld_allocate_local_buffers();
-	if (status) {
-		pr_err(MODULE_NAME ": %s - Failure in Function "
-		       "sdio_dld_allocate_local_buffers(). status=%d\n",
-		       __func__, status);
-		return status;
-	}
-	return 0;
-}
-
-/**
-  * sdio_dld_create_thread
-  * creates thread and wakes it up.
-  *
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_create_thread(void)
-{
-	sdio_dld->dld_main_thread.task_name = SDIO_DL_MAIN_THREAD_NAME;
-
-	sdio_dld->dld_main_thread.dld_task =
-		kthread_create(sdio_dld_main_task,
-			       (void *)(sdio_dld->card),
-			       sdio_dld->dld_main_thread.task_name);
-
-	if (IS_ERR(sdio_dld->dld_main_thread.dld_task)) {
-		pr_err(MODULE_NAME ": %s - kthread_create() failed\n",
-			__func__);
-		return -ENOMEM;
-	}
-	wake_up_process(sdio_dld->dld_main_thread.dld_task);
-	return 0;
-}
-
-/**
-  * start_timer
-  * sets the timer and starts.
-  *
-  * @timer: the timer to configure and add
-  * @ms: the ms until it expires
-  * @return None.
-  */
-static void start_timer(struct timer_list *timer, unsigned int ms)
-{
-	if ((ms == 0) || (timer == NULL)) {
-		pr_err(MODULE_NAME ": %s - invalid parameter", __func__);
-	} else {
-		timer->expires = jiffies +
-			msecs_to_jiffies(ms);
-		add_timer(timer);
-	}
-}
-
-/**
-  * sdio_dld_timer_handler
-  * this is the timer handler. whenever it is invoked, it wakes
-  * up the main loop task, and the write callback, and starts
-  * the timer again.
-  *
-  * @data: a pointer to the tty device driver structure.
-  * @return None.
-  */
-
-static void sdio_dld_timer_handler(unsigned long data)
-{
-	pr_debug(MODULE_NAME " Timer Expired\n");
-	spin_lock_irqsave(&lock2, lock_flags2);
-	if (sdio_dld->main_loop_event.wake_up_signal == 0) {
-		sdio_dld->main_loop_event.wake_up_signal = 1;
-		wake_up(&sdio_dld->main_loop_event.wait_event);
-	}
-	spin_unlock_irqrestore(&lock2, lock_flags2);
-
-	sdio_dld->write_callback_event.wake_up_signal = 1;
-	wake_up(&sdio_dld->write_callback_event.wait_event);
-
-	start_timer(&sdio_dld->timer, sdio_dld->poll_ms);
-}
-
-/**
-  * sdio_dld_push_timer_handler
-  * this is a timer handler of the push_timer.
-  *
-  * @data: a pointer to the tty device driver structure.
-  * @return None.
-  */
-static void sdio_dld_push_timer_handler(unsigned long data)
-{
-	pr_err(MODULE_NAME " %s - Push Timer Expired... Trying to "
-		"push data to TTY Core for over then %d ms.\n",
-		__func__, sdio_dld->push_timer_ms);
-}
-
-/**
-  * sdio_dld_open
-  * this is the open callback of the tty driver.
-  * it initializes the sdio func, allocates the buffers, and
-  * creates the main thread.
-  *
-  * @tty: a pointer to the tty struct.
-  * @file: file descriptor.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_open(struct tty_struct *tty, struct file *file)
-{
-	int status = 0;
-	int func_in_array =
-		REAL_FUNC_TO_FUNC_IN_ARRAY(sdio_dld->sdioc_boot_func);
-	struct sdio_func *str_func = sdio_dld->card->sdio_func[func_in_array];
-
-	if (atomic_read(&sdio_dld_in_use) == 1)
-		return -EBUSY;
-
-	atomic_set(&sdio_dld_in_use, 1);
-	sdio_dld->tty_str = tty;
-	sdio_dld->tty_str->low_latency = 1;
-	sdio_dld->tty_str->icanon = 0;
-	set_bit(TTY_NO_WRITE_SPLIT, &sdio_dld->tty_str->flags);
-
-	pr_info(MODULE_NAME ": %s, TTY DEVICE FOR FLASHLESS BOOT OPENED\n",
-	       __func__);
-	sdio_dld_info.start_time = get_jiffies_64(); /* read the current time */
-
-	if (!tty) {
-		pr_err(MODULE_NAME ": %s - param ""tty"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	atomic_set(&sdio_dld->dld_main_thread.please_close, 0);
-	sdio_dld->dld_main_thread.exit_wait.wake_up_signal = 0;
-
-	status = sdio_dld_allocate_buffers(str_func);
-	if (status) {
-		pr_err(MODULE_NAME ": %s, failed in "
-		       "sdio_dld_allocate_buffers(). status=%d\n",
-		       __func__, status);
-		return status;
-	}
-
-	/* init waiting event of the write callback */
-	init_waitqueue_head(&sdio_dld->write_callback_event.wait_event);
-
-	/* init waiting event of the main loop */
-	init_waitqueue_head(&sdio_dld->main_loop_event.wait_event);
-
-	/* configure and init the timer */
-	sdio_dld->poll_ms = TIMER_DURATION;
-	init_timer(&sdio_dld->timer);
-	sdio_dld->timer.data = (unsigned long) sdio_dld;
-	sdio_dld->timer.function = sdio_dld_timer_handler;
-	sdio_dld->timer.expires = jiffies +
-		msecs_to_jiffies(sdio_dld->poll_ms);
-	add_timer(&sdio_dld->timer);
-
-	sdio_dld->push_timer_ms = PUSH_TIMER_DURATION;
-	init_timer(&sdio_dld->push_timer);
-	sdio_dld->push_timer.data = (unsigned long) sdio_dld;
-	sdio_dld->push_timer.function = sdio_dld_push_timer_handler;
-
-	status = sdio_dld_create_thread();
-	if (status) {
-		del_timer_sync(&sdio_dld->timer);
-		del_timer_sync(&sdio_dld->push_timer);
-		sdio_dld_dealloc_local_buffers();
-		pr_err(MODULE_NAME ": %s, failed in sdio_dld_create_thread()."
-				   "status=%d\n", __func__, status);
-		return status;
-	}
-	return 0;
-}
-
-/**
-  * sdio_dld_close
-  * this is the close callback of the tty driver. it requests
-  * the main thread to exit, and waits for notification of it.
-  * it also de-allocates the buffers, and unregisters the tty
-  * driver and device.
-  *
-  * @tty: a pointer to the tty struct.
-  * @file: file descriptor.
-  * @return None.
-  */
-static void sdio_dld_close(struct tty_struct *tty, struct file *file)
-{
-	struct sdioc_reg_chunk *reg = &sdio_dld->sdio_dloader_data.sdioc_reg;
-
-	/* informing the SDIOC that it can exit boot phase */
-	sdio_dld->sdio_dloader_data.sdioc_reg.good_to_exit_ptr.reg_val =
-		SDIOC_EXIT_CODE;
-
-	atomic_set(&sdio_dld->dld_main_thread.please_close, 1);
-
-	pr_debug(MODULE_NAME ": %s - CLOSING - WAITING...", __func__);
-
-	wait_event(sdio_dld->dld_main_thread.exit_wait.wait_event,
-		   sdio_dld->dld_main_thread.exit_wait.wake_up_signal);
-	pr_debug(MODULE_NAME ": %s - CLOSING - WOKE UP...", __func__);
-
-#ifdef CONFIG_DEBUG_FS
-	gd.curr_i = curr_index;
-	gd.duration_ms = sdio_dld_info.time_msec;
-	gd.global_bytes_sent = sdio_dld_info.global_bytes_write_toio;
-	gd.global_bytes_received = 0;
-	gd.throughput_Mbs = sdio_dld_info.throughput;
-	gd.host_outgoing_buffer_size_KB = sdio_dld->sdio_dloader_data.
-		outgoing_data.buffer_size/BYTES_IN_KB;
-	gd.client_up_buffer_size_KB = reg->ul_buff_size.reg_val/BYTES_IN_KB;
-	gd.client_dl_buffer_size_KB = reg->dl_buff_size.reg_val/BYTES_IN_KB;
-	gd.client_dl_buffer_address = reg->dl_buff_address.reg_val;
-	gd.client_up_buffer_address = reg->up_buff_address.reg_val;
-	gd.global_bytes_received = sdio_dld_info.global_bytes_read_fromio;
-	gd.global_bytes_pushed = sdio_dld_info.global_bytes_push_tty;
-#endif
-
-	/* saving register values before deallocating sdio_dld
-	   in order to use it in sdio_dld_print_info() through shell command */
-	sdio_dld_info.cl_dl_rd_ptr = reg->dl_rd_ptr.reg_val;
-	sdio_dld_info.cl_dl_wr_ptr = reg->dl_wr_ptr.reg_val;
-	sdio_dld_info.cl_up_rd_ptr = reg->up_rd_ptr.reg_val;
-	sdio_dld_info.cl_up_wr_ptr = reg->up_wr_ptr.reg_val;
-
-	sdio_dld_info.host_read_ptr =
-		sdio_dld->sdio_dloader_data.outgoing_data.offset_read_p;
-
-	sdio_dld_info.host_write_ptr =
-		sdio_dld->sdio_dloader_data.outgoing_data.offset_write_p;
-
-	sdio_dld_info.cl_dl_buffer_size =
-		sdio_dld->sdio_dloader_data.sdioc_reg.dl_buff_size.reg_val;
-
-	sdio_dld_info.cl_up_buffer_size =
-		sdio_dld->sdio_dloader_data.sdioc_reg.ul_buff_size.reg_val;
-
-	sdio_dld_info.host_outgoing_buffer_size =
-		sdio_dld->sdio_dloader_data.outgoing_data.buffer_size;
-
-	sdio_dld_info.cl_dl_buffer_address =
-		sdio_dld->sdio_dloader_data.sdioc_reg.dl_buff_address.reg_val;
-
-	sdio_dld_info.cl_up_buffer_address =
-		sdio_dld->sdio_dloader_data.sdioc_reg.up_buff_address.reg_val;
-
-	sdio_dld_print_info();
-
-	if (sdio_dld->done_callback)
-		sdio_dld->done_callback();
-
-	schedule_work(&cleanup);
-	pr_info(MODULE_NAME ": %s - Bootloader done, returning...", __func__);
-}
-
-/**
-  * writing_size_to_buf
-  * writes from src buffer into dest buffer. if dest buffer
-  * reaches its end, rollover happens.
-  *
-  * @dest: destination buffer.
-  * @src: source buffer.
-  * @dest_wr_ptr: writing pointer in destination buffer.
-  * @dest_size: destination buffer size.
-  * @dest_rd_ptr: reading pointer in destination buffer.
-  * @size_to_write: size of bytes to write.
-  * @return -how many bytes actually written to destination
-  * buffer.
-  *
-  * ONLY destination buffer is treated as cyclic buffer.
-  */
-static int writing_size_to_buf(char *dest,
-			       const unsigned char *src,
-			       int *dest_wr_ptr,
-			       int dest_size,
-			       int dest_rd_ptr,
-			       int size_to_write)
-{
-	int actually_written = 0;
-	int size_to_add = *dest_wr_ptr;
-
-	if (!dest) {
-		pr_err(MODULE_NAME ": %s - param ""dest"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!src) {
-		pr_err(MODULE_NAME ": %s - param ""src"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!dest_wr_ptr) {
-		pr_err(MODULE_NAME ": %s - param ""dest_wr_ptr"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	for (actually_written = 0 ;
-	      actually_written < size_to_write ; ++actually_written) {
-		/* checking if buffer is full */
-		if (((size_to_add + 1) % dest_size) == dest_rd_ptr) {
-			*dest_wr_ptr = size_to_add;
-			return actually_written;
-		}
-
-		dest[size_to_add] = src[actually_written];
-		size_to_add = (size_to_add+1)%dest_size;
-	}
-
-	*dest_wr_ptr = size_to_add;
-
-	return actually_written;
-}
-
-/**
-  * sdioc_bytes_till_end_of_buffer - this routine calculates how many bytes are
-  * empty/in use. if calculation requires rap around - it will ignore the rap
-  * around and will do the calculation untill the end of the buffer
-  *
-  * @write_ptr: writing pointer.
-  * @read_ptr: reading pointer.
-  * @total_size: buffer size.
-  * @free_bytes: return value-how many free bytes.
-  * @bytes_in_use: return value-how many bytes in use.
-  * @return 0 on success or negative value on error.
-  *
-  * buffer is treated as a cyclic buffer.
-  */
-static int sdioc_bytes_till_end_of_buffer(int write_ptr,
-					  int read_ptr,
-					  int total_size,
-					  int *free_bytes,
-					  int *bytes_in_use)
-{
-	if (!free_bytes) {
-		pr_err(MODULE_NAME ": %s - param ""free_bytes"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!bytes_in_use) {
-		pr_err(MODULE_NAME ": %s - param ""bytes_in_use"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (write_ptr >= read_ptr) {
-		if (read_ptr == 0)
-			*free_bytes = total_size - write_ptr - 1;
-		else
-			*free_bytes = total_size - write_ptr;
-		*bytes_in_use = write_ptr - read_ptr;
-	} else {
-		*bytes_in_use = total_size - read_ptr;
-		*free_bytes = read_ptr - write_ptr - 1;
-	}
-
-	return  0;
-}
-
-/**
-  * sdioc_bytes_free_in_buffer
-  * this routine calculates how many bytes are free in a buffer
-  * and how many are in use, according to its reading and
-  * writing pointer offsets.
-  *
-  * @write_ptr: writing pointer.
-  * @read_ptr: reading pointer.
-  * @total_size: buffer size.
-  * @free_bytes: return value-how many free bytes in buffer.
-  * @bytes_in_use: return value-how many bytes in use in buffer.
-  * @return 0 on success or negative value on error.
-  *
-  * buffer is treated as a cyclic buffer.
-  */
-static int sdioc_bytes_free_in_buffer(int write_ptr,
-				      int read_ptr,
-				      int total_size,
-				      int *free_bytes,
-				      int *bytes_in_use)
-{
-	if (!free_bytes) {
-		pr_err(MODULE_NAME ": %s - param ""free_bytes"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!bytes_in_use) {
-		pr_err(MODULE_NAME ": %s - param ""bytes_in_use"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	/* if pointers equel - buffers are empty. nothing to read/write */
-
-	if (write_ptr >= read_ptr)
-		*bytes_in_use = write_ptr - read_ptr;
-	else
-		*bytes_in_use = total_size - (read_ptr - write_ptr);
-
-	*free_bytes = total_size - *bytes_in_use - 1;
-
-	return 0;
-}
-
-/*
-* sdio_dld_write_room
-*
-* This is the write_room function of the tty driver.
-*
-* @tty: pointer to tty struct.
-* @return free bytes for write.
-*
-*/
-static int sdio_dld_write_room(struct tty_struct *tty)
-{
-	return sdio_dld->sdio_dloader_data.outgoing_data.buffer_size;
-}
-
-/**
-  * sdio_dld_write_callback
-  * this is the write callback of the tty driver.
-  *
-  * @tty: pointer to tty struct.
-  * @buf: buffer to write from.
-  * @count: number of bytes to write.
-  * @return bytes written or negative value on error.
-  *
-  * if destination buffer has not enough room for the incoming
-  * data, returns an error.
-  */
-static int sdio_dld_write_callback(struct tty_struct *tty,
-				   const unsigned char *buf, int count)
-{
-	struct sdio_data *outgoing = &sdio_dld->sdio_dloader_data.outgoing_data;
-	int dst_free_bytes = 0;
-	int dummy = 0;
-	int status = 0;
-	int bytes_written = 0;
-	int total_written = 0;
-	static int write_retry;
-	int pending_to_write = count;
-
-#ifdef CONFIG_DEBUG_FS
-	debugfs_glob.global_count = count;
-	update_gd(SDIO_DLD_DEBUGFS_CASE_5_CODE);
-#endif
-
-	pr_debug(MODULE_NAME ": %s - WRITING CALLBACK CALLED WITH %d bytes\n",
-		 __func__, count);
-
-	if (!outgoing->data) {
-		pr_err(MODULE_NAME ": %s - param ""outgoing->data"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	pr_debug(MODULE_NAME ": %s - WRITE CALLBACK size to write to outgoing"
-		 " buffer %d\n", __func__, count);
-
-	/* as long as there is something to write to outgoing buffer */
-	do {
-		int bytes_to_write = 0;
-		status = sdioc_bytes_free_in_buffer(
-			outgoing->offset_write_p,
-			outgoing->offset_read_p,
-			outgoing->buffer_size,
-			&dst_free_bytes,
-			&dummy);
-
-		if (status) {
-			pr_err(MODULE_NAME ": %s - Failure in Function "
-			       "sdioc_bytes_free_in_buffer(). status=%d\n",
-			       __func__, status);
-			return status;
-		}
-
-		/*
-		 * if there is free room in outgoing buffer
-		 * lock mutex and request trigger notification from the main
-		 * task. unlock mutex, and wait for sinal
-		 */
-		if (dst_free_bytes > 0) {
-			write_retry = 0;
-			/*
-			 * if there is more data to write to outgoing buffer
-			 * than it can receive, wait for signal from main task
-			 */
-			if (pending_to_write > dst_free_bytes) {
-
-				/* sampling updated dst_free_bytes */
-				status = sdioc_bytes_free_in_buffer(
-				outgoing->offset_write_p,
-				outgoing->offset_read_p,
-				outgoing->buffer_size,
-				&dst_free_bytes,
-				&dummy);
-
-				if (status) {
-					pr_err(MODULE_NAME ": %s - Failure in "
-							   "Function "
-					       "sdioc_bytes_free_in_buffer(). "
-					       "status=%d\n", __func__, status);
-					return status;
-				}
-			}
-
-			bytes_to_write = min(pending_to_write, dst_free_bytes);
-			bytes_written =
-				writing_size_to_buf(outgoing->data,
-						    buf+total_written,
-						    &outgoing->offset_write_p,
-						    outgoing->buffer_size,
-						    outgoing->offset_read_p,
-						    bytes_to_write);
-
-			/* keeping sdio_dld_info up to date */
-			sdio_dld_info.host_write_ptr =
-				sdio_dld->sdio_dloader_data.
-					    outgoing_data.offset_write_p;
-
-#ifdef CONFIG_DEBUG_FS
-			debugfs_glob.global_write_tty = bytes_written;
-			update_gd(SDIO_DLD_DEBUGFS_CASE_3_CODE);
-#endif
-			sdio_dld_info.global_bytes_write_tty += bytes_written;
-
-			spin_lock_irqsave(&lock2, lock_flags2);
-			if (sdio_dld->main_loop_event.wake_up_signal == 0) {
-				sdio_dld->main_loop_event.wake_up_signal = 1;
-				wake_up(&sdio_dld->main_loop_event.wait_event);
-			}
-			spin_unlock_irqrestore(&lock2, lock_flags2);
-
-			/*
-			 * although outgoing buffer has enough room, writing
-			 * failed
-			 */
-			if (bytes_written != bytes_to_write) {
-				pr_err(MODULE_NAME ": %s - couldn't write "
-				       "%d bytes to " "outgoing buffer."
-				       "bytes_written=%d\n",
-				       __func__, bytes_to_write,
-				       bytes_written);
-			       return -EIO;
-			}
-
-			total_written += bytes_written;
-			pending_to_write -= bytes_written;
-			outgoing->num_of_bytes_in_use += bytes_written;
-
-			pr_debug(MODULE_NAME ": %s - WRITE CHUNK to outgoing "
-					   "buffer. pending_to_write=%d, "
-					   "outgoing_free_bytes=%d, "
-					   "bytes_written=%d\n",
-				 __func__,
-				 pending_to_write,
-				 dst_free_bytes,
-				 bytes_written);
-
-		} else {
-			write_retry++;
-
-			pr_debug(MODULE_NAME ": %s - WRITE CALLBACK - NO ROOM."
-			       " pending_to_write=%d, write_retry=%d\n",
-				 __func__,
-				 pending_to_write,
-				 write_retry);
-
-			spin_lock_irqsave(&lock1, lock_flags1);
-			sdio_dld->write_callback_event.wake_up_signal = 0;
-			spin_unlock_irqrestore(&lock1, lock_flags1);
-
-			pr_debug(MODULE_NAME ": %s - WRITE CALLBACK - "
-					     "WAITING...", __func__);
-#ifdef CONFIG_DEBUG_FS
-			update_gd(SDIO_DLD_DEBUGFS_CASE_8_CODE);
-#endif
-			wait_event(sdio_dld->write_callback_event.wait_event,
-				   sdio_dld->write_callback_event.
-				   wake_up_signal);
-#ifdef CONFIG_DEBUG_FS
-			update_gd(SDIO_DLD_DEBUGFS_CASE_9_CODE);
-#endif
-			pr_debug(MODULE_NAME ": %s - WRITE CALLBACK - "
-					     "WOKE UP...", __func__);
-		}
-	} while (pending_to_write > 0 && write_retry < WRITE_RETRIES);
-
-	if (pending_to_write > 0) {
-
-		pr_err(MODULE_NAME ": %s - WRITE CALLBACK - pending data is "
-				   "%d out of %d > 0. total written in this "
-				   "callback = %d\n",
-		       __func__, pending_to_write, count, total_written);
-	}
-
-	if (write_retry == WRITE_RETRIES) {
-		pr_err(MODULE_NAME ": %s, write_retry=%d= max\n",
-		       __func__, write_retry);
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	debugfs_glob.global_bytes_cb_tty = total_written;
-	update_gd(SDIO_DLD_DEBUGFS_CASE_10_CODE);
-#endif
-
-	return total_written;
-}
-
-/**
-  * sdio_memcpy_fromio_wrapper -
-  * reads from sdioc, and updats the sdioc registers according
-  * to how many bytes were actually read.
-  *
-  * @str_func: a pointer to func struct.
-  * @client_rd_ptr: sdioc value of downlink read ptr.
-  * @client_wr_ptr: sdioc value of downlink write ptr.
-  * @buffer_to_store: buffer to store incoming data.
-  * @address_to_read: address to start reading from in sdioc.
-  * @size_to_read: size of bytes to read.
-  * @client_buffer_size: sdioc downlink buffer size.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_memcpy_fromio_wrapper(struct sdio_func *str_func,
-				      unsigned int client_rd_ptr,
-				      unsigned int client_wr_ptr,
-				      void *buffer_to_store,
-				      unsigned int address_to_read_from,
-				      int size_to_read,
-				      int client_buffer_size)
-{
-	int status = 0;
-	struct sdioc_reg_chunk *reg_str =
-		&sdio_dld->sdio_dloader_data.sdioc_reg;
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!buffer_to_store) {
-		pr_err(MODULE_NAME ": %s - param ""buffer_to_store"" is "
-				   "NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (size_to_read < 0) {
-		pr_err(MODULE_NAME ": %s - invalid size to read=%d\n",
-			__func__, size_to_read);
-		return -EINVAL;
-	}
-
-	sdio_claim_host(str_func);
-
-	pr_debug(MODULE_NAME ": %s, READING DATA - from add %d, "
-			   "size_to_read=%d\n",
-	       __func__, address_to_read_from, size_to_read);
-
-	status = sdio_memcpy_fromio(str_func,
-				    (void *)buffer_to_store,
-				    address_to_read_from,
-				    size_to_read);
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_fromio()"
-		       " DATA failed. status=%d.\n",
-		       __func__, status);
-		sdio_release_host(str_func);
-		return status;
-	}
-
-	/* updating an offset according to cyclic buffer size */
-	reg_str->dl_rd_ptr.reg_val =
-		(reg_str->dl_rd_ptr.reg_val + size_to_read) %
-		client_buffer_size;
-	/* keeping sdio_dld_info up to date */
-	sdio_dld_info.cl_dl_rd_ptr = reg_str->dl_rd_ptr.reg_val;
-
-	status = sdio_memcpy_toio(str_func,
-				  reg_str->dl_rd_ptr.reg_offset,
-				  (void *)&reg_str->dl_rd_ptr.reg_val,
-				  sizeof(reg_str->dl_rd_ptr.reg_val));
-
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_toio() "
-		       "UPDATE PTR failed. status=%d.\n",
-		       __func__, status);
-	}
-
-	sdio_release_host(str_func);
-	return status;
-}
-
-/**
-  * sdio_memcpy_toio_wrapper
-  * writes to sdioc, and updats the sdioc registers according
-  * to how many bytes were actually read.
-  *
-  * @str_func: a pointer to func struct.
-  * @client_wr_ptr: sdioc downlink write ptr.
-  * @h_read_ptr: host incoming read ptrs
-  * @buf_write_from: buffer to write from.
-  * @bytes_to_write: number of bytes to write.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_memcpy_toio_wrapper(struct sdio_func *str_func,
-				    unsigned int client_wr_ptr,
-				    unsigned int h_read_ptr,
-				    void *buf_write_from,
-				    int bytes_to_write)
-{
-	int status = 0;
-	struct sdioc_reg_chunk *reg_str =
-		&sdio_dld->sdio_dloader_data.sdioc_reg;
-	struct sdio_data *outgoing = &sdio_dld->sdio_dloader_data.outgoing_data;
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!buf_write_from) {
-		pr_err(MODULE_NAME ": %s - param ""buf_write_from"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	sdio_claim_host(str_func);
-
-	pr_debug(MODULE_NAME ": %s, WRITING DATA TOIO to address 0x%x, "
-		 "bytes_to_write=%d\n",
-		 __func__,
-		reg_str->up_buff_address.reg_val + reg_str->up_wr_ptr.reg_val,
-		 bytes_to_write);
-
-	status = sdio_memcpy_toio(str_func,
-				  reg_str->up_buff_address.reg_val +
-				  reg_str->up_wr_ptr.reg_val,
-				  (void *) (outgoing->data + h_read_ptr),
-				  bytes_to_write);
-
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_toio() "
-		       "DATA failed. status=%d.\n", __func__, status);
-		sdio_release_host(str_func);
-		return status;
-	}
-
-	sdio_dld_info.global_bytes_write_toio += bytes_to_write;
-	outgoing->num_of_bytes_in_use -= bytes_to_write;
-
-	/*
-	 * if writing to client succeeded, then
-	 * 1. update the client up_wr_ptr
-	 * 2. update the host outgoing rd ptr
-	 **/
-	reg_str->up_wr_ptr.reg_val =
-		((reg_str->up_wr_ptr.reg_val + bytes_to_write) %
-		 reg_str->ul_buff_size.reg_val);
-
-	/* keeping sdio_dld_info up to date */
-	sdio_dld_info.cl_up_wr_ptr = reg_str->up_wr_ptr.reg_val;
-
-	outgoing->offset_read_p =
-		((outgoing->offset_read_p + bytes_to_write) %
-		  outgoing->buffer_size);
-
-	/* keeping sdio_dld_info up to date*/
-	sdio_dld_info.host_read_ptr = outgoing->offset_read_p;
-
-#ifdef CONFIG_DEBUG_FS
-	debugfs_glob.global_write_toio = bytes_to_write;
-	update_gd(SDIO_DLD_DEBUGFS_CASE_4_CODE);
-#endif
-
-	/* updating uplink write pointer according to size that was written */
-	status = sdio_memcpy_toio(str_func,
-				  reg_str->up_wr_ptr.reg_offset,
-				  (void *)(&reg_str->up_wr_ptr.reg_val),
-				  sizeof(reg_str->up_wr_ptr.reg_val));
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_toio() "
-				       "UPDATE PTR failed. status=%d.\n",
-		       __func__, status);
-	}
-
-	sdio_release_host(str_func);
-	return status;
-}
-
-/**
-  * sdio_dld_read
-  * reads from sdioc
-  *
-  * @client_rd_ptr: sdioc downlink read ptr.
-  * @client_wr_ptr: sdioc downlink write ptr.
-  * @reg_str: sdioc register shadowing struct.
-  * @str_func: a pointer to func struct.
-  * @bytes_read:how many bytes read.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_read(unsigned int client_rd_ptr,
-			 unsigned int client_wr_ptr,
-			 struct sdioc_reg_chunk *reg_str,
-			 struct sdio_func *str_func,
-			 int *bytes_read)
-{
-	int status = 0;
-	struct sdio_data *incoming = &sdio_dld->sdio_dloader_data.incoming_data;
-
-	if (!reg_str) {
-		pr_err(MODULE_NAME ": %s - param ""reg_str"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!bytes_read) {
-		pr_err(MODULE_NAME ": %s - param ""bytes_read"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	/* there is data to read in ONE chunk */
-	if (client_wr_ptr > client_rd_ptr) {
-		status = sdio_memcpy_fromio_wrapper(
-			str_func,
-			client_rd_ptr,
-			client_wr_ptr,
-			(void *)incoming->data,
-			reg_str->dl_buff_address.reg_val + client_rd_ptr,
-			client_wr_ptr - client_rd_ptr,
-			reg_str->dl_buff_size.reg_val);
-
-		if (status) {
-			pr_err(MODULE_NAME ": %s - Failure in Function "
-			       "sdio_memcpy_fromio_wrapper(). "
-			       "SINGLE CHUNK READ. status=%d\n",
-			       __func__, status);
-			return status;
-		}
-
-		incoming->num_of_bytes_in_use += client_wr_ptr - client_rd_ptr;
-		*bytes_read = client_wr_ptr - client_rd_ptr;
-
-#ifdef CONFIG_DEBUG_FS
-			debugfs_glob.global_to_read =
-				client_wr_ptr - client_rd_ptr;
-			update_gd(SDIO_DLD_DEBUGFS_CASE_11_CODE);
-#endif
-	}
-
-	/* there is data to read in TWO chunks */
-	else {
-		int dl_buf_size = reg_str->dl_buff_size.reg_val;
-		int tail_size = dl_buf_size - client_rd_ptr;
-
-		/* reading chunk#1: from rd_ptr to the end of the buffer */
-		status = sdio_memcpy_fromio_wrapper(
-			str_func,
-			client_rd_ptr,
-			dl_buf_size,
-			(void *)incoming->data,
-			reg_str->dl_buff_address.reg_val + client_rd_ptr,
-			tail_size,
-			dl_buf_size);
-
-		if (status) {
-			pr_err(MODULE_NAME ": %s - Failure in Function "
-			       "sdio_memcpy_fromio_wrapper(). "
-			       "1 of 2 CHUNKS READ. status=%d\n",
-			       __func__, status);
-			return status;
-		}
-
-		incoming->num_of_bytes_in_use += tail_size;
-		*bytes_read = tail_size;
-
-#ifdef CONFIG_DEBUG_FS
-			debugfs_glob.global_to_read = tail_size;
-			update_gd(SDIO_DLD_DEBUGFS_CASE_11_CODE);
-#endif
-
-		/* reading chunk#2: reading from beginning buffer */
-		status = sdio_memcpy_fromio_wrapper(
-			str_func,
-			client_rd_ptr,
-			client_wr_ptr,
-			(void *)(incoming->data + tail_size),
-			reg_str->dl_buff_address.reg_val,
-			client_wr_ptr,
-			reg_str->dl_buff_size.reg_val);
-
-		if (status) {
-			pr_err(MODULE_NAME ": %s - Failure in Function "
-			       "sdio_memcpy_fromio_wrapper(). "
-			       "2 of 2 CHUNKS READ. status=%d\n",
-			       __func__, status);
-			return status;
-		}
-
-		incoming->num_of_bytes_in_use += client_wr_ptr;
-		*bytes_read += client_wr_ptr;
-
-#ifdef CONFIG_DEBUG_FS
-			debugfs_glob.global_to_read = client_wr_ptr;
-			update_gd(SDIO_DLD_DEBUGFS_CASE_11_CODE);
-#endif
-	}
-	return 0;
-}
-
-/**
-  * sdio_dld_main_task
-  * sdio downloader main task. reads mailboxf checks if there is
-  * anything to read, checks if host has anything to
-  * write.
-  *
-  * @card: a pointer to mmc_card.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_main_task(void *card)
-{
-	int status = 0;
-	struct tty_struct *tty = sdio_dld->tty_str;
-	struct sdioc_reg_chunk *reg_str =
-		&sdio_dld->sdio_dloader_data.sdioc_reg;
-	int func = sdio_dld->sdioc_boot_func;
-	struct sdio_func *str_func = NULL;
-	struct sdio_data *outgoing = &sdio_dld->sdio_dloader_data.outgoing_data;
-	struct sdio_data *incoming = &sdio_dld->sdio_dloader_data.incoming_data;
-	struct sdio_dld_task *task = &sdio_dld->dld_main_thread;
-	int retries = 0;
-#ifdef PUSH_STRING
-	int bytes_pushed = 0;
-#endif
-
-	msleep(SLEEP_MS);
-
-	if (!card) {
-		pr_err(MODULE_NAME ": %s - param ""card"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!tty) {
-		pr_err(MODULE_NAME ": %s - param ""tty"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	str_func = ((struct mmc_card *)card)->
-		sdio_func[REAL_FUNC_TO_FUNC_IN_ARRAY(func)];
-
-	if (!str_func) {
-		pr_err(MODULE_NAME ": %s - param ""str_func"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	while (true) {
-		/* client pointers for both buffers */
-		int client_ul_wr_ptr = 0;
-		int client_ul_rd_ptr = 0;
-		int client_dl_wr_ptr = 0;
-		int client_dl_rd_ptr = 0;
-
-		/* host pointer for outgoing buffer */
-		int h_out_wr_ptr = 0;
-		int h_out_rd_ptr = 0;
-
-		int h_bytes_rdy_wr = 0;
-		int c_bytes_rdy_rcve = 0;
-
-		int need_to_write = 0;
-		int need_to_read = 0;
-
-		/*
-		 * forever, checking for signal to die, then read MailBox.
-		 * if nothing to read or nothing to write to client, sleep,
-		 * and again read MailBox
-		 */
-		do {
-			int dummy = 0;
-
-			/*  checking if a signal to die was sent */
-			if (atomic_read(&task->please_close) == 1) {
-
-				pr_debug(MODULE_NAME ": %s - 0x%x was written "
-					 "to 9K\n", __func__, SDIOC_EXIT_CODE);
-
-				sdio_claim_host(str_func);
-
-				/* returned value is not checked on purpose */
-				sdio_memcpy_toio(
-					str_func,
-					reg_str->good_to_exit_ptr.reg_offset,
-					(void *)&reg_str->good_to_exit_ptr.
-					reg_val,
-					sizeof(reg_str->good_to_exit_ptr.
-					       reg_val));
-
-				sdio_release_host(str_func);
-
-				task->exit_wait.wake_up_signal = 1;
-				wake_up(&task->exit_wait.wait_event);
-				return 0;
-			}
-
-			status = mailbox_to_seq_chunk_read_ptrs(str_func);
-			if (status) {
-				pr_err(MODULE_NAME ": %s - Failure in Function "
-				       "mailbox_to_seq_chunk_read_ptrs(). "
-				       "status=%d\n", __func__, status);
-				return status;
-			}
-
-			/* calculate how many bytes the host has send */
-			h_out_wr_ptr = outgoing->offset_write_p;
-			h_out_rd_ptr = outgoing->offset_read_p;
-
-			status = sdioc_bytes_till_end_of_buffer(
-				h_out_wr_ptr,
-				h_out_rd_ptr,
-				outgoing->buffer_size,
-				&dummy,
-				&h_bytes_rdy_wr);
-
-			if (status) {
-				pr_err(MODULE_NAME ": %s - Failure in Function "
-				       "sdioc_bytes_till_end_of_buffer(). "
-				       "status=%d\n", __func__, status);
-				return status;
-			}
-
-			/* is there something to read from client */
-			client_dl_wr_ptr = reg_str->dl_wr_ptr.reg_val;
-			client_dl_rd_ptr = reg_str->dl_rd_ptr.reg_val;
-
-			if (client_dl_rd_ptr != client_dl_wr_ptr)
-				need_to_read = 1;
-
-			/*
-			 *  calculate how many bytes the client can receive
-			 *  from host
-			 */
-			client_ul_wr_ptr = reg_str->up_wr_ptr.reg_val;
-			client_ul_rd_ptr = reg_str->up_rd_ptr.reg_val;
-
-			status = sdioc_bytes_till_end_of_buffer(
-				client_ul_wr_ptr,
-				client_ul_rd_ptr,
-				reg_str->ul_buff_size.reg_val,
-				&c_bytes_rdy_rcve,
-				&dummy);
-
-			if (status) {
-				pr_err(MODULE_NAME ": %s - Failure in Function "
-				       "sdioc_bytes_till_end_of_buffer(). "
-				       "status=%d\n", __func__, status);
-				return status;
-			}
-
-			/* if host has anything to write */
-			if (h_bytes_rdy_wr > 0)
-				need_to_write = 1;
-
-			if (need_to_write || need_to_read)
-				break;
-
-			spin_lock_irqsave(&lock2, lock_flags2);
-			sdio_dld->main_loop_event.wake_up_signal = 0;
-			spin_unlock_irqrestore(&lock2, lock_flags2);
-
-			pr_debug(MODULE_NAME ": %s - MAIN LOOP - WAITING...\n",
-				 __func__);
-#ifdef CONFIG_DEBUG_FS
-			update_gd(SDIO_DLD_DEBUGFS_CASE_6_CODE);
-#endif
-			wait_event(sdio_dld->main_loop_event.wait_event,
-				   sdio_dld->main_loop_event.wake_up_signal);
-#ifdef CONFIG_DEBUG_FS
-			update_gd(SDIO_DLD_DEBUGFS_CASE_7_CODE);
-#endif
-
-			pr_debug(MODULE_NAME ": %s - MAIN LOOP - WOKE UP...\n",
-				 __func__);
-
-		} while (1);
-
-		/* CHECK IF THERE IS ANYTHING TO READ IN CLIENT */
-		if (need_to_read) {
-#ifdef PUSH_STRING
-			int num_push = 0;
-			int left = 0;
-			int bytes_read;
-#else
-			int i;
-#endif
-			need_to_read = 0;
-
-			status = sdio_dld_read(client_dl_rd_ptr,
-					       client_dl_wr_ptr,
-					       reg_str,
-					       str_func,
-					       &bytes_read);
-
-			if (status) {
-				pr_err(MODULE_NAME ": %s - Failure in Function "
-				       "sdio_dld_read(). status=%d\n",
-				       __func__, status);
-				return status;
-			}
-
-			sdio_dld_info.global_bytes_read_fromio +=
-				bytes_read;
-
-			bytes_pushed = 0;
-#ifdef PUSH_STRING
-			left = incoming->num_of_bytes_in_use;
-			start_timer(&sdio_dld->push_timer,
-				    sdio_dld->push_timer_ms);
-			do {
-				num_push = tty_insert_flip_string(
-					tty,
-					incoming->data+bytes_pushed,
-					left);
-
-				bytes_pushed += num_push;
-				left -= num_push;
-				tty_flip_buffer_push(tty);
-			} while (left != 0);
-
-			del_timer(&sdio_dld->push_timer);
-
-			if (bytes_pushed != incoming->num_of_bytes_in_use) {
-				pr_err(MODULE_NAME ": %s - failed\n",
-				       __func__);
-			}
-#else
-			pr_debug(MODULE_NAME ": %s - NEED TO READ %d\n",
-			       __func__, incoming->num_of_bytes_in_use);
-
-			for (i = 0 ; i < incoming->num_of_bytes_in_use ; ++i) {
-				int err = 0;
-				err = tty_insert_flip_char(tty,
-							   incoming->data[i],
-							   TTY_NORMAL);
-				tty_flip_buffer_push(tty);
-			}
-
-			pr_debug(MODULE_NAME ": %s - JUST READ\n", __func__);
-#endif /*PUSH_STRING*/
-			sdio_dld_info.global_bytes_push_tty +=
-				incoming->num_of_bytes_in_use;
-#ifdef CONFIG_DEBUG_FS
-			debugfs_glob.global_push_to_tty = bytes_read;
-			update_gd(SDIO_DLD_DEBUGFS_CASE_12_CODE);
-#endif
-			incoming->num_of_bytes_in_use = 0;
-			tty_flip_buffer_push(tty);
-		}
-
-		/* CHECK IF THERE IS ANYTHING TO WRITE IN HOST AND HOW MUCH */
-		if (need_to_write) {
-			int dummy = 0;
-
-			do {
-				int bytes_to_write = min(c_bytes_rdy_rcve,
-							 h_bytes_rdy_wr);
-
-				/*
-				 * in case nothing to send or no room to
-				 * receive
-				 */
-				if (bytes_to_write == 0)
-					break;
-
-				if (client_ul_rd_ptr == 0 &&
-				    (client_ul_rd_ptr != client_ul_wr_ptr))
-					break;
-
-				/*
-				 * if client_rd_ptr points to start, but there
-				 * is data to read wait until WRITE_TILL_END
-				 * before writing a chunk of data, to avoid
-				 * writing until (BUF_SIZE - 1), because it will
-				 * yield an extra write of "1" bytes
-				 */
-				if (client_ul_rd_ptr == 0 &&
-				    (client_ul_rd_ptr != client_ul_wr_ptr) &&
-				    retries < WRITE_TILL_END_RETRIES) {
-					retries++;
-					break;
-				}
-				retries = 0;
-
-#ifdef CONFIG_DEBUG_FS
-				debugfs_glob.global_8k_has = h_bytes_rdy_wr;
-				debugfs_glob.global_9k_has = c_bytes_rdy_rcve;
-				debugfs_glob.global_min = bytes_to_write;
-				update_gd(SDIO_DLD_DEBUGFS_CASE_2_CODE);
-#endif
-				need_to_write = 0;
-
-				pr_debug(MODULE_NAME ": %s - NEED TO WRITE "
-					 "TOIO %d\n",
-					 __func__, bytes_to_write);
-
-				status = sdio_memcpy_toio_wrapper(
-					str_func,
-					reg_str->up_wr_ptr.reg_val,
-					outgoing->offset_read_p,
-					(void *)((char *)outgoing->data +
-						 outgoing->offset_read_p),
-					bytes_to_write);
-
-				if (status) {
-					pr_err(MODULE_NAME ": %s - Failure in "
-					       "Function "
-					       "sdio_memcpy_toio_wrapper(). "
-					       "SINGLE CHUNK WRITE. "
-					       "status=%d\n",
-					       __func__, status);
-					return status;
-				}
-
-				sdio_claim_host(str_func);
-
-				status = sdio_memcpy_fromio(
-					str_func,
-					(void *)&reg_str->up_rd_ptr.reg_val,
-					SDIOC_UL_RD_PTR,
-					sizeof(reg_str->up_rd_ptr.reg_val));
-
-				if (status) {
-					pr_err(MODULE_NAME ": %s - "
-					       "sdio_memcpy_fromio() "
-					       "failed. status=%d\n",
-					       __func__, status);
-					sdio_release_host(str_func);
-
-					return status;
-				}
-
-				sdio_release_host(str_func);
-
-				spin_lock_irqsave(&lock1, lock_flags1);
-				if (sdio_dld->write_callback_event.
-				    wake_up_signal == 0) {
-					sdio_dld->write_callback_event.
-						wake_up_signal = 1;
-					wake_up(&sdio_dld->
-						write_callback_event.
-						wait_event);
-				}
-
-				spin_unlock_irqrestore(&lock1, lock_flags1);
-				client_ul_wr_ptr = reg_str->up_wr_ptr.reg_val;
-				client_ul_rd_ptr = reg_str->up_rd_ptr.reg_val;
-
-				status = sdioc_bytes_till_end_of_buffer(
-					client_ul_wr_ptr,
-					client_ul_rd_ptr,
-					reg_str->ul_buff_size.reg_val,
-					&c_bytes_rdy_rcve,
-					&dummy);
-
-				/* calculate how many bytes host has to send */
-				h_out_wr_ptr = outgoing->offset_write_p;
-				h_out_rd_ptr = outgoing->offset_read_p;
-
-				status = sdioc_bytes_till_end_of_buffer(
-					h_out_wr_ptr,
-					h_out_rd_ptr,
-					outgoing->buffer_size,
-					&dummy,
-					&h_bytes_rdy_wr);
-
-			} while (h_out_wr_ptr != h_out_rd_ptr);
-		}
-	}
-	return 0;
-}
-
-/**
-  * sdio_dld_init_global
-  * initialization of sdio_dld global struct
-  *
-  * @card: a pointer to mmc_card.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_dld_init_global(struct mmc_card *card,
-				int(*done)(void))
-{
-	if (!card) {
-		pr_err(MODULE_NAME ": %s - param ""card"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!done) {
-		pr_err(MODULE_NAME ": %s - param ""done"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	sdio_dld->done_callback = done;
-	sdio_dld->card = card;
-	init_waitqueue_head(&sdio_dld->dld_main_thread.exit_wait.wait_event);
-	sdio_dld->write_callback_event.wake_up_signal = 1;
-	sdio_dld->main_loop_event.wake_up_signal = 1;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.dl_buff_size.reg_offset =
-		SDIOC_DL_BUFF_SIZE_OFFSET;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.dl_rd_ptr.reg_offset =
-		SDIOC_DL_RD_PTR;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.dl_wr_ptr.reg_offset =
-		SDIOC_DL_WR_PTR;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.ul_buff_size.reg_offset =
-		SDIOC_UP_BUFF_SIZE_OFFSET;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.up_rd_ptr.reg_offset =
-		SDIOC_UL_RD_PTR;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.up_wr_ptr.reg_offset =
-		SDIOC_UL_WR_PTR;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.good_to_exit_ptr.reg_offset =
-		SDIOC_EXIT_PTR;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.dl_buff_address.reg_offset =
-		SDIOC_DL_BUFF_ADDRESS;
-
-	sdio_dld->sdio_dloader_data.sdioc_reg.up_buff_address.reg_offset =
-		SDIOC_UP_BUFF_ADDRESS;
-
-	sdio_dld_set_op_mode(SDIO_DLD_NORMAL_MODE);
-
-	return 0;
-}
-
-/**
- * sdio_downloader_setup
- * initializes the TTY driver
- *
- * @card: a pointer to mmc_card.
- * @num_of_devices: number of devices.
- * @channel_number: channel number.
- * @return 0 on success or negative value on error.
- *
- * The TTY stack needs to know in advance how many devices it should
- * plan to manage. Use this call to set up the ports that will
- * be exported through SDIO.
- */
-int sdio_downloader_setup(struct mmc_card *card,
-			  unsigned int num_of_devices,
-			  int channel_number,
-			  int(*done)(void))
-{
-	int status = 0;
-	int result = 0;
-	int func_in_array = 0;
-	struct sdio_func *str_func = NULL;
-	struct device *tty_dev;
-
-	if (atomic_read(&sdio_dld_in_use) == 1)
-		return -EBUSY;
-
-	/*
-	 * If the setup is already complete tear down the existing
-	 * one and reinitialize. This might happen during modem restarts
-	 * in boot phase.
-	 */
-	if (atomic_read(&sdio_dld_setup_done) == 1)
-		sdio_dld_tear_down(NULL);
-
-	if (num_of_devices == 0 || num_of_devices > MAX_NUM_DEVICES) {
-		pr_err(MODULE_NAME ": %s - invalid number of devices\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!card) {
-		pr_err(MODULE_NAME ": %s - param ""card"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	if (!done) {
-		pr_err(MODULE_NAME ": %s - param ""done"" is NULL.\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	sdio_dld = kzalloc(sizeof(struct sdio_downloader), GFP_KERNEL);
-	if (!sdio_dld) {
-		pr_err(MODULE_NAME ": %s - couldn't allocate sdio_dld data "
-		       "structure.", __func__);
-		return -ENOMEM;
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	bootloader_debugfs_init();
-#endif /* CONFIG_DEBUG_FS */
-
-	status = sdio_dld_init_global(card, done);
-
-	if (status) {
-		pr_err(MODULE_NAME ": %s - Failure in Function "
-		       "sdio_dld_init_global(). status=%d\n",
-		       __func__, status);
-		kfree(sdio_dld);
-		return status;
-	}
-
-	sdio_dld->tty_drv = alloc_tty_driver(num_of_devices);
-
-	if (!sdio_dld->tty_drv) {
-		pr_err(MODULE_NAME ": %s - param ""sdio_dld->tty_drv"" is "
-				   "NULL.\n", __func__);
-		kfree(sdio_dld);
-		return -EINVAL;
-	}
-
-	sdio_dld_set_op_mode((enum sdio_dld_op_mode)sdio_op_mode);
-
-	/* according to op_mode, a different tty device is created */
-	if (sdio_dld->op_mode == SDIO_DLD_BOOT_TEST_MODE)
-		sdio_dld->tty_drv->name = TTY_SDIO_DEV_TEST;
-	else
-	    sdio_dld->tty_drv->name = TTY_SDIO_DEV;
-
-	sdio_dld->tty_drv->owner = THIS_MODULE;
-	sdio_dld->tty_drv->driver_name = "SDIO_Dloader";
-
-	/* uses dynamically assigned dev_t values */
-	sdio_dld->tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
-	sdio_dld->tty_drv->subtype = SERIAL_TYPE_NORMAL;
-	sdio_dld->tty_drv->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV
-				| TTY_DRIVER_RESET_TERMIOS;
-
-	/* initializing the tty driver */
-	sdio_dld->tty_drv->init_termios = tty_std_termios;
-	sdio_dld->tty_drv->init_termios.c_cflag =
-		B4800 | CS8 | CREAD | HUPCL | CLOCAL;
-	sdio_dld->tty_drv->init_termios.c_ispeed = INPUT_SPEED;
-	sdio_dld->tty_drv->init_termios.c_ospeed = OUTPUT_SPEED;
-
-	tty_set_operations(sdio_dld->tty_drv, &sdio_dloader_tty_ops);
-
-	status = tty_register_driver(sdio_dld->tty_drv);
-	if (status) {
-		put_tty_driver(sdio_dld->tty_drv);
-		pr_err(MODULE_NAME ": %s - tty_register_driver() failed\n",
-			__func__);
-
-		sdio_dld->tty_drv = NULL;
-		kfree(sdio_dld);
-		return status;
-	}
-
-	tty_dev = tty_register_device(sdio_dld->tty_drv, 0, NULL);
-	if (IS_ERR(tty_dev)) {
-		pr_err(MODULE_NAME ": %s - tty_register_device() "
-			"failed\n", __func__);
-		tty_unregister_driver(sdio_dld->tty_drv);
-		put_tty_driver(sdio_dld->tty_drv);
-		kfree(sdio_dld);
-		return PTR_ERR(tty_dev);
-	}
-
-	sdio_dld->sdioc_boot_func = SDIOC_CHAN_TO_FUNC_NUM(channel_number);
-	func_in_array = REAL_FUNC_TO_FUNC_IN_ARRAY(sdio_dld->sdioc_boot_func);
-	str_func = sdio_dld->card->sdio_func[func_in_array];
-	status = sdio_dld_init_func(str_func);
-	if (status) {
-		pr_err(MODULE_NAME ": %s - Failure in Function "
-		       "sdio_dld_init_func(). status=%d\n",
-		       __func__, status);
-		goto exit_err;
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	sdio_dld_debug_init();
-#endif
-
-	sdio_claim_host(str_func);
-
-	/*
-	 * notifing the client by writing what mode we are by writing
-	 * to a special register
-	 */
-	status = sdio_memcpy_toio(str_func,
-				  SDIOC_OP_MODE_PTR,
-				  (void *)&sdio_dld->op_mode,
-				  sizeof(sdio_dld->op_mode));
-
-	sdio_release_host(str_func);
-
-	if (status) {
-		pr_err(MODULE_NAME ": %s - sdio_memcpy_toio() "
-		       "writing to OP_MODE_REGISTER failed. "
-		       "status=%d.\n",
-		       __func__, status);
-		goto exit_err;
-	}
-
-	atomic_set(&sdio_dld_setup_done, 1);
-	return 0;
-
-exit_err:
-	tty_unregister_device(sdio_dld->tty_drv, 0);
-	result = tty_unregister_driver(sdio_dld->tty_drv);
-	if (result)
-		pr_err(MODULE_NAME ": %s - tty_unregister_driver() "
-		       "failed. result=%d\n", __func__, -result);
-	put_tty_driver(sdio_dld->tty_drv);
-	kfree(sdio_dld);
-	atomic_set(&sdio_dld_setup_done, 0);
-	return status;
-}
-
-static void sdio_dld_tear_down(struct work_struct *work)
-{
-	int status = 0;
-
-	if (atomic_read(&sdio_dld_in_use) == 1) {
-		del_timer_sync(&sdio_dld->timer);
-		del_timer_sync(&sdio_dld->push_timer);
-		sdio_dld_dealloc_local_buffers();
-	}
-
-	tty_unregister_device(sdio_dld->tty_drv, 0);
-
-	status = tty_unregister_driver(sdio_dld->tty_drv);
-	if (status) {
-		pr_err(MODULE_NAME ": %s - tty_unregister_driver() failed\n",
-		       __func__);
-	}
-
-	put_tty_driver(sdio_dld->tty_drv);
-	kfree(sdio_dld);
-	atomic_set(&sdio_dld_in_use, 0);
-	atomic_set(&sdio_dld_setup_done, 0);
-}
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SDIO Downloader");
-MODULE_AUTHOR("Yaniv Gardi <ygardi@codeaurora.org>");
-MODULE_VERSION(DRV_VERSION);
-
diff --git a/arch/arm/mach-msm/sdio_al_private.h b/arch/arm/mach-msm/sdio_al_private.h
deleted file mode 100644
index 3a5ab79..0000000
--- a/arch/arm/mach-msm/sdio_al_private.h
+++ /dev/null
@@ -1,267 +0,0 @@
-/* Copyright (c) 2011, 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.
- */
-
-/*
- * SDIO-Abstraction-Layer internal interface.
- */
-
-#ifndef __SDIO_AL_PRIVATE__
-#define __SDIO_AL_PRIVATE__
-
-#include <linux/mmc/card.h>
-#include <linux/platform_device.h>
-#include <mach/sdio_al.h>
-
-#define DRV_VERSION "1.30"
-#define MODULE_NAME "sdio_al"
-#define SDIOC_CHAN_TO_FUNC_NUM(x)	((x)+2)
-#define REAL_FUNC_TO_FUNC_IN_ARRAY(x)	((x)-1)
-#define SDIO_PREFIX "SDIO_"
-#define PEER_CHANNEL_NAME_SIZE		4
-#define CHANNEL_NAME_SIZE (sizeof(SDIO_PREFIX) + PEER_CHANNEL_NAME_SIZE)
-#define SDIO_TEST_POSTFIX_SIZE 5
-#define MAX_NUM_OF_SDIO_DEVICES	2
-#define TEST_CH_NAME_SIZE (CHANNEL_NAME_SIZE + SDIO_TEST_POSTFIX_SIZE)
-
-struct sdio_al_device; /* Forward Declaration */
-
-enum sdio_channel_state {
-	SDIO_CHANNEL_STATE_INVALID,	 /* before reading software header */
-	SDIO_CHANNEL_STATE_IDLE,         /* channel valid, not opened    */
-	SDIO_CHANNEL_STATE_CLOSED,       /* was closed */
-	SDIO_CHANNEL_STATE_OPEN,	 /* opened */
-	SDIO_CHANNEL_STATE_CLOSING,      /* during flush, when closing */
-};
-/**
- * Peer SDIO-Client channel configuration.
- *
- *  @is_ready - channel is ready and the data is valid.
- *
- *  @max_rx_threshold - maximum rx threshold, according to the
- *		total buffers size on the peer pipe.
- *  @max_tx_threshold - maximum tx threshold, according to the
- *		total buffers size on the peer pipe.
- *  @tx_buf_size - size of a single buffer on the peer pipe; a
- *		transfer smaller than the buffer size still
- *		make the buffer unusable for the next transfer.
- * @max_packet_size
- * @is_host_ok_to_sleep - Host marks this bit when it's okay to
- *		sleep (no pending transactions)
- */
-struct peer_sdioc_channel_config {
-	u32 is_ready;
-	u32 max_rx_threshold; /* Downlink */
-	u32 max_tx_threshold; /* Uplink */
-	u32 tx_buf_size;
-	u32 max_packet_size;
-	u32 is_host_ok_to_sleep;
-	u32 is_packet_mode;
-	u32 peer_operation;
-	u32 is_low_latency_ch;
-	u32 reserved[23];
-};
-
-
-/**
- * Peer SDIO-Client channel statsitics.
- *
- * @last_any_read_avail - the last read avail in all the
- *		 channels including this channel.
- * @last_read_avail - the last read_avail that was read from HW
- *	    mailbox.
- * @last_old_read_avail - the last read_avail channel shadow.
- * @total_notifs - the total number of read notifications sent
- *	 to this channel client
- * @total_read_times - the total number of successful sdio_read
- *	     calls for this channel
- */
-struct sdio_channel_statistics {
-	int last_any_read_avail;
-	int last_read_avail;
-	int last_old_read_avail;
-	int total_notifs;
-	int total_read_times;
-};
-
-/**
- *  SDIO Channel context.
- *
- *  @name - channel name. Used by the caller to open the
- *	  channel.
- *
- *  @read_threshold - Threshold on SDIO-Client mailbox for Rx
- *				Data available bytes. When the limit exceed
- *				the SDIO-Client generates an interrupt to the
- *				host.
- *
- *  @write_threshold - Threshold on SDIO-Client mailbox for Tx
- *				Data available bytes. When the limit exceed
- *				the SDIO-Client generates an interrupt to the
- *				host.
- *
- *  @def_read_threshold - Default theshold on SDIO-Client for Rx
- *
- *  @min_write_avail - Threshold of minimal available bytes
- *					 to write. Below that threshold the host
- *					 will initiate reading the mailbox.
- *
- *  @poll_delay_msec - Delay between polling the mailbox. When
- *				 the SDIO-Client doesn't generates EOT
- *				 interrupt for Rx Available bytes, the host
- *				 should poll the SDIO-Client mailbox.
- *
- *  @is_packet_mode - The host get interrupt when a packet is
- *				available at the SDIO-client (pipe EOT
- *				indication).
- *
- *  @num - channel number.
- *
- *  @notify - Client's callback. Should not call sdio read/write.
- *
- *  @priv - Client's private context, provided to callback.
- *
- *  @is_valid - Channel is used (we have a list of
- *		SDIO_AL_MAX_CHANNELS and not all of them are in
- *		use).
- *
- *  @is_open - Channel is open.
- *
- *  @func - SDIO Function handle.
- *
- *  @rx_pipe_index - SDIO-Client Pipe Index for Rx Data.
- *
- *  @tx_pipe_index - SDIO-Client Pipe Index for Tx Data.
- *
- *  @ch_lock - Channel lock to protect channel specific Data
- *
- *  @rx_pending_bytes - Total number of Rx pending bytes, at Rx
- *				  packet list. Maximum of 16KB-1 limited by
- *				  SDIO-Client specification.
- *
- *  @read_avail - Available bytes to read.
- *
- *  @write_avail - Available bytes to write.
- *
- *  @rx_size_list_head - The head of Rx Pending Packets List.
- *
- *  @pdev - platform device - clients to probe for the sdio-al.
- *
- *  @signature - Context Validity check.
- *
- *  @sdio_al_dev - a pointer to the sdio_al_device instance of
- *   this channel
- *
- *   @statistics - channel statistics
- *
- */
-struct sdio_channel {
-	/* Channel Configuration Parameters*/
-	char name[CHANNEL_NAME_SIZE];
-	char ch_test_name[TEST_CH_NAME_SIZE];
-	int read_threshold;
-	int write_threshold;
-	int def_read_threshold;
-	int threshold_change_cnt;
-	int min_write_avail;
-	int poll_delay_msec;
-	int is_packet_mode;
-	int is_low_latency_ch;
-
-	struct peer_sdioc_channel_config ch_config;
-
-	/* Channel Info */
-	int num;
-
-	void (*notify)(void *priv, unsigned channel_event);
-	void *priv;
-
-	int state;
-
-	struct sdio_func *func;
-
-	int rx_pipe_index;
-	int tx_pipe_index;
-
-	struct mutex ch_lock;
-
-	u32 read_avail;
-	u32 write_avail;
-
-	u32 peer_tx_buf_size;
-
-	u16 rx_pending_bytes;
-
-	struct list_head rx_size_list_head;
-
-	struct platform_device *pdev;
-
-	u32 total_rx_bytes;
-	u32 total_tx_bytes;
-
-	u32 signature;
-
-	struct sdio_al_device *sdio_al_dev;
-
-	struct sdio_channel_statistics statistics;
-};
-
-/**
- * sdio_downloader_setup
- * initializes the TTY driver
- *
- * @card: a pointer to mmc_card.
- * @num_of_devices: number of devices.
- * @channel_number: channel number.
- * @return 0 on success or negative value on error.
- *
- * The TTY stack needs to know in advance how many devices it should
- * plan to manage. Use this call to set up the ports that will
- * be exported through SDIO.
- */
-int sdio_downloader_setup(struct mmc_card *card,
-			  unsigned int num_of_devices,
-			  int func_number,
-			  int(*func)(void));
-
-/**
- * test_channel_init
- * initializes a test channel
- *
- * @name: the channel name.
- * @return 0 on success or negative value on error.
- *
- */
-int test_channel_init(char *name);
-
-/**
- * sdio_al_register_lpm_cb
- * Allow the sdio_al test to register for lpm voting
- * notifications
- *
- * @device_handle: the device handle.
- * @wakeup_callback: callback function to be called when voting.
- *
- */
-void sdio_al_register_lpm_cb(void *device_handle,
-				       int(*lpm_callback)(void *, int));
-
-/**
- * sdio_al_unregister_lpm_cb
- * Allow the sdio_al test to unregister for lpm voting
- * notifications
- *
- * @device_handle: the device handle.
- *
- */
-void sdio_al_unregister_lpm_cb(void *device_handle);
-
-#endif /* __SDIO_AL_PRIVATE__ */
diff --git a/arch/arm/mach-msm/sdio_al_test.c b/arch/arm/mach-msm/sdio_al_test.c
deleted file mode 100644
index 2c9f675..0000000
--- a/arch/arm/mach-msm/sdio_al_test.c
+++ /dev/null
@@ -1,6500 +0,0 @@
-/* Copyright (c) 2010-2011, 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.
- */
-
-/*
- * SDIO-Abstraction-Layer Test Module.
- *
- */
-
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/workqueue.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/platform_device.h>
-#include <mach/sdio_smem.h>
-#include <linux/wakelock.h>
-#include <linux/uaccess.h>
-
-#include "sdio_al_private.h"
-#include <linux/debugfs.h>
-
-#include <linux/kthread.h>
-enum lpm_test_msg_type {
-	LPM_NO_MSG,	/* 0 */
-	LPM_MSG_SEND,	/* 1 */
-	LPM_MSG_REC,	/* 2 */
-	LPM_SLEEP,	/* 3 */
-	LPM_WAKEUP,	/* 4 */
-	LPM_NOTIFY	/* 5 */
-};
-
-#define LPM_NO_MSG_NAME "LPM No Event"
-#define LPM_MSG_SEND_NAME "LPM Send Msg Event"
-#define LPM_MSG_REC_NAME "LPM Receive Msg Event"
-#define LPM_SLEEP_NAME "LPM Sleep Event"
-#define LPM_WAKEUP_NAME "LPM Wakeup Event"
-
-/** Module name string */
-#define TEST_MODULE_NAME "sdio_al_test"
-
-#define TEST_SIGNATURE 0x12345678
-#define TEST_CONFIG_SIGNATURE 0xBEEFCAFE
-
-#define MAX_XFER_SIZE (16*1024)
-#define SMEM_MAX_XFER_SIZE 0xBC000
-#define A2_MIN_PACKET_SIZE 5
-#define RMNT_PACKET_SIZE (4*1024)
-#define DUN_PACKET_SIZE (2*1024)
-#define CSVT_PACKET_SIZE 1700
-
-#define TEST_DBG(x...) if (test_ctx->runtime_debug) pr_info(x)
-
-#define LPM_TEST_NUM_OF_PACKETS 100
-#define LPM_MAX_OPEN_CHAN_PER_DEV 4
-#define LPM_ARRAY_SIZE	(7*LPM_TEST_NUM_OF_PACKETS*LPM_MAX_OPEN_CHAN_PER_DEV)
-#define SDIO_LPM_TEST "sdio_lpm_test_reading_task"
-#define LPM_TEST_CONFIG_SIGNATURE 0xDEADBABE
-#define LPM_MSG_NAME_SIZE 20
-#define MAX_STR_SIZE	10
-#define MAX_AVG_RTT_TIME_USEC	2500
-#define SDIO_RMNT_RTT_PACKET_SIZE	32
-#define SDIO_CSVT_RTT_PACKET_SIZE	1900
-
-#define A2_HEADER_OVERHEAD 8
-
-enum rx_process_state {
-	RX_PROCESS_PACKET_INIT,
-	RX_PROCESS_A2_HEADER,
-	RX_PROCESS_PACKET_DATA,
-};
-
-enum sdio_test_case_type {
-	SDIO_TEST_LOOPBACK_HOST,
-	SDIO_TEST_LOOPBACK_CLIENT,
-	SDIO_TEST_LPM_HOST_WAKER,
-	SDIO_TEST_LPM_CLIENT_WAKER,
-	SDIO_TEST_LPM_RANDOM,
-	SDIO_TEST_HOST_SENDER_NO_LP,
-	SDIO_TEST_CLOSE_CHANNEL,
-	SDIO_TEST_A2_VALIDATION,
-	/* The following tests are not part of the 9k tests and should be
-	 * kept last in case new tests are added
-	 */
-	SDIO_TEST_PERF,
-	SDIO_TEST_RTT,
-	SDIO_TEST_MODEM_RESET,
-};
-
-struct lpm_task {
-	struct task_struct *lpm_task;
-	const char *task_name;
-};
-
-struct lpm_entry_type {
-	enum lpm_test_msg_type msg_type;
-	char msg_name[LPM_MSG_NAME_SIZE];
-	u32 counter;
-	u32 current_ms;
-	u32 read_avail_mask;
-	char chan_name[CHANNEL_NAME_SIZE];
-};
-
-struct lpm_msg {
-	u32 signature;
-	u32 counter;
-	u32 reserve1;
-	u32 reserve2;
-};
-
-struct test_config_msg {
-	u32 signature;
-	u32 test_case;
-	u32 test_param;
-	u32 num_packets;
-	u32 num_iterations;
-};
-
-struct test_result_msg {
-	u32 signature;
-	u32 is_successful;
-};
-
-struct test_work {
-	struct work_struct work;
-	struct test_channel *test_ch;
-};
-
-enum sdio_channels_ids {
-	SDIO_RPC,
-	SDIO_QMI,
-	SDIO_RMNT,
-	SDIO_DIAG,
-	SDIO_DUN,
-	SDIO_SMEM,
-	SDIO_CSVT,
-	SDIO_MAX_CHANNELS
-};
-
-enum sdio_test_results {
-	TEST_NO_RESULT,
-	TEST_FAILED,
-	TEST_PASSED
-};
-
-enum sdio_lpm_vote_state {
-	SDIO_NO_VOTE,
-	SDIO_VOTE_FOR_SLEEP,
-	SDIO_VOTE_AGAINST_SLEEP
-};
-
-struct sdio_test_device {
-	int open_channels_counter_to_recv;
-	int open_channels_counter_to_send;
-	struct lpm_entry_type *lpm_arr;
-	int array_size;
-	void *sdio_al_device;
-	spinlock_t lpm_array_lock;
-	unsigned long lpm_array_lock_flags;
-	u32 next_avail_entry_in_array;
-	struct lpm_task lpm_test_task;
-	u32 next_mask_id;
-	u32 read_avail_mask;
-	int modem_result_per_dev;
-	int final_result_per_dev;
-};
-
-struct test_channel {
-	struct sdio_channel *ch;
-
-	char name[CHANNEL_NAME_SIZE];
-	int ch_id;
-
-	struct sdio_test_device *test_device;
-
-	u32 *buf;
-	u32 buf_size;
-
-	struct workqueue_struct *workqueue;
-	struct test_work test_work;
-
-	u32 rx_bytes;
-	u32 tx_bytes;
-
-	wait_queue_head_t   wait_q;
-	atomic_t rx_notify_count;
-	atomic_t tx_notify_count;
-	atomic_t any_notify_count;
-	atomic_t wakeup_client;
-	atomic_t card_detected_event;
-
-	int wait_counter;
-
-	int is_used;
-	int test_type;
-	int ch_ready;
-
-	struct test_config_msg config_msg;
-
-	int test_completed;
-	int test_result;
-	struct timer_list timer;
-	int timer_interval_ms;
-
-	struct timer_list timeout_timer;
-	int timeout_ms;
-	void *sdio_al_device;
-	int is_ok_to_sleep;
-	unsigned int packet_length;
-	int random_packet_size;
-	int next_index_in_sent_msg_per_chan;
-	int channel_mask_id;
-	int modem_result_per_chan;
-	int notify_counter_per_chan;
-	int max_burst_size;        /* number of writes before close/open */
-	int card_removed;
-};
-
-struct sdio_al_test_debug {
-	u32 dun_throughput;
-	u32 rmnt_throughput;
-	struct dentry *debug_root;
-	struct dentry *debug_test_result;
-	struct dentry *debug_dun_throughput;
-	struct dentry *debug_rmnt_throughput;
-	struct dentry *rpc_sender_test;
-	struct dentry *rpc_qmi_diag_sender_test;
-	struct dentry *smem_test;
-	struct dentry *smem_rpc_test;
-	struct dentry *rmnet_a2_validation_test;
-	struct dentry *dun_a2_validation_test;
-	struct dentry *rmnet_a2_perf_test;
-	struct dentry *dun_a2_perf_test;
-	struct dentry *csvt_a2_perf_test;
-	struct dentry *rmnet_dun_a2_perf_test;
-	struct dentry *rpc_sender_rmnet_a2_perf_test;
-	struct dentry *all_channels_test;
-	struct dentry *host_sender_no_lp_diag_test;
-	struct dentry *host_sender_no_lp_diag_rpc_test;
-	struct dentry *rmnet_small_packets_test;
-	struct dentry *rmnet_rtt_test;
-	struct dentry *csvt_rtt_test;
-	struct dentry *modem_reset_rpc_test;
-	struct dentry *modem_reset_rmnet_test;
-	struct dentry *modem_reset_channels_4bit_dev_test;
-	struct dentry *modem_reset_channels_8bit_dev_test;
-	struct dentry *modem_reset_all_channels_test;
-	struct dentry *open_close_test;
-	struct dentry *open_close_dun_rmnet_test;
-	struct dentry *close_chan_lpm_test;
-	struct dentry *lpm_test_client_wakes_host_test;
-	struct dentry *lpm_test_host_wakes_client_test;
-	struct dentry *lpm_test_random_single_channel_test;
-	struct dentry *lpm_test_random_multi_channel_test;
-};
-
-struct test_context {
-	dev_t dev_num;
-	struct device *dev;
-	struct cdev *cdev;
-	int number_of_active_devices;
-	int max_number_of_devices;
-
-	struct sdio_test_device test_dev_arr[MAX_NUM_OF_SDIO_DEVICES];
-
-	struct test_channel *test_ch;
-
-	struct test_channel *test_ch_arr[SDIO_MAX_CHANNELS];
-
-	long testcase;
-
-	const char *name;
-
-	int exit_flag;
-
-	u32 signature;
-
-	int runtime_debug;
-
-	struct platform_device *smem_pdev;
-	struct sdio_smem_client *sdio_smem;
-	int smem_was_init;
-	u8 *smem_buf;
-	uint32_t smem_counter;
-
-	struct platform_device *csvt_app_pdev;
-
-	wait_queue_head_t   wait_q;
-	int test_completed;
-	int test_result;
-	struct sdio_al_test_debug debug;
-
-	struct wake_lock wake_lock;
-
-	unsigned int lpm_pseudo_random_seed;
-};
-
-/* FORWARD DECLARATIONS */
-static int set_params_loopback_9k(struct test_channel *tch);
-static int set_params_smem_test(struct test_channel *tch);
-static int set_params_a2_validation(struct test_channel *tch);
-static int set_params_a2_perf(struct test_channel *tch);
-static int set_params_8k_sender_no_lp(struct test_channel *tch);
-static int set_params_a2_small_pkts(struct test_channel *tch);
-static int set_params_rtt(struct test_channel *tch);
-static int set_params_loopback_9k_close(struct test_channel *tch);
-static int close_channel_lpm_test(int channel_num);
-static int set_params_lpm_test(struct test_channel *tch,
-				enum sdio_test_case_type test,
-				int timer_interval_ms);
-static void set_pseudo_random_seed(void);
-static int set_params_modem_reset(struct test_channel *tch);
-static int test_start(void);
-static void rx_cleanup(struct test_channel *test_ch, int *rx_packet_count);
-static void sdio_al_test_cleanup_channels(void);
-static void notify(void *priv, unsigned channel_event);
-#ifdef CONFIG_MSM_SDIO_SMEM
-static int sdio_smem_open(struct sdio_smem_client *sdio_smem);
-#endif
-
-/*
- * Seed for pseudo random time sleeping in Random LPM test.
- * If not set, current time in jiffies is used.
- */
-static unsigned int seed;
-module_param(seed, int, 0);
-static struct test_context *test_ctx;
-
-static void sdio_al_test_initial_dev_and_chan(struct test_context *test_ctx)
-{
-	int i = 0;
-
-	if (!test_ctx) {
-		pr_err(TEST_MODULE_NAME ":%s - test_ctx is NULL.\n", __func__);
-		return;
-	}
-
-	for (i = 0 ; i < MAX_NUM_OF_SDIO_DEVICES ; ++i)
-		test_ctx->test_dev_arr[i].sdio_al_device = NULL;
-
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-		if (!tch)
-			continue;
-		tch->is_used = 0;
-	}
-
-	sdio_al_test_cleanup_channels();
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static int message_repeat;
-
-static int sdio_al_test_extract_number(const char __user *buf,
-					size_t count)
-{
-	int ret = 0;
-	int number = -1;
-	char local_buf[MAX_STR_SIZE] = {0};
-	char *start = NULL;
-
-	if (count > MAX_STR_SIZE) {
-		pr_err(TEST_MODULE_NAME ": %s - MAX_STR_SIZE(%d) < count(%d). "
-		       "Please choose smaller number\n",
-		       __func__, MAX_STR_SIZE, (int)count);
-		return -EINVAL;
-	}
-
-	if (copy_from_user(local_buf, buf, count)) {
-		pr_err(TEST_MODULE_NAME ": %s - copy_from_user() failed\n",
-		       __func__);
-		return -EINVAL;
-	}
-
-	/* adding null termination to the string */
-	local_buf[count] = '\0';
-
-	/* stripping leading and trailing white spaces */
-	start = strstrip(local_buf);
-
-	ret = kstrtoint(start, 10, &number);
-
-	if (ret) {
-		pr_err(TEST_MODULE_NAME " : %s - kstrtoint() failed\n",
-		       __func__);
-		return ret;
-	}
-
-	return number;
-}
-
-static int sdio_al_test_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	message_repeat = 1;
-	return 0;
-}
-
-static void sdio_al_test_cleanup_channels(void)
-{
-	int channel_num;
-	int dummy = 0;
-
-	for (channel_num = 0 ; channel_num < SDIO_MAX_CHANNELS ;
-	      ++channel_num) {
-		if (channel_num == SDIO_SMEM)
-			continue;
-
-		 rx_cleanup(test_ctx->test_ch_arr[channel_num], &dummy);
-	}
-
-	return;
-}
-
-/* RPC SENDER TEST */
-static ssize_t rpc_sender_test_write(struct file *file,
-				      const char __user *buf,
-				      size_t count,
-				      loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RPC SENDER TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rpc_sender_test_read(struct file *file,
-				     char __user *buffer,
-				     size_t count,
-				     loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRPC_SENDER_TEST\n"
-		 "===============\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rpc_sender_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rpc_sender_test_write,
-	.read = rpc_sender_test_read,
-};
-
-/* RPC, QMI & DIAG SENDER TEST */
-static ssize_t rpc_qmi_diag_sender_test_write(struct file *file,
-					       const char __user *buf,
-					       size_t count,
-					       loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RPC, QMI AND DIAG SENDER TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]);
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_QMI]);
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_DIAG]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rpc_qmi_diag_sender_test_read(struct file *file,
-					      char __user
-					      *buffer, size_t count,
-					      loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRPC_QMI_DIAG_SENDER_TEST\n"
-		 "========================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rpc_qmi_diag_sender_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rpc_qmi_diag_sender_test_write,
-	.read = rpc_qmi_diag_sender_test_read,
-};
-
-/* SMEM TEST */
-static ssize_t smem_test_write(struct file *file,
-				const char __user *buf,
-				size_t count,
-				loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- SMEM TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t smem_test_read(struct file *file,
-			       char __user *buffer,
-			       size_t count,
-			       loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nSMEM_TEST\n"
-		 "=========\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations smem_test_ops = {
-	.open = sdio_al_test_open,
-	.write = smem_test_write,
-	.read = smem_test_read,
-};
-
-/* SMEM & RPC TEST */
-static ssize_t smem_rpc_test_write(struct file *file,
-				    const char __user *buf,
-				    size_t count,
-				    loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- SMEM AND RPC TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]);
-		set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t smem_rpc_test_read(struct file *file,
-				   char __user *buffer,
-				   size_t count,
-				   loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nSMEM_RPC_TEST\n"
-		 "=============\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations smem_rpc_test_ops = {
-	.open = sdio_al_test_open,
-	.write = smem_rpc_test_write,
-	.read = smem_rpc_test_read,
-};
-
-/* RMNET A2 VALIDATION TEST */
-static ssize_t rmnet_a2_validation_test_write(struct file *file,
-						const char __user *buf,
-						size_t count,
-						loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RMNET A2 VALIDATION TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_validation(test_ctx->test_ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rmnet_a2_validation_test_read(struct file *file,
-						char __user *buffer,
-						size_t count,
-						loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRMNET_A2_VALIDATION_TEST\n"
-		 "=========================\n"
-		 "Description:\n"
-		 "In this test, the HOST sends multiple packets to the\n"
-		 "CLIENT and validates the packets loop backed from A2\n"
-		 "for the RMNET channel.\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rmnet_a2_validation_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rmnet_a2_validation_test_write,
-	.read = rmnet_a2_validation_test_read,
-};
-
-/* DUN A2 VALIDATION TEST */
-static ssize_t dun_a2_validation_test_write(struct file *file,
-						const char __user *buf,
-						size_t count,
-						loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- DUN A2 VALIDATION TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_validation(test_ctx->test_ch_arr[SDIO_DUN]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t dun_a2_validation_test_read(struct file *file,
-						char __user *buffer,
-						size_t count,
-						loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		"\nDUN_A2_VALIDATION_TEST\n"
-		"=========================\n"
-		"Description:\n"
-		"In this test, the HOST sends multiple packets to the\n"
-		"CLIENT and validates the packets loop backed from A2\n"
-		"for the DUN channel.\n\n"
-		"END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations dun_a2_validation_test_ops = {
-	.open = sdio_al_test_open,
-	.write = dun_a2_validation_test_write,
-	.read = dun_a2_validation_test_read,
-};
-
-/* RMNET A2 PERFORMANCE TEST */
-static ssize_t rmnet_a2_perf_test_write(struct file *file,
-					 const char __user *buf,
-					 size_t count,
-					 loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RMNET A2 PERFORMANCE TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rmnet_a2_perf_test_read(struct file *file,
-					char __user *buffer,
-					size_t count,
-					loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRMNET_A2_PERFORMANCE_TEST\n"
-		 "=========================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rmnet_a2_perf_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rmnet_a2_perf_test_write,
-	.read = rmnet_a2_perf_test_read,
-};
-
-/* DUN A2 PERFORMANCE TEST */
-static ssize_t dun_a2_perf_test_write(struct file *file,
-				       const char __user *buf,
-				       size_t count,
-				       loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- DUN A2 PERFORMANCE TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t dun_a2_perf_test_read(struct file *file,
-				      char __user *buffer,
-				      size_t count,
-				      loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nDUN_A2_PERFORMANCE_TEST\n"
-		 "=======================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations dun_a2_perf_test_ops = {
-	.open = sdio_al_test_open,
-	.write = dun_a2_perf_test_write,
-	.read = dun_a2_perf_test_read,
-};
-
-/* CSVT A2 PERFORMANCE TEST */
-static ssize_t csvt_a2_perf_test_write(struct file *file,
-					const char __user *buf,
-					size_t count,
-					loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- CSVT A2 PERFORMANCE TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_CSVT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t csvt_a2_perf_test_read(struct file *file,
-				       char __user *buffer,
-				       size_t count,
-				       loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nCSVT_A2_PERFORMANCE_TEST\n"
-		 "========================\n"
-		 "Description:\n"
-		 "Loopback test on the CSVT Channel, in order to check "
-		 "throughput performance.\n"
-		 "Packet size that are sent on the CSVT channel in this "
-		 "test is %d.bytes\n\n"
-		 "END OF DESCRIPTION\n", CSVT_PACKET_SIZE);
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations csvt_a2_perf_test_ops = {
-	.open = sdio_al_test_open,
-	.write = csvt_a2_perf_test_write,
-	.read = csvt_a2_perf_test_read,
-};
-
-/* RMNET DUN A2 PERFORMANCE TEST */
-static ssize_t rmnet_dun_a2_perf_test_write(struct file *file,
-					     const char __user *buf,
-					     size_t count,
-					     loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RMNET AND DUN A2 PERFORMANCE TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]);
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rmnet_dun_a2_perf_test_read(struct file *file,
-					    char __user *buffer,
-					    size_t count,
-					    loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRMNET_DUN_A2_PERFORMANCE_TEST\n"
-		 "=============================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rmnet_dun_a2_perf_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rmnet_dun_a2_perf_test_write,
-	.read = rmnet_dun_a2_perf_test_read,
-};
-
-/* RPC SENDER & RMNET A2 PERFORMANCE TEST */
-static ssize_t rpc_sender_rmnet_a2_perf_test_write(struct file *file,
-						    const char __user *buf,
-						    size_t count,
-						    loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "--RPC SENDER AND RMNET A2 "
-		"PERFORMANCE --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]);
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rpc_sender_rmnet_a2_perf_test_read(struct file *file,
-						   char __user *buffer,
-						   size_t count,
-						   loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRPC_SENDER_RMNET_A2_PERFORMANCE_TEST\n"
-		 "====================================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rpc_sender_rmnet_a2_perf_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rpc_sender_rmnet_a2_perf_test_write,
-	.read = rpc_sender_rmnet_a2_perf_test_read,
-};
-
-/* ALL CHANNELS TEST */
-static ssize_t all_channels_test_write(struct file *file,
-					const char __user *buf,
-					size_t count,
-					loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- ALL THE CHANNELS TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_RPC]);
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_QMI]);
-		set_params_loopback_9k(test_ctx->test_ch_arr[SDIO_DIAG]);
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_RMNT]);
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_DUN]);
-		set_params_smem_test(test_ctx->test_ch_arr[SDIO_SMEM]);
-		set_params_a2_perf(test_ctx->test_ch_arr[SDIO_CSVT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t all_channels_test_read(struct file *file,
-				       char __user *buffer,
-				       size_t count,
-				       loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nALL_CHANNELS_TEST\n"
-		 "=================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations all_channels_test_ops = {
-	.open = sdio_al_test_open,
-	.write = all_channels_test_write,
-	.read = all_channels_test_read,
-};
-
-/* HOST SENDER NO LP DIAG TEST */
-static ssize_t host_sender_no_lp_diag_test_write(struct file *file,
-						  const char __user *buf,
-						  size_t count,
-						  loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- HOST SENDER NO LP FOR DIAG TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_DIAG]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t host_sender_no_lp_diag_test_read(struct file *file,
-						 char __user *buffer,
-						 size_t count,
-						 loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nHOST_SENDER_NO_LP_DIAG_TEST\n"
-		 "===========================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations host_sender_no_lp_diag_test_ops = {
-	.open = sdio_al_test_open,
-	.write = host_sender_no_lp_diag_test_write,
-	.read = host_sender_no_lp_diag_test_read,
-};
-
-/* HOST SENDER NO LP DIAG, RPC TEST */
-static ssize_t host_sender_no_lp_diag_rpc_test_write(
-						 struct file *file,
-						 const char __user *buf,
-						 size_t count,
-						 loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- HOST SENDER NO LP FOR DIAG, RPC "
-		"TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_DIAG]);
-		set_params_8k_sender_no_lp(test_ctx->test_ch_arr[SDIO_RPC]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t host_sender_no_lp_diag_rpc_test_read(
-						 struct file *file,
-						 char __user *buffer,
-						 size_t count,
-						 loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nHOST_SENDER_NO_LP_DIAG_RPC_TEST\n"
-		 "===================================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations host_sender_no_lp_diag_rpc_test_ops = {
-	.open = sdio_al_test_open,
-	.write = host_sender_no_lp_diag_rpc_test_write,
-	.read = host_sender_no_lp_diag_rpc_test_read,
-};
-
-/* RMNET SMALL PACKETS TEST */
-static ssize_t rmnet_small_packets_test_write(struct file *file,
-					       const char __user *buf,
-					       size_t count,
-					       loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RMNET SMALL PACKETS (5-128) TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_a2_small_pkts(test_ctx->test_ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rmnet_small_packets_test_read(struct file *file,
-					      char __user *buffer,
-					      size_t count,
-					      loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRMNET_SMALL_PACKETS_TEST\n"
-		 "========================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rmnet_small_packets_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rmnet_small_packets_test_write,
-	.read = rmnet_small_packets_test_read,
-};
-
-/* RMNET RTT TEST */
-static ssize_t rmnet_rtt_test_write(struct file *file,
-				     const char __user *buf,
-				     size_t count,
-				     loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- RMNET RTT TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_rtt(test_ctx->test_ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t rmnet_rtt_test_read(struct file *file,
-				    char __user *buffer,
-				    size_t count,
-				    loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nRMNET_RTT_TEST\n"
-		 "==============\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations rmnet_rtt_test_ops = {
-	.open = sdio_al_test_open,
-	.write = rmnet_rtt_test_write,
-	.read = rmnet_rtt_test_read,
-};
-
-/* CSVT RTT TEST */
-static ssize_t csvt_rtt_test_write(struct file *file,
-				    const char __user *buf,
-				    size_t count,
-				    loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- CSVT RTT TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_rtt(test_ctx->test_ch_arr[SDIO_CSVT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t csvt_rtt_test_read(struct file *file,
-				   char __user *buffer,
-				   size_t count,
-				   loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nCSVT_RTT_TEST\n"
-		 "==============\n"
-		 "Description:\n"
-		 "In this test the HOST send a message of %d bytes "
-		 "to the CLIENT\n\n"
-		 "END OF DESCRIPTION\n", SDIO_CSVT_RTT_PACKET_SIZE);
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations csvt_rtt_test_ops = {
-	.open = sdio_al_test_open,
-	.write = csvt_rtt_test_write,
-	.read = csvt_rtt_test_read,
-};
-
-/* MODEM RESET RPC TEST */
-static ssize_t modem_reset_rpc_test_write(struct file *file,
-					   const char __user *buf,
-					   size_t count,
-					   loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- MODEM RESET - RPC CHANNEL TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_RPC]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t modem_reset_rpc_test_read(struct file *file,
-					  char __user *buffer,
-					  size_t count,
-					  loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nMODEM_RESET_RPC_TEST\n"
-		 "====================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations modem_reset_rpc_test_ops = {
-	.open = sdio_al_test_open,
-	.write = modem_reset_rpc_test_write,
-	.read = modem_reset_rpc_test_read,
-};
-
-/* MODEM RESET RMNET TEST */
-static ssize_t modem_reset_rmnet_test_write(struct file *file,
-					     const char __user *buf,
-					     size_t count,
-					     loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- MODEM RESET - RMNT CHANNEL TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t modem_reset_rmnet_test_read(struct file *file,
-					    char __user *buffer,
-					    size_t count,
-					    loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nMODEM_RESET_RMNET_TEST\n"
-		 "======================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations modem_reset_rmnet_test_ops = {
-	.open = sdio_al_test_open,
-	.write = modem_reset_rmnet_test_write,
-	.read = modem_reset_rmnet_test_read,
-};
-
-/* MODEM RESET - CHANNELS IN 4BIT DEVICE TEST */
-static ssize_t modem_reset_channels_4bit_dev_test_write(
-						struct file *file,
-						const char __user *buf,
-						size_t count,
-						loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- MODEM RESET - ALL CHANNELS IN "
-		"4BIT DEVICE TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_RPC]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_QMI]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_DIAG]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t modem_reset_channels_4bit_dev_test_read(
-						struct file *file,
-						char __user *buffer,
-						size_t count,
-						loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nMODEM_RESET_CHANNELS_4BIT_DEV_TEST\n"
-		 "==================================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations modem_reset_channels_4bit_dev_test_ops = {
-	.open = sdio_al_test_open,
-	.write = modem_reset_channels_4bit_dev_test_write,
-	.read = modem_reset_channels_4bit_dev_test_read,
-};
-
-/* MODEM RESET - CHANNELS IN 8BIT DEVICE TEST */
-static ssize_t modem_reset_channels_8bit_dev_test_write(
-						struct file *file,
-						const char __user *buf,
-						size_t count,
-						loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- MODEM RESET - ALL CHANNELS IN "
-		"8BIT DEVICE TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_RMNT]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_DUN]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t modem_reset_channels_8bit_dev_test_read(
-						struct file *file,
-						char __user *buffer,
-						size_t count,
-						loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nMODEM_RESET_CHANNELS_8BIT_DEV_TEST\n"
-		 "==================================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations modem_reset_channels_8bit_dev_test_ops = {
-	.open = sdio_al_test_open,
-	.write = modem_reset_channels_8bit_dev_test_write,
-	.read = modem_reset_channels_8bit_dev_test_read,
-};
-
-/* MODEM RESET - ALL CHANNELS TEST */
-static ssize_t modem_reset_all_channels_test_write(struct file *file,
-						    const char __user *buf,
-						    size_t count,
-						    loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- MODEM RESET - ALL CHANNELS TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_RPC]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_QMI]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_DIAG]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_RMNT]);
-		set_params_modem_reset(test_ctx->test_ch_arr[SDIO_DUN]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t modem_reset_all_channels_test_read(struct file *file,
-						   char __user *buffer,
-						   size_t count,
-						   loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nMODEM_RESET_ALL_CHANNELS_TEST\n"
-		 "=============================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations modem_reset_all_channels_test_ops = {
-	.open = sdio_al_test_open,
-	.write = modem_reset_all_channels_test_write,
-	.read = modem_reset_all_channels_test_read,
-};
-
-/* HOST SENDER WITH OPEN/CLOSE TEST */
-static ssize_t open_close_test_write(struct file *file,
-						   const char __user *buf,
-						   size_t count,
-						   loff_t *ppos)
-{
-	int ret = 0;
-	struct test_channel **ch_arr = test_ctx->test_ch_arr;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- HOST SENDER WITH OPEN/CLOSE TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k_close(ch_arr[SDIO_DIAG]);
-		set_params_loopback_9k_close(ch_arr[SDIO_RPC]);
-		set_params_loopback_9k_close(ch_arr[SDIO_SMEM]);
-		set_params_loopback_9k_close(ch_arr[SDIO_QMI]);
-		set_params_loopback_9k_close(ch_arr[SDIO_RMNT]);
-		set_params_loopback_9k_close(ch_arr[SDIO_DUN]);
-		set_params_loopback_9k_close(ch_arr[SDIO_CSVT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-
-		pr_info(TEST_MODULE_NAME " -- correctness test for"
-				"DIAG ");
-		set_params_loopback_9k(ch_arr[SDIO_DIAG]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t open_close_test_read(struct file *file,
-						  char __user *buffer,
-						  size_t count,
-						  loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nOPEN_CLOSE_TEST\n"
-		 "============================\n"
-		 "Description:\n"
-		 "In this test the host sends 5k packets to the modem in the "
-		 "following sequence: Send a random burst of packets on "
-		 "Diag and Rmnet channels, read 0 or a random number "
-		 "of packets, close and re-open the channel. At the end of the "
-		 "test, the channel is verified by running a loopback test\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations open_close_test_ops = {
-	.open = sdio_al_test_open,
-	.write = open_close_test_write,
-	.read = open_close_test_read,
-};
-
-/* HOST SENDER WITH OPEN/CLOSE FOR DUN & RMNET TEST */
-static ssize_t open_close_dun_rmnet_test_write(struct file *file,
-						   const char __user *buf,
-						   size_t count,
-						   loff_t *ppos)
-{
-	int ret = 0;
-	struct test_channel **ch_arr = test_ctx->test_ch_arr;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- HOST SENDER WITH OPEN/CLOSE FOR "
-		"DUN AND RMNET TEST --");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_loopback_9k_close(ch_arr[SDIO_DUN]);
-		set_params_loopback_9k_close(ch_arr[SDIO_RMNT]);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t open_close_dun_rmnet_test_read(struct file *file,
-						  char __user *buffer,
-						  size_t count,
-						  loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nOPEN_CLOSE_DUN_RMNET_TEST\n"
-		 "============================\n"
-		 "Description:\n"
-		 "In this test the host sends 5k packets to the modem in the "
-		 "following sequence: Send a random burst of packets on "
-		 "DUN and Rmnet channels, read 0 or a random number "
-		 "of packets, close and re-open the channel.\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations open_close_dun_rmnet_test_ops = {
-	.open = sdio_al_test_open,
-	.write = open_close_dun_rmnet_test_write,
-	.read = open_close_dun_rmnet_test_read,
-};
-
-/* CLOSE CHANNEL & LPM TEST HOST WAKES THE CLIENT TEST */
-static ssize_t close_chan_lpm_test_write(struct file *file,
-					  const char __user *buf,
-					  size_t count,
-					  loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int channel_num = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- CLOSE CHANNEL & LPM TEST "
-		"HOST WAKES THE CLIENT TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		for (channel_num = 0 ; channel_num < SDIO_MAX_CHANNELS ;
-		     channel_num++) {
-
-			ret = close_channel_lpm_test(channel_num);
-
-			if (ret)
-				break;
-
-			set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
-					    SDIO_TEST_LPM_HOST_WAKER, 120);
-
-			ret = test_start();
-
-			if (ret)
-				break;
-		}
-
-		if (ret) {
-			pr_err(TEST_MODULE_NAME " -- Close channel & LPM Test "
-			       "FAILED: %d --\n", ret);
-		} else {
-			pr_err(TEST_MODULE_NAME " -- Close channel & LPM Test "
-			       "PASSED\n");
-		}
-	}
-
-	return count;
-}
-
-static ssize_t close_chan_lpm_test_read(struct file *file,
-					 char __user *buffer,
-					 size_t count,
-					 loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nCLOSE_CHAN_LPM_TEST\n"
-		 "===================\n"
-		 "Description:\n"
-		 "TBD\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations close_chan_lpm_test_ops = {
-	.open = sdio_al_test_open,
-	.write = close_chan_lpm_test_write,
-	.read = close_chan_lpm_test_read,
-};
-
-/* LPM TEST FOR DEVICE 1. CLIENT WAKES THE HOST TEST */
-static ssize_t lpm_test_client_wakes_host_test_write(struct file *file,
-						      const char __user *buf,
-						      size_t count,
-						      loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- LPM TEST FOR DEVICE 1. CLIENT "
-		"WAKES THE HOST TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
-				    SDIO_TEST_LPM_CLIENT_WAKER, 90);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t lpm_test_client_wakes_host_test_read(struct file *file,
-						     char __user *buffer,
-						     size_t count,
-						     loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nLPM_TEST_CLIENT_WAKES_HOST_TEST\n"
-		 "===============================\n"
-		 "Description:\n"
-		 "In this test, the HOST is going into LPM mode,\n"
-		 "and the CLIENT is responsible to send it a message\n"
-		 "in order to wake it up\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations lpm_test_client_wakes_host_test_ops = {
-	.open = sdio_al_test_open,
-	.write = lpm_test_client_wakes_host_test_write,
-	.read = lpm_test_client_wakes_host_test_read,
-};
-
-/* LPM TEST FOR DEVICE 1. HOST WAKES THE CLIENT TEST */
-static ssize_t lpm_test_host_wakes_client_test_write(struct file *file,
-						      const char __user *buf,
-						      size_t count,
-						      loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- LPM TEST FOR DEVICE 1. HOST "
-		"WAKES THE CLIENT TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
-			    SDIO_TEST_LPM_HOST_WAKER, 120);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t lpm_test_host_wakes_client_test_read(struct file *file,
-						     char __user *buffer,
-						     size_t count,
-						     loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nLPM_TEST_HOST_WAKES_CLIENT_TEST\n"
-		 "===============================\n"
-		 "Description:\n"
-		 "In this test, the CLIENT goes into LPM mode, and the\n"
-		 "HOST is responsible to send it a message\n"
-		 "in order to wake it up\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations lpm_test_host_wakes_client_test_ops = {
-	.open = sdio_al_test_open,
-	.write = lpm_test_host_wakes_client_test_write,
-	.read = lpm_test_host_wakes_client_test_read,
-};
-
-/* LPM TEST RANDOM, SINGLE CHANNEL TEST */
-static ssize_t lpm_test_random_single_channel_test_write(
-						struct file *file,
-						const char __user *buf,
-						size_t count,
-						loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- LPM TEST RANDOM SINGLE "
-		"CHANNEL TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_pseudo_random_seed();
-		set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
-				    SDIO_TEST_LPM_RANDOM, 0);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t lpm_test_random_single_channel_test_read(
-						struct file *file,
-						char __user *buffer,
-						size_t count,
-						loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nLPM_TEST_RANDOM_SINGLE_CHANNEL_TEST\n"
-		 "===================================\n"
-		 "Description:\n"
-		 "In this test, the HOST and CLIENT "
-		 "send messages to each other,\n"
-		 "random in time, over RPC channel only.\n"
-		 "All events are being recorded, and later on,\n"
-		 "they are being analysed by the HOST and by the CLIENT\n,"
-		 "in order to check if the LPM mechanism worked properly,\n"
-		 "meaning:"
-		 " When all the relevant conditions are met, a device should:\n"
-		 "1. Go to sleep\n"
-		 "2. Wake up\n"
-		 "3. Stay awake\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations lpm_test_random_single_channel_test_ops = {
-	.open = sdio_al_test_open,
-	.write = lpm_test_random_single_channel_test_write,
-	.read = lpm_test_random_single_channel_test_read,
-};
-
-/* LPM TEST RANDOM, MULTI CHANNEL TEST */
-static ssize_t lpm_test_random_multi_channel_test_write(
-						struct file *file,
-						const char __user *buf,
-						size_t count,
-						loff_t *ppos)
-{
-	int ret = 0;
-	int i = 0;
-	int number = -1;
-
-	pr_info(TEST_MODULE_NAME "-- LPM TEST RANDOM MULTI CHANNEL TEST --\n");
-
-	number = sdio_al_test_extract_number(buf, count);
-
-	if (number < 0) {
-		pr_err(TEST_MODULE_NAME " : %s - sdio_al_test_extract_number() "
-		       "failed. number = %d\n", __func__, number);
-		return count;
-	}
-
-	for (i = 0 ; i < number ; ++i) {
-		pr_info(TEST_MODULE_NAME " - Cycle # %d / %d\n", i+1, number);
-		pr_info(TEST_MODULE_NAME " ===================");
-
-		sdio_al_test_initial_dev_and_chan(test_ctx);
-
-		set_pseudo_random_seed();
-
-		set_params_lpm_test(test_ctx->test_ch_arr[SDIO_RPC],
-				    SDIO_TEST_LPM_RANDOM, 0);
-		set_params_lpm_test(test_ctx->test_ch_arr[SDIO_DIAG],
-				    SDIO_TEST_LPM_RANDOM, 0);
-		set_params_lpm_test(test_ctx->test_ch_arr[SDIO_QMI],
-				SDIO_TEST_LPM_RANDOM, 0);
-
-		ret = test_start();
-
-		if (ret)
-			break;
-	}
-
-	return count;
-}
-
-static ssize_t lpm_test_random_multi_channel_test_read(
-				 struct file *file,
-				 char __user *buffer,
-				 size_t count,
-				 loff_t *offset)
-{
-	memset((void *)buffer, 0, count);
-
-	snprintf(buffer, count,
-		 "\nLPM_TEST_RANDOM_MULTI_CHANNEL_TEST\n"
-		 "==================================\n"
-		 "Description:\n"
-		 "In this test, the HOST and CLIENT "
-		 "send messages to each other,\n"
-		 "random in time, over RPC, QMI AND DIAG channels\n"
-		 "(i.e, on both SDIO devices).\n"
-		 "All events are being recorded, and later on,\n"
-		 "they are being analysed by the HOST and by the CLIENT,\n"
-		 "in order to check if the LPM mechanism worked properly,\n"
-		 "meaning:"
-		 " When all the relevant conditions are met, a device should:\n"
-		 "1. Go to sleep\n"
-		 "2. Wake up\n"
-		 "3. Stay awake\n\n"
-		 "END OF DESCRIPTION\n");
-
-	if (message_repeat == 1) {
-		message_repeat = 0;
-		return strnlen(buffer, count);
-	} else {
-		return 0;
-	}
-}
-
-const struct file_operations lpm_test_random_multi_channel_test_ops = {
-	.open = sdio_al_test_open,
-	.write = lpm_test_random_multi_channel_test_write,
-	.read = lpm_test_random_multi_channel_test_read,
-};
-
-static int sdio_al_test_debugfs_init(void)
-{
-	test_ctx->debug.debug_root = debugfs_create_dir("sdio_al_test",
-							       NULL);
-	if (!test_ctx->debug.debug_root)
-		return -ENOENT;
-
-	test_ctx->debug.debug_test_result = debugfs_create_u32(
-					"test_result",
-					S_IRUGO | S_IWUGO,
-					test_ctx->debug.debug_root,
-					&test_ctx->test_result);
-
-	test_ctx->debug.debug_dun_throughput = debugfs_create_u32(
-					"dun_throughput",
-					S_IRUGO | S_IWUGO,
-					test_ctx->debug.debug_root,
-					&test_ctx->debug.dun_throughput);
-
-	test_ctx->debug.debug_rmnt_throughput = debugfs_create_u32(
-					"rmnt_throughput",
-					S_IRUGO | S_IWUGO,
-					test_ctx->debug.debug_root,
-					&test_ctx->debug.rmnt_throughput);
-
-	test_ctx->debug.rpc_sender_test =
-		debugfs_create_file("10_rpc_sender_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &rpc_sender_test_ops);
-
-	test_ctx->debug.rpc_qmi_diag_sender_test =
-		debugfs_create_file("20_rpc_qmi_diag_sender_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &rpc_qmi_diag_sender_test_ops);
-
-	test_ctx->debug.rmnet_a2_validation_test =
-		debugfs_create_file("30_rmnet_a2_validation_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &rmnet_a2_validation_test_ops);
-
-	test_ctx->debug.dun_a2_validation_test =
-		debugfs_create_file("40_dun_a2_validation_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &dun_a2_validation_test_ops);
-
-	test_ctx->debug.rmnet_a2_perf_test =
-		debugfs_create_file("50_rmnet_a2_perf_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &rmnet_a2_perf_test_ops);
-
-	test_ctx->debug.dun_a2_perf_test =
-		debugfs_create_file("60_dun_a2_perf_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &dun_a2_perf_test_ops);
-
-	test_ctx->debug.csvt_a2_perf_test =
-		debugfs_create_file("71_csvt_a2_perf_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &csvt_a2_perf_test_ops);
-
-	test_ctx->debug.rmnet_dun_a2_perf_test =
-		debugfs_create_file("70_rmnet_dun_a2_perf_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &rmnet_dun_a2_perf_test_ops);
-
-	test_ctx->debug.rpc_sender_rmnet_a2_perf_test =
-		debugfs_create_file("80_rpc_sender_rmnet_a2_perf_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &rpc_sender_rmnet_a2_perf_test_ops);
-
-	test_ctx->debug.smem_test =
-		debugfs_create_file("90_smem_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &smem_test_ops);
-
-	test_ctx->debug.smem_rpc_test =
-		debugfs_create_file("100_smem_rpc_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &smem_rpc_test_ops);
-
-	test_ctx->debug.all_channels_test =
-		debugfs_create_file("150_all_channels_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &all_channels_test_ops);
-
-	test_ctx->debug.host_sender_no_lp_diag_test =
-		debugfs_create_file("160_host_sender_no_lp_diag_test",
-				    S_IRUGO | S_IWUGO,
-				    test_ctx->debug.debug_root,
-				    NULL,
-				    &host_sender_no_lp_diag_test_ops);
-
-	test_ctx->debug.host_sender_no_lp_diag_rpc_test =
-		debugfs_create_file("170_host_sender_no_lp_diag_rpc_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &host_sender_no_lp_diag_rpc_test_ops);
-
-	test_ctx->debug.rmnet_small_packets_test =
-		debugfs_create_file("180_rmnet_small_packets_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &rmnet_small_packets_test_ops);
-
-	test_ctx->debug.rmnet_rtt_test =
-		debugfs_create_file("190_rmnet_rtt_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &rmnet_rtt_test_ops);
-
-	test_ctx->debug.csvt_rtt_test =
-		debugfs_create_file("191_csvt_rtt_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &csvt_rtt_test_ops);
-
-	test_ctx->debug.modem_reset_rpc_test =
-		debugfs_create_file("220_modem_reset_rpc_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &modem_reset_rpc_test_ops);
-
-	test_ctx->debug.modem_reset_rmnet_test =
-		debugfs_create_file("230_modem_reset_rmnet_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &modem_reset_rmnet_test_ops);
-
-	test_ctx->debug.modem_reset_channels_4bit_dev_test =
-		debugfs_create_file("240_modem_reset_channels_4bit_dev_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &modem_reset_channels_4bit_dev_test_ops);
-
-	test_ctx->debug.modem_reset_channels_8bit_dev_test =
-		debugfs_create_file("250_modem_reset_channels_8bit_dev_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &modem_reset_channels_8bit_dev_test_ops);
-
-	test_ctx->debug.modem_reset_all_channels_test =
-		debugfs_create_file("260_modem_reset_all_channels_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &modem_reset_all_channels_test_ops);
-
-	test_ctx->debug.open_close_test =
-		debugfs_create_file("270_open_close_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &open_close_test_ops);
-
-	test_ctx->debug.open_close_dun_rmnet_test =
-		debugfs_create_file("271_open_close_dun_rmnet_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &open_close_dun_rmnet_test_ops);
-
-	test_ctx->debug.close_chan_lpm_test =
-		debugfs_create_file("280_close_chan_lpm_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &close_chan_lpm_test_ops);
-
-	test_ctx->debug.lpm_test_client_wakes_host_test =
-		debugfs_create_file("600_lpm_test_client_wakes_host_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &lpm_test_client_wakes_host_test_ops);
-
-	test_ctx->debug.lpm_test_host_wakes_client_test =
-		debugfs_create_file("610_lpm_test_host_wakes_client_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &lpm_test_host_wakes_client_test_ops);
-
-	test_ctx->debug.lpm_test_random_single_channel_test =
-		debugfs_create_file("620_lpm_test_random_single_channel_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &lpm_test_random_single_channel_test_ops);
-
-	test_ctx->debug.lpm_test_random_multi_channel_test =
-		debugfs_create_file("630_lpm_test_random_multi_channel_test",
-				     S_IRUGO | S_IWUGO,
-				     test_ctx->debug.debug_root,
-				     NULL,
-				     &lpm_test_random_multi_channel_test_ops);
-
-	if ((!test_ctx->debug.debug_dun_throughput) &&
-	    (!test_ctx->debug.debug_rmnt_throughput)) {
-		debugfs_remove_recursive(test_ctx->debug.debug_root);
-		test_ctx->debug.debug_root = NULL;
-		return -ENOENT;
-	}
-	return 0;
-}
-
-static void sdio_al_test_debugfs_cleanup(void)
-{
-       debugfs_remove(test_ctx->debug.debug_dun_throughput);
-       debugfs_remove(test_ctx->debug.debug_rmnt_throughput);
-       debugfs_remove(test_ctx->debug.debug_root);
-}
-#endif
-
-static int channel_name_to_id(char *name)
-{
-	pr_info(TEST_MODULE_NAME "%s: channel name %s\n",
-		__func__, name);
-
-	if (!strncmp(name, "SDIO_RPC_TEST",
-		     strnlen("SDIO_RPC_TEST", CHANNEL_NAME_SIZE)))
-		return SDIO_RPC;
-	else if (!strncmp(name, "SDIO_QMI_TEST",
-			  strnlen("SDIO_QMI_TEST", TEST_CH_NAME_SIZE)))
-		return SDIO_QMI;
-	else if (!strncmp(name, "SDIO_RMNT_TEST",
-			  strnlen("SDIO_RMNT_TEST", TEST_CH_NAME_SIZE)))
-		return SDIO_RMNT;
-	else if (!strncmp(name, "SDIO_DIAG_TEST",
-			  strnlen("SDIO_DIAG", TEST_CH_NAME_SIZE)))
-		return SDIO_DIAG;
-	else if (!strncmp(name, "SDIO_DUN_TEST",
-			  strnlen("SDIO_DUN_TEST", TEST_CH_NAME_SIZE)))
-		return SDIO_DUN;
-	else if (!strncmp(name, "SDIO_SMEM_TEST",
-			  strnlen("SDIO_SMEM_TEST", TEST_CH_NAME_SIZE)))
-		return SDIO_SMEM;
-	else if (!strncmp(name, "SDIO_CSVT_TEST",
-			  strnlen("SDIO_CSVT_TEST", TEST_CH_NAME_SIZE)))
-		return SDIO_CSVT;
-	else
-		return SDIO_MAX_CHANNELS;
-
-	return SDIO_MAX_CHANNELS;
-}
-
-/**
- * Allocate and add SDIO_SMEM platform device
- */
-#ifdef CONFIG_MSM_SDIO_SMEM
-static int add_sdio_smem(void)
-{
-	int ret = 0;
-
-	test_ctx->smem_pdev = platform_device_alloc("SDIO_SMEM", -1);
-	ret = platform_device_add(test_ctx->smem_pdev);
-	if (ret) {
-		pr_err(TEST_MODULE_NAME ": platform_device_add failed, "
-				   "ret=%d\n", ret);
-		return ret;
-	}
-	return 0;
-}
-#endif
-
-static int open_sdio_ch(struct test_channel *tch)
-{
-	int ret = 0;
-
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ": %s NULL tch\n", __func__);
-		return -EINVAL;
-	}
-
-	if (!tch->ch_ready) {
-		TEST_DBG(TEST_MODULE_NAME ":openning channel %s\n",
-			tch->name);
-		if (tch->ch_id == SDIO_SMEM) {
-#ifdef CONFIG_MSM_SDIO_SMEM
-			if (!test_ctx->smem_pdev)
-				ret = add_sdio_smem();
-			else
-				ret = sdio_smem_open(test_ctx->sdio_smem);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME
-					":openning channel %s failed\n",
-				tch->name);
-				tch->ch_ready = false;
-				return -EINVAL;
-			}
-#endif
-		} else {
-			tch->ch_ready = true;
-			ret = sdio_open(tch->name , &tch->ch, tch,
-					notify);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME
-					":openning channel %s failed\n",
-				tch->name);
-				tch->ch_ready = false;
-				return -EINVAL;
-			}
-		}
-	}
-	return ret;
-}
-
-static int close_sdio_ch(struct test_channel *tch)
-{
-	int ret = 0;
-
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ": %s NULL tch\n", __func__);
-		return -EINVAL;
-	}
-
-	if (tch->ch_id == SDIO_SMEM) {
-#ifdef CONFIG_MSM_SDIO_SMEM
-		TEST_DBG(TEST_MODULE_NAME":%s closing channel %s",
-		       __func__, tch->name);
-		ret = sdio_smem_unregister_client();
-		test_ctx->smem_counter = 0;
-#endif
-	} else {
-		ret = sdio_close(tch->ch);
-	}
-
-	if (ret) {
-		pr_err(TEST_MODULE_NAME":%s close channel %s"
-				" failed\n", __func__, tch->name);
-	} else {
-		TEST_DBG(TEST_MODULE_NAME":%s close channel %s"
-				" success\n", __func__, tch->name);
-		tch->ch_ready = false;
-	}
-	return ret;
-}
-
-/**
- * Config message
- */
-
-static void send_config_msg(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 write_avail = 0;
-	int size = sizeof(test_ch->config_msg);
-
-	pr_debug(TEST_MODULE_NAME "%s\n", __func__);
-
-	memcpy(test_ch->buf, (void *)&test_ch->config_msg, size);
-
-	if (test_ctx->exit_flag) {
-		pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-		return;
-	}
-
-	pr_info(TEST_MODULE_NAME ":Sending the config message.\n");
-
-	/* wait for data ready event */
-	write_avail = sdio_write_avail(test_ch->ch);
-	pr_debug(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
-	if (write_avail < size) {
-		wait_event(test_ch->wait_q,
-			   atomic_read(&test_ch->tx_notify_count));
-		atomic_dec(&test_ch->tx_notify_count);
-	}
-
-	write_avail = sdio_write_avail(test_ch->ch);
-	pr_debug(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
-	if (write_avail < size) {
-		pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
-		return;
-	}
-
-	ret = sdio_write(test_ch->ch, test_ch->buf, size);
-	if (ret)
-		pr_err(TEST_MODULE_NAME ":%s sdio_write err=%d.\n",
-			__func__, -ret);
-	else
-		pr_info(TEST_MODULE_NAME ":%s sent config_msg successfully.\n",
-		       __func__);
-}
-
-/**
- * Loopback Test
- */
-static void loopback_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 read_avail = 0;
-	u32 write_avail = 0;
-
-	while (1) {
-
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-
-		TEST_DBG(TEST_MODULE_NAME "--LOOPBACK WAIT FOR EVENT--.\n");
-		/* wait for data ready event */
-		wait_event(test_ch->wait_q,
-			   atomic_read(&test_ch->rx_notify_count));
-		atomic_dec(&test_ch->rx_notify_count);
-
-		read_avail = sdio_read_avail(test_ch->ch);
-		if (read_avail == 0)
-			continue;
-
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		if (write_avail < read_avail) {
-			pr_info(TEST_MODULE_NAME
-				":not enough write avail.\n");
-			continue;
-		}
-
-		ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME
-			       ":worker, sdio_read err=%d.\n", -ret);
-			continue;
-		}
-		test_ch->rx_bytes += read_avail;
-
-		TEST_DBG(TEST_MODULE_NAME ":worker total rx bytes = 0x%x.\n",
-			 test_ch->rx_bytes);
-
-
-		ret = sdio_write(test_ch->ch,
-				 test_ch->buf, read_avail);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME
-				":loopback sdio_write err=%d.\n",
-				-ret);
-			continue;
-		}
-		test_ch->tx_bytes += read_avail;
-
-		TEST_DBG(TEST_MODULE_NAME
-			 ":loopback total tx bytes = 0x%x.\n",
-			 test_ch->tx_bytes);
-	} /* end of while */
-}
-
-/**
- * Check if all tests completed
- */
-static void check_test_completion(void)
-{
-	int i;
-
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
-			continue;
-		if (!tch->test_completed) {
-			pr_info(TEST_MODULE_NAME ": %s - Channel %s test is "
-				"not completed", __func__, tch->name);
-			return;
-		}
-	}
-	pr_info(TEST_MODULE_NAME ": %s - Test is completed", __func__);
-	test_ctx->test_completed = 1;
-	wake_up(&test_ctx->wait_q);
-}
-
-static int pseudo_random_seed(unsigned int *seed_number)
-{
-	if (!seed_number)
-		return 0;
-
-	*seed_number = (unsigned int)(((unsigned long)*seed_number *
-				(unsigned long)1103515367) + 35757);
-	return (int)((*seed_number / (64*1024)) % 500);
-}
-
-/* this function must be locked before accessing it */
-static void lpm_test_update_entry(struct test_channel *tch,
-				  enum lpm_test_msg_type msg_type,
-				   char *msg_name,
-				  int counter)
-{
-	u32 index = 0;
-	static int print_full = 1;
-	struct sdio_test_device *test_device;
-
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
-		return;
-	}
-
-	test_device = tch->test_device;
-
-	if (!test_device) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
-		return;
-	}
-
-	if (!test_device->lpm_arr) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL lpm_arr\n", __func__);
-		return;
-	}
-
-	if (test_device->next_avail_entry_in_array >=
-					test_device->array_size) {
-		pr_err(TEST_MODULE_NAME ": %s - lpm array is full",
-			__func__);
-
-		if (print_full) {
-			print_hex_dump(KERN_INFO, TEST_MODULE_NAME ": lpm_arr:",
-				0, 32, 2,
-				(void *)test_device->lpm_arr,
-				sizeof(test_device->lpm_arr), false);
-			print_full = 0;
-		}
-		return;
-	}
-
-	index = test_device->next_avail_entry_in_array;
-	if ((msg_type == LPM_MSG_SEND) || (msg_type == LPM_MSG_REC))
-		test_device->lpm_arr[index].counter = counter;
-	else
-		test_device->lpm_arr[index].counter = 0;
-
-	test_device->lpm_arr[index].msg_type = msg_type;
-	memcpy(test_device->lpm_arr[index].msg_name, msg_name,
-	       LPM_MSG_NAME_SIZE);
-	test_device->lpm_arr[index].current_ms =
-		jiffies_to_msecs(get_jiffies_64());
-
-	test_device->lpm_arr[index].read_avail_mask =
-		test_device->read_avail_mask;
-
-	if ((msg_type == LPM_SLEEP) || (msg_type == LPM_WAKEUP))
-		memcpy(test_device->lpm_arr[index].chan_name, "DEVICE  ",
-		       CHANNEL_NAME_SIZE);
-	else
-		memcpy(test_device->lpm_arr[index].chan_name, tch->name,
-		       CHANNEL_NAME_SIZE);
-
-	test_device->next_avail_entry_in_array++;
-}
-
-static int wait_for_result_msg(struct test_channel *test_ch)
-{
-	u32 read_avail = 0;
-	int ret = 0;
-
-	pr_info(TEST_MODULE_NAME ": %s - START, channel %s\n",
-		__func__, test_ch->name);
-
-	while (1) {
-		read_avail = sdio_read_avail(test_ch->ch);
-
-		if (read_avail == 0) {
-			pr_info(TEST_MODULE_NAME
-				": read_avail is 0 for chan %s\n",
-				test_ch->name);
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->rx_notify_count));
-			atomic_dec(&test_ch->rx_notify_count);
-			continue;
-		}
-
-		memset(test_ch->buf, 0x00, test_ch->buf_size);
-
-		ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME ":  sdio_read for chan"
-				"%s failed, err=%d.\n",
-				test_ch->name, -ret);
-			goto exit_err;
-		}
-
-		if (test_ch->buf[0] != TEST_CONFIG_SIGNATURE) {
-			pr_info(TEST_MODULE_NAME ": Not a test_result "
-				"signature. expected 0x%x. received 0x%x "
-				"for chan %s\n",
-				TEST_CONFIG_SIGNATURE,
-				test_ch->buf[0],
-				test_ch->name);
-			continue;
-		} else {
-			pr_info(TEST_MODULE_NAME ": Signature is "
-				"TEST_CONFIG_SIGNATURE as expected for"
-				"channel %s\n", test_ch->name);
-			break;
-		}
-	}
-
-	return test_ch->buf[1];
-
-exit_err:
-	return 0;
-}
-
-static void print_random_lpm_test_array(struct sdio_test_device *test_dev)
-{
-	int i;
-
-	if (!test_dev) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
-		return;
-	}
-
-	for (i = 0 ; i < test_dev->next_avail_entry_in_array ; ++i) {
-		if (i == 0)
-			pr_err(TEST_MODULE_NAME ": index %4d, chan=%2s, "
-			       "code=%1d=%4s, msg#%1d, ms from before=-1, "
-			       "read_mask=0x%d, ms=%2u",
-			       i,
-			       test_dev->lpm_arr[i].chan_name,
-			       test_dev->lpm_arr[i].msg_type,
-			       test_dev->lpm_arr[i].msg_name,
-			       test_dev->lpm_arr[i].counter,
-			       test_dev->lpm_arr[i].read_avail_mask,
-			       test_dev->lpm_arr[i].current_ms);
-		else
-			pr_err(TEST_MODULE_NAME ": index "
-			       "%4d, %2s, code=%1d=%4s, msg#%1d, ms from "
-			       "before=%2u, read_mask=0x%d, ms=%2u",
-			       i,
-			       test_dev->lpm_arr[i].chan_name,
-			       test_dev->lpm_arr[i].msg_type,
-			       test_dev->lpm_arr[i].msg_name,
-			       test_dev->lpm_arr[i].counter,
-			       test_dev->lpm_arr[i].current_ms -
-			       test_dev->lpm_arr[i-1].current_ms,
-			       test_dev->lpm_arr[i].read_avail_mask,
-			       test_dev->lpm_arr[i].current_ms);
-
-		udelay(1000);
-	}
-}
-
-static int check_random_lpm_test_array(struct sdio_test_device *test_dev)
-{
-	int i = 0, j = 0;
-	unsigned int delta_ms = 0;
-	int arr_ind = 0;
-	int ret = 0;
-	int notify_counter = 0;
-	int sleep_counter = 0;
-	int wakeup_counter = 0;
-	int lpm_activity_counter = 0;
-
-	if (!test_dev) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
-		return -ENODEV;
-	}
-
-	for (i = 0; i < test_dev->next_avail_entry_in_array; i++) {
-		notify_counter = 0;
-		sleep_counter = 0;
-		wakeup_counter = 0;
-
-		if ((test_dev->lpm_arr[i].msg_type == LPM_MSG_SEND) ||
-		     (test_dev->lpm_arr[i].msg_type == LPM_MSG_REC)) {
-			/* find the next message in the array */
-			arr_ind = test_dev->next_avail_entry_in_array;
-			for (j = i+1; j < arr_ind; j++) {
-				if ((test_dev->lpm_arr[j].msg_type ==
-				     LPM_MSG_SEND) ||
-				    (test_dev->lpm_arr[j].msg_type ==
-				     LPM_MSG_REC) ||
-				    (test_dev->lpm_arr[j].msg_type ==
-				     LPM_NOTIFY))
-					break;
-				if (test_dev->lpm_arr[j].msg_type ==
-				    LPM_SLEEP)
-					sleep_counter++;
-				if (test_dev->lpm_arr[j].msg_type ==
-				    LPM_WAKEUP)
-					wakeup_counter++;
-			}
-			if (j == arr_ind) {
-				ret = 0;
-				break;
-			}
-
-			delta_ms = test_dev->lpm_arr[j].current_ms -
-				test_dev->lpm_arr[i].current_ms;
-			if (delta_ms < 30) {
-				if ((sleep_counter == 0)
-				    && (wakeup_counter == 0)) {
-					continue;
-				} else {
-					pr_err(TEST_MODULE_NAME "%s: lpm "
-						"activity while delta is less "
-						"than 30, i=%d, j=%d, "
-						"sleep_counter=%d, "
-						"wakeup_counter=%d",
-					       __func__, i, j,
-					       sleep_counter, wakeup_counter);
-					ret = -ENODEV;
-					break;
-				}
-			} else {
-				if ((delta_ms > 90) &&
-				    (test_dev->lpm_arr[i].
-						read_avail_mask == 0)) {
-					if (j != i+3) {
-						pr_err(TEST_MODULE_NAME
-						       "%s: unexpected "
-						       "lpm activity "
-						       "while delta is "
-						       "bigger than "
-						       "90, i=%d, "
-						       "j=%d, "
-						       "notify_counter"
-						       "=%d",
-						       __func__, i, j,
-						       notify_counter);
-						ret = -ENODEV;
-						break;
-					}
-					lpm_activity_counter++;
-				}
-			}
-		}
-	}
-
-	pr_info(TEST_MODULE_NAME ": %s - lpm_activity_counter=%d",
-		__func__, lpm_activity_counter);
-
-	return ret;
-}
-
-static int lpm_test_main_task(void *ptr)
-{
-	u32 read_avail = 0;
-	int last_msg_index = 0;
-	struct test_channel *test_ch = (struct test_channel *)ptr;
-	struct sdio_test_device *test_dev;
-	struct lpm_msg lpm_msg;
-	int ret = 0;
-	int host_result = 0;
-
-	if (!test_ch) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
-		return -ENODEV;
-	}
-
-	pr_err(TEST_MODULE_NAME ": %s - STARTED. channel %s\n",
-	       __func__, test_ch->name);
-
-	test_dev = test_ch->test_device;
-
-	if (!test_dev) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL Test Device\n", __func__);
-		return -ENODEV;
-	}
-
-	while (last_msg_index < test_ch->config_msg.num_packets - 1) {
-
-		TEST_DBG(TEST_MODULE_NAME ": %s - "
-			"IN LOOP last_msg_index=%d\n",
-		       __func__, last_msg_index);
-
-		read_avail = sdio_read_avail(test_ch->ch);
-		if (read_avail == 0) {
-			TEST_DBG(TEST_MODULE_NAME
-					":read_avail 0 for chan %s, "
-					"wait for event\n",
-					test_ch->name);
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->rx_notify_count));
-			atomic_dec(&test_ch->rx_notify_count);
-
-			read_avail = sdio_read_avail(test_ch->ch);
-			if (read_avail == 0) {
-				pr_err(TEST_MODULE_NAME
-					":read_avail size %d for chan %s not as"
-					" expected\n",
-					read_avail, test_ch->name);
-				continue;
-			}
-		}
-
-		memset(test_ch->buf, 0x00, sizeof(test_ch->buf));
-
-		ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME ":sdio_read for chan %s"
-				" err=%d.\n", test_ch->name, -ret);
-			goto exit_err;
-		}
-
-		memcpy((void *)&lpm_msg, test_ch->buf, sizeof(lpm_msg));
-
-		/*
-		 * when reading from channel, we want to turn off the bit
-		 * mask that implies that there is pending data on that channel
-		 */
-		if (test_ch->test_device != NULL) {
-			spin_lock_irqsave(&test_dev->lpm_array_lock,
-					  test_dev->lpm_array_lock_flags);
-
-			test_ch->notify_counter_per_chan--;
-
-			/*
-			 * if the channel has no pending data, turn off the
-			 * pending data bit mask of the channel
-			 */
-			if (test_ch->notify_counter_per_chan == 0) {
-				test_ch->test_device->read_avail_mask =
-					test_ch->test_device->read_avail_mask &
-					~test_ch->channel_mask_id;
-			}
-
-			last_msg_index = lpm_msg.counter;
-			lpm_test_update_entry(test_ch,
-					      LPM_MSG_REC,
-					      "RECEIVE",
-					      last_msg_index);
-
-			spin_unlock_irqrestore(&test_dev->lpm_array_lock,
-					       test_dev->lpm_array_lock_flags);
-		}
-	}
-
-	pr_info(TEST_MODULE_NAME ":%s: Finished to recieve all (%d) "
-		"packets from the modem %s. Waiting for result_msg",
-		__func__, test_ch->config_msg.num_packets, test_ch->name);
-
-	/* Wait for the resault message from the modem */
-	test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
-
-	/*
-	 * the DEVICE modem result is a failure if one of the channels on
-	 * that device, got modem_result = 0. this is why we bitwise "AND" each
-	 * time another channel completes its task
-	 */
-	test_dev->modem_result_per_dev &= test_ch->modem_result_per_chan;
-
-	/*
-	 * when reading from channel, we want to turn off the bit
-	 * mask that implies that there is pending data on that channel
-	 */
-	spin_lock_irqsave(&test_dev->lpm_array_lock,
-					  test_dev->lpm_array_lock_flags);
-
-	test_dev->open_channels_counter_to_recv--;
-
-	/* turning off the read_avail bit of the channel */
-	test_ch->test_device->read_avail_mask =
-		test_ch->test_device->read_avail_mask &
-		~test_ch->channel_mask_id;
-
-	spin_unlock_irqrestore(&test_dev->lpm_array_lock,
-					       test_dev->lpm_array_lock_flags);
-
-	/* Wait for all the packets to be sent to the modem */
-	while (1) {
-		spin_lock_irqsave(&test_dev->lpm_array_lock,
-				  test_dev->lpm_array_lock_flags);
-
-		if (test_ch->next_index_in_sent_msg_per_chan >=
-		    test_ch->config_msg.num_packets - 1) {
-
-			spin_unlock_irqrestore(&test_dev->lpm_array_lock,
-					       test_dev->lpm_array_lock_flags);
-			break;
-		} else {
-			pr_info(TEST_MODULE_NAME ":%s: Didn't finished to send "
-				"all packets, "
-				"next_index_in_sent_msg_per_chan = %d ",
-				__func__,
-				test_ch->next_index_in_sent_msg_per_chan);
-		}
-		spin_unlock_irqrestore(&test_dev->lpm_array_lock,
-				       test_dev->lpm_array_lock_flags);
-		msleep(60);
-	}
-
-	/*
-	 * if device has still open channels to test, then the test on the
-	 * device is still running but the test on current channel is completed
-	 */
-	if (test_dev->open_channels_counter_to_recv != 0 ||
-	    test_dev->open_channels_counter_to_send != 0) {
-		test_ch->test_completed = 1;
-		return 0;
-	} else {
-		test_ctx->number_of_active_devices--;
-		sdio_al_unregister_lpm_cb(test_ch->sdio_al_device);
-
-		if (test_ch->test_type == SDIO_TEST_LPM_RANDOM)
-			host_result = check_random_lpm_test_array(test_dev);
-
-		if (host_result ||
-		    !test_dev->modem_result_per_dev ||
-		    test_ctx->runtime_debug)
-			print_random_lpm_test_array(test_dev);
-
-		pr_info(TEST_MODULE_NAME ": %s - host_result=%d.(0 for "
-			"SUCCESS) device_modem_result=%d (1 for SUCCESS)",
-			__func__, host_result, test_dev->modem_result_per_dev);
-
-		test_ch->test_completed = 1;
-		if (test_dev->modem_result_per_dev && !host_result) {
-			pr_info(TEST_MODULE_NAME ": %s - Random LPM "
-				"TEST_PASSED for device %d of %d\n",
-				__func__,
-				(test_ctx->max_number_of_devices-
-				test_ctx->number_of_active_devices),
-				test_ctx->max_number_of_devices);
-			test_dev->final_result_per_dev = 1; /* PASSED */
-		} else {
-			pr_info(TEST_MODULE_NAME ": %s - Random LPM "
-				"TEST_FAILED for device %d of %d\n",
-				__func__,
-				(test_ctx->max_number_of_devices-
-				test_ctx->number_of_active_devices),
-				test_ctx->max_number_of_devices);
-			test_dev->final_result_per_dev = 0; /* FAILED */
-		}
-
-		check_test_completion();
-
-		kfree(test_ch->test_device->lpm_arr);
-
-		return 0;
-	}
-
-exit_err:
-	pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
-		test_ch->name);
-	test_ch->test_completed = 1;
-	test_dev->open_channels_counter_to_recv--;
-	test_dev->next_avail_entry_in_array = 0;
-	test_ch->next_index_in_sent_msg_per_chan = 0;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return -ENODEV;
-}
-
-static int lpm_test_create_read_thread(struct test_channel *test_ch)
-{
-	struct sdio_test_device *test_dev;
-
-	pr_info(TEST_MODULE_NAME ": %s - STARTED channel %s\n",
-		__func__, test_ch->name);
-
-	if (!test_ch) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
-		return -ENODEV;
-	}
-
-	test_dev = test_ch->test_device;
-
-	if (!test_dev) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test device\n", __func__);
-		return -ENODEV;
-	}
-
-	test_dev->lpm_test_task.task_name = SDIO_LPM_TEST;
-
-	test_dev->lpm_test_task.lpm_task =
-		kthread_create(lpm_test_main_task,
-			       (void *)(test_ch),
-			       test_dev->lpm_test_task.task_name);
-
-	if (IS_ERR(test_dev->lpm_test_task.lpm_task)) {
-		pr_err(TEST_MODULE_NAME ": %s - kthread_create() failed\n",
-			__func__);
-		return -ENOMEM;
-	}
-
-	wake_up_process(test_dev->lpm_test_task.lpm_task);
-
-	return 0;
-}
-
-static void lpm_continuous_rand_test(struct test_channel *test_ch)
-{
-	unsigned int local_ms = 0;
-	int ret = 0;
-	unsigned int write_avail = 0;
-	struct sdio_test_device *test_dev;
-
-	pr_info(MODULE_NAME ": %s - STARTED\n", __func__);
-
-	if (!test_ch) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
-		return;
-	}
-
-	test_dev = test_ch->test_device;
-
-	if (!test_dev) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL Test Device\n", __func__);
-		return;
-	}
-
-	ret = lpm_test_create_read_thread(test_ch);
-	if (ret != 0) {
-		pr_err(TEST_MODULE_NAME ": %s - failed to create lpm reading "
-		       "thread", __func__);
-	}
-
-	while (1) {
-
-		struct lpm_msg msg;
-		u32 ret = 0;
-
-		/* sleeping period is dependent on number of open channels */
-		test_ch->config_msg.test_param =
-				test_ctx->lpm_pseudo_random_seed;
-
-		local_ms = test_dev->open_channels_counter_to_send *
-			test_ctx->lpm_pseudo_random_seed;
-		TEST_DBG(TEST_MODULE_NAME ":%s: SLEEPING for %d ms",
-		       __func__, local_ms);
-		msleep(local_ms);
-
-		msg.counter = test_ch->next_index_in_sent_msg_per_chan;
-		msg.signature = LPM_TEST_CONFIG_SIGNATURE;
-		msg.reserve1 = 0;
-		msg.reserve2 = 0;
-
-		/* wait for data ready event */
-		write_avail = sdio_write_avail(test_ch->ch);
-		pr_debug(TEST_MODULE_NAME ": %s: write_avail=%d\n",
-		       __func__, write_avail);
-		if (write_avail < sizeof(msg)) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->tx_notify_count));
-			atomic_dec(&test_ch->tx_notify_count);
-		}
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		if (write_avail < sizeof(msg)) {
-			pr_info(TEST_MODULE_NAME ": %s: not enough write "
-				"avail.\n", __func__);
-			break;
-		}
-
-		ret = sdio_write(test_ch->ch, (u32 *)&msg, sizeof(msg));
-		if (ret)
-			pr_err(TEST_MODULE_NAME ":%s: sdio_write err=%d.\n",
-				__func__, -ret);
-
-		TEST_DBG(TEST_MODULE_NAME ": %s: for chan %s, write, "
-			 "msg # %d\n",
-			 __func__,
-			 test_ch->name,
-			 test_ch->next_index_in_sent_msg_per_chan);
-
-		if (test_ch->test_type == SDIO_TEST_LPM_RANDOM) {
-			spin_lock_irqsave(&test_dev->lpm_array_lock,
-					  test_dev->lpm_array_lock_flags);
-			lpm_test_update_entry(test_ch, LPM_MSG_SEND,
-					      "SEND  ",
-					      test_ch->
-					      next_index_in_sent_msg_per_chan);
-
-			test_ch->next_index_in_sent_msg_per_chan++;
-
-			if (test_ch->next_index_in_sent_msg_per_chan ==
-			    test_ch->config_msg.num_packets) {
-				spin_unlock_irqrestore(
-				    &test_dev->lpm_array_lock,
-				    test_dev->lpm_array_lock_flags);
-				break;
-			}
-
-			spin_unlock_irqrestore(&test_dev->lpm_array_lock,
-					       test_dev->lpm_array_lock_flags);
-		}
-	}
-
-	spin_lock_irqsave(&test_dev->lpm_array_lock,
-				  test_dev->lpm_array_lock_flags);
-	test_dev->open_channels_counter_to_send--;
-	spin_unlock_irqrestore(&test_dev->lpm_array_lock,
-				       test_dev->lpm_array_lock_flags);
-
-	pr_info(TEST_MODULE_NAME ": %s: - Finished to send all (%d) "
-		"packets to the modem on channel %s",
-		__func__, test_ch->config_msg.num_packets, test_ch->name);
-
-	return;
-}
-
-static void lpm_test(struct test_channel *test_ch)
-{
-	pr_info(TEST_MODULE_NAME ": %s - START channel %s\n", __func__,
-		test_ch->name);
-
-	if (!test_ch) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL test channel\n", __func__);
-		return;
-	}
-
-	test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
-	pr_debug(TEST_MODULE_NAME ": %s - delete the timeout timer\n",
-	       __func__);
-	del_timer_sync(&test_ch->timeout_timer);
-
-	if (test_ch->modem_result_per_chan == 0) {
-		pr_err(TEST_MODULE_NAME ": LPM TEST - Client didn't sleep. "
-		       "Result Msg - is_successful=%d\n", test_ch->buf[1]);
-		goto exit_err;
-	} else {
-		pr_info(TEST_MODULE_NAME ": %s -"
-			"LPM 9K WAS SLEEPING - PASS\n", __func__);
-		if (test_ch->test_result == TEST_PASSED) {
-			pr_info(TEST_MODULE_NAME ": LPM TEST_PASSED\n");
-			test_ch->test_completed = 1;
-			check_test_completion();
-		} else {
-			pr_err(TEST_MODULE_NAME ": LPM TEST - Host didn't "
-			       "sleep. Client slept\n");
-			goto exit_err;
-		}
-	}
-
-	return;
-
-exit_err:
-	pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
-		test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-
-/**
- * LPM Test while the host wakes up the modem
- */
-static void lpm_test_host_waker(struct test_channel *test_ch)
-{
-	pr_info(TEST_MODULE_NAME ": %s - START\n", __func__);
-	wait_event(test_ch->wait_q, atomic_read(&test_ch->wakeup_client));
-	atomic_set(&test_ch->wakeup_client, 0);
-
-	pr_info(TEST_MODULE_NAME ": %s - Sending the config_msg to wakeup "
-		" the client\n", __func__);
-	send_config_msg(test_ch);
-
-	lpm_test(test_ch);
-}
-
-/**
-  * Writes number of packets into test channel
-  * @test_ch: test channel control struct
-  * @burst_size: number of packets to send
-  */
-static int write_packet_burst(struct test_channel *test_ch,
-		int burst_size)
-{
-	int ret = 0;
-	int packet_count = 0;
-	unsigned int random_num = 0;
-	int size = test_ch->packet_length; /* first packet size */
-	u32 write_avail = 0;
-
-	while (packet_count < burst_size) {
-		/* wait for data ready event */
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":%s write_avail=%d,size=%d on chan"
-				" %s\n", __func__,
-				write_avail, size, test_ch->name);
-		if (write_avail < size) {
-			TEST_DBG(TEST_MODULE_NAME ":%s wait for event on"
-					" chan %s\n", __func__, test_ch->name);
-			wait_event(test_ch->wait_q,
-					atomic_read(&test_ch->tx_notify_count));
-			atomic_dec(&test_ch->tx_notify_count);
-		}
-		write_avail = sdio_write_avail(test_ch->ch);
-		if (write_avail < size) {
-			pr_info(TEST_MODULE_NAME ":%s not enough write"
-					" avail %d, need %d on chan %s\n",
-					__func__, write_avail, size,
-					test_ch->name);
-			continue;
-		}
-		ret = sdio_write(test_ch->ch, test_ch->buf, size);
-		if (ret) {
-			pr_err(TEST_MODULE_NAME ":%s sdio_write "
-					"failed (%d) on chan %s\n", __func__,
-					ret, test_ch->name);
-			break;
-		}
-		udelay(1000); /*low bus usage while running number of channels*/
-		TEST_DBG(TEST_MODULE_NAME ":%s() successfully write %d bytes"
-				", packet_count=%d on chan %s\n", __func__,
-				size, packet_count, test_ch->name);
-		test_ch->tx_bytes += size;
-		packet_count++;
-		/* get next packet size */
-		random_num = get_random_int();
-		size = (random_num % test_ch->packet_length) + 1;
-	}
-	return ret;
-}
-
-/**
-  * Reads packet from test channel and checks that packet number
-  * encoded into the packet is equal to packet_counter
-  * This function is applicable for packet mode channels only
-  *
-  * @test_ch: test channel
-  * @size: expected packet size
-  * @packet_counter: number to validate readed packet
-  */
-static int read_data_from_packet_ch(struct test_channel *test_ch,
-				unsigned int size,
-				int packet_counter)
-{
-	u32 read_avail = 0;
-	int ret = 0;
-
-	if (!test_ch || !test_ch->ch) {
-		pr_err(TEST_MODULE_NAME
-				":%s: NULL channel\n", __func__);
-		return -EINVAL;
-	}
-
-	if (!test_ch->ch->is_packet_mode) {
-		pr_err(TEST_MODULE_NAME
-				":%s:not packet mode ch %s\n",
-				__func__, test_ch->name);
-		return -EINVAL;
-	}
-	read_avail = sdio_read_avail(test_ch->ch);
-	/* wait for read data ready event */
-	if (read_avail < size) {
-		TEST_DBG(TEST_MODULE_NAME ":%s() wait for rx data on "
-				"chan %s\n", __func__, test_ch->name);
-		wait_event(test_ch->wait_q,
-				atomic_read(&test_ch->rx_notify_count));
-		atomic_dec(&test_ch->rx_notify_count);
-	}
-	read_avail = sdio_read_avail(test_ch->ch);
-	TEST_DBG(TEST_MODULE_NAME ":%s read_avail=%d bytes on chan %s\n",
-			__func__, read_avail, test_ch->name);
-
-	if (read_avail != size) {
-		pr_err(TEST_MODULE_NAME
-				":read_avail size %d for chan %s not as "
-				"expected size %d\n",
-				read_avail, test_ch->name, size);
-		return -EINVAL;
-	}
-
-	ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
-	if (ret) {
-		pr_err(TEST_MODULE_NAME ":%s() sdio_read for chan %s (%d)\n",
-				__func__, test_ch->name, -ret);
-		return ret;
-	}
-	if ((test_ch->buf[0] != packet_counter) && (size != 1)) {
-		pr_err(TEST_MODULE_NAME ":Read WRONG DATA"
-				" for chan %s, size=%d\n",
-				test_ch->name, size);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-
-/**
-  * Reads packet from test channel and checks that packet number
-  * encoded into the packet is equal to packet_counter
-  * This function is applicable for streaming mode channels only
-  *
-  * @test_ch: test channel
-  * @size: expected packet size
-  * @packet_counter: number to validate readed packet
-  */
-static int read_data_from_stream_ch(struct test_channel *test_ch,
-				unsigned int size,
-				int packet_counter)
-{
-	u32 read_avail = 0;
-	int ret = 0;
-
-	if (!test_ch || !test_ch->ch) {
-		pr_err(TEST_MODULE_NAME
-				":%s: NULL channel\n", __func__);
-		return -EINVAL;
-	}
-
-	if (test_ch->ch->is_packet_mode) {
-		pr_err(TEST_MODULE_NAME
-				":%s:not streaming mode ch %s\n",
-				__func__, test_ch->name);
-		return -EINVAL;
-	}
-	read_avail = sdio_read_avail(test_ch->ch);
-	/* wait for read data ready event */
-	if (read_avail < size) {
-		TEST_DBG(TEST_MODULE_NAME ":%s() wait for rx data on "
-				"chan %s\n", __func__, test_ch->name);
-		wait_event(test_ch->wait_q,
-				atomic_read(&test_ch->rx_notify_count));
-		atomic_dec(&test_ch->rx_notify_count);
-	}
-	read_avail = sdio_read_avail(test_ch->ch);
-	TEST_DBG(TEST_MODULE_NAME ":%s read_avail=%d bytes on chan %s\n",
-			__func__, read_avail, test_ch->name);
-
-	if (read_avail < size) {
-		pr_err(TEST_MODULE_NAME
-				":read_avail size %d for chan %s not as "
-				"expected size %d\n",
-				read_avail, test_ch->name, size);
-		return -EINVAL;
-	}
-
-	ret = sdio_read(test_ch->ch, test_ch->buf, size + A2_HEADER_OVERHEAD);
-	if (ret) {
-		pr_err(TEST_MODULE_NAME ":%s() sdio_read for chan %s (%d)\n",
-				__func__, test_ch->name, -ret);
-		return ret;
-	}
-	if ((test_ch->buf[A2_HEADER_OVERHEAD/4] != packet_counter) &&
-	    (size != 1)) {
-		pr_err(TEST_MODULE_NAME ":Read WRONG DATA"
-				" for chan %s, size=%d, packet_counter=%d\n",
-				test_ch->name, size, packet_counter);
-		print_hex_dump(KERN_INFO, TEST_MODULE_NAME ": rmnet:",
-				0, 32, 2,
-				(void *)test_ch->buf,
-				size + A2_HEADER_OVERHEAD, false);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/**
- *   Test close channel feature for SDIO_SMEM channel:
- *   close && re-open the SDIO_SMEM channel.
- */
-#ifdef CONFIG_MSM_SDIO_SMEM
-static void open_close_smem_test(struct test_channel *test_ch)
-{
-	int i = 0;
-	int ret = 0;
-
-	pr_info(TEST_MODULE_NAME ":%s\n", __func__);
-
-	for (i = 0; i < 100 ; ++i) {
-		ret = close_sdio_ch(test_ch);
-		if (ret) {
-			pr_err(TEST_MODULE_NAME ":%s close_sdio_ch for ch %s"
-						" failed\n",
-						__func__, test_ch->name);
-			goto exit_err;
-		}
-		ret = open_sdio_ch(test_ch);
-		if (ret) {
-			pr_err(TEST_MODULE_NAME ":%s open_sdio_ch for ch %s "
-						" failed\n",
-						__func__, test_ch->name);
-			goto exit_err;
-		}
-	}
-
-	pr_info(TEST_MODULE_NAME ":%s TEST PASS for chan %s.\n", __func__,
-			test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-exit_err:
-	pr_info(TEST_MODULE_NAME ":%s TEST FAIL for chan %s.\n", __func__,
-			test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-#endif
-
-/**
- *   Test close channel feature:
- *   1. write random packet number into channel
- *   2. read some data from channel (do this only for second half of
- *   requested packets to send).
- *   3. close && re-open then repeat 1.
- *
- *   Total packets to send: test_ch->config_msg.num_packets.
- *   Burst size is random in [1..test_ch->max_burst_size] range
- *   Packet size is random in [1..test_ch->packet_length]
- */
-static void open_close_test(struct test_channel *test_ch)
-{
-	int ret = 0;
-	u32 read_avail = 0;
-	int total_packet_count = 0;
-	int size = 0;
-	u16 *buf16 = NULL;
-	int i;
-	int max_packet_count = 0;
-	unsigned int random_num = 0;
-	int curr_burst_size = 0;
-
-	if (!test_ch || !test_ch->ch) {
-		pr_err(TEST_MODULE_NAME ":%s NULL channel\n",
-				__func__);
-		return;
-	}
-
-	curr_burst_size = test_ch->max_burst_size;
-	size = test_ch->packet_length;
-	buf16 = (u16 *) test_ch->buf;
-
-	/* the test sends configured number of packets in
-	   2 portions: first without reading between write bursts,
-	   second with it */
-	max_packet_count = test_ch->config_msg.num_packets / 2;
-
-	pr_info(TEST_MODULE_NAME ":%s channel %s, total packets:%d,"
-			" max packet size %d, max burst size:%d\n",
-			__func__, test_ch->name,
-			test_ch->config_msg.num_packets, test_ch->packet_length,
-			test_ch->max_burst_size);
-	for (i = 0 ; i < size / 2 ; i++)
-		buf16[i] = (u16) (i & 0xFFFF);
-
-	for (i = 0; i < 2 ; i++) {
-		total_packet_count = 0;
-		while (total_packet_count < max_packet_count) {
-			if (test_ctx->exit_flag) {
-				pr_info(TEST_MODULE_NAME ":%s exit test\n",
-						__func__);
-				return;
-			}
-			test_ch->buf[0] = total_packet_count;
-			random_num = get_random_int();
-			curr_burst_size = (random_num %
-					test_ch->max_burst_size) + 1;
-
-			/* limit burst size to send
-			 * no more than configured packets */
-			if (curr_burst_size + total_packet_count >
-					max_packet_count) {
-				curr_burst_size = max_packet_count -
-					total_packet_count;
-			}
-			TEST_DBG(TEST_MODULE_NAME ":%s Current burst size:%d"
-					" on chan %s\n", __func__,
-					curr_burst_size, test_ch->name);
-			ret = write_packet_burst(test_ch, curr_burst_size);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME ":%s write burst failed (%d), ch %s\n",
-						__func__, ret, test_ch->name);
-				goto exit_err;
-			}
-			if (i > 0) {
-				/* read from channel */
-				if (test_ch->ch->is_packet_mode)
-					ret = read_data_from_packet_ch(test_ch,
-							size,
-							total_packet_count);
-				else
-					ret = read_data_from_stream_ch(test_ch,
-							size,
-							total_packet_count);
-				if (ret) {
-					pr_err(TEST_MODULE_NAME ":%s read"
-							" failed:%d, chan %s\n",
-							__func__, ret,
-							test_ch->name);
-					goto exit_err;
-				}
-			}
-			TEST_DBG(TEST_MODULE_NAME ":%s before close, ch %s\n",
-					__func__, test_ch->name);
-			ret = close_sdio_ch(test_ch);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME":%s close channel %s"
-						" failed (%d)\n",
-						__func__, test_ch->name, ret);
-				goto exit_err;
-			} else {
-				TEST_DBG(TEST_MODULE_NAME":%s close channel %s"
-						" success\n", __func__,
-						test_ch->name);
-				total_packet_count += curr_burst_size;
-				atomic_set(&test_ch->rx_notify_count, 0);
-				atomic_set(&test_ch->tx_notify_count, 0);
-				atomic_set(&test_ch->any_notify_count, 0);
-			}
-			TEST_DBG(TEST_MODULE_NAME ":%s before open, ch %s\n",
-					__func__, test_ch->name);
-			ret = open_sdio_ch(test_ch);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME":%s open channel %s"
-						" failed (%d)\n",
-						__func__, test_ch->name, ret);
-				goto exit_err;
-			} else {
-				read_avail = sdio_read_avail(test_ch->ch);
-				if (read_avail > 0) {
-					pr_err(TEST_MODULE_NAME": after open"
-						" ch %s read_availis not zero"
-						" (%d bytes)\n",
-						test_ch->name, read_avail);
-					goto exit_err;
-				}
-			}
-			TEST_DBG(TEST_MODULE_NAME ":%s total tx = %d,"
-					" packet# = %d, size = %d for ch %s\n",
-					__func__, test_ch->tx_bytes,
-					total_packet_count, size,
-					test_ch->name);
-		} /* end of while */
-	}
-	pr_info(TEST_MODULE_NAME ":%s Test end: total rx bytes = 0x%x,"
-			" total tx bytes = 0x%x for chan %s\n", __func__,
-			test_ch->rx_bytes, test_ch->tx_bytes, test_ch->name);
-	pr_info(TEST_MODULE_NAME ":%s TEST PASS for chan %s.\n", __func__,
-			test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-exit_err:
-	pr_info(TEST_MODULE_NAME ":%s TEST FAIL for chan %s.\n", __func__,
-			test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-/**
- * sender Test
- */
-static void sender_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 read_avail = 0;
-	u32 write_avail = 0;
-	int packet_count = 0;
-	int size = 512;
-	u16 *buf16 = (u16 *) test_ch->buf;
-	int i;
-	int max_packet_count = 10000;
-	int random_num = 0;
-
-	max_packet_count = test_ch->config_msg.num_packets;
-
-	for (i = 0 ; i < size / 2 ; i++)
-		buf16[i] = (u16) (i & 0xFFFF);
-
-
-	pr_info(TEST_MODULE_NAME
-		 ":SENDER TEST START for chan %s\n", test_ch->name);
-
-	while (packet_count < max_packet_count) {
-
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-
-		random_num = get_random_int();
-		size = (random_num % test_ch->packet_length) + 1;
-
-		TEST_DBG(TEST_MODULE_NAME "SENDER WAIT FOR EVENT for chan %s\n",
-			test_ch->name);
-
-		/* wait for data ready event */
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
-		if (write_avail < size) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->tx_notify_count));
-			atomic_dec(&test_ch->tx_notify_count);
-		}
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
-		if (write_avail < size) {
-			pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
-			continue;
-		}
-
-		test_ch->buf[0] = packet_count;
-
-		ret = sdio_write(test_ch->ch, test_ch->buf, size);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME ":sender sdio_write err=%d.\n",
-				-ret);
-			goto exit_err;
-		}
-
-		/* wait for read data ready event */
-		TEST_DBG(TEST_MODULE_NAME ":sender wait for rx data for "
-					  "chan %s\n",
-			 test_ch->name);
-		read_avail = sdio_read_avail(test_ch->ch);
-		wait_event(test_ch->wait_q,
-			   atomic_read(&test_ch->rx_notify_count));
-		atomic_dec(&test_ch->rx_notify_count);
-
-		read_avail = sdio_read_avail(test_ch->ch);
-
-		if (read_avail != size) {
-			pr_info(TEST_MODULE_NAME
-				":read_avail size %d for chan %s not as "
-				"expected size %d.\n",
-				read_avail, test_ch->name, size);
-			goto exit_err;
-		}
-
-		memset(test_ch->buf, 0x00, size);
-
-		ret = sdio_read(test_ch->ch, test_ch->buf, size);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME ":sender sdio_read for chan %s"
-						 " err=%d.\n",
-				test_ch->name, -ret);
-			goto exit_err;
-		}
-
-
-		if ((test_ch->buf[0] != packet_count) && (size != 1)) {
-			pr_info(TEST_MODULE_NAME ":sender sdio_read WRONG DATA"
-						 " for chan %s, size=%d\n",
-				test_ch->name, size);
-			goto exit_err;
-		}
-
-		test_ch->tx_bytes += size;
-		test_ch->rx_bytes += size;
-		packet_count++;
-
-		TEST_DBG(TEST_MODULE_NAME
-			 ":sender total rx bytes = 0x%x , packet#=%d, size=%d"
-			 " for chan %s\n",
-			 test_ch->rx_bytes, packet_count, size, test_ch->name);
-		TEST_DBG(TEST_MODULE_NAME
-			 ":sender total tx bytes = 0x%x , packet#=%d, size=%d"
-			 " for chan %s\n",
-			 test_ch->tx_bytes, packet_count, size, test_ch->name);
-
-	} /* end of while */
-
-	pr_info(TEST_MODULE_NAME
-		 ":SENDER TEST END: total rx bytes = 0x%x, "
-		 " total tx bytes = 0x%x for chan %s\n",
-		 test_ch->rx_bytes, test_ch->tx_bytes, test_ch->name);
-
-	pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s.\n",
-		test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-
-exit_err:
-	pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
-		test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-/**
- * A2 Perf Test
- */
-static void a2_performance_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 read_avail = 0;
-	u32 write_avail = 0;
-	int tx_packet_count = 0;
-	int rx_packet_count = 0;
-	int size = 0;
-	u16 *buf16 = (u16 *) test_ch->buf;
-	int i;
-	int total_bytes = 0;
-	int max_packets = 10000;
-	u32 packet_size = test_ch->buf_size;
-	int rand_size = 0;
-
-	u64 start_jiffy, end_jiffy, delta_jiffies;
-	unsigned int time_msec = 0;
-	u32 throughput = 0;
-
-	max_packets = test_ch->config_msg.num_packets;
-	packet_size = test_ch->packet_length;
-
-	for (i = 0; i < packet_size / 2; i++)
-		buf16[i] = (u16) (i & 0xFFFF);
-
-	pr_info(TEST_MODULE_NAME ": A2 PERFORMANCE TEST START for chan %s\n",
-		test_ch->name);
-
-	start_jiffy = get_jiffies_64(); /* read the current time */
-
-	while (tx_packet_count < max_packets) {
-
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-
-		if (test_ch->random_packet_size) {
-			rand_size = get_random_int();
-			packet_size = (rand_size % test_ch->packet_length) + 1;
-			if (packet_size < A2_MIN_PACKET_SIZE)
-				packet_size = A2_MIN_PACKET_SIZE;
-		}
-
-		/* wait for data ready event */
-		/* use a func to avoid compiler optimizations */
-		write_avail = sdio_write_avail(test_ch->ch);
-		read_avail = sdio_read_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d, "
-					 "read_avail=%d for chan %s\n",
-			test_ch->name, write_avail, read_avail,
-			test_ch->name);
-		if ((write_avail == 0) && (read_avail == 0)) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->any_notify_count));
-			atomic_set(&test_ch->any_notify_count, 0);
-		}
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d\n",
-			 test_ch->name, write_avail);
-		if (write_avail > 0) {
-			size = min(packet_size, write_avail) ;
-			TEST_DBG(TEST_MODULE_NAME ":tx size = %d for chan %s\n",
-				 size, test_ch->name);
-			test_ch->buf[0] = tx_packet_count;
-			test_ch->buf[(size/4)-1] = tx_packet_count;
-
-			ret = sdio_write(test_ch->ch, test_ch->buf, size);
-			if (ret) {
-				pr_info(TEST_MODULE_NAME ":sdio_write err=%d"
-							 " for chan %s\n",
-					-ret, test_ch->name);
-				goto exit_err;
-			}
-			tx_packet_count++;
-			test_ch->tx_bytes += size;
-		}
-
-		read_avail = sdio_read_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
-			 test_ch->name, read_avail);
-		if (read_avail > 0) {
-			size = min(packet_size, read_avail);
-			pr_debug(TEST_MODULE_NAME ":rx size = %d.\n", size);
-			ret = sdio_read(test_ch->ch, test_ch->buf, size);
-			if (ret) {
-				pr_info(TEST_MODULE_NAME ": sdio_read size %d "
-							 " err=%d"
-							 " for chan %s\n",
-					size, -ret, test_ch->name);
-				goto exit_err;
-			}
-			rx_packet_count++;
-			test_ch->rx_bytes += size;
-		}
-
-		TEST_DBG(TEST_MODULE_NAME
-			 ":total rx bytes = %d , rx_packet#=%d"
-			 " for chan %s\n",
-			 test_ch->rx_bytes, rx_packet_count, test_ch->name);
-		TEST_DBG(TEST_MODULE_NAME
-			 ":total tx bytes = %d , tx_packet#=%d"
-			 " for chan %s\n",
-			 test_ch->tx_bytes, tx_packet_count, test_ch->name);
-
-	} /* while (tx_packet_count < max_packets ) */
-
-	end_jiffy = get_jiffies_64(); /* read the current time */
-
-	delta_jiffies = end_jiffy - start_jiffy;
-	time_msec = jiffies_to_msecs(delta_jiffies);
-
-	pr_info(TEST_MODULE_NAME ":total rx bytes = 0x%x , rx_packet#=%d for"
-				 " chan %s.\n",
-		test_ch->rx_bytes, rx_packet_count, test_ch->name);
-	pr_info(TEST_MODULE_NAME ":total tx bytes = 0x%x , tx_packet#=%d"
-				 " for chan %s.\n",
-		test_ch->tx_bytes, tx_packet_count, test_ch->name);
-
-	total_bytes = (test_ch->tx_bytes + test_ch->rx_bytes);
-	pr_err(TEST_MODULE_NAME ":total bytes = %d, time msec = %d"
-				" for chan %s\n",
-		   total_bytes , (int) time_msec, test_ch->name);
-
-	if (!test_ch->random_packet_size) {
-		if (time_msec) {
-			throughput = (total_bytes / time_msec) * 8 / 1000;
-			pr_err(TEST_MODULE_NAME ": %s - Performance = "
-			       "%d Mbit/sec for chan %s\n",
-			       __func__, throughput, test_ch->name);
-		} else {
-			pr_err(TEST_MODULE_NAME ": %s - time_msec = 0 Couldn't "
-			       "calculate performence for chan %s\n",
-			   __func__, test_ch->name);
-		}
-
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	switch (test_ch->ch_id) {
-	case SDIO_DUN:
-		test_ctx->debug.dun_throughput = throughput;
-		break;
-	case SDIO_RMNT:
-		test_ctx->debug.rmnt_throughput = throughput;
-		break;
-	default:
-		pr_err(TEST_MODULE_NAME "No debugfs for this channel "
-					"throughput");
-	}
-#endif
-
-	pr_err(TEST_MODULE_NAME ": A2 PERFORMANCE TEST END for chan %s.\n",
-	       test_ch->name);
-
-	pr_err(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-
-exit_err:
-	pr_err(TEST_MODULE_NAME ": TEST FAIL for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-/**
- * rx_cleanup
- * This function reads all the messages sent by the modem until
- * the read_avail is 0 after 1 second of sleep.
- * The function returns the number of packets that was received.
- */
-static void rx_cleanup(struct test_channel *test_ch, int *rx_packet_count)
-{
-	int read_avail = 0;
-	int ret = 0;
-	int counter = 0;
-
-	if (!test_ch || !test_ch->ch) {
-		pr_err(TEST_MODULE_NAME ":%s NULL channel\n",
-				__func__);
-		return;
-	}
-
-	read_avail = sdio_read_avail(test_ch->ch);
-	TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
-		 test_ch->name, read_avail);
-
-	/* If no pending messages, wait to see if the modem sends data */
-	if (read_avail == 0) {
-		msleep(1000);
-		read_avail = sdio_read_avail(test_ch->ch);
-	}
-
-	while ((read_avail > 0) && (counter < 10)) {
-		TEST_DBG(TEST_MODULE_NAME ": read_avail=%d for ch %s\n",
-			 read_avail, test_ch->name);
-
-		ret = sdio_read(test_ch->ch, test_ch->buf, read_avail);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME ": sdio_read size %d "
-						 " err=%d for chan %s\n",
-				read_avail, -ret, test_ch->name);
-			break;
-		}
-		(*rx_packet_count)++;
-		test_ch->rx_bytes += read_avail;
-		read_avail = sdio_read_avail(test_ch->ch);
-		if (read_avail == 0) {
-			msleep(1000);
-			counter++;
-			read_avail = sdio_read_avail(test_ch->ch);
-		}
-	}
-	pr_info(TEST_MODULE_NAME ": finished cleanup for ch %s, "
-				 "rx_packet_count=%d, total rx bytes=%d\n",
-			 test_ch->name, *rx_packet_count, test_ch->rx_bytes);
-}
-
-
-/**
- * A2 RTT Test
- * This function sends a packet and calculate the RTT time of
- * this packet.
- * The test also calculte Min, Max and Average RTT
- */
-static void a2_rtt_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 read_avail = 0;
-	u32 write_avail = 0;
-	int tx_packet_count = 0;
-	int rx_packet_count = 0;
-	u16 *buf16 = NULL;
-	int i;
-	int max_packets = 0;
-	u32 packet_size = 0;
-	s64 start_time, end_time;
-	int delta_usec = 0;
-	int time_average = 0;
-	int min_delta_usec = 0xFFFF;
-	int max_delta_usec = 0;
-	int total_time = 0;
-	int expected_read_size = 0;
-	int delay_ms = 0;
-	int slow_rtt_counter = 0;
-	int read_avail_so_far = 0;
-
-	if (test_ch) {
-		/*
-		 * Cleanup the pending RX data (such as loopback of the
-		 * config msg)
-		 */
-		rx_cleanup(test_ch, &rx_packet_count);
-		rx_packet_count = 0;
-	} else {
-		return;
-	}
-
-	max_packets = test_ch->config_msg.num_packets;
-	packet_size = test_ch->packet_length;
-	buf16 = (u16 *) test_ch->buf;
-
-	for (i = 0; i < packet_size / 2; i++)
-		buf16[i] = (u16) (i & 0xFFFF);
-
-	pr_info(TEST_MODULE_NAME ": A2 RTT TEST START for chan %s\n",
-		test_ch->name);
-
-	switch (test_ch->ch_id) {
-	case SDIO_RMNT:
-		delay_ms = 100;
-		break;
-	case SDIO_CSVT:
-		delay_ms = 0;
-		break;
-	default:
-		pr_err(TEST_MODULE_NAME ": %s - ch_id invalid.\n",
-		       __func__);
-		return;
-	}
-
-	while (tx_packet_count < max_packets) {
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-		start_time = 0;
-		end_time = 0;
-		read_avail_so_far = 0;
-
-		if (delay_ms)
-			msleep(delay_ms);
-
-		/* wait for data ready event */
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":ch %s: write_avail=%d\n",
-			test_ch->name, write_avail);
-		if (write_avail == 0) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->tx_notify_count));
-			atomic_dec(&test_ch->tx_notify_count);
-		}
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d\n",
-			 test_ch->name, write_avail);
-		if (write_avail > 0) {
-			TEST_DBG(TEST_MODULE_NAME ":tx size = %d for chan %s\n",
-				 packet_size, test_ch->name);
-			test_ch->buf[0] = tx_packet_count;
-
-			start_time = ktime_to_us(ktime_get());
-			ret = sdio_write(test_ch->ch, test_ch->buf,
-					 packet_size);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME ":sdio_write err=%d"
-							 " for chan %s\n",
-					-ret, test_ch->name);
-				goto exit_err;
-			}
-			tx_packet_count++;
-			test_ch->tx_bytes += packet_size;
-		} else {
-				pr_err(TEST_MODULE_NAME ": Invalid write_avail"
-							 " %d for chan %s\n",
-					write_avail, test_ch->name);
-				goto exit_err;
-		}
-
-		expected_read_size = packet_size + A2_HEADER_OVERHEAD;
-
-		while (read_avail_so_far < expected_read_size) {
-
-			read_avail = sdio_read_avail(test_ch->ch);
-
-			if (!read_avail) {
-				wait_event(test_ch->wait_q,
-					   atomic_read(&test_ch->
-						       rx_notify_count));
-
-				atomic_dec(&test_ch->rx_notify_count);
-				continue;
-			}
-
-			read_avail_so_far += read_avail;
-
-			if (read_avail_so_far > expected_read_size) {
-				pr_err(TEST_MODULE_NAME ": %s - Invalid "
-				       "read_avail(%d)  read_avail_so_far(%d) "
-				       "can't be larger than "
-				       "expected_read_size(%d).",
-				       __func__,
-				       read_avail,
-				       read_avail_so_far,
-				       expected_read_size);
-				goto exit_err;
-			}
-
-			/*
-			 * must read entire pending bytes, so later, we will
-			 * get a notification when more data arrives
-			 */
-			ret = sdio_read(test_ch->ch, test_ch->buf,
-					read_avail);
-
-			if (ret) {
-				pr_info(TEST_MODULE_NAME ": sdio_read size %d "
-					" err=%d for chan %s\n",
-					read_avail, -ret,
-					test_ch->name);
-				goto exit_err;
-			}
-		}
-
-		end_time = ktime_to_us(ktime_get());
-		rx_packet_count++;
-		test_ch->rx_bytes += expected_read_size;
-
-		delta_usec = (int)(end_time - start_time);
-		total_time += delta_usec;
-		if (delta_usec < min_delta_usec)
-				min_delta_usec = delta_usec;
-		if (delta_usec > max_delta_usec)
-				max_delta_usec = delta_usec;
-
-		/* checking the RTT per channel criteria */
-		if (delta_usec > MAX_AVG_RTT_TIME_USEC) {
-			pr_err(TEST_MODULE_NAME ": %s - "
-			       "msg # %d - rtt time (%d usec) is "
-			       "longer than %d usec\n",
-			       __func__,
-			       tx_packet_count,
-			       delta_usec,
-			       MAX_AVG_RTT_TIME_USEC);
-			slow_rtt_counter++;
-		}
-
-		TEST_DBG(TEST_MODULE_NAME
-			 ":RTT time=%d for packet #%d for chan %s\n",
-			 delta_usec, tx_packet_count, test_ch->name);
-	} /* while (tx_packet_count < max_packets ) */
-
-	pr_info(TEST_MODULE_NAME ": %s - tx_packet_count = %d\n",
-		__func__, tx_packet_count);
-
-	pr_info(TEST_MODULE_NAME ": %s - total rx bytes = 0x%x, "
-		"rx_packet# = %d for chan %s.\n",
-		__func__, test_ch->rx_bytes, rx_packet_count, test_ch->name);
-
-	pr_info(TEST_MODULE_NAME ": %s - total tx bytes = 0x%x, "
-		"tx_packet# = %d for chan %s.\n",
-		__func__, test_ch->tx_bytes, tx_packet_count, test_ch->name);
-
-	pr_info(TEST_MODULE_NAME ": %s - slow_rtt_counter = %d for "
-		"chan %s.\n",
-		__func__, slow_rtt_counter, test_ch->name);
-
-	if (tx_packet_count) {
-		time_average = total_time / tx_packet_count;
-		pr_info(TEST_MODULE_NAME ":Average RTT time = %d for chan %s\n",
-		   time_average, test_ch->name);
-	} else {
-		pr_err(TEST_MODULE_NAME ": %s - tx_packet_count=0. couldn't "
-		       "calculate average rtt time", __func__);
-	}
-
-	pr_info(TEST_MODULE_NAME ":MIN RTT time = %d for chan %s\n",
-		   min_delta_usec, test_ch->name);
-	pr_info(TEST_MODULE_NAME ":MAX RTT time = %d for chan %s\n",
-		   max_delta_usec, test_ch->name);
-
-	pr_info(TEST_MODULE_NAME ": A2 RTT TEST END for chan %s.\n",
-	       test_ch->name);
-
-	if (ret)
-		goto exit_err;
-
-	if (time_average == 0 || time_average > MAX_AVG_RTT_TIME_USEC) {
-		pr_err(TEST_MODULE_NAME ": %s - average_time = %d. Invalid "
-		       "value",
-		       __func__, time_average);
-		goto exit_err;
-
-	}
-
-	pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-
-exit_err:
-	pr_err(TEST_MODULE_NAME ": TEST FAIL for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-/**
- * Process Rx Data - Helper for A2 Validation Test
- * @test_ch(in/out) : Test channel that contains Rx data buffer to process.
- *
- * @rx_unprocessed_bytes(in) : Number of bytes to process in the buffer.
- *
- * @rx_process_packet_state(in/out) :
- * Current processing state (used to identify what to process
- * next in a partial packet)
- *
- * @rx_packet_size(in/out) :
- * Number of bytes remaining in the packet to be processed.
- *
- * @rx_packet_count(in/out) :
- * Number of packets processed.
- */
-static int process_rx_data(struct test_channel *test_ch,
-			   u32 rx_unprocessed_bytes,
-			   int *rx_process_packet_state,
-			   u16 *rx_packet_size,
-			   int *rx_packet_count)
-{
-	u8 *buf = (u8 *)test_ch->buf;
-	int eop = 0;
-	int i = 0;
-	int ret = 0;
-	u32 *ptr = 0;
-	u16 size = 0;
-
-	/* process rx data */
-	while (rx_unprocessed_bytes) {
-		TEST_DBG(TEST_MODULE_NAME ": unprocessed bytes : %u\n",
-			rx_unprocessed_bytes);
-
-		switch (*rx_process_packet_state) {
-		case RX_PROCESS_PACKET_INIT:
-			/* process the A2 header */
-			TEST_DBG(TEST_MODULE_NAME ": "
-				"RX_PROCESS_PACKET_INIT\n");
-			*rx_process_packet_state = RX_PROCESS_PACKET_INIT;
-			if (rx_unprocessed_bytes < 4)
-				break;
-
-			i += 4;
-			rx_unprocessed_bytes -= 4;
-
-		case RX_PROCESS_A2_HEADER:
-			/* process the rest of A2 header */
-			TEST_DBG(TEST_MODULE_NAME ": RX_PROCESS_A2_HEADER\n");
-			*rx_process_packet_state = RX_PROCESS_A2_HEADER;
-			if (rx_unprocessed_bytes < 4)
-				break;
-
-			ptr = (u32 *)&buf[i];
-			/*
-			 * upper 2 bytes of the last 4 bytes of A2 header
-			 * contains the size of the packet
-			 */
-			*rx_packet_size = *ptr >> 0x10;
-
-			i += 4;
-			rx_unprocessed_bytes -= 4;
-
-		case RX_PROCESS_PACKET_DATA:
-			/* process the2_2_ packet data */
-			TEST_DBG(TEST_MODULE_NAME ": RX_PROCESS_PACKET_DATA "
-				 "- packet size - %u\n", *rx_packet_size);
-			*rx_process_packet_state = RX_PROCESS_PACKET_DATA;
-
-			size = *rx_packet_size;
-			if (*rx_packet_size <= rx_unprocessed_bytes) {
-				eop = *rx_packet_size;
-				*rx_packet_size = 0;
-			} else {
-				eop = rx_unprocessed_bytes;
-				*rx_packet_size = *rx_packet_size -
-						  rx_unprocessed_bytes;
-			}
-
-			/* no more bytes available to process */
-			if (!eop)
-				break;
-			/*
-			 * end of packet is starting from
-			 * the current position
-			 */
-			eop = eop + i;
-			TEST_DBG(TEST_MODULE_NAME ": size - %u, "
-				 "packet size - %u eop - %d\n",
-				 size, *rx_packet_size, eop);
-
-			/* validate the data */
-			for (; i < eop; i++) {
-				if (buf[i] != (test_ch->rx_bytes % 256)) {
-					pr_err(TEST_MODULE_NAME ": "
-					       "Corrupt data. buf:%u, "
-					       "data:%u\n", buf[i],
-					       test_ch->rx_bytes % 256);
-					ret = -EINVAL;
-					goto err;
-				}
-				rx_unprocessed_bytes--;
-				test_ch->rx_bytes++;
-			}
-
-			/* have more data to be processed */
-			if (*rx_packet_size)
-				break;
-
-			/*
-			 * A2 sends data in 4 byte alignment,
-			 * skip the padding
-			 */
-			if (size % 4) {
-				i += 4 - (size % 4);
-				rx_unprocessed_bytes -= 4 - (size % 4);
-			}
-			*rx_packet_count = *rx_packet_count + 1;
-
-			/* re init the state to process new packet */
-			*rx_process_packet_state = RX_PROCESS_PACKET_INIT;
-			break;
-		default:
-			pr_err(TEST_MODULE_NAME ": Invalid case: %d\n",
-			       *rx_process_packet_state);
-			ret = -EINVAL;
-			goto err;
-		}
-		TEST_DBG(TEST_MODULE_NAME ": Continue processing "
-			"if more data is available\n");
-	}
-
-err:
-	return ret;
-}
-
-/**
- * A2 Validation Test
- * Send packets and validate the returned packets.
- * Transmit one packet at a time, while process multiple rx
- * packets in a single transaction.
- * A transaction is of size min(random number, write_avail).
- * A packet consists of a min of 1 byte to channel supported max.
- */
-static void a2_validation_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 read_avail = 0;
-	u32 write_avail = 0;
-	int tx_packet_count = 0;
-	int rx_packet_count = 0;
-	int initial_rx_packet_count = 0;
-	u32 size = 0;
-	u8 *buf8 = (u8 *)test_ch->buf;
-	int i = 0;
-	int max_packets = test_ch->config_msg.num_packets;
-	u16 tx_packet_size = 0;
-	u16 rx_packet_size = 0;
-	u32 random_num = 0;
-	int rx_process_packet_state = RX_PROCESS_PACKET_INIT;
-
-	pr_info(TEST_MODULE_NAME ": A2 VALIDATION TEST START for chan %s\n",
-		test_ch->name);
-
-	/* Wait for the initial rx messages before starting the test. */
-	rx_cleanup(test_ch, &initial_rx_packet_count);
-
-	test_ch->tx_bytes = 0;
-	test_ch->rx_bytes = 0;
-
-	/* Continue till we have transmitted and received all packets */
-	while ((tx_packet_count < max_packets) ||
-	       (rx_packet_count < max_packets)) {
-
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-
-		random_num = get_random_int();
-		size = (random_num % test_ch->packet_length) + 1;
-		TEST_DBG(TEST_MODULE_NAME ": Random tx packet size =%u", size);
-
-		/*
-		 * wait for data ready event
-		 * use a func to avoid compiler optimizations
-		 */
-		write_avail = sdio_write_avail(test_ch->ch);
-		read_avail = sdio_read_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ": write_avail=%d, "
-			"read_avail=%d for chan %s\n",
-			write_avail, read_avail, test_ch->name);
-
-		if ((write_avail == 0) && (read_avail == 0)) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->any_notify_count));
-			atomic_set(&test_ch->any_notify_count, 0);
-		}
-
-		/* Transmit data */
-		write_avail = sdio_write_avail(test_ch->ch);
-		if ((tx_packet_count < max_packets) && (write_avail > 0)) {
-			tx_packet_size = min(size, write_avail) ;
-			TEST_DBG(TEST_MODULE_NAME ": tx size = %u, "
-				"write_avail = %u tx_packet# = %d\n",
-				tx_packet_size, write_avail,
-				tx_packet_count);
-			memset(test_ch->buf, 0, test_ch->buf_size);
-			/* populate the buffer */
-			for (i = 0; i < tx_packet_size; i++) {
-				buf8[i] = test_ch->tx_bytes % 256;
-				test_ch->tx_bytes++;
-			}
-
-			ret = sdio_write(test_ch->ch, test_ch->buf,
-					  tx_packet_size);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME ":sdio_write err=%d"
-					" for chan %s\n",
-					-ret, test_ch->name);
-				goto exit_err;
-			}
-			tx_packet_count++;
-		}
-
-		/* Receive data */
-		read_avail = sdio_read_avail(test_ch->ch);
-		if (read_avail > 0) {
-			TEST_DBG(TEST_MODULE_NAME ": rx size = %u, "
-				"rx_packet#=%d.\n",
-				read_avail, rx_packet_count);
-			memset(test_ch->buf, 0, test_ch->buf_size);
-
-			ret = sdio_read(test_ch->ch, test_ch->buf,
-					read_avail);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME ": sdio_read "
-					"size %d err=%d for chan %s\n",
-					size, -ret, test_ch->name);
-				goto exit_err;
-			}
-
-			/* Process data */
-			ret = process_rx_data(test_ch, read_avail,
-					      &rx_process_packet_state,
-					      &rx_packet_size,
-					      &rx_packet_count);
-
-			if (ret != 0)
-				goto exit_err;
-		}
-		TEST_DBG(TEST_MODULE_NAME ": Continue loop ...\n");
-	}
-
-	if (test_ch->tx_bytes != test_ch->rx_bytes) {
-		pr_err(TEST_MODULE_NAME ": Total number of bytes "
-			"transmitted (%u) does not match the total "
-			"number of bytes received (%u).", test_ch->tx_bytes,
-			test_ch->rx_bytes);
-		goto exit_err;
-	}
-
-	pr_info(TEST_MODULE_NAME ": A2 VALIDATION TEST END for chan %s.\n",
-		test_ch->name);
-
-	pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-
-exit_err:
-	pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-/**
- * sender No loopback Test
- */
-static void sender_no_loopback_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 write_avail = 0;
-	int packet_count = 0;
-	int size = 512;
-	u16 *buf16 = (u16 *) test_ch->buf;
-	int i;
-	int max_packet_count = 10000;
-	unsigned int random_num = 0;
-
-	max_packet_count = test_ch->config_msg.num_packets;
-
-	for (i = 0 ; i < size / 2 ; i++)
-		buf16[i] = (u16) (i & 0xFFFF);
-
-	pr_info(TEST_MODULE_NAME
-		 ":SENDER NO LP TEST START for chan %s\n", test_ch->name);
-
-	while (packet_count < max_packet_count) {
-
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-
-		random_num = get_random_int();
-		size = (random_num % test_ch->packet_length) + 1;
-
-		TEST_DBG(TEST_MODULE_NAME ":SENDER WAIT FOR EVENT "
-					  "for chan %s\n",
-			test_ch->name);
-
-		/* wait for data ready event */
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
-		if (write_avail < size) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->tx_notify_count));
-			atomic_dec(&test_ch->tx_notify_count);
-		}
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":write_avail=%d\n", write_avail);
-		if (write_avail < size) {
-			pr_info(TEST_MODULE_NAME ":not enough write avail.\n");
-			continue;
-		}
-
-		test_ch->buf[0] = packet_count;
-
-		ret = sdio_write(test_ch->ch, test_ch->buf, size);
-		if (ret) {
-			pr_info(TEST_MODULE_NAME ":sender sdio_write err=%d.\n",
-				-ret);
-			goto exit_err;
-		}
-
-		test_ch->tx_bytes += size;
-		packet_count++;
-
-		TEST_DBG(TEST_MODULE_NAME
-			 ":sender total tx bytes = 0x%x , packet#=%d, size=%d"
-			 " for chan %s\n",
-			 test_ch->tx_bytes, packet_count, size, test_ch->name);
-
-	} /* end of while */
-
-	pr_info(TEST_MODULE_NAME
-		 ":SENDER TEST END: total tx bytes = 0x%x, "
-		 " for chan %s\n",
-		 test_ch->tx_bytes, test_ch->name);
-
-	test_ch->modem_result_per_chan = wait_for_result_msg(test_ch);
-
-	if (test_ch->modem_result_per_chan) {
-		pr_info(TEST_MODULE_NAME ": TEST PASS for chan %s.\n",
-			test_ch->name);
-		test_ch->test_result = TEST_PASSED;
-	} else {
-		pr_info(TEST_MODULE_NAME ": TEST FAILURE for chan %s.\n",
-			test_ch->name);
-		test_ch->test_result = TEST_FAILED;
-	}
-	test_ch->test_completed = 1;
-	check_test_completion();
-	return;
-
-exit_err:
-	pr_info(TEST_MODULE_NAME ": TEST FAIL for chan %s.\n",
-		test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-
-/**
- * Modem reset Test
- * The test verifies that it finished sending all the packets
- * while there might be modem reset in the middle
- */
-static void modem_reset_test(struct test_channel *test_ch)
-{
-	int ret = 0 ;
-	u32 read_avail = 0;
-	u32 write_avail = 0;
-	int tx_packet_count = 0;
-	int rx_packet_count = 0;
-	int size = 0;
-	u16 *buf16 = (u16 *) test_ch->buf;
-	int i;
-	int max_packets = 10000;
-	u32 packet_size = test_ch->buf_size;
-	int is_err = 0;
-
-	max_packets = test_ch->config_msg.num_packets;
-	packet_size = test_ch->packet_length;
-
-	for (i = 0; i < packet_size / 2; i++)
-		buf16[i] = (u16) (i & 0xFFFF);
-
-	pr_info(TEST_MODULE_NAME ": Modem Reset TEST START for chan %s\n",
-		test_ch->name);
-
-	while (tx_packet_count < max_packets) {
-
-		if (test_ctx->exit_flag) {
-			pr_info(TEST_MODULE_NAME ":Exit Test.\n");
-			return;
-		}
-
-		if (test_ch->card_removed) {
-			pr_info(TEST_MODULE_NAME ": card removal was detected "
-				"for chan %s, tx_total=0x%x\n",
-				test_ch->name, test_ch->tx_bytes);
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->card_detected_event));
-			atomic_set(&test_ch->card_detected_event, 0);
-			pr_info(TEST_MODULE_NAME ": card_detected_event "
-					"for chan %s\n", test_ch->name);
-			if (test_ch->card_removed)
-				continue;
-			is_err = 0;
-			/* Need to wait for the modem to be ready */
-			msleep(5000);
-			pr_info(TEST_MODULE_NAME ": sending the config message "
-					"for chan %s\n", test_ch->name);
-			send_config_msg(test_ch);
-		}
-
-		/* wait for data ready event */
-		/* use a func to avoid compiler optimizations */
-		write_avail = sdio_write_avail(test_ch->ch);
-		read_avail = sdio_read_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d, "
-					 "read_avail=%d for chan %s\n",
-			test_ch->name, write_avail, read_avail,
-			test_ch->name);
-		if ((write_avail == 0) && (read_avail == 0)) {
-			wait_event(test_ch->wait_q,
-				   atomic_read(&test_ch->any_notify_count));
-			atomic_set(&test_ch->any_notify_count, 0);
-		}
-		if (atomic_read(&test_ch->card_detected_event)) {
-			atomic_set(&test_ch->card_detected_event, 0);
-			pr_info(TEST_MODULE_NAME ": card_detected_event "
-				"for chan %s, tx_total=0x%x\n",
-				test_ch->name,  test_ch->tx_bytes);
-			if (test_ch->card_removed)
-				continue;
-			/* Need to wait for the modem to be ready */
-			msleep(5000);
-			is_err = 0;
-			pr_info(TEST_MODULE_NAME ": sending the config message "
-					"for chan %s\n", test_ch->name);
-			send_config_msg(test_ch);
-		}
-
-		write_avail = sdio_write_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, write_avail=%d\n",
-			 test_ch->name, write_avail);
-		if (write_avail > 0) {
-			size = min(packet_size, write_avail) ;
-			pr_debug(TEST_MODULE_NAME ":tx size = %d for chan %s\n",
-				 size, test_ch->name);
-			test_ch->buf[0] = tx_packet_count;
-			test_ch->buf[(size/4)-1] = tx_packet_count;
-
-			TEST_DBG(TEST_MODULE_NAME ":channel %s, sdio_write, "
-				"size=%d\n", test_ch->name, size);
-			if (is_err) {
-				msleep(100);
-				continue;
-			}
-			ret = sdio_write(test_ch->ch, test_ch->buf, size);
-			if (ret) {
-				pr_info(TEST_MODULE_NAME ":sdio_write err=%d"
-							 " for chan %s\n",
-					-ret, test_ch->name);
-				is_err = 1;
-				msleep(20);
-				continue;
-			}
-			tx_packet_count++;
-			test_ch->tx_bytes += size;
-			test_ch->config_msg.num_packets--;
-		}
-
-		read_avail = sdio_read_avail(test_ch->ch);
-		TEST_DBG(TEST_MODULE_NAME ":channel %s, read_avail=%d\n",
-			 test_ch->name, read_avail);
-		if (read_avail > 0) {
-			size = min(packet_size, read_avail);
-			pr_debug(TEST_MODULE_NAME ":rx size = %d.\n", size);
-			TEST_DBG(TEST_MODULE_NAME ":channel %s, sdio_read, "
-				"size=%d\n", test_ch->name, size);
-			if (is_err) {
-				msleep(100);
-				continue;
-			}
-			ret = sdio_read(test_ch->ch, test_ch->buf, size);
-			if (ret) {
-				pr_info(TEST_MODULE_NAME ": sdio_read size %d "
-							 " err=%d"
-							 " for chan %s\n",
-					size, -ret, test_ch->name);
-				is_err = 1;
-				msleep(20);
-				continue;
-			}
-			rx_packet_count++;
-			test_ch->rx_bytes += size;
-		}
-
-		TEST_DBG(TEST_MODULE_NAME
-			 ":total rx bytes = %d , rx_packet#=%d"
-			 " for chan %s\n",
-			 test_ch->rx_bytes, rx_packet_count, test_ch->name);
-		TEST_DBG(TEST_MODULE_NAME
-			 ":total tx bytes = %d , tx_packet#=%d"
-			 " for chan %s\n",
-			 test_ch->tx_bytes, tx_packet_count, test_ch->name);
-
-		udelay(500);
-
-	} /* while (tx_packet_count < max_packets ) */
-
-	pr_info(TEST_MODULE_NAME ":total rx bytes = 0x%x , rx_packet#=%d for"
-				 " chan %s.\n",
-		test_ch->rx_bytes, rx_packet_count, test_ch->name);
-	pr_info(TEST_MODULE_NAME ":total tx bytes = 0x%x , tx_packet#=%d"
-				 " for chan %s.\n",
-		test_ch->tx_bytes, tx_packet_count, test_ch->name);
-
-	pr_err(TEST_MODULE_NAME ": Modem Reset TEST END for chan %s.\n",
-	       test_ch->name);
-
-	pr_err(TEST_MODULE_NAME ": TEST PASS for chan %s\n", test_ch->name);
-	test_ch->test_completed = 1;
-	test_ch->test_result = TEST_PASSED;
-	check_test_completion();
-	return;
-}
-
-/**
- * Worker thread to handle the tests types
- */
-static void worker(struct work_struct *work)
-{
-	struct test_channel *test_ch = NULL;
-	struct test_work *test_work = container_of(work,
-						 struct	test_work,
-						 work);
-	int test_type = 0;
-
-	test_ch = test_work->test_ch;
-
-	if (test_ch == NULL) {
-		pr_err(TEST_MODULE_NAME ":NULL test_ch\n");
-		return;
-	}
-
-	test_type = test_ch->test_type;
-
-	switch (test_type) {
-	case SDIO_TEST_LOOPBACK_HOST:
-		loopback_test(test_ch);
-		break;
-	case SDIO_TEST_LOOPBACK_CLIENT:
-		sender_test(test_ch);
-		break;
-	case SDIO_TEST_PERF:
-		a2_performance_test(test_ch);
-		break;
-	case SDIO_TEST_LPM_CLIENT_WAKER:
-		lpm_test(test_ch);
-		break;
-	case SDIO_TEST_LPM_HOST_WAKER:
-		lpm_test_host_waker(test_ch);
-		break;
-	case SDIO_TEST_HOST_SENDER_NO_LP:
-		sender_no_loopback_test(test_ch);
-		break;
-	case SDIO_TEST_LPM_RANDOM:
-		lpm_continuous_rand_test(test_ch);
-		break;
-	case SDIO_TEST_RTT:
-		a2_rtt_test(test_ch);
-		break;
-	case SDIO_TEST_CLOSE_CHANNEL:
-		if (test_ch->ch_id != SDIO_SMEM)
-			open_close_test(test_ch);
-		break;
-	case SDIO_TEST_MODEM_RESET:
-		modem_reset_test(test_ch);
-		break;
-	case SDIO_TEST_A2_VALIDATION:
-		a2_validation_test(test_ch);
-		break;
-	default:
-		pr_err(TEST_MODULE_NAME ":Bad Test type = %d.\n",
-			(int) test_type);
-	}
-}
-
-
-/**
- * Notification Callback
- *
- * Notify the worker
- *
- */
-static void notify(void *priv, unsigned channel_event)
-{
-	struct test_channel *test_ch = (struct test_channel *) priv;
-
-	pr_debug(TEST_MODULE_NAME ": %s - notify event=%d.\n",
-		 __func__, channel_event);
-
-	if (test_ch->ch == NULL) {
-		pr_info(TEST_MODULE_NAME ": %s - notify before ch ready.\n",
-			__func__);
-		return;
-	}
-
-	switch (channel_event) {
-	case SDIO_EVENT_DATA_READ_AVAIL:
-		atomic_inc(&test_ch->rx_notify_count);
-		atomic_set(&test_ch->any_notify_count, 1);
-		TEST_DBG(TEST_MODULE_NAME ": %s - SDIO_EVENT_DATA_READ_AVAIL, "
-			 "any_notify_count=%d, rx_notify_count=%d\n",
-			 __func__,
-			 atomic_read(&test_ch->any_notify_count),
-			 atomic_read(&test_ch->rx_notify_count));
-		/*
-		 * when there is pending data on a channel we would like to
-		 * turn on the bit mask that implies that there is pending
-		 * data for that channel on that deivce
-		 */
-		if (test_ch->test_device != NULL &&
-		    test_ch->test_type == SDIO_TEST_LPM_RANDOM) {
-			spin_lock_irqsave(&test_ch->test_device->lpm_array_lock,
-					  test_ch->test_device->
-						  lpm_array_lock_flags);
-			test_ch->test_device->read_avail_mask |=
-				test_ch->channel_mask_id;
-			test_ch->notify_counter_per_chan++;
-
-			lpm_test_update_entry(test_ch, LPM_NOTIFY, "NOTIFY", 0);
-			spin_unlock_irqrestore(&test_ch->test_device->
-					       lpm_array_lock,
-					       test_ch->test_device->
-						  lpm_array_lock_flags);
-		}
-		break;
-
-	case SDIO_EVENT_DATA_WRITE_AVAIL:
-		atomic_inc(&test_ch->tx_notify_count);
-		atomic_set(&test_ch->any_notify_count, 1);
-		TEST_DBG(TEST_MODULE_NAME ": %s - SDIO_EVENT_DATA_WRITE_AVAIL, "
-			 "any_notify_count=%d, tx_notify_count=%d\n",
-			 __func__,
-			 atomic_read(&test_ch->any_notify_count),
-			 atomic_read(&test_ch->tx_notify_count));
-		break;
-
-	default:
-		BUG();
-	}
-	wake_up(&test_ch->wait_q);
-
-}
-
-#ifdef CONFIG_MSM_SDIO_SMEM
-static int sdio_smem_test_cb(int event)
-{
-	struct test_channel *tch = test_ctx->test_ch_arr[SDIO_SMEM];
-	int i;
-	int *smem_buf = (int *)test_ctx->smem_buf;
-	uint32_t val = 0;
-	int ret = 0;
-
-	pr_debug(TEST_MODULE_NAME ":%s: Received event %d\n", __func__, event);
-
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ": %s NULL tch\n", __func__);
-		return -EINVAL;
-	}
-
-	switch (event) {
-	case SDIO_SMEM_EVENT_READ_DONE:
-		tch->rx_bytes += SMEM_MAX_XFER_SIZE;
-		for (i = 0; i < SMEM_MAX_XFER_SIZE;) {
-			val = (int)*smem_buf;
-			if ((val != test_ctx->smem_counter) && tch->is_used) {
-				pr_err(TEST_MODULE_NAME ":%s: Invalid value %d "
-				"expected %d in smem arr",
-				__func__, val, test_ctx->smem_counter);
-				pr_err(TEST_MODULE_NAME ":SMEM test FAILED\n");
-				tch->test_completed = 1;
-				tch->test_result = TEST_FAILED;
-				check_test_completion();
-				ret = -EINVAL;
-				goto exit;
-			}
-			i += 4;
-			smem_buf++;
-			test_ctx->smem_counter++;
-		}
-		if (tch->rx_bytes >= 40000000) {
-			if ((!tch->test_completed) && tch->is_used) {
-				pr_info(TEST_MODULE_NAME ":SMEM test PASSED\n");
-				tch->test_completed = 1;
-				tch->test_result = TEST_PASSED;
-				check_test_completion();
-			}
-		}
-		break;
-	case SDIO_SMEM_EVENT_READ_ERR:
-		if (tch->is_used) {
-			pr_err(TEST_MODULE_NAME ":Read overflow, "
-						"SMEM test FAILED\n");
-			tch->test_completed = 1;
-			tch->test_result = TEST_FAILED;
-			ret = -EIO;
-		}
-		break;
-	default:
-		if (tch->is_used) {
-			pr_err(TEST_MODULE_NAME ":Unhandled event %d\n", event);
-			ret = -EINVAL;
-		}
-		break;
-	}
-exit:
-	return ret;
-}
-
-static int sdio_smem_open(struct sdio_smem_client *sdio_smem)
-{
-	int ret = 0;
-
-	if (!sdio_smem) {
-		pr_info(TEST_MODULE_NAME "%s: NULL sdio_smem_client\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	if (test_ctx->test_ch_arr[SDIO_SMEM]->ch_ready) {
-		pr_info(TEST_MODULE_NAME "%s: SDIO_SMEM channel is already opened\n",
-			__func__);
-		return 0;
-	}
-
-	test_ctx->test_ch_arr[SDIO_SMEM]->ch_ready = 1;
-	sdio_smem->buf = test_ctx->smem_buf;
-	sdio_smem->size = SMEM_MAX_XFER_SIZE;
-	sdio_smem->cb_func = sdio_smem_test_cb;
-	ret = sdio_smem_register_client();
-	if (ret)
-		pr_info(TEST_MODULE_NAME "%s: Error (%d) registering sdio_smem "
-					 "test client\n",
-			__func__, ret);
-
-	return ret;
-}
-
-static int sdio_smem_test_probe(struct platform_device *pdev)
-{
-	test_ctx->sdio_smem = container_of(pdev, struct sdio_smem_client,
-					   plat_dev);
-
-	return sdio_smem_open(test_ctx->sdio_smem);
-}
-
-static struct platform_driver sdio_smem_client_drv = {
-	.probe		= sdio_smem_test_probe,
-	.driver		= {
-		.name	= "SDIO_SMEM_CLIENT",
-		.owner	= THIS_MODULE,
-	},
-};
-#endif
-
-static void sdio_test_lpm_timeout_handler(unsigned long data)
-{
-	struct test_channel *tch = (struct test_channel *)data;
-
-	pr_info(TEST_MODULE_NAME ": %s - LPM TEST TIMEOUT Expired after "
-			    "%d ms\n", __func__, tch->timeout_ms);
-	tch->test_completed = 1;
-	pr_info(TEST_MODULE_NAME ": %s - tch->test_result = TEST_FAILED\n",
-		__func__);
-	tch->test_completed = 1;
-	tch->test_result = TEST_FAILED;
-	check_test_completion();
-	return;
-}
-
-static void sdio_test_lpm_timer_handler(unsigned long data)
-{
-	struct test_channel *tch = (struct test_channel *)data;
-
-	pr_info(TEST_MODULE_NAME ": %s - LPM TEST Timer Expired after "
-			    "%d ms\n", __func__, tch->timer_interval_ms);
-
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ": %s - LPM TEST FAILED. "
-		       "tch is NULL\n", __func__);
-		return;
-	}
-
-	if (!tch->ch) {
-		pr_err(TEST_MODULE_NAME ": %s - LPM TEST FAILED. tch->ch "
-		       "is NULL\n", __func__);
-		tch->test_result = TEST_FAILED;
-		return;
-	}
-
-	/* Verfiy that we voted for sleep */
-	if (tch->is_ok_to_sleep) {
-		tch->test_result = TEST_PASSED;
-		pr_info(TEST_MODULE_NAME ": %s - 8K voted for sleep\n",
-			__func__);
-	} else {
-		tch->test_result = TEST_FAILED;
-		pr_info(TEST_MODULE_NAME ": %s - 8K voted against sleep\n",
-			__func__);
-
-	}
-
-	sdio_al_unregister_lpm_cb(tch->sdio_al_device);
-
-	if (tch->test_type == SDIO_TEST_LPM_HOST_WAKER) {
-		atomic_set(&tch->wakeup_client, 1);
-		wake_up(&tch->wait_q);
-	}
-}
-
-int sdio_test_wakeup_callback(void *device_handle, int is_vote_for_sleep)
-{
-	int i = 0;
-
-	TEST_DBG(TEST_MODULE_NAME ": %s is_vote_for_sleep=%d!!!",
-		__func__, is_vote_for_sleep);
-
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
-			continue;
-		if (tch->sdio_al_device == device_handle) {
-			tch->is_ok_to_sleep = is_vote_for_sleep;
-
-			if (tch->test_type == SDIO_TEST_LPM_RANDOM) {
-				spin_lock_irqsave(&tch->test_device->
-						  lpm_array_lock,
-						  tch->test_device->
-						  lpm_array_lock_flags);
-				if (is_vote_for_sleep == 1)
-					lpm_test_update_entry(tch,
-							      LPM_SLEEP,
-							      "SLEEP ", 0);
-				else
-					lpm_test_update_entry(tch,
-							      LPM_WAKEUP,
-							      "WAKEUP", 0);
-
-				spin_unlock_irqrestore(&tch->test_device->
-						       lpm_array_lock,
-						       tch->test_device->
-						       lpm_array_lock_flags);
-				break;
-			}
-		}
-	}
-
-	return 0;
-}
-
-static int sdio_test_find_dev(struct test_channel *tch)
-{
-	int j;
-	int null_index = -1;
-
-	for (j = 0 ; j < MAX_NUM_OF_SDIO_DEVICES; ++j) {
-
-		struct sdio_test_device *test_dev =
-		&test_ctx->test_dev_arr[j];
-
-		if (test_dev->sdio_al_device == NULL) {
-			if (null_index == -1)
-				null_index = j;
-			continue;
-		}
-
-		if (test_dev->sdio_al_device ==
-		    tch->ch->sdio_al_dev) {
-			test_dev->open_channels_counter_to_recv++;
-			test_dev->open_channels_counter_to_send++;
-			tch->test_device = test_dev;
-			/* setting mask id for pending data for
-			   this channel */
-			tch->channel_mask_id = test_dev->next_mask_id;
-			test_dev->next_mask_id *= 2;
-			pr_info(TEST_MODULE_NAME ": %s - channel %s "
-				"got read_mask_id = 0x%x. device "
-				"next_mask_id=0x%x",
-				__func__, tch->name, tch->channel_mask_id,
-				test_dev->next_mask_id);
-			break;
-		}
-	}
-
-	/*
-	 * happens ones a new device is "discovered" while testing. i.e
-	 * if testing a few channels, a new deivce will be "discovered" once
-	 * the first channel of a device is being tested
-	 */
-	if (j == MAX_NUM_OF_SDIO_DEVICES) {
-
-		struct sdio_test_device *test_dev =
-			&test_ctx->
-			test_dev_arr[null_index];
-		test_dev->sdio_al_device =
-			tch->ch->sdio_al_dev;
-
-		test_ctx->number_of_active_devices++;
-		test_ctx->max_number_of_devices++;
-		test_dev->open_channels_counter_to_recv++;
-		test_dev->open_channels_counter_to_send++;
-		test_dev->next_avail_entry_in_array = 0;
-		tch->test_device = test_dev;
-		tch->test_device->array_size =
-			LPM_ARRAY_SIZE;
-		test_dev->modem_result_per_dev = 1;
-		tch->modem_result_per_chan = 0;
-		test_dev->next_avail_entry_in_array = 0;
-
-		spin_lock_init(&test_dev->
-			       lpm_array_lock);
-
-		if (tch->test_type == SDIO_TEST_LPM_RANDOM) {
-			pr_err(MODULE_NAME ": %s - "
-			       "Allocating Msg Array for "
-			       "Maximum open channels for device (%d) "
-			       "Channels. Array has %d entries",
-			       __func__,
-			       LPM_MAX_OPEN_CHAN_PER_DEV,
-			       test_dev->array_size);
-
-			test_dev->lpm_arr =
-				kzalloc(sizeof(
-				struct lpm_entry_type) *
-					tch->
-					test_device->array_size,
-				GFP_KERNEL);
-
-			if (!test_dev->lpm_arr) {
-				pr_err(MODULE_NAME ": %s - "
-					"lpm_arr is NULL",
-					__func__);
-				return -ENOMEM;
-			}
-		}
-
-		/*
-		 * in new device, initialize next_mask_id, and setting
-		 * mask_id to the channel
-		 */
-		test_dev->next_mask_id = 0x1;
-		tch->channel_mask_id = test_dev->next_mask_id;
-		test_dev->next_mask_id *= 2;
-		pr_info(TEST_MODULE_NAME ": %s - channel %s got "
-			"read_mask_id = 0x%x. device next_mask_id=0x%x",
-			__func__,
-			tch->name,
-			tch->channel_mask_id,
-			test_dev->next_mask_id);
-	}
-
-	return 0;
-}
-
-static void check_test_result(void)
-{
-	int result = 1;
-	int i = 0;
-
-	test_ctx->max_number_of_devices = 0;
-
-	pr_info(TEST_MODULE_NAME ": %s - Woke Up\n", __func__);
-
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
-			continue;
-
-		if (tch->test_type == SDIO_TEST_LPM_RANDOM)
-			result &= tch->test_device->final_result_per_dev;
-		else
-			if (tch->test_result == TEST_FAILED) {
-				pr_info(TEST_MODULE_NAME ": %s - "
-					"Test FAILED\n", __func__);
-				test_ctx->test_result = TEST_FAILED;
-				pr_err(TEST_MODULE_NAME ": %s - "
-				       "test_result %d",
-				       __func__, test_ctx->test_result);
-				return;
-			}
-	}
-
-	if (result == 0) {
-		pr_info(TEST_MODULE_NAME ": %s - Test FAILED\n", __func__);
-		test_ctx->test_result = TEST_FAILED;
-		pr_err(TEST_MODULE_NAME ": %s - "
-		       "test_result %d",
-		       __func__, test_ctx->test_result);
-		return;
-	}
-
-	pr_info(TEST_MODULE_NAME ": %s - Test PASSED", __func__);
-	test_ctx->test_result = TEST_PASSED;
-	pr_err(TEST_MODULE_NAME ": %s - "
-	       "test_result %d",
-	       __func__, test_ctx->test_result);
-	return;
-}
-
-/**
- * Test Main
- */
-static int test_start(void)
-{
-	int ret = -ENOMEM;
-	int i;
-
-	pr_debug(TEST_MODULE_NAME ":Starting Test ....\n");
-
-	test_ctx->test_completed = 0;
-	test_ctx->test_result = TEST_NO_RESULT;
-	test_ctx->debug.dun_throughput = 0;
-	test_ctx->debug.rmnt_throughput = 0;
-	test_ctx->number_of_active_devices = 0;
-
-	pr_err(TEST_MODULE_NAME ": %s - test_result %d",
-	       __func__, test_ctx->test_result);
-
-	memset(test_ctx->test_dev_arr, 0,
-		sizeof(struct sdio_test_device)*MAX_NUM_OF_SDIO_DEVICES);
-
-	/* Open The Channels */
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used))
-			continue;
-
-		tch->rx_bytes = 0;
-		tch->tx_bytes = 0;
-
-		atomic_set(&tch->tx_notify_count, 0);
-		atomic_set(&tch->rx_notify_count, 0);
-		atomic_set(&tch->any_notify_count, 0);
-		atomic_set(&tch->wakeup_client, 0);
-
-		/* in case there are values left from previous tests */
-		tch->notify_counter_per_chan = 0;
-		tch->next_index_in_sent_msg_per_chan = 0;
-
-		memset(tch->buf, 0x00, tch->buf_size);
-		tch->test_result = TEST_NO_RESULT;
-
-		tch->test_completed = 0;
-
-		ret = open_sdio_ch(tch);
-		if (ret)
-			continue;
-
-		if (tch->ch_id != SDIO_SMEM) {
-			ret = sdio_test_find_dev(tch);
-
-			if (ret) {
-				pr_err(TEST_MODULE_NAME ": %s - "
-				       "sdio_test_find_dev() returned with "
-				       "error", __func__);
-				return -ENODEV;
-			}
-
-			tch->sdio_al_device = tch->ch->sdio_al_dev;
-		}
-
-		if ((tch->test_type == SDIO_TEST_LPM_HOST_WAKER) ||
-		    (tch->test_type == SDIO_TEST_LPM_CLIENT_WAKER) ||
-		    (tch->test_type == SDIO_TEST_LPM_RANDOM))
-			sdio_al_register_lpm_cb(tch->sdio_al_device,
-					 sdio_test_wakeup_callback);
-	}
-
-	/*
-	 * make some space between opening the channels and sending the
-	 * config messages
-	 */
-	msleep(100);
-
-	/*
-	 * try to delay send_config_msg of all channels to after the point
-	 * when we open them all
-	 */
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used))
-			continue;
-
-		if ((tch->ch_ready) && (tch->ch_id != SDIO_SMEM))
-			send_config_msg(tch);
-
-		if ((tch->test_type == SDIO_TEST_LPM_HOST_WAKER) ||
-		    (tch->test_type == SDIO_TEST_LPM_CLIENT_WAKER) ||
-		    (tch->test_type == SDIO_TEST_LPM_RANDOM)) {
-			if (tch->timer_interval_ms > 0) {
-				pr_info(TEST_MODULE_NAME ": %s - init timer, "
-					"ms=%d\n",
-					__func__, tch->timer_interval_ms);
-				init_timer(&tch->timer);
-				tch->timer.data = (unsigned long)tch;
-				tch->timer.function =
-					sdio_test_lpm_timer_handler;
-				tch->timer.expires = jiffies +
-				    msecs_to_jiffies(tch->timer_interval_ms);
-				add_timer(&tch->timer);
-			}
-		}
-	}
-
-	pr_debug(TEST_MODULE_NAME ":queue_work..\n");
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used) || (!tch->ch_ready))
-			continue;
-
-		if (tch->ch_id == SDIO_SMEM) {
-#ifdef CONFIG_MSM_SDIO_SMEM
-			if (tch->test_type == SDIO_TEST_CLOSE_CHANNEL)
-				open_close_smem_test(tch);
-#endif
-		} else {
-			queue_work(tch->workqueue, &tch->test_work.work);
-		}
-
-	}
-
-	pr_info(TEST_MODULE_NAME ": %s - Waiting for the test completion\n",
-		__func__);
-
-	wait_event(test_ctx->wait_q, test_ctx->test_completed);
-	check_test_result();
-
-	/*
-	 * Close the channels and zero the is_used flag so that if the modem
-	 * will be reset after the test completion we won't re-open
-	 * the channels
-	 */
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-
-		if ((!tch) || (!tch->is_used))
-			continue;
-		if (!tch->ch_ready) {
-			tch->is_used = 0;
-			continue;
-		}
-
-		close_sdio_ch(tch);
-		tch->is_used = 0;
-	}
-
-	if (test_ctx->test_result == TEST_PASSED)
-		return 0;
-	else
-		return -EINVAL;
-}
-
-static int set_params_loopback_9k(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_LOOPBACK_CLIENT;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-	tch->config_msg.num_packets = 10000;
-	tch->config_msg.num_iterations = 1;
-
-	tch->packet_length = 512;
-	if (tch->ch_id == SDIO_RPC)
-		tch->packet_length = 128;
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-static int set_params_loopback_9k_close(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_CLOSE_CHANNEL;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-	tch->config_msg.num_packets = 5000;
-	tch->config_msg.num_iterations = 1;
-	tch->max_burst_size = 10;
-	switch (tch->ch_id) {
-	case SDIO_DUN:
-	case SDIO_RPC:
-		tch->packet_length = 128; /* max is 2K*/
-		break;
-	case SDIO_DIAG:
-	case SDIO_RMNT:
-	default:
-		tch->packet_length = 512; /* max is 4k */
-	}
-	tch->timer_interval_ms = 0;
-	return 0;
-}
-static int set_params_a2_perf(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_PERF;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-
-	switch (tch->ch_id) {
-	case SDIO_DIAG:
-		tch->packet_length = 512;
-		break;
-	case SDIO_DUN:
-		tch->packet_length = DUN_PACKET_SIZE;
-		break;
-	case SDIO_CSVT:
-		tch->packet_length = CSVT_PACKET_SIZE;
-		break;
-	default:
-		tch->packet_length = MAX_XFER_SIZE;
-		break;
-	}
-
-	pr_info(TEST_MODULE_NAME ": %s: packet_length=%d", __func__,
-			tch->packet_length);
-
-	tch->config_msg.num_packets = 10000;
-	tch->config_msg.num_iterations = 1;
-	tch->random_packet_size = 0;
-
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static int set_params_rtt(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_RTT;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-
-	switch (tch->ch_id) {
-	case SDIO_RMNT:
-		tch->packet_length = SDIO_RMNT_RTT_PACKET_SIZE;
-		break;
-	case SDIO_CSVT:
-		tch->packet_length = SDIO_CSVT_RTT_PACKET_SIZE;
-		break;
-	default:
-		pr_err(TEST_MODULE_NAME ": %s - ch_id invalid.\n", __func__);
-		return -EINVAL;
-	}
-
-	pr_info(TEST_MODULE_NAME ": %s: packet_length=%d", __func__,
-			tch->packet_length);
-
-	tch->config_msg.num_packets = 200;
-	tch->config_msg.num_iterations = 1;
-	tch->random_packet_size = 0;
-
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static int set_params_a2_small_pkts(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_PERF;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-	tch->packet_length = 128;
-
-	tch->config_msg.num_packets = 1000000;
-	tch->config_msg.num_iterations = 1;
-	tch->random_packet_size = 1;
-
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static int set_params_modem_reset(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_MODEM_RESET;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-	tch->packet_length = 512;
-	if (tch->ch_id == SDIO_RPC)
-		tch->packet_length = 128;
-	else if ((tch->ch_id == SDIO_RMNT) || (tch->ch_id == SDIO_DUN))
-		tch->packet_length = MAX_XFER_SIZE;
-
-	tch->config_msg.num_packets = 50000;
-	tch->config_msg.num_iterations = 1;
-
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static int set_params_a2_validation(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_A2_VALIDATION;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_LOOPBACK_CLIENT;
-
-	if (tch->ch_id == SDIO_RMNT)
-		tch->packet_length = RMNT_PACKET_SIZE;
-	else if (tch->ch_id == SDIO_DUN)
-		tch->packet_length = DUN_PACKET_SIZE;
-	else
-		tch->packet_length = MAX_XFER_SIZE;
-
-	tch->config_msg.num_packets = 10000;
-	tch->config_msg.num_iterations = 1;
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static int set_params_smem_test(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static int set_params_lpm_test(struct test_channel *tch,
-				enum sdio_test_case_type test,
-				int timer_interval_ms)
-{
-	static int first_time = 1;
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ": %s - NULL channel\n", __func__);
-		return -EINVAL;
-	}
-
-	tch->is_used = 1;
-	tch->test_type = test;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = test;
-	tch->config_msg.num_packets = LPM_TEST_NUM_OF_PACKETS;
-	tch->config_msg.num_iterations = 1;
-	tch->timer_interval_ms = timer_interval_ms;
-	tch->timeout_ms = 10000;
-
-	tch->packet_length = 0;
-	if (test != SDIO_TEST_LPM_RANDOM) {
-		init_timer(&tch->timeout_timer);
-		tch->timeout_timer.data = (unsigned long)tch;
-		tch->timeout_timer.function = sdio_test_lpm_timeout_handler;
-		tch->timeout_timer.expires = jiffies +
-			msecs_to_jiffies(tch->timeout_ms);
-		add_timer(&tch->timeout_timer);
-		pr_info(TEST_MODULE_NAME ": %s - Initiated LPM TIMEOUT TIMER."
-			"set to %d ms\n",
-			__func__, tch->timeout_ms);
-	}
-
-	if (first_time) {
-		pr_info(TEST_MODULE_NAME ": %s - wake_lock_init() called\n",
-		__func__);
-		wake_lock_init(&test_ctx->wake_lock,
-			       WAKE_LOCK_SUSPEND, TEST_MODULE_NAME);
-		first_time = 0;
-	}
-
-	pr_info(TEST_MODULE_NAME ": %s - wake_lock() for the TEST is "
-		"called channel %s. to prevent real sleeping\n",
-		__func__, tch->name);
-	wake_lock(&test_ctx->wake_lock);
-
-	return 0;
-}
-
-static int set_params_8k_sender_no_lp(struct test_channel *tch)
-{
-	if (!tch) {
-		pr_err(TEST_MODULE_NAME ":NULL channel\n");
-		return -EINVAL;
-	}
-	tch->is_used = 1;
-	tch->test_type = SDIO_TEST_HOST_SENDER_NO_LP;
-	tch->config_msg.signature = TEST_CONFIG_SIGNATURE;
-	tch->config_msg.test_case = SDIO_TEST_HOST_SENDER_NO_LP;
-	tch->config_msg.num_packets = 1000;
-	tch->config_msg.num_iterations = 1;
-
-	tch->packet_length = 512;
-	if (tch->ch_id == SDIO_RPC)
-		tch->packet_length = 128;
-	tch->timer_interval_ms = 0;
-
-	return 0;
-}
-
-static void set_pseudo_random_seed(void)
-{
-	/* Set the seed accoring to the kernel command parameters if any or
-	   get a random value */
-	if (seed != 0) {
-		test_ctx->lpm_pseudo_random_seed = seed;
-	} else {
-		test_ctx->lpm_pseudo_random_seed =
-			(unsigned int)(get_jiffies_64() & 0xFFFF);
-		test_ctx->lpm_pseudo_random_seed =
-			pseudo_random_seed(&test_ctx->lpm_pseudo_random_seed);
-	}
-
-	pr_info(TEST_MODULE_NAME ":%s: seed is %u",
-		   __func__, test_ctx->lpm_pseudo_random_seed);
-}
-
-/*
-   for each channel
-   1. open channel
-   2. close channel
-*/
-static int close_channel_lpm_test(int channel_num)
-{
-	int ret = 0;
-	struct test_channel *tch = NULL;
-	tch = test_ctx->test_ch_arr[channel_num];
-
-	if (!tch) {
-		pr_info(TEST_MODULE_NAME ":%s ch#%d is NULL\n",
-			__func__, channel_num);
-		return 0;
-	}
-
-	ret = open_sdio_ch(tch);
-	if (ret) {
-		pr_err(TEST_MODULE_NAME":%s open channel %s"
-			" failed\n", __func__, tch->name);
-		return ret;
-	} else {
-		pr_info(TEST_MODULE_NAME":%s open channel %s"
-			" success\n", __func__, tch->name);
-	}
-	ret = close_sdio_ch(tch);
-	if (ret) {
-		pr_err(TEST_MODULE_NAME":%s close channel %s"
-				" failed\n", __func__, tch->name);
-		return ret;
-	} else {
-		pr_info(TEST_MODULE_NAME":%s close channel %s"
-				" success\n", __func__, tch->name);
-	}
-
-	tch->is_used = 0;
-
-	return ret;
-}
-
-/**
- * Write File.
- *
- * @note Trigger the test from user space by:
- * echo 1 > /dev/sdio_al_test
- *
- */
-ssize_t test_write(struct file *filp, const char __user *buf, size_t size,
-		   loff_t *f_pos)
-{
-	sdio_al_test_initial_dev_and_chan(test_ctx);
-
-	if (strict_strtol(buf, 10, &test_ctx->testcase))
-		return -EINVAL;
-
-	switch (test_ctx->testcase) {
-	case 98:
-		pr_info(TEST_MODULE_NAME " set runtime debug on");
-		test_ctx->runtime_debug = 1;
-		return size;
-	case 99:
-		pr_info(TEST_MODULE_NAME " set runtime debug off");
-		test_ctx->runtime_debug = 0;
-		return size;
-	default:
-		pr_info(TEST_MODULE_NAME ":Bad Test number = %d.\n",
-			(int)test_ctx->testcase);
-		return size;
-	}
-
-	return size;
-}
-
-/**
- * Test Channel Init.
- */
-int test_channel_init(char *name)
-{
-	struct test_channel *test_ch;
-	int ch_id = 0;
-	int ret;
-
-	pr_debug(TEST_MODULE_NAME ":%s.\n", __func__);
-	pr_info(TEST_MODULE_NAME ": init test channel %s.\n", name);
-
-	ch_id = channel_name_to_id(name);
-	pr_debug(TEST_MODULE_NAME ":id = %d.\n", ch_id);
-	if (test_ctx->test_ch_arr[ch_id] == NULL) {
-		test_ch = kzalloc(sizeof(*test_ch), GFP_KERNEL);
-		if (test_ch == NULL) {
-			pr_err(TEST_MODULE_NAME ":kzalloc err for allocating "
-						"test_ch %s.\n",
-			       name);
-			return -ENOMEM;
-		}
-		test_ctx->test_ch_arr[ch_id] = test_ch;
-
-		test_ch->ch_id = ch_id;
-
-		strncpy(test_ch->name, name,
-		       strnlen(name, TEST_CH_NAME_SIZE)-SDIO_TEST_POSTFIX_SIZE);
-
-		test_ch->buf_size = MAX_XFER_SIZE;
-
-		test_ch->buf = kzalloc(test_ch->buf_size, GFP_KERNEL);
-		if (test_ch->buf == NULL) {
-			kfree(test_ch);
-			test_ctx->test_ch = NULL;
-			return -ENOMEM;
-		}
-
-		if (test_ch->ch_id == SDIO_SMEM) {
-			test_ctx->smem_buf = kzalloc(SMEM_MAX_XFER_SIZE,
-						     GFP_KERNEL);
-			if (test_ctx->smem_buf == NULL) {
-				pr_err(TEST_MODULE_NAME ":%s: Unable to "
-							"allocate smem buf\n",
-				       __func__);
-				kfree(test_ch);
-				test_ctx->test_ch = NULL;
-				return -ENOMEM;
-			}
-
-#ifdef CONFIG_MSM_SDIO_SMEM
-			ret = platform_driver_register(&sdio_smem_client_drv);
-			if (ret) {
-				pr_err(TEST_MODULE_NAME ":%s: Unable to "
-							"register sdio smem "
-							"test client\n",
-				       __func__);
-				return ret;
-			}
-#endif
-		} else {
-			test_ch->workqueue =
-				create_singlethread_workqueue(test_ch->name);
-			test_ch->test_work.test_ch = test_ch;
-			INIT_WORK(&test_ch->test_work.work, worker);
-
-			init_waitqueue_head(&test_ch->wait_q);
-		}
-	} else {
-		test_ch = test_ctx->test_ch_arr[ch_id];
-		pr_info(TEST_MODULE_NAME ":%s: ch %s was detected again\n",
-			__func__, test_ch->name);
-		test_ch->card_removed = 0;
-		if ((test_ch->is_used) &&
-		    (test_ch->test_type == SDIO_TEST_MODEM_RESET)) {
-			if (test_ch->ch_id == SDIO_SMEM) {
-#ifdef CONFIG_MSM_SDIO_SMEM
-				ret = add_sdio_smem();
-				if (ret) {
-					test_ch->ch_ready = false;
-					return 0;
-				}
-#endif
-			} else {
-				ret = open_sdio_ch(test_ch);
-				if (ret) {
-					pr_info(TEST_MODULE_NAME
-						":%s: open channel %s failed\n",
-					__func__, test_ch->name);
-					return 0;
-				}
-				ret = sdio_test_find_dev(test_ch);
-
-				if (ret) {
-					pr_err(TEST_MODULE_NAME ": %s - "
-					       "sdio_test_find_dev() returned "
-					       "with error", __func__);
-					return -ENODEV;
-				}
-
-				test_ch->sdio_al_device =
-					test_ch->ch->sdio_al_dev;
-			}
-			atomic_set(&test_ch->card_detected_event, 1);
-			wake_up(&test_ch->wait_q);
-		}
-	}
-
-	return 0;
-}
-
-static int sdio_test_channel_probe(struct platform_device *pdev)
-{
-	if (!pdev)
-		return -EIO;
-	return test_channel_init((char *)pdev->name);
-}
-
-static int sdio_test_channel_remove(struct platform_device *pdev)
-{
-	int ch_id;
-
-	if (!pdev)
-		return -EIO;
-
-	ch_id = channel_name_to_id((char *)pdev->name);
-	if (test_ctx->test_ch_arr[ch_id] == NULL)
-		return 0;
-
-	pr_info(TEST_MODULE_NAME "%s: remove ch %s\n",
-		__func__, test_ctx->test_ch_arr[ch_id]->name);
-
-	if ((ch_id == SDIO_SMEM) && (test_ctx->smem_pdev)) {
-		platform_device_unregister(test_ctx->smem_pdev);
-		test_ctx->smem_pdev = NULL;
-	}
-
-	test_ctx->test_ch_arr[ch_id]->ch_ready = 0;
-	test_ctx->test_ch_arr[ch_id]->card_removed = 1;
-
-	return 0;
-
-}
-
-static int sdio_test_channel_csvt_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-
-	if (!pdev)
-		return -ENODEV;
-
-	test_ctx->csvt_app_pdev = platform_device_alloc("SDIO_CSVT_TEST_APP",
-							-1);
-	ret = platform_device_add(test_ctx->csvt_app_pdev);
-		if (ret) {
-			pr_err(MODULE_NAME ":platform_device_add failed, "
-					   "ret=%d\n", ret);
-			return ret;
-		}
-
-	return sdio_test_channel_probe(pdev);
-}
-
-static int sdio_test_channel_csvt_remove(struct platform_device *pdev)
-{
-	if (!pdev)
-		return -ENODEV;
-
-	platform_device_unregister(test_ctx->csvt_app_pdev);
-
-	return sdio_test_channel_remove(pdev);
-}
-
-static struct platform_driver sdio_rpc_drv = {
-	.probe		= sdio_test_channel_probe,
-	.remove		= sdio_test_channel_remove,
-	.driver		= {
-		.name	= "SDIO_RPC_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver sdio_qmi_drv = {
-	.probe		= sdio_test_channel_probe,
-	.remove		= sdio_test_channel_remove,
-	.driver		= {
-		.name	= "SDIO_QMI_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver sdio_diag_drv = {
-	.probe		= sdio_test_channel_probe,
-	.remove		= sdio_test_channel_remove,
-	.driver		= {
-		.name	= "SDIO_DIAG_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver sdio_smem_drv = {
-	.probe		= sdio_test_channel_probe,
-	.remove		= sdio_test_channel_remove,
-	.driver		= {
-		.name	= "SDIO_SMEM_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver sdio_rmnt_drv = {
-	.probe		= sdio_test_channel_probe,
-	.remove		= sdio_test_channel_remove,
-	.driver		= {
-		.name	= "SDIO_RMNT_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver sdio_dun_drv = {
-	.probe		= sdio_test_channel_probe,
-	.remove		= sdio_test_channel_remove,
-	.driver		= {
-		.name	= "SDIO_DUN_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct platform_driver sdio_csvt_drv = {
-	.probe		= sdio_test_channel_csvt_probe,
-	.remove		= sdio_test_channel_csvt_remove,
-	.driver		= {
-		.name	= "SDIO_CSVT_TEST",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static struct class *test_class;
-
-const struct file_operations test_fops = {
-	.owner = THIS_MODULE,
-	.write = test_write,
-};
-
-/**
- * Module Init.
- */
-static int __init test_init(void)
-{
-	int ret;
-
-	pr_debug(TEST_MODULE_NAME ":test_init.\n");
-
-	test_ctx = kzalloc(sizeof(struct test_context), GFP_KERNEL);
-
-	if (test_ctx == NULL) {
-		pr_err(TEST_MODULE_NAME ":kzalloc err.\n");
-		return -ENOMEM;
-	}
-	test_ctx->test_ch = NULL;
-	test_ctx->signature = TEST_SIGNATURE;
-
-	test_ctx->name = "UNKNOWN";
-
-	init_waitqueue_head(&test_ctx->wait_q);
-
-#ifdef CONFIG_DEBUG_FS
-	sdio_al_test_debugfs_init();
-#endif
-
-	test_class = class_create(THIS_MODULE, TEST_MODULE_NAME);
-
-	ret = alloc_chrdev_region(&test_ctx->dev_num, 0, 1, TEST_MODULE_NAME);
-	if (ret) {
-		pr_err(TEST_MODULE_NAME "alloc_chrdev_region err.\n");
-		return -ENODEV;
-	}
-
-	test_ctx->dev = device_create(test_class, NULL, test_ctx->dev_num,
-				      test_ctx, TEST_MODULE_NAME);
-	if (IS_ERR(test_ctx->dev)) {
-		pr_err(TEST_MODULE_NAME ":device_create err.\n");
-		return -ENODEV;
-	}
-
-	test_ctx->cdev = cdev_alloc();
-	if (test_ctx->cdev == NULL) {
-		pr_err(TEST_MODULE_NAME ":cdev_alloc err.\n");
-		return -ENODEV;
-	}
-	cdev_init(test_ctx->cdev, &test_fops);
-	test_ctx->cdev->owner = THIS_MODULE;
-
-	ret = cdev_add(test_ctx->cdev, test_ctx->dev_num, 1);
-	if (ret)
-		pr_err(TEST_MODULE_NAME ":cdev_add err=%d\n", -ret);
-	else
-		pr_debug(TEST_MODULE_NAME ":SDIO-AL-Test init OK..\n");
-
-	platform_driver_register(&sdio_rpc_drv);
-	platform_driver_register(&sdio_qmi_drv);
-	platform_driver_register(&sdio_diag_drv);
-	platform_driver_register(&sdio_smem_drv);
-	platform_driver_register(&sdio_rmnt_drv);
-	platform_driver_register(&sdio_dun_drv);
-	platform_driver_register(&sdio_csvt_drv);
-
-	return ret;
-}
-
-/**
- * Module Exit.
- */
-static void __exit test_exit(void)
-{
-	int i;
-
-	pr_debug(TEST_MODULE_NAME ":test_exit.\n");
-
-	test_ctx->exit_flag = true;
-
-	msleep(100); /* allow gracefully exit of the worker thread */
-
-	cdev_del(test_ctx->cdev);
-	device_destroy(test_class, test_ctx->dev_num);
-	unregister_chrdev_region(test_ctx->dev_num, 1);
-
-	platform_driver_unregister(&sdio_rpc_drv);
-	platform_driver_unregister(&sdio_qmi_drv);
-	platform_driver_unregister(&sdio_diag_drv);
-	platform_driver_unregister(&sdio_smem_drv);
-	platform_driver_unregister(&sdio_rmnt_drv);
-	platform_driver_unregister(&sdio_dun_drv);
-	platform_driver_unregister(&sdio_csvt_drv);
-
-	for (i = 0; i < SDIO_MAX_CHANNELS; i++) {
-		struct test_channel *tch = test_ctx->test_ch_arr[i];
-		if (!tch)
-			continue;
-		kfree(tch->buf);
-		kfree(tch);
-	}
-
-#ifdef CONFIG_DEBUG_FS
-	sdio_al_test_debugfs_cleanup();
-#endif
-
-	kfree(test_ctx);
-
-	pr_debug(TEST_MODULE_NAME ":test_exit complete.\n");
-}
-
-module_init(test_init);
-module_exit(test_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("SDIO_AL Test");
-MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
-
-
diff --git a/arch/arm/mach-msm/sdio_cmux.c b/arch/arm/mach-msm/sdio_cmux.c
deleted file mode 100644
index 48ca6b7..0000000
--- a/arch/arm/mach-msm/sdio_cmux.c
+++ /dev/null
@@ -1,901 +0,0 @@
-/* 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
- * 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.
- */
-
-#define DEBUG
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/termios.h>
-#include <linux/debugfs.h>
-#include <linux/moduleparam.h>
-
-#include <mach/sdio_al.h>
-#include <mach/sdio_cmux.h>
-
-#include "modem_notifier.h"
-
-#define MAX_WRITE_RETRY 5
-#define MAGIC_NO_V1 0x33FC
-
-static int msm_sdio_cmux_debug_mask;
-module_param_named(debug_mask, msm_sdio_cmux_debug_mask,
-		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-
-enum cmd_type {
-	DATA = 0,
-	OPEN,
-	CLOSE,
-	STATUS,
-	NUM_CMDS
-};
-
-#define DSR_POS 0x1
-#define CTS_POS 0x2
-#define RI_POS 0x4
-#define CD_POS 0x8
-
-struct sdio_cmux_ch {
-	int lc_id;
-
-	struct mutex lc_lock;
-	wait_queue_head_t open_wait_queue;
-	int is_remote_open;
-	int is_local_open;
-	int is_channel_reset;
-
-	char local_status;
-	char remote_status;
-
-	struct mutex tx_lock;
-	struct list_head tx_list;
-
-	void *priv;
-	struct mutex rx_cb_lock;
-	void (*receive_cb)(void *, int, void *);
-	void (*write_done)(void *, int, void *);
-	void (*status_callback)(int, void *);
-} logical_ch[SDIO_CMUX_NUM_CHANNELS];
-
-struct sdio_cmux_hdr {
-	uint16_t magic_no;
-	uint8_t status;         /* This field is reserved for commands other
-				 * than STATUS */
-	uint8_t cmd;
-	uint8_t pad_bytes;
-	uint8_t lc_id;
-	uint16_t pkt_len;
-};
-
-struct sdio_cmux_pkt {
-	struct sdio_cmux_hdr *hdr;
-	void *data;
-};
-
-struct sdio_cmux_list_elem {
-	struct list_head list;
-	struct sdio_cmux_pkt cmux_pkt;
-};
-
-#define logical_ch_is_local_open(x)                        \
-	(logical_ch[(x)].is_local_open)
-
-#define logical_ch_is_remote_open(x)                       \
-	(logical_ch[(x)].is_remote_open)
-
-static void sdio_cdemux_fn(struct work_struct *work);
-static DECLARE_WORK(sdio_cdemux_work, sdio_cdemux_fn);
-static struct workqueue_struct *sdio_cdemux_wq;
-
-static DEFINE_MUTEX(write_lock);
-static uint32_t bytes_to_write;
-static DEFINE_MUTEX(temp_rx_lock);
-static LIST_HEAD(temp_rx_list);
-
-static void sdio_cmux_fn(struct work_struct *work);
-static DECLARE_WORK(sdio_cmux_work, sdio_cmux_fn);
-static struct workqueue_struct *sdio_cmux_wq;
-
-static struct sdio_channel *sdio_qmi_chl;
-static uint32_t sdio_cmux_inited;
-
-static uint32_t abort_tx;
-static DEFINE_MUTEX(modem_reset_lock);
-
-static DEFINE_MUTEX(probe_lock);
-
-enum {
-	MSM_SDIO_CMUX_DEBUG = 1U << 0,
-	MSM_SDIO_CMUX_DUMP_BUFFER = 1U << 1,
-};
-
-static struct platform_device sdio_ctl_dev = {
-	.name		= "SDIO_CTL",
-	.id		= -1,
-};
-
-#if defined(DEBUG)
-#define D_DUMP_BUFFER(prestr, cnt, buf) \
-do { \
-	if (msm_sdio_cmux_debug_mask & MSM_SDIO_CMUX_DUMP_BUFFER) { \
-		int i; \
-		pr_debug("%s", prestr); \
-		for (i = 0; i < cnt; i++) \
-			pr_info("%.2x", buf[i]); \
-		pr_debug("\n"); \
-	} \
-} while (0)
-
-#define D(x...) \
-do { \
-	if (msm_sdio_cmux_debug_mask & MSM_SDIO_CMUX_DEBUG) \
-		pr_debug(x); \
-} while (0)
-
-#else
-#define D_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
-#define D(x...) do {} while (0)
-#endif
-
-static int sdio_cmux_ch_alloc(int id)
-{
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS) {
-		pr_err("%s: Invalid lc_id - %d\n", __func__, id);
-		return -EINVAL;
-	}
-
-	logical_ch[id].lc_id = id;
-	mutex_init(&logical_ch[id].lc_lock);
-	init_waitqueue_head(&logical_ch[id].open_wait_queue);
-	logical_ch[id].is_remote_open = 0;
-	logical_ch[id].is_local_open = 0;
-	logical_ch[id].is_channel_reset = 0;
-
-	INIT_LIST_HEAD(&logical_ch[id].tx_list);
-	mutex_init(&logical_ch[id].tx_lock);
-
-	logical_ch[id].priv = NULL;
-	mutex_init(&logical_ch[id].rx_cb_lock);
-	logical_ch[id].receive_cb = NULL;
-	logical_ch[id].write_done = NULL;
-	return 0;
-}
-
-static int sdio_cmux_ch_clear_and_signal(int id)
-{
-	struct sdio_cmux_list_elem *list_elem;
-
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS) {
-		pr_err("%s: Invalid lc_id - %d\n", __func__, id);
-		return -EINVAL;
-	}
-
-	mutex_lock(&logical_ch[id].lc_lock);
-	logical_ch[id].is_remote_open = 0;
-	mutex_lock(&logical_ch[id].tx_lock);
-	while (!list_empty(&logical_ch[id].tx_list)) {
-		list_elem = list_first_entry(&logical_ch[id].tx_list,
-					     struct sdio_cmux_list_elem,
-					     list);
-		list_del(&list_elem->list);
-		kfree(list_elem->cmux_pkt.hdr);
-		kfree(list_elem);
-	}
-	mutex_unlock(&logical_ch[id].tx_lock);
-	mutex_lock(&logical_ch[id].rx_cb_lock);
-	if (logical_ch[id].receive_cb)
-		logical_ch[id].receive_cb(NULL, 0, logical_ch[id].priv);
-	mutex_unlock(&logical_ch[id].rx_cb_lock);
-	if (logical_ch[id].write_done)
-		logical_ch[id].write_done(NULL, 0, logical_ch[id].priv);
-	mutex_unlock(&logical_ch[id].lc_lock);
-	wake_up(&logical_ch[id].open_wait_queue);
-	return 0;
-}
-
-static int sdio_cmux_write_cmd(const int id, enum cmd_type type)
-{
-	int write_size = 0;
-	void *write_data = NULL;
-	struct sdio_cmux_list_elem *list_elem;
-
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS) {
-		pr_err("%s: Invalid lc_id - %d\n", __func__, id);
-		return -EINVAL;
-	}
-
-	if (type < 0 || type > NUM_CMDS) {
-		pr_err("%s: Invalid cmd - %d\n", __func__, type);
-		return -EINVAL;
-	}
-
-	write_size = sizeof(struct sdio_cmux_hdr);
-	list_elem = kmalloc(sizeof(struct sdio_cmux_list_elem), GFP_KERNEL);
-	if (!list_elem) {
-		pr_err("%s: list_elem alloc failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	write_data = kmalloc(write_size, GFP_KERNEL);
-	if (!write_data) {
-		pr_err("%s: write_data alloc failed\n", __func__);
-		kfree(list_elem);
-		return -ENOMEM;
-	}
-
-	list_elem->cmux_pkt.hdr = (struct sdio_cmux_hdr *)write_data;
-	list_elem->cmux_pkt.data = NULL;
-
-	list_elem->cmux_pkt.hdr->lc_id = (uint8_t)id;
-	list_elem->cmux_pkt.hdr->pkt_len = (uint16_t)0;
-	list_elem->cmux_pkt.hdr->cmd = (uint8_t)type;
-	list_elem->cmux_pkt.hdr->status = (uint8_t)0;
-	if (type == STATUS)
-		list_elem->cmux_pkt.hdr->status = logical_ch[id].local_status;
-	list_elem->cmux_pkt.hdr->pad_bytes = (uint8_t)0;
-	list_elem->cmux_pkt.hdr->magic_no = (uint16_t)MAGIC_NO_V1;
-
-	mutex_lock(&logical_ch[id].tx_lock);
-	list_add_tail(&list_elem->list, &logical_ch[id].tx_list);
-	mutex_unlock(&logical_ch[id].tx_lock);
-
-	mutex_lock(&write_lock);
-	bytes_to_write += write_size;
-	mutex_unlock(&write_lock);
-	queue_work(sdio_cmux_wq, &sdio_cmux_work);
-
-	return 0;
-}
-
-int sdio_cmux_open(const int id,
-		   void (*receive_cb)(void *, int, void *),
-		   void (*write_done)(void *, int, void *),
-		   void (*status_callback)(int, void *),
-		   void *priv)
-{
-	int r;
-	struct sdio_cmux_list_elem *list_elem, *list_elem_tmp;
-
-	if (!sdio_cmux_inited)
-		return -ENODEV;
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS) {
-		pr_err("%s: Invalid id - %d\n", __func__, id);
-		return -EINVAL;
-	}
-
-	r = wait_event_timeout(logical_ch[id].open_wait_queue,
-				logical_ch[id].is_remote_open, (1 * HZ));
-	if (r < 0) {
-		pr_err("ERROR %s: wait_event_timeout() failed for"
-		       " ch%d with rc %d\n", __func__, id, r);
-		return r;
-	}
-	if (r == 0) {
-		pr_err("ERROR %s: Wait Timed Out for ch%d\n", __func__, id);
-		return -ETIMEDOUT;
-	}
-
-	mutex_lock(&logical_ch[id].lc_lock);
-	if (!logical_ch[id].is_remote_open) {
-		pr_err("%s: Remote ch%d not opened\n", __func__, id);
-		mutex_unlock(&logical_ch[id].lc_lock);
-		return -EINVAL;
-	}
-	if (logical_ch[id].is_local_open) {
-		mutex_unlock(&logical_ch[id].lc_lock);
-		return 0;
-	}
-	logical_ch[id].is_local_open = 1;
-	logical_ch[id].priv = priv;
-	logical_ch[id].write_done = write_done;
-	logical_ch[id].status_callback = status_callback;
-	mutex_lock(&logical_ch[id].rx_cb_lock);
-	logical_ch[id].receive_cb = receive_cb;
-	if (logical_ch[id].receive_cb) {
-		mutex_lock(&temp_rx_lock);
-		list_for_each_entry_safe(list_elem, list_elem_tmp,
-					 &temp_rx_list, list) {
-			if ((int)list_elem->cmux_pkt.hdr->lc_id == id) {
-				logical_ch[id].receive_cb(
-					list_elem->cmux_pkt.data,
-					(int)list_elem->cmux_pkt.hdr->pkt_len,
-					logical_ch[id].priv);
-				list_del(&list_elem->list);
-				kfree(list_elem->cmux_pkt.hdr);
-				kfree(list_elem);
-			}
-		}
-		mutex_unlock(&temp_rx_lock);
-	}
-	mutex_unlock(&logical_ch[id].rx_cb_lock);
-	mutex_unlock(&logical_ch[id].lc_lock);
-	sdio_cmux_write_cmd(id, OPEN);
-	return 0;
-}
-EXPORT_SYMBOL(sdio_cmux_open);
-
-int sdio_cmux_close(int id)
-{
-	struct sdio_cmux_ch *ch;
-
-	if (!sdio_cmux_inited)
-		return -ENODEV;
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS) {
-		pr_err("%s: Invalid channel close\n", __func__);
-		return -EINVAL;
-	}
-
-	ch = &logical_ch[id];
-	mutex_lock(&ch->lc_lock);
-	mutex_lock(&logical_ch[id].rx_cb_lock);
-	ch->receive_cb = NULL;
-	mutex_unlock(&logical_ch[id].rx_cb_lock);
-	mutex_lock(&ch->tx_lock);
-	ch->write_done = NULL;
-	mutex_unlock(&ch->tx_lock);
-	ch->is_local_open = 0;
-	ch->priv = NULL;
-	mutex_unlock(&ch->lc_lock);
-	sdio_cmux_write_cmd(ch->lc_id, CLOSE);
-	return 0;
-}
-EXPORT_SYMBOL(sdio_cmux_close);
-
-int sdio_cmux_write_avail(int id)
-{
-	int write_avail;
-
-	mutex_lock(&logical_ch[id].lc_lock);
-	if (logical_ch[id].is_channel_reset) {
-		mutex_unlock(&logical_ch[id].lc_lock);
-		return -ENETRESET;
-	}
-	mutex_unlock(&logical_ch[id].lc_lock);
-	write_avail = sdio_write_avail(sdio_qmi_chl);
-	return write_avail - bytes_to_write;
-}
-EXPORT_SYMBOL(sdio_cmux_write_avail);
-
-int sdio_cmux_write(int id, void *data, int len)
-{
-	struct sdio_cmux_list_elem *list_elem;
-	uint32_t write_size;
-	void *write_data = NULL;
-	struct sdio_cmux_ch *ch;
-	int ret;
-
-	if (!sdio_cmux_inited)
-		return -ENODEV;
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS) {
-		pr_err("%s: Invalid channel id %d\n", __func__, id);
-		return -ENODEV;
-	}
-
-	ch = &logical_ch[id];
-	if (len <= 0) {
-		pr_err("%s: Invalid len %d bytes to write\n",
-			__func__, len);
-		return -EINVAL;
-	}
-
-	write_size = sizeof(struct sdio_cmux_hdr) + len;
-	list_elem = kmalloc(sizeof(struct sdio_cmux_list_elem), GFP_KERNEL);
-	if (!list_elem) {
-		pr_err("%s: list_elem alloc failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	write_data = kmalloc(write_size, GFP_KERNEL);
-	if (!write_data) {
-		pr_err("%s: write_data alloc failed\n", __func__);
-		kfree(list_elem);
-		return -ENOMEM;
-	}
-
-	list_elem->cmux_pkt.hdr = (struct sdio_cmux_hdr *)write_data;
-	list_elem->cmux_pkt.data = (void *)((char *)write_data +
-						sizeof(struct sdio_cmux_hdr));
-	memcpy(list_elem->cmux_pkt.data, data, len);
-
-	list_elem->cmux_pkt.hdr->lc_id = (uint8_t)ch->lc_id;
-	list_elem->cmux_pkt.hdr->pkt_len = (uint16_t)len;
-	list_elem->cmux_pkt.hdr->cmd = (uint8_t)DATA;
-	list_elem->cmux_pkt.hdr->status = (uint8_t)0;
-	list_elem->cmux_pkt.hdr->pad_bytes = (uint8_t)0;
-	list_elem->cmux_pkt.hdr->magic_no = (uint16_t)MAGIC_NO_V1;
-
-	mutex_lock(&ch->lc_lock);
-	if (!ch->is_remote_open || !ch->is_local_open) {
-		pr_err("%s: Local ch%d sending data before sending/receiving"
-		       " OPEN command\n", __func__, ch->lc_id);
-		if (ch->is_channel_reset)
-			ret = -ENETRESET;
-		else
-			ret = -ENODEV;
-		mutex_unlock(&ch->lc_lock);
-		kfree(write_data);
-		kfree(list_elem);
-		return ret;
-	}
-	mutex_lock(&ch->tx_lock);
-	list_add_tail(&list_elem->list, &ch->tx_list);
-	mutex_unlock(&ch->tx_lock);
-	mutex_unlock(&ch->lc_lock);
-
-	mutex_lock(&write_lock);
-	bytes_to_write += write_size;
-	mutex_unlock(&write_lock);
-	queue_work(sdio_cmux_wq, &sdio_cmux_work);
-
-	return len;
-}
-EXPORT_SYMBOL(sdio_cmux_write);
-
-int is_remote_open(int id)
-{
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS)
-		return -ENODEV;
-
-	return logical_ch_is_remote_open(id);
-}
-EXPORT_SYMBOL(is_remote_open);
-
-int sdio_cmux_is_channel_reset(int id)
-{
-	int ret;
-	if (id < 0 || id >= SDIO_CMUX_NUM_CHANNELS)
-		return -ENODEV;
-
-	mutex_lock(&logical_ch[id].lc_lock);
-	ret = logical_ch[id].is_channel_reset;
-	mutex_unlock(&logical_ch[id].lc_lock);
-	return ret;
-}
-EXPORT_SYMBOL(sdio_cmux_is_channel_reset);
-
-int sdio_cmux_tiocmget(int id)
-{
-	int ret =  (logical_ch[id].remote_status & DSR_POS ? TIOCM_DSR : 0) |
-		(logical_ch[id].remote_status & CTS_POS ? TIOCM_CTS : 0) |
-		(logical_ch[id].remote_status & CD_POS ? TIOCM_CD : 0) |
-		(logical_ch[id].remote_status & RI_POS ? TIOCM_RI : 0) |
-		(logical_ch[id].local_status & CTS_POS ? TIOCM_RTS : 0) |
-		(logical_ch[id].local_status & DSR_POS ? TIOCM_DTR : 0);
-	return ret;
-}
-EXPORT_SYMBOL(sdio_cmux_tiocmget);
-
-int sdio_cmux_tiocmset(int id, unsigned int set, unsigned int clear)
-{
-	if (set & TIOCM_DTR)
-		logical_ch[id].local_status |= DSR_POS;
-
-	if (set & TIOCM_RTS)
-		logical_ch[id].local_status |= CTS_POS;
-
-	if (clear & TIOCM_DTR)
-		logical_ch[id].local_status &= ~DSR_POS;
-
-	if (clear & TIOCM_RTS)
-		logical_ch[id].local_status &= ~CTS_POS;
-
-	sdio_cmux_write_cmd(id, STATUS);
-	return 0;
-}
-EXPORT_SYMBOL(sdio_cmux_tiocmset);
-
-static int copy_packet(void *pkt, int size)
-{
-	struct sdio_cmux_list_elem *list_elem = NULL;
-	void *temp_pkt = NULL;
-
-	list_elem = kmalloc(sizeof(struct sdio_cmux_list_elem), GFP_KERNEL);
-	if (!list_elem) {
-		pr_err("%s: list_elem alloc failed\n", __func__);
-		return -ENOMEM;
-	}
-	temp_pkt = kmalloc(size, GFP_KERNEL);
-	if (!temp_pkt) {
-		pr_err("%s: temp_pkt alloc failed\n", __func__);
-		kfree(list_elem);
-		return -ENOMEM;
-	}
-
-	memcpy(temp_pkt, pkt, size);
-	list_elem->cmux_pkt.hdr = temp_pkt;
-	list_elem->cmux_pkt.data = (void *)((char *)temp_pkt +
-					    sizeof(struct sdio_cmux_hdr));
-	mutex_lock(&temp_rx_lock);
-	list_add_tail(&list_elem->list, &temp_rx_list);
-	mutex_unlock(&temp_rx_lock);
-	return 0;
-}
-
-static int process_cmux_pkt(void *pkt, int size)
-{
-	struct sdio_cmux_hdr *mux_hdr;
-	uint32_t id, data_size;
-	void *data;
-	char *dump_buf = (char *)pkt;
-
-	D_DUMP_BUFFER("process_cmux_pkt:", size, dump_buf);
-	mux_hdr = (struct sdio_cmux_hdr *)pkt;
-	switch (mux_hdr->cmd) {
-	case OPEN:
-		id = (uint32_t)(mux_hdr->lc_id);
-		D("%s: Received OPEN command for ch%d\n", __func__, id);
-		mutex_lock(&logical_ch[id].lc_lock);
-		logical_ch[id].is_remote_open = 1;
-		if (logical_ch[id].is_channel_reset) {
-			sdio_cmux_write_cmd(id, OPEN);
-			logical_ch[id].is_channel_reset = 0;
-		}
-		mutex_unlock(&logical_ch[id].lc_lock);
-		wake_up(&logical_ch[id].open_wait_queue);
-		break;
-
-	case CLOSE:
-		id = (uint32_t)(mux_hdr->lc_id);
-		D("%s: Received CLOSE command for ch%d\n", __func__, id);
-		sdio_cmux_ch_clear_and_signal(id);
-		break;
-
-	case DATA:
-		id = (uint32_t)(mux_hdr->lc_id);
-		D("%s: Received DATA for ch%d\n", __func__, id);
-		/*Channel is not locally open & if single packet received
-		  then drop it*/
-		mutex_lock(&logical_ch[id].lc_lock);
-		if (!logical_ch[id].is_remote_open) {
-			mutex_unlock(&logical_ch[id].lc_lock);
-			pr_err("%s: Remote Ch%d sent data before sending/"
-			       "receiving OPEN command\n", __func__, id);
-			return -ENODEV;
-		}
-
-		data = (void *)((char *)pkt + sizeof(struct sdio_cmux_hdr));
-		data_size = (int)(((struct sdio_cmux_hdr *)pkt)->pkt_len);
-		mutex_unlock(&logical_ch[id].lc_lock);
-		/*
-		 * The lc_lock is released before the call to receive_cb
-		 * to avoid a dead lock where in the receive_cb would call a
-		 * function that tries to acquire a rx_lock which is already
-		 * acquired by a Thread that is waiting on lc_lock.
-		 */
-		mutex_lock(&logical_ch[id].rx_cb_lock);
-		if (logical_ch[id].receive_cb)
-			logical_ch[id].receive_cb(data, data_size,
-						logical_ch[id].priv);
-		else
-			copy_packet(pkt, size);
-		mutex_unlock(&logical_ch[id].rx_cb_lock);
-		break;
-
-	case STATUS:
-		id = (uint32_t)(mux_hdr->lc_id);
-		D("%s: Received STATUS command for ch%d\n", __func__, id);
-		if (logical_ch[id].remote_status != mux_hdr->status) {
-			mutex_lock(&logical_ch[id].lc_lock);
-			logical_ch[id].remote_status = mux_hdr->status;
-			mutex_unlock(&logical_ch[id].lc_lock);
-			if (logical_ch[id].status_callback)
-				logical_ch[id].status_callback(
-							sdio_cmux_tiocmget(id),
-							logical_ch[id].priv);
-		}
-		break;
-	}
-	return 0;
-}
-
-static void parse_cmux_data(void *data, int size)
-{
-	int data_parsed = 0, pkt_size;
-	char *temp_ptr;
-
-	D("Entered %s\n", __func__);
-	temp_ptr = (char *)data;
-	while (data_parsed < size) {
-		pkt_size = sizeof(struct sdio_cmux_hdr) +
-			   (int)(((struct sdio_cmux_hdr *)temp_ptr)->pkt_len);
-		D("Parsed %d bytes, Current Pkt Size %d bytes,"
-		  " Total size %d bytes\n", data_parsed, pkt_size, size);
-		process_cmux_pkt((void *)temp_ptr, pkt_size);
-		data_parsed += pkt_size;
-		temp_ptr += pkt_size;
-	}
-
-	kfree(data);
-}
-
-static void sdio_cdemux_fn(struct work_struct *work)
-{
-	int r = 0, read_avail = 0;
-	void *cmux_data;
-
-	while (1) {
-		read_avail = sdio_read_avail(sdio_qmi_chl);
-		if (read_avail < 0) {
-			pr_err("%s: sdio_read_avail failed with rc %d\n",
-				__func__, read_avail);
-			return;
-		}
-
-		if (read_avail == 0) {
-			D("%s: Nothing to read\n", __func__);
-			return;
-		}
-
-		D("%s: kmalloc %d bytes\n", __func__, read_avail);
-		cmux_data = kmalloc(read_avail, GFP_KERNEL);
-		if (!cmux_data) {
-			pr_err("%s: kmalloc Failed\n", __func__);
-			return;
-		}
-
-		D("%s: sdio_read %d bytes\n", __func__, read_avail);
-		r = sdio_read(sdio_qmi_chl, cmux_data, read_avail);
-		if (r < 0) {
-			pr_err("%s: sdio_read failed with rc %d\n",
-				__func__, r);
-			kfree(cmux_data);
-			return;
-		}
-
-		parse_cmux_data(cmux_data, read_avail);
-	}
-	return;
-}
-
-static void sdio_cmux_fn(struct work_struct *work)
-{
-	int i, r = 0;
-	void *write_data;
-	uint32_t write_size, write_avail, write_retry = 0;
-	int bytes_written;
-	struct sdio_cmux_list_elem *list_elem = NULL;
-	struct sdio_cmux_ch *ch;
-
-	for (i = 0; i < SDIO_CMUX_NUM_CHANNELS; ++i) {
-		ch = &logical_ch[i];
-		bytes_written = 0;
-		mutex_lock(&ch->tx_lock);
-		while (!list_empty(&ch->tx_list)) {
-			list_elem = list_first_entry(&ch->tx_list,
-					     struct sdio_cmux_list_elem,
-					     list);
-			list_del(&list_elem->list);
-			mutex_unlock(&ch->tx_lock);
-
-			write_data = (void *)list_elem->cmux_pkt.hdr;
-			write_size = sizeof(struct sdio_cmux_hdr) +
-				(uint32_t)list_elem->cmux_pkt.hdr->pkt_len;
-
-			mutex_lock(&modem_reset_lock);
-			while (!(abort_tx) &&
-				((write_avail = sdio_write_avail(sdio_qmi_chl))
-						< write_size)) {
-				mutex_unlock(&modem_reset_lock);
-				pr_err("%s: sdio_write_avail %d bytes, "
-				       "write size %d bytes. Waiting...\n",
-					__func__, write_avail, write_size);
-				msleep(250);
-				mutex_lock(&modem_reset_lock);
-			}
-			while (!(abort_tx) &&
-				((r = sdio_write(sdio_qmi_chl,
-						write_data, write_size)) < 0)
-				&& (r != -ENODEV)
-				&& (write_retry++ < MAX_WRITE_RETRY)) {
-				mutex_unlock(&modem_reset_lock);
-				pr_err("%s: sdio_write failed with rc %d."
-				       "Retrying...", __func__, r);
-				msleep(250);
-				mutex_lock(&modem_reset_lock);
-			}
-			if (!r && !abort_tx) {
-				D("%s: sdio_write_completed %dbytes\n",
-				  __func__, write_size);
-				bytes_written += write_size;
-			} else if (r == -ENODEV) {
-				pr_err("%s: aborting_tx because sdio_write"
-				       " returned %d\n", __func__, r);
-				r = 0;
-				abort_tx = 1;
-			}
-			mutex_unlock(&modem_reset_lock);
-			kfree(list_elem->cmux_pkt.hdr);
-			kfree(list_elem);
-			mutex_lock(&write_lock);
-			bytes_to_write -= write_size;
-			mutex_unlock(&write_lock);
-			mutex_lock(&ch->tx_lock);
-		}
-		if (ch->write_done)
-			ch->write_done(NULL, bytes_written, ch->priv);
-		mutex_unlock(&ch->tx_lock);
-	}
-	return;
-}
-
-static void sdio_qmi_chl_notify(void *priv, unsigned event)
-{
-	if (event == SDIO_EVENT_DATA_READ_AVAIL) {
-		D("%s: Received SDIO_EVENT_DATA_READ_AVAIL\n", __func__);
-		queue_work(sdio_cdemux_wq, &sdio_cdemux_work);
-	}
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static int debug_tbl(char *buf, int max)
-{
-	int i = 0;
-	int j;
-
-	for (j = 0; j < SDIO_CMUX_NUM_CHANNELS; ++j) {
-		i += scnprintf(buf + i, max - i,
-			"ch%02d  local open=%s  remote open=%s\n",
-			j, logical_ch_is_local_open(j) ? "Y" : "N",
-			logical_ch_is_remote_open(j) ? "Y" : "N");
-	}
-
-	return i;
-}
-
-#define DEBUG_BUFMAX 4096
-static char debug_buffer[DEBUG_BUFMAX];
-
-static ssize_t debug_read(struct file *file, char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	int (*fill)(char *buf, int max) = file->private_data;
-	int bsize = fill(debug_buffer, DEBUG_BUFMAX);
-	return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
-}
-
-static int debug_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-
-static const struct file_operations debug_ops = {
-	.read = debug_read,
-	.open = debug_open,
-};
-
-static void debug_create(const char *name, mode_t mode,
-				struct dentry *dent,
-				int (*fill)(char *buf, int max))
-{
-	debugfs_create_file(name, mode, dent, fill, &debug_ops);
-}
-
-#endif
-
-static int sdio_cmux_probe(struct platform_device *pdev)
-{
-	int i, r;
-
-	mutex_lock(&probe_lock);
-	D("%s Begins\n", __func__);
-	if (sdio_cmux_inited) {
-		mutex_lock(&modem_reset_lock);
-		r =  sdio_open("SDIO_QMI", &sdio_qmi_chl, NULL,
-				sdio_qmi_chl_notify);
-		if (r < 0) {
-			mutex_unlock(&modem_reset_lock);
-			pr_err("%s: sdio_open() failed\n", __func__);
-			goto error0;
-		}
-		abort_tx = 0;
-		mutex_unlock(&modem_reset_lock);
-		mutex_unlock(&probe_lock);
-		return 0;
-	}
-
-	for (i = 0; i < SDIO_CMUX_NUM_CHANNELS; ++i)
-		sdio_cmux_ch_alloc(i);
-	INIT_LIST_HEAD(&temp_rx_list);
-
-	sdio_cmux_wq = create_singlethread_workqueue("sdio_cmux");
-	if (IS_ERR(sdio_cmux_wq)) {
-		pr_err("%s: create_singlethread_workqueue() ENOMEM\n",
-			__func__);
-		r = -ENOMEM;
-		goto error0;
-	}
-
-	sdio_cdemux_wq = create_singlethread_workqueue("sdio_cdemux");
-	if (IS_ERR(sdio_cdemux_wq)) {
-		pr_err("%s: create_singlethread_workqueue() ENOMEM\n",
-			__func__);
-		r = -ENOMEM;
-		goto error1;
-	}
-
-	r = sdio_open("SDIO_QMI", &sdio_qmi_chl, NULL, sdio_qmi_chl_notify);
-	if (r < 0) {
-		pr_err("%s: sdio_open() failed\n", __func__);
-		goto error2;
-	}
-
-	platform_device_register(&sdio_ctl_dev);
-	sdio_cmux_inited = 1;
-	D("SDIO Control MUX Driver Initialized.\n");
-	mutex_unlock(&probe_lock);
-	return 0;
-
-error2:
-	destroy_workqueue(sdio_cdemux_wq);
-error1:
-	destroy_workqueue(sdio_cmux_wq);
-error0:
-	mutex_unlock(&probe_lock);
-	return r;
-}
-
-static int sdio_cmux_remove(struct platform_device *pdev)
-{
-	int i;
-
-	mutex_lock(&modem_reset_lock);
-	abort_tx = 1;
-
-	for (i = 0; i < SDIO_CMUX_NUM_CHANNELS; ++i) {
-		mutex_lock(&logical_ch[i].lc_lock);
-		logical_ch[i].is_channel_reset = 1;
-		mutex_unlock(&logical_ch[i].lc_lock);
-		sdio_cmux_ch_clear_and_signal(i);
-	}
-	sdio_qmi_chl = NULL;
-	mutex_unlock(&modem_reset_lock);
-
-	return 0;
-}
-
-static struct platform_driver sdio_cmux_driver = {
-	.probe          = sdio_cmux_probe,
-	.remove         = sdio_cmux_remove,
-	.driver         = {
-			.name   = "SDIO_QMI",
-			.owner  = THIS_MODULE,
-	},
-};
-
-static int __init sdio_cmux_init(void)
-{
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *dent;
-
-	dent = debugfs_create_dir("sdio_cmux", 0);
-	if (!IS_ERR(dent))
-		debug_create("tbl", 0444, dent, debug_tbl);
-#endif
-
-	msm_sdio_cmux_debug_mask = 0;
-	return platform_driver_register(&sdio_cmux_driver);
-}
-
-module_init(sdio_cmux_init);
-MODULE_DESCRIPTION("MSM SDIO Control MUX");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/sdio_ctl.c b/arch/arm/mach-msm/sdio_ctl.c
deleted file mode 100644
index cacdce9..0000000
--- a/arch/arm/mach-msm/sdio_ctl.c
+++ /dev/null
@@ -1,575 +0,0 @@
-/* Copyright (c) 2010-2012, 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.
- */
-
-/*
- * SDIO Control Driver -- Provides a binary SDIO muxed control port
- *                       interface.
- */
-
-#include <linux/cdev.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/mutex.h>
-#include <linux/uaccess.h>
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <asm/ioctls.h>
-#include <linux/platform_device.h>
-#include <mach/msm_smd.h>
-#include <mach/sdio_al.h>
-#include <mach/sdio_cmux.h>
-#include "modem_notifier.h"
-#include <linux/slab.h>
-
-#define MAX_WRITE_RETRY 5
-#define MAGIC_NO_V1 0x33FC
-#define NUM_SDIO_CTL_PORTS 10
-#define DEVICE_NAME "sdioctl"
-#define MAX_BUF_SIZE 2048
-#define DEBUG
-
-static int msm_sdio_ctl_debug_mask;
-module_param_named(debug_mask, msm_sdio_ctl_debug_mask,
-		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-
-struct sdio_ctl_dev {
-	int id;
-	char name[9];
-	struct cdev cdev;
-	struct device *devicep;
-	struct mutex dev_lock;
-	int ref_count;
-
-	struct mutex rx_lock;
-	uint32_t read_avail;
-	struct list_head rx_list;
-
-	wait_queue_head_t read_wait_queue;
-	wait_queue_head_t write_wait_queue;
-} *sdio_ctl_devp[NUM_SDIO_CTL_PORTS];
-
-struct sdio_ctl_pkt {
-	int data_size;
-	void *data;
-};
-
-struct sdio_ctl_list_elem {
-	struct list_head list;
-	struct sdio_ctl_pkt ctl_pkt;
-};
-
-struct class *sdio_ctl_classp;
-static dev_t sdio_ctl_number;
-static uint32_t sdio_ctl_inited;
-
-enum {
-	MSM_SDIO_CTL_DEBUG = 1U << 0,
-	MSM_SDIO_CTL_DUMP_BUFFER = 1U << 1,
-};
-
-#if defined(DEBUG)
-#define D_DUMP_BUFFER(prestr, cnt, buf) \
-do { \
-	if (msm_sdio_ctl_debug_mask & MSM_SDIO_CTL_DUMP_BUFFER) { \
-		int i; \
-		pr_info("%s", prestr); \
-		for (i = 0; i < cnt; i++) \
-			pr_info("%.2x", buf[i]); \
-		pr_info("\n"); \
-	} \
-} while (0)
-
-#define D(x...) \
-do { \
-	if (msm_sdio_ctl_debug_mask & MSM_SDIO_CTL_DEBUG) \
-		pr_info(x); \
-} while (0)
-
-#else
-#define D_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
-#define D(x...) do {} while (0)
-#endif
-
-static uint32_t cmux_ch_id[] = {
-	SDIO_CMUX_DATA_CTL_0,
-	SDIO_CMUX_DATA_CTL_1,
-	SDIO_CMUX_DATA_CTL_2,
-	SDIO_CMUX_DATA_CTL_3,
-	SDIO_CMUX_DATA_CTL_4,
-	SDIO_CMUX_DATA_CTL_5,
-	SDIO_CMUX_DATA_CTL_6,
-	SDIO_CMUX_DATA_CTL_7,
-	SDIO_CMUX_USB_CTL_0,
-	SDIO_CMUX_CSVT_CTL_0
-};
-
-static int get_ctl_dev_index(int id)
-{
-	int dev_index;
-	for (dev_index = 0; dev_index < NUM_SDIO_CTL_PORTS; dev_index++) {
-		if (cmux_ch_id[dev_index] == id)
-			return dev_index;
-	}
-	return -ENODEV;
-}
-
-static void sdio_ctl_receive_cb(void *data, int size, void *priv)
-{
-	struct sdio_ctl_list_elem *list_elem = NULL;
-	int id = ((struct sdio_ctl_dev *)(priv))->id;
-	int dev_index;
-
-	if (id < 0 || id > cmux_ch_id[NUM_SDIO_CTL_PORTS - 1])
-		return;
-	dev_index = get_ctl_dev_index(id);
-	if (dev_index < 0) {
-		pr_err("%s: Ch%d is not exported to user-space\n",
-			__func__, id);
-		return;
-	}
-
-	if (!data || size <= 0) {
-		wake_up(&sdio_ctl_devp[dev_index]->read_wait_queue);
-		return;
-	}
-
-	list_elem = kmalloc(sizeof(struct sdio_ctl_list_elem), GFP_KERNEL);
-	if (!list_elem) {
-		pr_err("%s: list_elem alloc failed\n", __func__);
-		return;
-	}
-
-	list_elem->ctl_pkt.data = kmalloc(size, GFP_KERNEL);
-	if (!list_elem->ctl_pkt.data) {
-		pr_err("%s: list_elem->data alloc failed\n", __func__);
-		kfree(list_elem);
-		return;
-	}
-	memcpy(list_elem->ctl_pkt.data, data, size);
-	list_elem->ctl_pkt.data_size = size;
-	mutex_lock(&sdio_ctl_devp[dev_index]->rx_lock);
-	list_add_tail(&list_elem->list, &sdio_ctl_devp[dev_index]->rx_list);
-	sdio_ctl_devp[dev_index]->read_avail += size;
-	mutex_unlock(&sdio_ctl_devp[dev_index]->rx_lock);
-	wake_up(&sdio_ctl_devp[dev_index]->read_wait_queue);
-}
-
-static void sdio_ctl_write_done(void *data, int size, void *priv)
-{
-	int id = ((struct sdio_ctl_dev *)(priv))->id;
-	int dev_index;
-	if (id < 0 || id > cmux_ch_id[NUM_SDIO_CTL_PORTS - 1])
-		return;
-
-	dev_index = get_ctl_dev_index(id);
-	if (dev_index < 0) {
-		pr_err("%s: Ch%d is not exported to user-space\n",
-			__func__, id);
-		return;
-	}
-	wake_up(&sdio_ctl_devp[dev_index]->write_wait_queue);
-}
-
-static long sdio_ctl_ioctl(struct file *file, unsigned int cmd,
-					      unsigned long arg)
-{
-	int ret;
-	struct sdio_ctl_dev *sdio_ctl_devp;
-
-	sdio_ctl_devp = file->private_data;
-	if (!sdio_ctl_devp)
-		return -ENODEV;
-
-	switch (cmd) {
-	case TIOCMGET:
-		ret = sdio_cmux_tiocmget(sdio_ctl_devp->id);
-		break;
-	case TIOCMSET:
-		ret = sdio_cmux_tiocmset(sdio_ctl_devp->id, arg, ~arg);
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	return ret;
-}
-
-static unsigned int sdio_ctl_poll(struct file *file, poll_table *wait)
-{
-	struct sdio_ctl_dev *sdio_ctl_devp;
-	unsigned int mask = 0;
-
-	sdio_ctl_devp = file->private_data;
-	if (!sdio_ctl_devp) {
-		pr_err("%s: on a NULL device\n", __func__);
-		return POLLERR;
-	}
-
-	poll_wait(file, &sdio_ctl_devp->read_wait_queue, wait);
-	mutex_lock(&sdio_ctl_devp->rx_lock);
-	if (sdio_cmux_is_channel_reset(sdio_ctl_devp->id)) {
-		mutex_unlock(&sdio_ctl_devp->rx_lock);
-		pr_err("%s notifying reset for sdio_ctl_dev id:%d\n",
-			__func__, sdio_ctl_devp->id);
-		return POLLERR;
-	}
-
-	if (sdio_ctl_devp->read_avail > 0)
-		mask |= POLLIN | POLLRDNORM;
-
-	mutex_unlock(&sdio_ctl_devp->rx_lock);
-
-	return mask;
-}
-
-ssize_t sdio_ctl_read(struct file *file,
-		      char __user *buf,
-		      size_t count,
-		      loff_t *ppos)
-{
-	int r = 0, id, bytes_to_read;
-	struct sdio_ctl_dev *sdio_ctl_devp;
-	struct sdio_ctl_list_elem *list_elem = NULL;
-
-	sdio_ctl_devp = file->private_data;
-
-	if (!sdio_ctl_devp)
-		return -ENODEV;
-
-	D("%s: read from ch%d\n", __func__, sdio_ctl_devp->id);
-
-	id = sdio_ctl_devp->id;
-	mutex_lock(&sdio_ctl_devp->rx_lock);
-	while (sdio_ctl_devp->read_avail <= 0) {
-		mutex_unlock(&sdio_ctl_devp->rx_lock);
-		r = wait_event_interruptible(sdio_ctl_devp->read_wait_queue,
-					     sdio_ctl_devp->read_avail > 0 ||
-					     !is_remote_open(id));
-		if (sdio_cmux_is_channel_reset(id))
-			return -ENETRESET;
-
-		if (!is_remote_open(id))
-			return -ENODEV;
-
-		if (r < 0) {
-			/* qualify error message */
-			/* we get this anytime a signal comes in */
-			if (r != -ERESTARTSYS)
-				pr_err("ERROR:%s: wait_event_interruptible "
-				       "ret %i\n", __func__, r);
-			return r;
-		}
-		mutex_lock(&sdio_ctl_devp->rx_lock);
-	}
-
-	if (list_empty(&sdio_ctl_devp->rx_list)) {
-		mutex_unlock(&sdio_ctl_devp->rx_lock);
-		D("%s: Nothing in ch%d's rx_list\n", __func__,
-		  sdio_ctl_devp->id);
-		return -EAGAIN;
-	}
-
-	list_elem = list_first_entry(&sdio_ctl_devp->rx_list,
-				     struct sdio_ctl_list_elem, list);
-	bytes_to_read = (uint32_t)(list_elem->ctl_pkt.data_size);
-	if (bytes_to_read > count) {
-		mutex_unlock(&sdio_ctl_devp->rx_lock);
-		pr_err("%s: Packet size %d > buf size %d\n", __func__,
-			bytes_to_read, count);
-		return -ENOMEM;
-	}
-
-	if (copy_to_user(buf, list_elem->ctl_pkt.data, bytes_to_read)) {
-		mutex_unlock(&sdio_ctl_devp->rx_lock);
-		pr_err("%s: copy_to_user failed for ch%d\n", __func__,
-			sdio_ctl_devp->id);
-		return -EFAULT;
-	}
-	sdio_ctl_devp->read_avail -= bytes_to_read;
-	list_del(&list_elem->list);
-	kfree(list_elem->ctl_pkt.data);
-	kfree(list_elem);
-	mutex_unlock(&sdio_ctl_devp->rx_lock);
-	D("%s: Returning %d bytes to ch%d\n", __func__,
-			bytes_to_read, sdio_ctl_devp->id);
-	return bytes_to_read;
-}
-
-
-ssize_t sdio_ctl_write(struct file *file,
-		       const char __user *buf,
-		       size_t count,
-		       loff_t *ppos)
-{
-	int r = 0, id;
-	char *temp_buf;
-	struct sdio_ctl_dev *sdio_ctl_devp;
-
-	if (count <= 0)
-		return -EINVAL;
-
-	sdio_ctl_devp = file->private_data;
-	if (!sdio_ctl_devp)
-		return -ENODEV;
-
-	D("%s: writing %i bytes on ch%d\n",
-	  __func__, count, sdio_ctl_devp->id);
-	id = sdio_ctl_devp->id;
-	mutex_lock(&sdio_ctl_devp->dev_lock);
-	while (sdio_cmux_write_avail(id) < count) {
-		mutex_unlock(&sdio_ctl_devp->dev_lock);
-		r = wait_event_interruptible(sdio_ctl_devp->write_wait_queue,
-					     sdio_cmux_write_avail(id) >= count
-					     || !is_remote_open(id));
-
-		if (sdio_cmux_is_channel_reset(id))
-			return -ENETRESET;
-
-		if (!is_remote_open(id))
-			return -ENODEV;
-
-		if (r < 0) {
-			/* qualify error message */
-			/* we get this anytime a signal comes in */
-			if (r != -ERESTARTSYS)
-				pr_err("ERROR:%s: wait_event_interruptible "
-				       "ret %i\n", __func__, r);
-			return r;
-		}
-		mutex_lock(&sdio_ctl_devp->dev_lock);
-	}
-
-	temp_buf = kmalloc(count, GFP_KERNEL);
-	if (!temp_buf) {
-		mutex_unlock(&sdio_ctl_devp->dev_lock);
-		pr_err("%s: temp_buf alloc failed\n", __func__);
-		return -ENOMEM;
-	}
-
-	if (copy_from_user(temp_buf, buf, count)) {
-		mutex_unlock(&sdio_ctl_devp->dev_lock);
-		pr_err("%s: copy_from_user failed\n", __func__);
-		kfree(temp_buf);
-		return -EFAULT;
-	}
-
-	r = sdio_cmux_write(id, (void *)temp_buf, count);
-	kfree(temp_buf);
-	mutex_unlock(&sdio_ctl_devp->dev_lock);
-	return r;
-}
-
-
-int sdio_ctl_open(struct inode *inode, struct file *file)
-{
-	int r = 0;
-	struct sdio_ctl_dev *sdio_ctl_devp;
-
-	if (!sdio_ctl_inited)
-		return -EIO;
-
-	sdio_ctl_devp = container_of(inode->i_cdev, struct sdio_ctl_dev, cdev);
-
-	if (!sdio_ctl_devp)
-		return -ENODEV;
-
-	D("%s called on sdioctl%d device\n", __func__, sdio_ctl_devp->id);
-	r = sdio_cmux_open(sdio_ctl_devp->id, sdio_ctl_receive_cb,
-			   sdio_ctl_write_done, NULL,
-			   sdio_ctl_devp);
-	if (r < 0) {
-		pr_err("ERROR %s: sdio_cmux_open failed with rc %d\n",
-			__func__, r);
-		return r;
-	}
-
-	mutex_lock(&sdio_ctl_devp->dev_lock);
-	sdio_ctl_devp->ref_count++;
-	mutex_unlock(&sdio_ctl_devp->dev_lock);
-
-	file->private_data = sdio_ctl_devp;
-	return 0;
-}
-
-int sdio_ctl_release(struct inode *inode, struct file *file)
-{
-	struct sdio_ctl_dev *sdio_ctl_devp;
-	struct sdio_ctl_list_elem *list_elem = NULL;
-
-	sdio_ctl_devp = file->private_data;
-	if (!sdio_ctl_devp)
-		return -EINVAL;
-
-	D("%s called on sdioctl%d device\n", __func__, sdio_ctl_devp->id);
-
-	mutex_lock(&sdio_ctl_devp->dev_lock);
-	if (sdio_ctl_devp->ref_count > 0) {
-		sdio_ctl_devp->ref_count--;
-		if (!sdio_ctl_devp->ref_count) {
-			mutex_lock(&sdio_ctl_devp->rx_lock);
-			while (!list_empty(&sdio_ctl_devp->rx_list)) {
-				list_elem = list_first_entry(
-						&sdio_ctl_devp->rx_list,
-						struct sdio_ctl_list_elem,
-						list);
-				list_del(&list_elem->list);
-				kfree(list_elem->ctl_pkt.data);
-				kfree(list_elem);
-			}
-			sdio_ctl_devp->read_avail = 0;
-			mutex_unlock(&sdio_ctl_devp->rx_lock);
-			sdio_cmux_close(sdio_ctl_devp->id);
-		}
-	}
-	mutex_unlock(&sdio_ctl_devp->dev_lock);
-
-	file->private_data = NULL;
-	return 0;
-}
-
-static const struct file_operations sdio_ctl_fops = {
-	.owner = THIS_MODULE,
-	.open = sdio_ctl_open,
-	.release = sdio_ctl_release,
-	.read = sdio_ctl_read,
-	.write = sdio_ctl_write,
-	.poll = sdio_ctl_poll,
-	.unlocked_ioctl = sdio_ctl_ioctl,
-};
-
-static int sdio_ctl_probe(struct platform_device *pdev)
-{
-	int i;
-	int r;
-
-	pr_info("%s Begins\n", __func__);
-	for (i = 0; i < NUM_SDIO_CTL_PORTS; ++i) {
-		sdio_ctl_devp[i] = kzalloc(sizeof(struct sdio_ctl_dev),
-					GFP_KERNEL);
-		if (IS_ERR(sdio_ctl_devp[i])) {
-			pr_err("ERROR:%s kmalloc() ENOMEM\n", __func__);
-			r = -ENOMEM;
-			goto error0;
-		}
-
-		sdio_ctl_devp[i]->id = cmux_ch_id[i];
-		sdio_ctl_devp[i]->ref_count = 0;
-
-		mutex_init(&sdio_ctl_devp[i]->dev_lock);
-		init_waitqueue_head(&sdio_ctl_devp[i]->read_wait_queue);
-		init_waitqueue_head(&sdio_ctl_devp[i]->write_wait_queue);
-		mutex_init(&sdio_ctl_devp[i]->rx_lock);
-		INIT_LIST_HEAD(&sdio_ctl_devp[i]->rx_list);
-		sdio_ctl_devp[i]->read_avail = 0;
-	}
-
-	r = alloc_chrdev_region(&sdio_ctl_number, 0, NUM_SDIO_CTL_PORTS,
-				DEVICE_NAME);
-	if (IS_ERR_VALUE(r)) {
-		pr_err("ERROR:%s: alloc_chrdev_region() ret %i.\n",
-		       __func__, r);
-		goto error0;
-	}
-
-	sdio_ctl_classp = class_create(THIS_MODULE, DEVICE_NAME);
-	if (IS_ERR(sdio_ctl_classp)) {
-		pr_err("ERROR:%s: class_create() ENOMEM\n", __func__);
-		r = -ENOMEM;
-		goto error1;
-	}
-
-	for (i = 0; i < NUM_SDIO_CTL_PORTS; ++i) {
-		cdev_init(&sdio_ctl_devp[i]->cdev, &sdio_ctl_fops);
-		sdio_ctl_devp[i]->cdev.owner = THIS_MODULE;
-
-		r = cdev_add(&sdio_ctl_devp[i]->cdev, (sdio_ctl_number + i),
-			     1);
-
-		if (IS_ERR_VALUE(r)) {
-			pr_err("%s: cdev_add() ret %i\n", __func__, r);
-			kfree(sdio_ctl_devp[i]);
-			goto error2;
-		}
-
-		sdio_ctl_devp[i]->devicep =
-				device_create(sdio_ctl_classp, NULL,
-				      (sdio_ctl_number + i), NULL,
-				      DEVICE_NAME "%d", cmux_ch_id[i]);
-
-		if (IS_ERR(sdio_ctl_devp[i]->devicep)) {
-			pr_err("%s: device_create() ENOMEM\n", __func__);
-			r = -ENOMEM;
-			cdev_del(&sdio_ctl_devp[i]->cdev);
-			kfree(sdio_ctl_devp[i]);
-			goto error2;
-		}
-	}
-
-	sdio_ctl_inited = 1;
-	D("SDIO Control Port Driver Initialized.\n");
-	return 0;
-
-error2:
-	while (--i >= 0) {
-		cdev_del(&sdio_ctl_devp[i]->cdev);
-		device_destroy(sdio_ctl_classp,
-			       MKDEV(MAJOR(sdio_ctl_number), i));
-	}
-
-	class_destroy(sdio_ctl_classp);
-	i = NUM_SDIO_CTL_PORTS;
-error1:
-	unregister_chrdev_region(MAJOR(sdio_ctl_number), NUM_SDIO_CTL_PORTS);
-error0:
-	while (--i >= 0)
-		kfree(sdio_ctl_devp[i]);
-	return r;
-}
-
-static int sdio_ctl_remove(struct platform_device *pdev)
-{
-	int i;
-
-	for (i = 0; i < NUM_SDIO_CTL_PORTS; ++i) {
-		cdev_del(&sdio_ctl_devp[i]->cdev);
-		kfree(sdio_ctl_devp[i]);
-		device_destroy(sdio_ctl_classp,
-			       MKDEV(MAJOR(sdio_ctl_number), i));
-	}
-	class_destroy(sdio_ctl_classp);
-	unregister_chrdev_region(MAJOR(sdio_ctl_number), NUM_SDIO_CTL_PORTS);
-
-	return 0;
-}
-
-static struct platform_driver sdio_ctl_driver = {
-	.probe		= sdio_ctl_probe,
-	.remove		= sdio_ctl_remove,
-	.driver		= {
-			.name	= "SDIO_CTL",
-			.owner	= THIS_MODULE,
-	},
-};
-
-static int __init sdio_ctl_init(void)
-{
-	msm_sdio_ctl_debug_mask = 0;
-	return platform_driver_register(&sdio_ctl_driver);
-}
-
-module_init(sdio_ctl_init);
-MODULE_DESCRIPTION("MSM SDIO Control Port");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/sdio_dmux.c b/arch/arm/mach-msm/sdio_dmux.c
deleted file mode 100644
index c6d665d..0000000
--- a/arch/arm/mach-msm/sdio_dmux.c
+++ /dev/null
@@ -1,925 +0,0 @@
-/* Copyright (c) 2010-2011, 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.
- *
- */
-
-/*
- *  SDIO DMUX module.
- */
-
-#define DEBUG
-
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/wakelock.h>
-#include <linux/debugfs.h>
-#include <linux/smp.h>
-#include <linux/cpumask.h>
-
-#include <mach/sdio_al.h>
-#include <mach/sdio_dmux.h>
-
-#define SDIO_CH_LOCAL_OPEN       0x1
-#define SDIO_CH_REMOTE_OPEN      0x2
-#define SDIO_CH_IN_RESET         0x4
-
-#define SDIO_MUX_HDR_MAGIC_NO    0x33fc
-
-#define SDIO_MUX_HDR_CMD_DATA    0
-#define SDIO_MUX_HDR_CMD_OPEN    1
-#define SDIO_MUX_HDR_CMD_CLOSE   2
-
-#define LOW_WATERMARK            2
-#define HIGH_WATERMARK           4
-
-static int msm_sdio_dmux_debug_enable;
-module_param_named(debug_enable, msm_sdio_dmux_debug_enable,
-		   int, S_IRUGO | S_IWUSR | S_IWGRP);
-
-#if defined(DEBUG)
-static uint32_t sdio_dmux_read_cnt;
-static uint32_t sdio_dmux_write_cnt;
-static uint32_t sdio_dmux_write_cpy_cnt;
-static uint32_t sdio_dmux_write_cpy_bytes;
-
-#define DBG(x...) do {		                 \
-		if (msm_sdio_dmux_debug_enable)  \
-			pr_debug(x);	         \
-	} while (0)
-
-#define DBG_INC_READ_CNT(x) do {	                               \
-		sdio_dmux_read_cnt += (x);                             \
-		if (msm_sdio_dmux_debug_enable)                        \
-			pr_debug("%s: total read bytes %u\n",          \
-				 __func__, sdio_dmux_read_cnt);        \
-	} while (0)
-
-#define DBG_INC_WRITE_CNT(x)  do {	                               \
-		sdio_dmux_write_cnt += (x);                            \
-		if (msm_sdio_dmux_debug_enable)                        \
-			pr_debug("%s: total written bytes %u\n",       \
-				 __func__, sdio_dmux_write_cnt);       \
-	} while (0)
-
-#define DBG_INC_WRITE_CPY(x)  do {	                                     \
-		sdio_dmux_write_cpy_bytes += (x);                            \
-		sdio_dmux_write_cpy_cnt++;                                   \
-		if (msm_sdio_dmux_debug_enable)                              \
-			pr_debug("%s: total write copy cnt %u, bytes %u\n",  \
-				 __func__, sdio_dmux_write_cpy_cnt,          \
-				 sdio_dmux_write_cpy_bytes);                 \
-	} while (0)
-#else
-#define DBG(x...) do { } while (0)
-#define DBG_INC_READ_CNT(x...) do { } while (0)
-#define DBG_INC_WRITE_CNT(x...) do { } while (0)
-#define DBG_INC_WRITE_CPY(x...) do { } while (0)
-#endif
-
-struct sdio_ch_info {
-	uint32_t status;
-	void (*receive_cb)(void *, struct sk_buff *);
-	void (*write_done)(void *, struct sk_buff *);
-	void *priv;
-	spinlock_t lock;
-	int num_tx_pkts;
-	int use_wm;
-};
-
-static struct sk_buff_head sdio_mux_write_pool;
-static spinlock_t sdio_mux_write_lock;
-
-static struct sdio_channel *sdio_mux_ch;
-static struct sdio_ch_info sdio_ch[SDIO_DMUX_NUM_CHANNELS];
-struct wake_lock sdio_mux_ch_wakelock;
-static int sdio_mux_initialized;
-static int fatal_error;
-
-struct sdio_mux_hdr {
-	uint16_t magic_num;
-	uint8_t reserved;
-	uint8_t cmd;
-	uint8_t pad_len;
-	uint8_t ch_id;
-	uint16_t pkt_len;
-};
-
-struct sdio_partial_pkt_info {
-	uint32_t valid;
-	struct sk_buff *skb;
-	struct sdio_mux_hdr *hdr;
-};
-
-static void sdio_mux_read_data(struct work_struct *work);
-static void sdio_mux_write_data(struct work_struct *work);
-static void sdio_mux_send_open_cmd(uint32_t id);
-
-static DEFINE_MUTEX(sdio_mux_lock);
-static DECLARE_WORK(work_sdio_mux_read, sdio_mux_read_data);
-static DECLARE_WORK(work_sdio_mux_write, sdio_mux_write_data);
-static DECLARE_DELAYED_WORK(delayed_work_sdio_mux_write, sdio_mux_write_data);
-
-static struct workqueue_struct *sdio_mux_workqueue;
-static struct sdio_partial_pkt_info sdio_partial_pkt;
-
-#define sdio_ch_is_open(x)						\
-	(sdio_ch[(x)].status == (SDIO_CH_LOCAL_OPEN | SDIO_CH_REMOTE_OPEN))
-
-#define sdio_ch_is_local_open(x)			\
-	(sdio_ch[(x)].status & SDIO_CH_LOCAL_OPEN)
-
-#define sdio_ch_is_remote_open(x)			\
-	(sdio_ch[(x)].status & SDIO_CH_REMOTE_OPEN)
-
-#define sdio_ch_is_in_reset(x)			\
-	(sdio_ch[(x)].status & SDIO_CH_IN_RESET)
-
-static inline void skb_set_data(struct sk_buff *skb,
-				unsigned char *data,
-				unsigned int len)
-{
-	/* panic if tail > end */
-	skb->data = data;
-	skb->tail = skb->data + len;
-	skb->len  = len;
-	skb->truesize = len + sizeof(struct sk_buff);
-}
-
-static void sdio_mux_save_partial_pkt(struct sdio_mux_hdr *hdr,
-				      struct sk_buff *skb_mux)
-{
-	struct sk_buff *skb;
-
-	/* i think we can avoid cloning here */
-	skb =  skb_clone(skb_mux, GFP_KERNEL);
-	if (!skb) {
-		pr_err("%s: cannot clone skb\n", __func__);
-		return;
-	}
-
-	/* protect? */
-	skb_set_data(skb, (unsigned char *)hdr,
-		     skb->tail - (unsigned char *)hdr);
-	sdio_partial_pkt.skb = skb;
-	sdio_partial_pkt.valid = 1;
-	DBG("%s: head %p data %p tail %p end %p len %d\n", __func__,
-	    skb->head, skb->data, skb->tail, skb->end, skb->len);
-	return;
-}
-
-static void *handle_sdio_mux_data(struct sdio_mux_hdr *hdr,
-				  struct sk_buff *skb_mux)
-{
-	struct sk_buff *skb;
-	void *rp = (void *)hdr;
-	unsigned long flags;
-
-	/* protect? */
-	rp += sizeof(*hdr);
-	if (rp < (void *)skb_mux->tail)
-		rp += (hdr->pkt_len + hdr->pad_len);
-
-	if (rp > (void *)skb_mux->tail) {
-		/* partial packet */
-		sdio_mux_save_partial_pkt(hdr, skb_mux);
-		goto packet_done;
-	}
-
-	DBG("%s: hdr %p next %p tail %p pkt_size %d\n",
-	    __func__, hdr, rp, skb_mux->tail, hdr->pkt_len + hdr->pad_len);
-
-	skb =  skb_clone(skb_mux, GFP_KERNEL);
-	if (!skb) {
-		pr_err("%s: cannot clone skb\n", __func__);
-		goto packet_done;
-	}
-
-	skb_set_data(skb, (unsigned char *)(hdr + 1), hdr->pkt_len);
-	DBG("%s: head %p data %p tail %p end %p len %d\n",
-	    __func__, skb->head, skb->data, skb->tail, skb->end, skb->len);
-
-	/* probably we should check channel status */
-	/* discard packet early if local side not open */
-	spin_lock_irqsave(&sdio_ch[hdr->ch_id].lock, flags);
-	if (sdio_ch[hdr->ch_id].receive_cb)
-		sdio_ch[hdr->ch_id].receive_cb(sdio_ch[hdr->ch_id].priv, skb);
-	else
-		dev_kfree_skb_any(skb);
-	spin_unlock_irqrestore(&sdio_ch[hdr->ch_id].lock, flags);
-
-packet_done:
-	return rp;
-}
-
-static void *handle_sdio_mux_command(struct sdio_mux_hdr *hdr,
-				     struct sk_buff *skb_mux)
-{
-	void *rp;
-	unsigned long flags;
-	int send_open = 0;
-
-	DBG("%s: cmd %d ch %d\n", __func__, hdr->cmd, hdr->ch_id);
-	switch (hdr->cmd) {
-	case SDIO_MUX_HDR_CMD_DATA:
-		rp = handle_sdio_mux_data(hdr, skb_mux);
-		break;
-	case SDIO_MUX_HDR_CMD_OPEN:
-		spin_lock_irqsave(&sdio_ch[hdr->ch_id].lock, flags);
-		sdio_ch[hdr->ch_id].status |= SDIO_CH_REMOTE_OPEN;
-		sdio_ch[hdr->ch_id].num_tx_pkts = 0;
-
-		if (sdio_ch_is_in_reset(hdr->ch_id)) {
-			DBG("%s: in reset - sending open cmd\n", __func__);
-			sdio_ch[hdr->ch_id].status &= ~SDIO_CH_IN_RESET;
-			send_open = 1;
-		}
-
-		/* notify client so it can update its status */
-		if (sdio_ch[hdr->ch_id].receive_cb)
-			sdio_ch[hdr->ch_id].receive_cb(
-					sdio_ch[hdr->ch_id].priv, NULL);
-
-		if (sdio_ch[hdr->ch_id].write_done)
-			sdio_ch[hdr->ch_id].write_done(
-					sdio_ch[hdr->ch_id].priv, NULL);
-		spin_unlock_irqrestore(&sdio_ch[hdr->ch_id].lock, flags);
-		rp = hdr + 1;
-		if (send_open)
-			sdio_mux_send_open_cmd(hdr->ch_id);
-
-		break;
-	case SDIO_MUX_HDR_CMD_CLOSE:
-		/* probably should drop pending write */
-		spin_lock_irqsave(&sdio_ch[hdr->ch_id].lock, flags);
-		sdio_ch[hdr->ch_id].status &= ~SDIO_CH_REMOTE_OPEN;
-		spin_unlock_irqrestore(&sdio_ch[hdr->ch_id].lock, flags);
-		rp = hdr + 1;
-		break;
-	default:
-		rp = hdr + 1;
-	}
-
-	return rp;
-}
-
-static void *handle_sdio_partial_pkt(struct sk_buff *skb_mux)
-{
-	struct sk_buff *p_skb;
-	struct sdio_mux_hdr *p_hdr;
-	void *ptr, *rp = skb_mux->data;
-
-	/* protoect? */
-	if (sdio_partial_pkt.valid) {
-		p_skb = sdio_partial_pkt.skb;
-
-		ptr = skb_push(skb_mux, p_skb->len);
-		memcpy(ptr, p_skb->data, p_skb->len);
-		sdio_partial_pkt.skb = NULL;
-		sdio_partial_pkt.valid = 0;
-		dev_kfree_skb_any(p_skb);
-
-		DBG("%s: head %p data %p tail %p end %p len %d\n", __func__,
-		    skb_mux->head, skb_mux->data, skb_mux->tail,
-		    skb_mux->end, skb_mux->len);
-
-		p_hdr = (struct sdio_mux_hdr *)skb_mux->data;
-		rp = handle_sdio_mux_command(p_hdr, skb_mux);
-	}
-	return rp;
-}
-
-static void sdio_mux_read_data(struct work_struct *work)
-{
-	struct sk_buff *skb_mux;
-	void *ptr = 0;
-	int sz, rc, len = 0;
-	struct sdio_mux_hdr *hdr;
-	static int workqueue_pinned;
-
-	if (!workqueue_pinned) {
-		struct cpumask cpus;
-
-		cpumask_clear(&cpus);
-		cpumask_set_cpu(0, &cpus);
-
-		if (sched_setaffinity(current->pid, &cpus))
-			pr_err("%s: sdio_dmux set CPU affinity failed\n",
-					__func__);
-		workqueue_pinned = 1;
-	}
-
-	DBG("%s: reading\n", __func__);
-	/* should probably have a separate read lock */
-	mutex_lock(&sdio_mux_lock);
-	sz = sdio_read_avail(sdio_mux_ch);
-	DBG("%s: read avail %d\n", __func__, sz);
-	if (sz <= 0) {
-		if (sz)
-			pr_err("%s: read avail failed %d\n", __func__, sz);
-		mutex_unlock(&sdio_mux_lock);
-		return;
-	}
-
-	/* net_ip_aling is probably not required */
-	if (sdio_partial_pkt.valid)
-		len = sdio_partial_pkt.skb->len;
-
-	/* If allocation fails attempt to get a smaller chunk of mem */
-	do {
-		skb_mux = __dev_alloc_skb(sz + NET_IP_ALIGN + len, GFP_KERNEL);
-		if (skb_mux)
-			break;
-
-		pr_err("%s: cannot allocate skb of size:%d + "
-			"%d (NET_SKB_PAD)\n", __func__,
-			sz + NET_IP_ALIGN + len, NET_SKB_PAD);
-		/* the skb structure adds NET_SKB_PAD bytes to the memory
-		 * request, which may push the actual request above PAGE_SIZE
-		 * in that case, we need to iterate one more time to make sure
-		 * we get the memory request under PAGE_SIZE
-		 */
-		if (sz + NET_IP_ALIGN + len + NET_SKB_PAD <= PAGE_SIZE) {
-			pr_err("%s: allocation failed\n", __func__);
-			mutex_unlock(&sdio_mux_lock);
-			return;
-		}
-		sz /= 2;
-	} while (1);
-
-	skb_reserve(skb_mux, NET_IP_ALIGN + len);
-	ptr = skb_put(skb_mux, sz);
-
-	/* half second wakelock is fine? */
-	wake_lock_timeout(&sdio_mux_ch_wakelock, HZ / 2);
-	rc = sdio_read(sdio_mux_ch, ptr, sz);
-	DBG("%s: read %d\n", __func__, rc);
-	if (rc) {
-		pr_err("%s: sdio read failed %d\n", __func__, rc);
-		dev_kfree_skb_any(skb_mux);
-		mutex_unlock(&sdio_mux_lock);
-		queue_work(sdio_mux_workqueue, &work_sdio_mux_read);
-		return;
-	}
-	mutex_unlock(&sdio_mux_lock);
-
-	DBG_INC_READ_CNT(sz);
-	DBG("%s: head %p data %p tail %p end %p len %d\n", __func__,
-	    skb_mux->head, skb_mux->data, skb_mux->tail,
-	    skb_mux->end, skb_mux->len);
-
-	/* move to a separate function */
-	/* probably do skb_pull instead of pointer adjustment */
-	hdr = handle_sdio_partial_pkt(skb_mux);
-	while ((void *)hdr < (void *)skb_mux->tail) {
-
-		if (((void *)hdr + sizeof(*hdr)) > (void *)skb_mux->tail) {
-			/* handle partial header */
-			sdio_mux_save_partial_pkt(hdr, skb_mux);
-			break;
-		}
-
-		if (hdr->magic_num != SDIO_MUX_HDR_MAGIC_NO) {
-			pr_err("%s: packet error\n", __func__);
-			break;
-		}
-
-		hdr = handle_sdio_mux_command(hdr, skb_mux);
-	}
-	dev_kfree_skb_any(skb_mux);
-
-	DBG("%s: read done\n", __func__);
-	queue_work(sdio_mux_workqueue, &work_sdio_mux_read);
-}
-
-static int sdio_mux_write(struct sk_buff *skb)
-{
-	int rc, sz;
-
-	mutex_lock(&sdio_mux_lock);
-	sz = sdio_write_avail(sdio_mux_ch);
-	DBG("%s: avail %d len %d\n", __func__, sz, skb->len);
-	if (skb->len <= sz) {
-		rc = sdio_write(sdio_mux_ch, skb->data, skb->len);
-		DBG("%s: write returned %d\n", __func__, rc);
-		if (rc == 0)
-			DBG_INC_WRITE_CNT(skb->len);
-	} else
-		rc = -ENOMEM;
-
-	mutex_unlock(&sdio_mux_lock);
-	return rc;
-}
-
-static int sdio_mux_write_cmd(void *data, uint32_t len)
-{
-	int avail, rc;
-	for (;;) {
-		mutex_lock(&sdio_mux_lock);
-		avail = sdio_write_avail(sdio_mux_ch);
-		DBG("%s: avail %d len %d\n", __func__, avail, len);
-		if (avail >= len) {
-			rc = sdio_write(sdio_mux_ch, data, len);
-			DBG("%s: write returned %d\n", __func__, rc);
-			if (!rc) {
-				DBG_INC_WRITE_CNT(len);
-				break;
-			}
-		}
-		mutex_unlock(&sdio_mux_lock);
-		msleep(250);
-	}
-	mutex_unlock(&sdio_mux_lock);
-	return 0;
-}
-
-static void sdio_mux_send_open_cmd(uint32_t id)
-{
-	struct sdio_mux_hdr hdr = {
-		.magic_num = SDIO_MUX_HDR_MAGIC_NO,
-		.cmd = SDIO_MUX_HDR_CMD_OPEN,
-		.reserved = 0,
-		.ch_id = id,
-		.pkt_len = 0,
-		.pad_len = 0
-	};
-
-	sdio_mux_write_cmd((void *)&hdr, sizeof(hdr));
-}
-
-static void sdio_mux_write_data(struct work_struct *work)
-{
-	int rc, reschedule = 0;
-	int notify = 0;
-	struct sk_buff *skb;
-	unsigned long flags;
-	int avail;
-	int ch_id;
-
-	spin_lock_irqsave(&sdio_mux_write_lock, flags);
-	while ((skb = __skb_dequeue(&sdio_mux_write_pool))) {
-		ch_id = ((struct sdio_mux_hdr *)skb->data)->ch_id;
-
-		avail = sdio_write_avail(sdio_mux_ch);
-		if (avail < skb->len) {
-			/* we may have to wait for write avail
-			 * notification from sdio al
-			 */
-			DBG("%s: sdio_write_avail(%d) < skb->len(%d)\n",
-					__func__, avail, skb->len);
-
-			reschedule = 1;
-			break;
-		}
-		spin_unlock_irqrestore(&sdio_mux_write_lock, flags);
-		rc = sdio_mux_write(skb);
-		spin_lock_irqsave(&sdio_mux_write_lock, flags);
-		if (rc == 0) {
-
-			spin_lock(&sdio_ch[ch_id].lock);
-			sdio_ch[ch_id].num_tx_pkts--;
-			spin_unlock(&sdio_ch[ch_id].lock);
-
-			if (sdio_ch[ch_id].write_done)
-				sdio_ch[ch_id].write_done(
-						sdio_ch[ch_id].priv, skb);
-			else
-				dev_kfree_skb_any(skb);
-		} else if (rc == -EAGAIN || rc == -ENOMEM) {
-			/* recoverable error - retry again later */
-			reschedule = 1;
-			break;
-		} else if (rc == -ENODEV) {
-			/*
-			 * sdio_al suffered some kind of fatal error
-			 * prevent future writes and clean up pending ones
-			 */
-			fatal_error = 1;
-			do {
-				ch_id = ((struct sdio_mux_hdr *)
-						skb->data)->ch_id;
-				spin_lock(&sdio_ch[ch_id].lock);
-				sdio_ch[ch_id].num_tx_pkts--;
-				spin_unlock(&sdio_ch[ch_id].lock);
-				dev_kfree_skb_any(skb);
-			} while ((skb = __skb_dequeue(&sdio_mux_write_pool)));
-			spin_unlock_irqrestore(&sdio_mux_write_lock, flags);
-			return;
-		} else {
-			/* unknown error condition - drop the
-			 * skb and reschedule for the
-			 * other skb's
-			 */
-			pr_err("%s: sdio_mux_write error %d"
-				   " for ch %d, skb=%p\n",
-				__func__, rc, ch_id, skb);
-			notify = 1;
-			break;
-		}
-	}
-
-	if (reschedule) {
-		if (sdio_ch_is_in_reset(ch_id)) {
-			notify = 1;
-		} else {
-			__skb_queue_head(&sdio_mux_write_pool, skb);
-			queue_delayed_work(sdio_mux_workqueue,
-					&delayed_work_sdio_mux_write,
-					msecs_to_jiffies(250)
-					);
-		}
-	}
-
-	if (notify) {
-		spin_lock(&sdio_ch[ch_id].lock);
-		sdio_ch[ch_id].num_tx_pkts--;
-		spin_unlock(&sdio_ch[ch_id].lock);
-
-		if (sdio_ch[ch_id].write_done)
-			sdio_ch[ch_id].write_done(
-				sdio_ch[ch_id].priv, skb);
-		else
-			dev_kfree_skb_any(skb);
-	}
-	spin_unlock_irqrestore(&sdio_mux_write_lock, flags);
-}
-
-int msm_sdio_is_channel_in_reset(uint32_t id)
-{
-	int rc = 0;
-
-	if (id >= SDIO_DMUX_NUM_CHANNELS)
-		return -EINVAL;
-
-	if (sdio_ch_is_in_reset(id))
-		rc = 1;
-
-	return rc;
-}
-
-int msm_sdio_dmux_write(uint32_t id, struct sk_buff *skb)
-{
-	int rc = 0;
-	struct sdio_mux_hdr *hdr;
-	unsigned long flags;
-	struct sk_buff *new_skb;
-
-	if (id >= SDIO_DMUX_NUM_CHANNELS)
-		return -EINVAL;
-	if (!skb)
-		return -EINVAL;
-	if (!sdio_mux_initialized)
-		return -ENODEV;
-	if (fatal_error)
-		return -ENODEV;
-
-	DBG("%s: writing to ch %d len %d\n", __func__, id, skb->len);
-	spin_lock_irqsave(&sdio_ch[id].lock, flags);
-	if (sdio_ch_is_in_reset(id)) {
-		spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-		pr_err("%s: port is in reset: %d\n", __func__,
-				sdio_ch[id].status);
-		return -ENETRESET;
-	}
-	if (!sdio_ch_is_local_open(id)) {
-		spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-		pr_err("%s: port not open: %d\n", __func__, sdio_ch[id].status);
-		return -ENODEV;
-	}
-	if (sdio_ch[id].use_wm &&
-			(sdio_ch[id].num_tx_pkts >= HIGH_WATERMARK)) {
-		spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-		pr_err("%s: watermark exceeded: %d\n", __func__, id);
-		return -EAGAIN;
-	}
-	spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-
-	spin_lock_irqsave(&sdio_mux_write_lock, flags);
-	/* if skb do not have any tailroom for padding,
-	   copy the skb into a new expanded skb */
-	if ((skb->len & 0x3) && (skb_tailroom(skb) < (4 - (skb->len & 0x3)))) {
-		/* revisit, probably dev_alloc_skb and memcpy is effecient */
-		new_skb = skb_copy_expand(skb, skb_headroom(skb),
-					  4 - (skb->len & 0x3), GFP_ATOMIC);
-		if (new_skb == NULL) {
-			pr_err("%s: cannot allocate skb\n", __func__);
-			rc = -ENOMEM;
-			goto write_done;
-		}
-		dev_kfree_skb_any(skb);
-		skb = new_skb;
-		DBG_INC_WRITE_CPY(skb->len);
-	}
-
-	hdr = (struct sdio_mux_hdr *)skb_push(skb, sizeof(struct sdio_mux_hdr));
-
-	/* caller should allocate for hdr and padding
-	   hdr is fine, padding is tricky */
-	hdr->magic_num = SDIO_MUX_HDR_MAGIC_NO;
-	hdr->cmd = SDIO_MUX_HDR_CMD_DATA;
-	hdr->reserved = 0;
-	hdr->ch_id = id;
-	hdr->pkt_len = skb->len - sizeof(struct sdio_mux_hdr);
-	if (skb->len & 0x3)
-		skb_put(skb, 4 - (skb->len & 0x3));
-
-	hdr->pad_len = skb->len - (sizeof(struct sdio_mux_hdr) + hdr->pkt_len);
-
-	DBG("%s: data %p, tail %p skb len %d pkt len %d pad len %d\n",
-	    __func__, skb->data, skb->tail, skb->len,
-	    hdr->pkt_len, hdr->pad_len);
-	__skb_queue_tail(&sdio_mux_write_pool, skb);
-
-	spin_lock(&sdio_ch[id].lock);
-	sdio_ch[id].num_tx_pkts++;
-	spin_unlock(&sdio_ch[id].lock);
-
-	queue_work(sdio_mux_workqueue, &work_sdio_mux_write);
-
-write_done:
-	spin_unlock_irqrestore(&sdio_mux_write_lock, flags);
-	return rc;
-}
-
-int msm_sdio_dmux_open(uint32_t id, void *priv,
-			void (*receive_cb)(void *, struct sk_buff *),
-			void (*write_done)(void *, struct sk_buff *))
-{
-	unsigned long flags;
-
-	DBG("%s: opening ch %d\n", __func__, id);
-	if (!sdio_mux_initialized)
-		return -ENODEV;
-	if (id >= SDIO_DMUX_NUM_CHANNELS)
-		return -EINVAL;
-
-	spin_lock_irqsave(&sdio_ch[id].lock, flags);
-	if (sdio_ch_is_local_open(id)) {
-		pr_info("%s: Already opened %d\n", __func__, id);
-		spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-		goto open_done;
-	}
-
-	sdio_ch[id].receive_cb = receive_cb;
-	sdio_ch[id].write_done = write_done;
-	sdio_ch[id].priv = priv;
-	sdio_ch[id].status |= SDIO_CH_LOCAL_OPEN;
-	sdio_ch[id].num_tx_pkts = 0;
-	sdio_ch[id].use_wm = 0;
-	spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-
-	sdio_mux_send_open_cmd(id);
-
-open_done:
-	pr_info("%s: opened ch %d\n", __func__, id);
-	return 0;
-}
-
-int msm_sdio_dmux_close(uint32_t id)
-{
-	struct sdio_mux_hdr hdr;
-	unsigned long flags;
-
-	if (id >= SDIO_DMUX_NUM_CHANNELS)
-		return -EINVAL;
-	DBG("%s: closing ch %d\n", __func__, id);
-	if (!sdio_mux_initialized)
-		return -ENODEV;
-	spin_lock_irqsave(&sdio_ch[id].lock, flags);
-
-	sdio_ch[id].receive_cb = NULL;
-	sdio_ch[id].priv = NULL;
-	sdio_ch[id].status &= ~SDIO_CH_LOCAL_OPEN;
-	sdio_ch[id].status &= ~SDIO_CH_IN_RESET;
-	spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-
-	hdr.magic_num = SDIO_MUX_HDR_MAGIC_NO;
-	hdr.cmd = SDIO_MUX_HDR_CMD_CLOSE;
-	hdr.reserved = 0;
-	hdr.ch_id = id;
-	hdr.pkt_len = 0;
-	hdr.pad_len = 0;
-
-	sdio_mux_write_cmd((void *)&hdr, sizeof(hdr));
-
-	pr_info("%s: closed ch %d\n", __func__, id);
-	return 0;
-}
-
-static void sdio_mux_notify(void *_dev, unsigned event)
-{
-	DBG("%s: event %d notified\n", __func__, event);
-
-	/* write avail may not be enouogh for a packet, but should be fine */
-	if ((event == SDIO_EVENT_DATA_WRITE_AVAIL) &&
-	    sdio_write_avail(sdio_mux_ch))
-		queue_work(sdio_mux_workqueue, &work_sdio_mux_write);
-
-	if ((event == SDIO_EVENT_DATA_READ_AVAIL) &&
-	    sdio_read_avail(sdio_mux_ch))
-		queue_work(sdio_mux_workqueue, &work_sdio_mux_read);
-}
-
-int msm_sdio_dmux_is_ch_full(uint32_t id)
-{
-	unsigned long flags;
-	int ret;
-
-	if (id >= SDIO_DMUX_NUM_CHANNELS)
-		return -EINVAL;
-
-	spin_lock_irqsave(&sdio_ch[id].lock, flags);
-	sdio_ch[id].use_wm = 1;
-	ret = sdio_ch[id].num_tx_pkts >= HIGH_WATERMARK;
-	DBG("%s: ch %d num tx pkts=%d, HWM=%d\n", __func__,
-			id, sdio_ch[id].num_tx_pkts, ret);
-	if (!sdio_ch_is_local_open(id)) {
-		ret = -ENODEV;
-		pr_err("%s: port not open: %d\n", __func__, sdio_ch[id].status);
-	}
-	spin_unlock_irqrestore(&sdio_ch[id].lock, flags);
-
-	return ret;
-}
-
-int msm_sdio_dmux_is_ch_low(uint32_t id)
-{
-	int ret;
-
-	if (id >= SDIO_DMUX_NUM_CHANNELS)
-		return -EINVAL;
-
-	sdio_ch[id].use_wm = 1;
-	ret = sdio_ch[id].num_tx_pkts <= LOW_WATERMARK;
-	DBG("%s: ch %d num tx pkts=%d, LWM=%d\n", __func__,
-			id, sdio_ch[id].num_tx_pkts, ret);
-	if (!sdio_ch_is_local_open(id)) {
-		ret = -ENODEV;
-		pr_err("%s: port not open: %d\n", __func__, sdio_ch[id].status);
-	}
-
-	return ret;
-}
-
-#ifdef CONFIG_DEBUG_FS
-
-static int debug_tbl(char *buf, int max)
-{
-	int i = 0;
-	int j;
-
-	for (j = 0; j < SDIO_DMUX_NUM_CHANNELS; ++j) {
-		i += scnprintf(buf + i, max - i,
-			"ch%02d  local open=%s  remote open=%s\n",
-			j, sdio_ch_is_local_open(j) ? "Y" : "N",
-			sdio_ch_is_remote_open(j) ? "Y" : "N");
-	}
-
-	return i;
-}
-
-#define DEBUG_BUFMAX 4096
-static char debug_buffer[DEBUG_BUFMAX];
-
-static ssize_t debug_read(struct file *file, char __user *buf,
-				size_t count, loff_t *ppos)
-{
-	int (*fill)(char *buf, int max) = file->private_data;
-	int bsize = fill(debug_buffer, DEBUG_BUFMAX);
-	return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
-}
-
-static int debug_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-
-static const struct file_operations debug_ops = {
-	.read = debug_read,
-	.open = debug_open,
-};
-
-static void debug_create(const char *name, mode_t mode,
-				struct dentry *dent,
-				int (*fill)(char *buf, int max))
-{
-	debugfs_create_file(name, mode, dent, fill, &debug_ops);
-}
-
-#endif
-
-static int sdio_dmux_probe(struct platform_device *pdev)
-{
-	int rc;
-
-	DBG("%s probe called\n", __func__);
-
-	if (!sdio_mux_initialized) {
-		sdio_mux_workqueue = create_singlethread_workqueue("sdio_dmux");
-		if (!sdio_mux_workqueue)
-			return -ENOMEM;
-
-		skb_queue_head_init(&sdio_mux_write_pool);
-		spin_lock_init(&sdio_mux_write_lock);
-
-		for (rc = 0; rc < SDIO_DMUX_NUM_CHANNELS; ++rc)
-			spin_lock_init(&sdio_ch[rc].lock);
-
-
-		wake_lock_init(&sdio_mux_ch_wakelock, WAKE_LOCK_SUSPEND,
-				   "sdio_dmux");
-	}
-
-	rc = sdio_open("SDIO_RMNT", &sdio_mux_ch, NULL, sdio_mux_notify);
-	if (rc < 0) {
-		pr_err("%s: sido open failed %d\n", __func__, rc);
-		wake_lock_destroy(&sdio_mux_ch_wakelock);
-		destroy_workqueue(sdio_mux_workqueue);
-		sdio_mux_initialized = 0;
-		return rc;
-	}
-
-	fatal_error = 0;
-	sdio_mux_initialized = 1;
-	return 0;
-}
-
-static int sdio_dmux_remove(struct platform_device *pdev)
-{
-	int i;
-	unsigned long ch_lock_flags;
-	unsigned long write_lock_flags;
-	struct sk_buff *skb;
-
-	DBG("%s remove called\n", __func__);
-	if (!sdio_mux_initialized)
-		return 0;
-
-	/* set reset state for any open channels */
-	for (i = 0; i < SDIO_DMUX_NUM_CHANNELS; ++i) {
-		spin_lock_irqsave(&sdio_ch[i].lock, ch_lock_flags);
-		if (sdio_ch_is_open(i)) {
-			sdio_ch[i].status |= SDIO_CH_IN_RESET;
-			sdio_ch[i].status &= ~SDIO_CH_REMOTE_OPEN;
-
-			/* notify client so it can update its status */
-			if (sdio_ch[i].receive_cb)
-				sdio_ch[i].receive_cb(
-						sdio_ch[i].priv, NULL);
-		}
-		spin_unlock_irqrestore(&sdio_ch[i].lock, ch_lock_flags);
-	}
-
-	/* cancel any pending writes */
-	spin_lock_irqsave(&sdio_mux_write_lock, write_lock_flags);
-	while ((skb = __skb_dequeue(&sdio_mux_write_pool))) {
-		i = ((struct sdio_mux_hdr *)skb->data)->ch_id;
-		if (sdio_ch[i].write_done)
-			sdio_ch[i].write_done(
-					sdio_ch[i].priv, skb);
-		else
-			dev_kfree_skb_any(skb);
-	}
-	spin_unlock_irqrestore(&sdio_mux_write_lock,
-			write_lock_flags);
-
-	return 0;
-}
-
-static struct platform_driver sdio_dmux_driver = {
-	.probe		= sdio_dmux_probe,
-	.remove   = sdio_dmux_remove,
-	.driver		= {
-		.name	= "SDIO_RMNT",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init sdio_dmux_init(void)
-{
-#ifdef CONFIG_DEBUG_FS
-	struct dentry *dent;
-
-	dent = debugfs_create_dir("sdio_dmux", 0);
-	if (!IS_ERR(dent))
-		debug_create("tbl", 0444, dent, debug_tbl);
-#endif
-	return platform_driver_register(&sdio_dmux_driver);
-}
-
-module_init(sdio_dmux_init);
-MODULE_DESCRIPTION("MSM SDIO DMUX");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/sdio_smem.c b/arch/arm/mach-msm/sdio_smem.c
deleted file mode 100644
index edc0d23..0000000
--- a/arch/arm/mach-msm/sdio_smem.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/* Copyright (c) 2010-2011, 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.
- */
-
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/module.h>
-#include <mach/sdio_al.h>
-#include <mach/sdio_smem.h>
-
-static void sdio_smem_read(struct work_struct *work);
-
-static struct sdio_channel *channel;
-static struct workqueue_struct *workq;
-static DECLARE_WORK(work_read, sdio_smem_read);
-static DECLARE_WAIT_QUEUE_HEAD(waitq);
-static int bytes_avail;
-static int sdio_ch_opened;
-
-static void sdio_smem_release(struct device *dev)
-{
-	pr_debug("sdio smem released\n");
-}
-
-static struct sdio_smem_client client;
-
-static void sdio_smem_read(struct work_struct *work)
-{
-	int err;
-	int read_avail;
-	char *data = client.buf;
-
-	if (!sdio_ch_opened)
-		return;
-
-	read_avail = sdio_read_avail(channel);
-	if (read_avail > bytes_avail ||
-		read_avail < 0) {
-		pr_err("Error: read_avail=%d bytes_avail=%d\n",
-			read_avail, bytes_avail);
-		goto read_err;
-	}
-
-	if (read_avail == 0)
-		return;
-
-	err = sdio_read(channel,
-			&data[client.size - bytes_avail],
-			read_avail);
-	if (err) {
-		pr_err("sdio_read error (%d)", err);
-		goto read_err;
-	}
-
-	bytes_avail -= read_avail;
-	pr_debug("read %d bytes (bytes_avail = %d)\n",
-			read_avail, bytes_avail);
-
-	if (!bytes_avail) {
-		bytes_avail = client.size;
-		err = client.cb_func(SDIO_SMEM_EVENT_READ_DONE);
-	}
-	if (err)
-		pr_err("error (%d) on callback\n", err);
-
-	return;
-
-read_err:
-	if (sdio_ch_opened)
-		client.cb_func(SDIO_SMEM_EVENT_READ_ERR);
-	return;
-}
-
-static void sdio_smem_notify(void *priv, unsigned event)
-{
-	pr_debug("%d event received\n", event);
-
-	if (event == SDIO_EVENT_DATA_READ_AVAIL ||
-	    event == SDIO_EVENT_DATA_WRITE_AVAIL)
-		queue_work(workq, &work_read);
-}
-
-int sdio_smem_register_client(void)
-{
-	int err = 0;
-
-	if (!client.buf || !client.size || !client.cb_func)
-		return -EINVAL;
-
-	pr_debug("buf = %p\n", client.buf);
-	pr_debug("size = 0x%x\n", client.size);
-
-	bytes_avail = client.size;
-	workq = create_singlethread_workqueue("sdio_smem");
-	if (!workq)
-		return -ENOMEM;
-
-	sdio_ch_opened = 1;
-	err = sdio_open("SDIO_SMEM", &channel, NULL, sdio_smem_notify);
-	if (err) {
-		sdio_ch_opened = 0;
-		pr_err("sdio_open error (%d)\n", err);
-		destroy_workqueue(workq);
-		return err;
-	}
-	pr_debug("SDIO SMEM channel opened\n");
-	return err;
-}
-
-int sdio_smem_unregister_client(void)
-{
-	int err = 0;
-
-	sdio_ch_opened = 0;
-	err = sdio_close(channel);
-	if (err) {
-		pr_err("sdio_close error (%d)\n", err);
-		return err;
-	}
-	pr_debug("SDIO SMEM channel closed\n");
-	flush_workqueue(workq);
-	destroy_workqueue(workq);
-	bytes_avail = 0;
-	client.buf = NULL;
-	client.cb_func = NULL;
-	client.size = 0;
-
-	return 0;
-}
-
-static int sdio_smem_probe(struct platform_device *pdev)
-{
-	client.plat_dev.name = "SDIO_SMEM_CLIENT";
-	client.plat_dev.id = -1;
-	client.plat_dev.dev.release = sdio_smem_release;
-
-	return platform_device_register(&client.plat_dev);
-}
-
-static int sdio_smem_remove(struct platform_device *pdev)
-{
-	platform_device_unregister(&client.plat_dev);
-	memset(&client, 0, sizeof(client));
-	sdio_ch_opened = 0;
-	return 0;
-}
-static struct platform_driver sdio_smem_drv = {
-	.probe		= sdio_smem_probe,
-	.remove		= sdio_smem_remove,
-	.driver		= {
-		.name	= "SDIO_SMEM",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init sdio_smem_init(void)
-{
-	return platform_driver_register(&sdio_smem_drv);
-};
-
-module_init(sdio_smem_init);
-
-MODULE_DESCRIPTION("SDIO SMEM");
-MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/sdio_tty.c b/arch/arm/mach-msm/sdio_tty.c
deleted file mode 100644
index c4b7673..0000000
--- a/arch/arm/mach-msm/sdio_tty.c
+++ /dev/null
@@ -1,824 +0,0 @@
-/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/platform_device.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/debugfs.h>
-#include <mach/sdio_al.h>
-
-#define INPUT_SPEED			4800
-#define OUTPUT_SPEED			4800
-#define SDIO_TTY_MODULE_NAME		"sdio_tty"
-#define SDIO_TTY_MAX_PACKET_SIZE	4096
-#define MAX_SDIO_TTY_DRV		1
-#define MAX_SDIO_TTY_DEVS		2
-#define MAX_SDIO_TTY_DEV_NAME_SIZE	25
-
-/* Configurations per channel device */
-/* CSVT */
-#define SDIO_TTY_CSVT_DEV		"sdio_tty_csvt_0"
-#define SDIO_TTY_CSVT_TEST_DEV		"sdio_tty_csvt_test_0"
-#define SDIO_TTY_CH_CSVT		"SDIO_CSVT"
-
-enum sdio_tty_state {
-	TTY_INITIAL = 0,
-	TTY_REGISTERED = 1,
-	TTY_OPENED = 2,
-	TTY_CLOSED = 3,
-};
-
-enum sdio_tty_devices {
-	SDIO_CSVT,
-	SDIO_CSVT_TEST_APP,
-};
-
-static const struct platform_device_id sdio_tty_id_table[] = {
-	{ "SDIO_CSVT",		SDIO_CSVT },
-	{ "SDIO_CSVT_TEST_APP",	SDIO_CSVT_TEST_APP },
-	{ },
-};
-MODULE_DEVICE_TABLE(platform, sdio_tty_id_table);
-
-struct sdio_tty {
-	struct sdio_channel *ch;
-	char *sdio_ch_name;
-	char tty_dev_name[MAX_SDIO_TTY_DEV_NAME_SIZE];
-	int device_id;
-	struct workqueue_struct *workq;
-	struct work_struct work_read;
-	wait_queue_head_t   waitq;
-	struct tty_driver *tty_drv;
-	struct tty_struct *tty_str;
-	int debug_msg_on;
-	char *read_buf;
-	enum sdio_tty_state sdio_tty_state;
-	int is_sdio_open;
-	int tty_open_count;
-	int total_rx;
-	int total_tx;
-};
-
-static struct sdio_tty *sdio_tty[MAX_SDIO_TTY_DEVS];
-
-#ifdef CONFIG_DEBUG_FS
-struct dentry *sdio_tty_debug_root;
-struct dentry *sdio_tty_debug_info;
-#endif
-
-#define DEBUG_MSG(sdio_tty_drv, x...) if (sdio_tty_drv->debug_msg_on) pr_info(x)
-
-/*
- * Enable sdio_tty debug messages
- * By default the sdio_tty debug messages are turned off
- */
-static int csvt_debug_msg_on;
-module_param(csvt_debug_msg_on, int, 0);
-
-static void sdio_tty_read(struct work_struct *work)
-{
-	int ret = 0;
-	int read_avail = 0;
-	int left = 0;
-	int total_push = 0;
-	int num_push = 0;
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	sdio_tty_drv = container_of(work, struct sdio_tty, work_read);
-
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty", __func__);
-		return ;
-	}
-
-	if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
-			__func__, sdio_tty_drv->sdio_tty_state);
-		return;
-	}
-
-	if (!sdio_tty_drv->read_buf) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL read_buf for dev %s",
-			__func__, sdio_tty_drv->tty_dev_name);
-		return;
-	}
-
-	/* Read the data from the SDIO channel as long as there is available
-	   data */
-	while (1) {
-		if (test_bit(TTY_THROTTLED, &sdio_tty_drv->tty_str->flags)) {
-			DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
-					": %s: TTY_THROTTLED bit is set for "
-					"dev %s, exit", __func__,
-					sdio_tty_drv->tty_dev_name);
-			return;
-		}
-
-		total_push = 0;
-		read_avail = sdio_read_avail(sdio_tty_drv->ch);
-
-		DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
-				": %s: read_avail is %d for dev %s", __func__,
-				read_avail, sdio_tty_drv->tty_dev_name);
-
-		if (read_avail == 0) {
-			DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME
-					": %s: read_avail is 0 for dev %s",
-					__func__, sdio_tty_drv->tty_dev_name);
-			return;
-		}
-
-		if (read_avail > SDIO_TTY_MAX_PACKET_SIZE) {
-			pr_err(SDIO_TTY_MODULE_NAME ": %s: read_avail(%d) is "
-				"bigger than SDIO_TTY_MAX_PACKET_SIZE(%d) "
-				"for dev %s", __func__, read_avail,
-				SDIO_TTY_MAX_PACKET_SIZE,
-				sdio_tty_drv->tty_dev_name);
-			return;
-		}
-
-		ret = sdio_read(sdio_tty_drv->ch,
-				sdio_tty_drv->read_buf,
-				read_avail);
-		if (ret < 0) {
-			pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_read error(%d) "
-				"for dev %s", __func__, ret,
-				sdio_tty_drv->tty_dev_name);
-			return;
-		}
-
-		left = read_avail;
-		do {
-			num_push = tty_insert_flip_string(
-				sdio_tty_drv->tty_str,
-				sdio_tty_drv->read_buf+total_push,
-				left);
-			total_push += num_push;
-			left -= num_push;
-			tty_flip_buffer_push(sdio_tty_drv->tty_str);
-		} while (left != 0);
-
-		if (total_push != read_avail) {
-			pr_err(SDIO_TTY_MODULE_NAME ": %s: failed, total_push"
-				"(%d) != read_avail(%d) for dev %s\n",
-				__func__, total_push, read_avail,
-				sdio_tty_drv->tty_dev_name);
-		}
-
-		tty_flip_buffer_push(sdio_tty_drv->tty_str);
-		sdio_tty_drv->total_rx += read_avail;
-
-		DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Rx: %d, "
-				"Total Rx = %d bytes for dev %s", __func__,
-				read_avail, sdio_tty_drv->total_rx,
-				sdio_tty_drv->tty_dev_name);
-	}
-}
-
-/**
-  * sdio_tty_write_room
-  *
-  * This is the write_room function of the tty driver.
-  *
-  * @tty: pointer to tty struct.
-  * @return free bytes for write.
-  *
-  */
-static int sdio_tty_write_room(struct tty_struct *tty)
-{
-	int write_avail = 0;
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	if (!tty) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
-		return -ENODEV;
-	}
-	sdio_tty_drv = tty->driver_data;
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-			__func__);
-		return -ENODEV;
-	}
-
-	if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
-			__func__, sdio_tty_drv->sdio_tty_state);
-		return -EPERM;
-	}
-
-	write_avail = sdio_write_avail(sdio_tty_drv->ch);
-	DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: write_avail=%d "
-			"for dev %s", __func__, write_avail,
-			sdio_tty_drv->tty_dev_name);
-
-	return write_avail;
-}
-
-/**
-  * sdio_tty_write_callback
-  * this is the write callback of the tty driver.
-  *
-  * @tty: pointer to tty struct.
-  * @buf: buffer to write from.
-  * @count: number of bytes to write.
-  * @return bytes written or negative value on error.
-  *
-  * if destination buffer has not enough room for the incoming
-  * data, writes the possible amount of bytes .
-  */
-static int sdio_tty_write_callback(struct tty_struct *tty,
-				   const unsigned char *buf, int count)
-{
-	int write_avail = 0;
-	int len = count;
-	int ret = 0;
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	if (!tty) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
-		return -ENODEV;
-	}
-	sdio_tty_drv = tty->driver_data;
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-			__func__);
-		return -ENODEV;
-	}
-
-	if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
-			__func__, sdio_tty_drv->sdio_tty_state);
-		return -EPERM;
-	}
-
-	DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Write Callback "
-			"called with %d bytes for dev %s\n", __func__, count,
-			sdio_tty_drv->tty_dev_name);
-	write_avail = sdio_write_avail(sdio_tty_drv->ch);
-	if (write_avail == 0) {
-		DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
-				"write_avail is 0 for dev %s\n",
-				__func__, sdio_tty_drv->tty_dev_name);
-		return 0;
-	}
-	if (write_avail > SDIO_TTY_MAX_PACKET_SIZE) {
-		DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
-				"write_avail(%d) is bigger than max packet "
-				"size(%d) for dev %s, setting to "
-				"max_packet_size\n", __func__, write_avail,
-				SDIO_TTY_MAX_PACKET_SIZE,
-				sdio_tty_drv->tty_dev_name);
-		write_avail = SDIO_TTY_MAX_PACKET_SIZE;
-	}
-	if (write_avail < count) {
-		DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: "
-				"write_avail(%d) is smaller than required(%d) "
-				"for dev %s, writing only %d bytes\n",
-				__func__, write_avail, count,
-				sdio_tty_drv->tty_dev_name, write_avail);
-		len = write_avail;
-	}
-	ret = sdio_write(sdio_tty_drv->ch, buf, len);
-	if (ret) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_write failed for "
-			"dev %s, ret=%d\n", __func__,
-			sdio_tty_drv->tty_dev_name, ret);
-		return 0;
-	}
-
-	sdio_tty_drv->total_tx += len;
-
-	DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Tx: %d, "
-			"Total Tx = %d for dev %s", __func__, len,
-			sdio_tty_drv->total_tx, sdio_tty_drv->tty_dev_name);
-	return len;
-}
-
-static void sdio_tty_notify(void *priv, unsigned event)
-{
-	struct sdio_tty *sdio_tty_drv = priv;
-
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-			__func__);
-	}
-
-	if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
-			__func__, sdio_tty_drv->sdio_tty_state);
-		return;
-	}
-
-	DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: event %d "
-			"received for dev %s\n", __func__, event,
-			sdio_tty_drv->tty_dev_name);
-
-	if (event == SDIO_EVENT_DATA_READ_AVAIL)
-		queue_work(sdio_tty_drv->workq, &sdio_tty_drv->work_read);
-}
-
-/**
-  * sdio_tty_open
-  * This is the open callback of the tty driver. it opens
-  * the sdio channel, and creates the workqueue.
-  *
-  * @tty: a pointer to the tty struct.
-  * @file: file descriptor.
-  * @return 0 on success or negative value on error.
-  */
-static int sdio_tty_open(struct tty_struct *tty, struct file *file)
-{
-	int ret = 0;
-	int i = 0;
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	if (!tty) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
-		return -ENODEV;
-	}
-
-	for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
-		if (sdio_tty[i] == NULL)
-			continue;
-		if (!strncmp(sdio_tty[i]->tty_dev_name, tty->name,
-				MAX_SDIO_TTY_DEV_NAME_SIZE)) {
-			sdio_tty_drv = sdio_tty[i];
-			break;
-		}
-	}
-
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-		       __func__);
-		return -ENODEV;
-	}
-
-	sdio_tty_drv->tty_open_count++;
-	if (sdio_tty_drv->sdio_tty_state == TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: tty dev(%s) is already open",
-			__func__, sdio_tty_drv->tty_dev_name);
-		return -EBUSY;
-	}
-
-	tty->driver_data = sdio_tty_drv;
-
-	sdio_tty_drv->tty_str = tty;
-	sdio_tty_drv->tty_str->low_latency = 1;
-	sdio_tty_drv->tty_str->icanon = 0;
-	set_bit(TTY_NO_WRITE_SPLIT, &sdio_tty_drv->tty_str->flags);
-
-	sdio_tty_drv->read_buf = kzalloc(SDIO_TTY_MAX_PACKET_SIZE, GFP_KERNEL);
-	if (sdio_tty_drv->read_buf == NULL) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate read_buf "
-			"for dev %s", __func__, sdio_tty_drv->tty_dev_name);
-		return -ENOMEM;
-	}
-
-	sdio_tty_drv->workq = create_singlethread_workqueue("sdio_tty_read");
-	if (!sdio_tty_drv->workq) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to create workq "
-			"for dev %s", __func__, sdio_tty_drv->tty_dev_name);
-		return -ENOMEM;
-	}
-
-	if (!sdio_tty_drv->is_sdio_open) {
-		ret = sdio_open(sdio_tty_drv->sdio_ch_name, &sdio_tty_drv->ch,
-				sdio_tty_drv, sdio_tty_notify);
-		if (ret < 0) {
-			pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_open err=%d "
-				"for dev %s\n", __func__, ret,
-				sdio_tty_drv->tty_dev_name);
-			destroy_workqueue(sdio_tty_drv->workq);
-			return ret;
-		}
-
-		pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY channel(%s) "
-			"opened\n", __func__, sdio_tty_drv->sdio_ch_name);
-
-		sdio_tty_drv->is_sdio_open = 1;
-	} else {
-		/* If SDIO channel is already open try to read the data
-		 * from the modem
-		 */
-		queue_work(sdio_tty_drv->workq, &sdio_tty_drv->work_read);
-
-	}
-
-	sdio_tty_drv->sdio_tty_state = TTY_OPENED;
-
-	pr_info(SDIO_TTY_MODULE_NAME ": %s: TTY device(%s) opened\n",
-		__func__, sdio_tty_drv->tty_dev_name);
-
-	return ret;
-}
-
-/**
-  * sdio_tty_close
-  * This is the close callback of the tty driver. it requests
-  * the main thread to exit, and waits for notification of it.
-  * it also de-allocates the buffers, and unregisters the tty
-  * driver and device.
-  *
-  * @tty: a pointer to the tty struct.
-  * @file: file descriptor.
-  * @return None.
-  */
-static void sdio_tty_close(struct tty_struct *tty, struct file *file)
-{
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	if (!tty) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
-		return;
-	}
-	sdio_tty_drv = tty->driver_data;
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-		       __func__);
-		return;
-	}
-	if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: trying to close a "
-			"TTY device that was not opened\n", __func__);
-		return;
-	}
-	if (--sdio_tty_drv->tty_open_count != 0)
-		return;
-
-	flush_workqueue(sdio_tty_drv->workq);
-	destroy_workqueue(sdio_tty_drv->workq);
-
-	kfree(sdio_tty_drv->read_buf);
-	sdio_tty_drv->read_buf = NULL;
-
-	sdio_tty_drv->sdio_tty_state = TTY_CLOSED;
-
-	pr_info(SDIO_TTY_MODULE_NAME ": %s: SDIO_TTY device(%s) closed\n",
-		__func__, sdio_tty_drv->tty_dev_name);
-}
-
-static void sdio_tty_unthrottle(struct tty_struct *tty)
-{
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	if (!tty) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL tty", __func__);
-		return;
-	}
-	sdio_tty_drv = tty->driver_data;
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-		       __func__);
-		return;
-	}
-
-	if (sdio_tty_drv->sdio_tty_state != TTY_OPENED) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_state = %d",
-		       __func__, sdio_tty_drv->sdio_tty_state);
-		return;
-	}
-
-	queue_work(sdio_tty_drv->workq, &sdio_tty_drv->work_read);
-	return;
-}
-
-static const struct tty_operations sdio_tty_ops = {
-	.open = sdio_tty_open,
-	.close = sdio_tty_close,
-	.write = sdio_tty_write_callback,
-	.write_room = sdio_tty_write_room,
-	.unthrottle = sdio_tty_unthrottle,
-};
-
-int sdio_tty_init_tty(char *tty_name, char *sdio_ch_name,
-			enum sdio_tty_devices device_id, int debug_msg_on)
-{
-	int ret = 0;
-	int i = 0;
-	struct device *tty_dev = NULL;
-	struct sdio_tty *sdio_tty_drv = NULL;
-
-	sdio_tty_drv = kzalloc(sizeof(struct sdio_tty), GFP_KERNEL);
-	if (sdio_tty_drv == NULL) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: failed to allocate sdio_tty "
-			"for dev %s", __func__, tty_name);
-		return -ENOMEM;
-	}
-
-	for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
-		if (sdio_tty[i] == NULL) {
-			sdio_tty[i] = sdio_tty_drv;
-			break;
-		}
-	}
-
-	if (i == MAX_SDIO_TTY_DEVS) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: tty dev(%s) creation failed,"
-			" max limit(%d) reached.", __func__, tty_name,
-			MAX_SDIO_TTY_DEVS);
-		kfree(sdio_tty_drv);
-		return -ENODEV;
-	}
-
-	snprintf(sdio_tty_drv->tty_dev_name, MAX_SDIO_TTY_DEV_NAME_SIZE,
-			"%s%d", tty_name, 0);
-	sdio_tty_drv->sdio_ch_name = sdio_ch_name;
-	sdio_tty_drv->device_id = device_id;
-	pr_info(SDIO_TTY_MODULE_NAME ": %s: dev=%s, id=%d, channel=%s\n",
-		__func__, sdio_tty_drv->tty_dev_name, sdio_tty_drv->device_id,
-		sdio_tty_drv->sdio_ch_name);
-
-	INIT_WORK(&sdio_tty_drv->work_read, sdio_tty_read);
-
-	sdio_tty_drv->tty_drv = alloc_tty_driver(MAX_SDIO_TTY_DRV);
-
-	if (!sdio_tty_drv->tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s - tty_drv is NULL for dev %s",
-			__func__, sdio_tty_drv->tty_dev_name);
-		kfree(sdio_tty_drv);
-		return -ENODEV;
-	}
-
-	sdio_tty_drv->tty_drv->name = tty_name;
-	sdio_tty_drv->tty_drv->owner = THIS_MODULE;
-	sdio_tty_drv->tty_drv->driver_name = "SDIO_tty";
-	/* uses dynamically assigned dev_t values */
-	sdio_tty_drv->tty_drv->type = TTY_DRIVER_TYPE_SERIAL;
-	sdio_tty_drv->tty_drv->subtype = SERIAL_TYPE_NORMAL;
-	sdio_tty_drv->tty_drv->flags = TTY_DRIVER_REAL_RAW
-		| TTY_DRIVER_DYNAMIC_DEV
-		| TTY_DRIVER_RESET_TERMIOS;
-
-	/* initializing the tty driver */
-	sdio_tty_drv->tty_drv->init_termios = tty_std_termios;
-	sdio_tty_drv->tty_drv->init_termios.c_cflag =
-		B4800 | CS8 | CREAD | HUPCL | CLOCAL;
-	sdio_tty_drv->tty_drv->init_termios.c_ispeed = INPUT_SPEED;
-	sdio_tty_drv->tty_drv->init_termios.c_ospeed = OUTPUT_SPEED;
-
-	tty_set_operations(sdio_tty_drv->tty_drv, &sdio_tty_ops);
-
-	ret = tty_register_driver(sdio_tty_drv->tty_drv);
-	if (ret) {
-		put_tty_driver(sdio_tty_drv->tty_drv);
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: tty_register_driver() "
-			"failed for dev %s\n", __func__,
-			sdio_tty_drv->tty_dev_name);
-
-		sdio_tty_drv->tty_drv = NULL;
-		kfree(sdio_tty_drv);
-		return -ENODEV;
-	}
-
-	tty_dev = tty_register_device(sdio_tty_drv->tty_drv, 0, NULL);
-	if (IS_ERR(tty_dev)) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: tty_register_device() "
-			"failed for dev %s\n", __func__,
-			sdio_tty_drv->tty_dev_name);
-		tty_unregister_driver(sdio_tty_drv->tty_drv);
-		put_tty_driver(sdio_tty_drv->tty_drv);
-		kfree(sdio_tty_drv);
-		return -ENODEV;
-	}
-
-	sdio_tty_drv->sdio_tty_state = TTY_REGISTERED;
-	if (debug_msg_on) {
-		pr_info(SDIO_TTY_MODULE_NAME ": %s: turn on debug msg for %s",
-			__func__, sdio_tty_drv->tty_dev_name);
-		sdio_tty_drv->debug_msg_on = debug_msg_on;
-	}
-	return 0;
-}
-
-int sdio_tty_uninit_tty(void *sdio_tty_handle)
-{
-	int ret = 0;
-	int i = 0;
-	struct sdio_tty *sdio_tty_drv = sdio_tty_handle;
-
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-		       __func__);
-		return -ENODEV;
-	}
-	if (sdio_tty_drv->sdio_tty_state == TTY_OPENED) {
-		flush_workqueue(sdio_tty_drv->workq);
-		destroy_workqueue(sdio_tty_drv->workq);
-
-		kfree(sdio_tty_drv->read_buf);
-		sdio_tty_drv->read_buf = NULL;
-	}
-
-	if (sdio_tty_drv->sdio_tty_state != TTY_INITIAL) {
-		tty_unregister_device(sdio_tty_drv->tty_drv, 0);
-
-		ret = tty_unregister_driver(sdio_tty_drv->tty_drv);
-		if (ret) {
-			pr_err(SDIO_TTY_MODULE_NAME ": %s: "
-				"tty_unregister_driver() failed for dev %s\n",
-				__func__, sdio_tty_drv->tty_dev_name);
-		}
-		put_tty_driver(sdio_tty_drv->tty_drv);
-		sdio_tty_drv->sdio_tty_state = TTY_INITIAL;
-		sdio_tty_drv->tty_drv = NULL;
-	}
-
-	for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
-		if (sdio_tty[i] == NULL)
-			continue;
-		if (sdio_tty[i]->device_id == sdio_tty_drv->device_id) {
-			sdio_tty[i] = NULL;
-			break;
-		}
-	}
-
-	DEBUG_MSG(sdio_tty_drv, SDIO_TTY_MODULE_NAME ": %s: Freeing sdio_tty "
-			"structure, dev=%s", __func__,
-			sdio_tty_drv->tty_dev_name);
-	kfree(sdio_tty_drv);
-
-	return 0;
-}
-
-static int sdio_tty_probe(struct platform_device *pdev)
-{
-	const struct platform_device_id *id = platform_get_device_id(pdev);
-	enum sdio_tty_devices device_id = id->driver_data;
-	char *device_name = NULL;
-	char *channel_name = NULL;
-	int debug_msg_on = 0;
-	int ret = 0;
-
-	pr_debug(SDIO_TTY_MODULE_NAME ": %s for %s", __func__, pdev->name);
-
-	switch (device_id) {
-	case SDIO_CSVT:
-		device_name = SDIO_TTY_CSVT_DEV;
-		channel_name = SDIO_TTY_CH_CSVT;
-		debug_msg_on = csvt_debug_msg_on;
-		break;
-	case SDIO_CSVT_TEST_APP:
-		device_name = SDIO_TTY_CSVT_TEST_DEV;
-		channel_name = SDIO_TTY_CH_CSVT;
-		debug_msg_on = csvt_debug_msg_on;
-		break;
-	default:
-		pr_err(SDIO_TTY_MODULE_NAME ": %s Invalid device:%s, id:%d",
-			__func__, pdev->name, device_id);
-		ret = -ENODEV;
-		break;
-	}
-
-	if (device_name) {
-		ret = sdio_tty_init_tty(device_name, channel_name,
-					device_id, debug_msg_on);
-		if (ret) {
-			pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_init_tty "
-				"failed for dev:%s", __func__, device_name);
-		}
-	}
-	return ret;
-}
-
-static int sdio_tty_remove(struct platform_device *pdev)
-{
-	const struct platform_device_id *id = platform_get_device_id(pdev);
-	enum sdio_tty_devices device_id = id->driver_data;
-	struct sdio_tty *sdio_tty_drv = NULL;
-	int i = 0;
-	int ret = 0;
-
-	pr_debug(SDIO_TTY_MODULE_NAME ": %s for %s", __func__, pdev->name);
-
-	for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
-		if (sdio_tty[i] == NULL)
-			continue;
-		if (sdio_tty[i]->device_id == device_id) {
-			sdio_tty_drv = sdio_tty[i];
-			break;
-		}
-	}
-
-	if (!sdio_tty_drv) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: NULL sdio_tty_drv",
-		       __func__);
-		return -ENODEV;
-	}
-
-	ret = sdio_tty_uninit_tty(sdio_tty_drv);
-	if (ret) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: sdio_tty_uninit_tty "
-			"failed for %s", __func__, pdev->name);
-	}
-	return ret;
-}
-
-static struct platform_driver sdio_tty_pdrv = {
-	.probe		= sdio_tty_probe,
-	.remove		= sdio_tty_remove,
-	.id_table	= sdio_tty_id_table,
-	.driver		= {
-		.name	= "SDIO_TTY",
-		.owner	= THIS_MODULE,
-	},
-};
-
-#ifdef CONFIG_DEBUG_FS
-void sdio_tty_print_info(void)
-{
-	int i = 0;
-
-	for (i = 0; i < MAX_SDIO_TTY_DEVS; i++) {
-		if (sdio_tty[i] == NULL)
-			continue;
-		pr_info(SDIO_TTY_MODULE_NAME ": %s: Total Rx=%d, Tx = %d "
-			"for dev %s", __func__, sdio_tty[i]->total_rx,
-			sdio_tty[i]->total_tx, sdio_tty[i]->tty_dev_name);
-	}
-}
-
-static int tty_debug_info_open(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t tty_debug_info_write(struct file *file,
-		const char __user *buf, size_t count, loff_t *ppos)
-{
-	sdio_tty_print_info();
-	return count;
-}
-
-const struct file_operations tty_debug_info_ops = {
-	.open = tty_debug_info_open,
-	.write = tty_debug_info_write,
-};
-#endif
-
-/*
- *  Module Init.
- *
- *  Register SDIO TTY driver.
- *
- */
-static int __init sdio_tty_init(void)
-{
-	int ret = 0;
-
-	ret = platform_driver_register(&sdio_tty_pdrv);
-	if (ret) {
-		pr_err(SDIO_TTY_MODULE_NAME ": %s: platform_driver_register "
-					    "failed", __func__);
-	}
-#ifdef CONFIG_DEBUG_FS
-	else {
-		sdio_tty_debug_root = debugfs_create_dir("sdio_tty", NULL);
-		if (sdio_tty_debug_root) {
-			sdio_tty_debug_info = debugfs_create_file(
-							"sdio_tty_debug",
-							S_IRUGO | S_IWUGO,
-							sdio_tty_debug_root,
-							NULL,
-							&tty_debug_info_ops);
-		}
-	}
-#endif
-	return ret;
-};
-
-/*
- *  Module Exit.
- *
- *  Unregister SDIO TTY driver.
- *
- */
-static void __exit sdio_tty_exit(void)
-{
-#ifdef CONFIG_DEBUG_FS
-	debugfs_remove(sdio_tty_debug_info);
-	debugfs_remove(sdio_tty_debug_root);
-#endif
-	platform_driver_unregister(&sdio_tty_pdrv);
-}
-
-module_init(sdio_tty_init);
-module_exit(sdio_tty_exit);
-
-MODULE_DESCRIPTION("SDIO TTY");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Maya Erez <merez@codeaurora.org>");
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 09b3113..1241e44 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -2285,7 +2285,7 @@
 				edge_to_pids[ch->type].subsys_name);
 		irq_chip->irq_mask(irq_data);
 		if (cpumask)
-			irq_chip->irq_set_affinity(irq_data, cpumask, true);
+			irq_set_affinity(int_cfg->irq_id, cpumask);
 	} else {
 		SMD_POWER_INFO("SMD Unmasking interrupts from %s\n",
 				edge_to_pids[ch->type].subsys_name);
diff --git a/arch/arm/mach-msm/smp2p.c b/arch/arm/mach-msm/smp2p.c
index df241f8..5574eae 100644
--- a/arch/arm/mach-msm/smp2p.c
+++ b/arch/arm/mach-msm/smp2p.c
@@ -940,7 +940,7 @@
 
 	if (size < sizeof(struct smp2p_smem)) {
 		SMP2P_ERR(
-			"%s pid %d item size too small; expected: %d actual: %d\n",
+			"%s pid %d item size too small; expected: %zu actual: %d\n",
 			__func__, remote_pid,
 			sizeof(struct smp2p_smem), size);
 		smem_item = NULL;
diff --git a/arch/arm/mach-msm/smp2p_private.h b/arch/arm/mach-msm/smp2p_private.h
index 8e0d7a3..7174950 100644
--- a/arch/arm/mach-msm/smp2p_private.h
+++ b/arch/arm/mach-msm/smp2p_private.h
@@ -1,6 +1,6 @@
 /* arch/arm/mach-msm/smp2p_private.h
  *
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -44,10 +44,10 @@
 #define SMP2P_GET_BITS(hdr_val, mask, bit) \
 	(((hdr_val) & (mask)) >> (bit))
 #define SMP2P_SET_BITS(hdr_val, mask, bit, new_value) \
-	do {\
+	{\
 		hdr_val = (hdr_val & ~(mask)) \
 		| (((new_value) << (bit)) & (mask)); \
-	} while (0)
+	}
 
 #define SMP2P_GET_LOCAL_PID(hdr) \
 	SMP2P_GET_BITS(hdr, SMP2P_LOCAL_PID_MASK, SMP2P_LOCAL_PID_BIT)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index a1a2e51..669b10e 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1500,7 +1500,9 @@
 		vm->flags = VM_LOWMEM | VM_ARM_STATIC_MAPPING;
 		vm->flags |= VM_ARM_MTYPE(type);
 		vm->caller = map_lowmem;
-		vm_area_add_early(vm++);
+		vm_area_add_early(vm);
+		mark_vmalloc_reserved_area(vm->addr, vm->size);
+		vm++;
 	}
 }
 
diff --git a/block/blk-core.c b/block/blk-core.c
index 123f79a..00eab3b 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -314,7 +314,8 @@
 	if (!q->notified_urgent &&
 		q->elevator->type->ops.elevator_is_urgent_fn &&
 		q->urgent_request_fn &&
-		q->elevator->type->ops.elevator_is_urgent_fn(q)) {
+		q->elevator->type->ops.elevator_is_urgent_fn(q) &&
+		list_empty(&q->flush_data_in_flight)) {
 		q->notified_urgent = true;
 		q->urgent_request_fn(q);
 	} else
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index 13c9080..9ccee05 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -30,7 +30,7 @@
 #define BT_PWR_DBG(fmt, arg...)  pr_debug("%s: " fmt "\n" , __func__ , ## arg)
 #define BT_PWR_INFO(fmt, arg...) pr_info("%s: " fmt "\n" , __func__ , ## arg)
 #define BT_PWR_ERR(fmt, arg...)  pr_err("%s: " fmt "\n" , __func__ , ## arg)
-
+#define BT_VDD_PA_CURRENT        60000
 
 static struct of_device_id bt_power_match_table[] = {
 	{	.compatible = "qca,ar3002" },
@@ -213,6 +213,9 @@
 				BT_PWR_ERR("bt_power vddpa config failed");
 				goto vdd_pa_fail;
 			}
+			regulator_set_optimum_mode(
+				bt_power_pdata->bt_vdd_pa->reg,
+				BT_VDD_PA_CURRENT);
 		}
 		if (bt_power_pdata->bt_chip_pwd) {
 			rc = bt_configure_vreg(bt_power_pdata->bt_chip_pwd);
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 0383d8f..8272528 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -5,7 +5,7 @@
  *  power management protocol extension to H4 to support AR300x Bluetooth Chip.
  *
  *  Copyright (c) 2009-2010 Atheros Communications Inc.
- *  Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2012-2014 The Linux Foundation. All rights reserved.
  *
  *  Acknowledgements:
  *  This file is based on hci_h4.c, which was written
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index cc8cf47..009ab57 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -564,10 +564,7 @@
 		rpra[i].buf.len = pra[i].buf.len;
 		if (!rpra[i].buf.len)
 			continue;
-		if (list[i].num) {
-			rpra[i].buf.pv = pra[i].buf.pv;
-			continue;
-		} else if (me->smmu.enabled && fds && (fds[i] >= 0)) {
+		if (me->smmu.enabled && fds && (fds[i] >= 0)) {
 			len = buf_page_size(pra[i].buf.len);
 			handles[i] = ion_import_dma_buf(me->iclient, fds[i]);
 			VERIFY(err, 0 == IS_ERR_OR_NULL(handles[i]));
@@ -583,6 +580,9 @@
 			pages[list[i].pgidx].addr = iova;
 			pages[list[i].pgidx].size = len;
 			continue;
+		} else if (list[i].num) {
+			rpra[i].buf.pv = pra[i].buf.pv;
+			continue;
 		}
 		if (rlen < pra[i].buf.len) {
 			struct fastrpc_buf *b;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 2dbb2f5..0edfdad 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -216,7 +216,11 @@
 	if (recv_pkt_cmd_code != DCI_PKT_RSP_CODE)
 		cmd_code_len = 4; /* delayed response */
 	write_len = (int)(*(uint16_t *)(buf+2)) - cmd_code_len;
-
+	if (write_len <= 0) {
+		pr_err("diag: Invalid length in %s, write_len: %d",
+					__func__, write_len);
+		return;
+	}
 	pr_debug("diag: len = %d\n", write_len);
 	tag = (int *)(buf + (4 + cmd_code_len)); /* Retrieve the Tag field */
 	req_entry = diag_dci_get_request_entry(*tag);
@@ -278,7 +282,7 @@
 {
 	uint16_t event_id, event_id_packet, length, temp_len;
 	uint8_t *event_mask_ptr, byte_mask, payload_len, payload_len_field;
-	uint8_t timestamp[8], bit_index, timestamp_len;
+	uint8_t timestamp[8] = {0}, bit_index, timestamp_len;
 	uint8_t event_data[MAX_EVENT_SIZE];
 	unsigned int byte_index, total_event_len, i;
 	struct diag_dci_client_tbl *entry;
@@ -383,17 +387,23 @@
 
 void extract_dci_log(unsigned char *buf)
 {
-	uint16_t log_code, item_num;
+	uint16_t log_code, item_num, log_length;
 	uint8_t equip_id, *log_mask_ptr, byte_mask;
 	unsigned int i, byte_index, byte_offset = 0;
 	struct diag_dci_client_tbl *entry;
 
+	log_length = *(uint16_t *)(buf + 2);
 	log_code = *(uint16_t *)(buf + 6);
 	equip_id = LOG_GET_EQUIP_ID(log_code);
 	item_num = LOG_GET_ITEM_NUM(log_code);
 	byte_index = item_num/8 + 2;
 	byte_mask = 0x01 << (item_num % 8);
 
+	if (log_length > USHRT_MAX - 4) {
+		pr_err("diag: Integer overflow in %s, log_len:%d",
+				__func__, log_length);
+		return;
+	}
 	byte_offset = (equip_id * 514) + byte_index;
 	if (byte_offset >=  DCI_LOG_MASK_SIZE) {
 		pr_err("diag: Invalid byte_offset %d in dci log\n",
@@ -430,8 +440,8 @@
 				*(int *)(entry->dci_data+entry->data_len) =
 								DCI_LOG_TYPE;
 				memcpy(entry->dci_data + entry->data_len + 4,
-					    buf + 4, *(uint16_t *)(buf + 2));
-				entry->data_len += 4 + *(uint16_t *)(buf + 2);
+					    buf + 4, log_length);
+				entry->data_len += 4 + log_length;
 			}
 			mutex_unlock(&entry->data_mutex);
 			mutex_unlock(&dci_health_mutex);
@@ -487,9 +497,9 @@
 	}
 	mutex_unlock(&dci_log_mask_mutex);
 
-	ret = diag_send_dci_log_mask(driver->smd_cntl[index].ch);
+	ret = diag_send_dci_log_mask(&driver->smd_cntl[index]);
 
-	ret = diag_send_dci_event_mask(driver->smd_cntl[index].ch);
+	ret = diag_send_dci_event_mask(&driver->smd_cntl[index]);
 
 	smd_info->notify_context = 0;
 }
@@ -562,8 +572,10 @@
 					&driver->smd_dci[i];
 		if (entry.client_id == smd_info->peripheral) {
 			if (smd_info->ch) {
+				mutex_lock(&smd_info->smd_ch_mutex);
 				smd_write(smd_info->ch,
 					driver->apps_dci_buf, len + 10);
+				mutex_unlock(&smd_info->smd_ch_mutex);
 				status = DIAG_DCI_NO_ERROR;
 			}
 			break;
@@ -757,7 +769,7 @@
 			ret = DIAG_DCI_NO_ERROR;
 		}
 		/* send updated mask to peripherals */
-		ret = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+		ret = diag_send_dci_log_mask(&driver->smd_cntl[MODEM_DATA]);
 	} else if (*(int *)temp == DCI_EVENT_TYPE) {
 		/* Minimum length of a event mask config is 12 + 4 bytes for
 		  atleast one event id to be set or reset. */
@@ -828,13 +840,29 @@
 			ret = DIAG_DCI_NO_ERROR;
 		}
 		/* send updated mask to peripherals */
-		ret = diag_send_dci_event_mask(driver->smd_cntl[MODEM_DATA].ch);
+		ret = diag_send_dci_event_mask(&driver->smd_cntl[MODEM_DATA]);
 	} else {
 		pr_alert("diag: Incorrect DCI transaction\n");
 	}
 	return ret;
 }
 
+int diag_dci_find_client_index_health(int client_id)
+{
+	int i, ret = DCI_CLIENT_INDEX_INVALID;
+
+	for (i = 0; i < MAX_DCI_CLIENTS; i++) {
+		if (driver->dci_client_tbl[i].client != NULL) {
+			if (driver->dci_client_tbl[i].client_id ==
+					client_id) {
+				ret = i;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
 int diag_dci_find_client_index(int client_id)
 {
 	int i, ret = DCI_CLIENT_INDEX_INVALID;
@@ -940,7 +968,7 @@
 }
 
 
-int diag_send_dci_event_mask(smd_channel_t *ch)
+int diag_send_dci_event_mask(struct diag_smd_info *smd_info)
 {
 	void *buf = driver->buf_event_mask_update;
 	int header_size = sizeof(struct diag_ctrl_event_mask);
@@ -963,10 +991,12 @@
 	}
 	memcpy(buf, driver->event_mask, header_size);
 	memcpy(buf+header_size, dci_cumulative_event_mask, DCI_EVENT_MASK_SIZE);
-	if (ch) {
+	if (smd_info && smd_info->ch) {
 		while (retry_count < 3) {
-			wr_size = smd_write(ch, buf,
+			mutex_lock(&smd_info->smd_ch_mutex);
+			wr_size = smd_write(smd_info->ch, buf,
 					 header_size + DCI_EVENT_MASK_SIZE);
+			mutex_unlock(&smd_info->smd_ch_mutex);
 			if (wr_size == -ENOMEM) {
 				retry_count++;
 				for (timer = 0; timer < 5; timer++)
@@ -1106,7 +1136,7 @@
 	mutex_unlock(&dci_log_mask_mutex);
 }
 
-int diag_send_dci_log_mask(smd_channel_t *ch)
+int diag_send_dci_log_mask(struct diag_smd_info *smd_info)
 {
 	void *buf = driver->buf_log_mask_update;
 	int header_size = sizeof(struct diag_ctrl_log_mask);
@@ -1114,7 +1144,7 @@
 	int i, wr_size = -ENOMEM, retry_count = 0, timer;
 	int ret = DIAG_DCI_NO_ERROR;
 
-	if (!ch) {
+	if (!smd_info || !smd_info->ch) {
 		pr_err("diag: ch not valid for dci log mask update\n");
 		return DIAG_DCI_SEND_DATA_FAIL;
 	}
@@ -1132,9 +1162,12 @@
 		memcpy(buf, driver->log_mask, header_size);
 		memcpy(buf+header_size, log_mask_ptr+2, 512);
 		/* if dirty byte is set and channel is valid */
-		if (ch && *(log_mask_ptr+1)) {
+		if (smd_info->ch && *(log_mask_ptr+1)) {
 			while (retry_count < 3) {
-				wr_size = smd_write(ch, buf, header_size + 512);
+				mutex_lock(&smd_info->smd_ch_mutex);
+				wr_size = smd_write(smd_info->ch, buf,
+							header_size + 512);
+				mutex_unlock(&smd_info->smd_ch_mutex);
 				if (wr_size == -ENOMEM) {
 					retry_count++;
 					for (timer = 0; timer < 5; timer++)
@@ -1406,7 +1439,7 @@
 		}
 	}
 	mutex_unlock(&dci_log_mask_mutex);
-	err = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+	err = diag_send_dci_log_mask(&driver->smd_cntl[MODEM_DATA]);
 	return err;
 }
 
@@ -1432,7 +1465,7 @@
 			*(update_ptr + j) |= *(event_mask_ptr + j);
 	}
 	mutex_unlock(&dci_event_mask_mutex);
-	err = diag_send_dci_event_mask(driver->smd_cntl[MODEM_DATA].ch);
+	err = diag_send_dci_event_mask(&driver->smd_cntl[MODEM_DATA]);
 	return err;
 }
 
diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h
index c9be39a..870b0f3 100644
--- a/drivers/char/diag/diag_dci.h
+++ b/drivers/char/diag/diag_dci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -56,6 +56,7 @@
 } __packed;
 
 struct diag_dci_client_tbl {
+	uint32_t client_id;
 	struct task_struct *client;
 	uint16_t list; /* bit mask */
 	int signal_type;
@@ -74,6 +75,7 @@
 
 /* This is used for DCI health stats */
 struct diag_dci_health_stats {
+	int client_id;
 	int dropped_logs;
 	int dropped_events;
 	int received_logs;
@@ -119,20 +121,22 @@
 								int recd_bytes);
 int diag_process_dci_transaction(unsigned char *buf, int len);
 void extract_dci_pkt_rsp(struct diag_smd_info *smd_info, unsigned char *buf);
+
+int diag_dci_find_client_index_health(int client_id);
 int diag_dci_find_client_index(int client_id);
 /* DCI Log streaming functions */
 void create_dci_log_mask_tbl(unsigned char *tbl_buf);
 void update_dci_cumulative_log_mask(int offset, unsigned int byte_index,
 						uint8_t byte_mask);
 void clear_client_dci_cumulative_log_mask(int client_index);
-int diag_send_dci_log_mask(smd_channel_t *ch);
+int diag_send_dci_log_mask(struct diag_smd_info *smd_info);
 void extract_dci_log(unsigned char *buf);
 int diag_dci_clear_log_mask(void);
 int diag_dci_query_log_mask(uint16_t log_code);
 /* DCI event streaming functions */
 void update_dci_cumulative_event_mask(int offset, uint8_t byte_mask);
 void clear_client_dci_cumulative_event_mask(int client_index);
-int diag_send_dci_event_mask(smd_channel_t *ch);
+int diag_send_dci_event_mask(struct diag_smd_info *smd_info);
 void extract_dci_events(unsigned char *buf);
 void create_dci_event_mask_tbl(unsigned char *tbl_buf);
 int diag_dci_clear_event_mask(void);
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index beaf75d..3a1c96b 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -33,14 +33,14 @@
 {
 	char *buf;
 	int ret;
-
+	unsigned int buf_size;
 	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
 	if (!buf) {
 		pr_err("diag: %s, Error allocating memory\n", __func__);
 		return -ENOMEM;
 	}
-
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+	buf_size = ksize(buf);
+	ret = scnprintf(buf, buf_size,
 		"modem ch: 0x%x\n"
 		"lpass ch: 0x%x\n"
 		"riva ch: 0x%x\n"
@@ -181,7 +181,7 @@
 		driver->real_time_mode);
 
 #ifdef CONFIG_DIAG_OVER_USB
-	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+	ret += scnprintf(buf+ret, buf_size-ret,
 		"usb_connected: %d\n",
 		driver->usb_connected);
 #endif
@@ -195,9 +195,11 @@
 				char __user *ubuf, size_t count, loff_t *ppos)
 {
 	char *buf = NULL;
-	int bytes_remaining, bytes_written = 0, bytes_in_buf = 0, i = 0;
+	unsigned int bytes_remaining, bytes_written = 0;
+	unsigned int bytes_in_buf = 0, i = 0;
 	struct diag_dci_data_info *temp_data = dci_data_smd;
-	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+	unsigned int buf_size;
+	buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
 
 	if (diag_dbgfs_dci_finished) {
 		diag_dbgfs_dci_finished = 0;
@@ -210,6 +212,7 @@
 		return -ENOMEM;
 	}
 
+	buf_size = ksize(buf);
 	bytes_remaining = buf_size;
 
 	if (diag_dbgfs_dci_data_index == 0) {
@@ -286,6 +289,7 @@
 {
 	char *buf;
 	int ret;
+	unsigned int buf_size;
 
 	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
 	if (!buf) {
@@ -293,7 +297,8 @@
 		return -ENOMEM;
 	}
 
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+	buf_size = ksize(buf);
+	ret = scnprintf(buf, buf_size,
 		"Pending status for work_stucts:\n"
 		"diag_drain_work: %d\n"
 		"Modem data diag_read_smd_work: %d\n"
@@ -341,7 +346,7 @@
 						diag_notify_update_smd_work)));
 
 #ifdef CONFIG_DIAG_OVER_USB
-	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+	ret += scnprintf(buf+ret, buf_size-ret,
 		"diag_proc_hdlc_work: %d\n"
 		"diag_read_work: %d\n",
 		work_pending(&(driver->diag_proc_hdlc_work)),
@@ -359,10 +364,11 @@
 	char *buf;
 	int ret = 0;
 	int i;
-	int bytes_remaining;
-	int bytes_in_buffer = 0;
-	int bytes_written;
-	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+	unsigned int bytes_remaining;
+	unsigned int bytes_in_buffer = 0;
+	unsigned int bytes_written;
+	unsigned int buf_size;
+	buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
 
 	if (diag_dbgfs_table_index >= diag_max_reg) {
 		/* Done. Reset to prepare for future requests */
@@ -375,7 +381,7 @@
 		pr_err("diag: %s, Error allocating memory\n", __func__);
 		return -ENOMEM;
 	}
-
+	buf_size = ksize(buf);
 	bytes_remaining = buf_size;
 
 	if (diag_dbgfs_table_index == 0) {
@@ -384,6 +390,7 @@
 			"WCNSS: %d, APPS: %d\n",
 			MODEM_DATA, LPASS_DATA, WCNSS_DATA, APPS_DATA);
 		bytes_in_buffer += bytes_written;
+		bytes_remaining -= bytes_written;
 	}
 
 	for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
@@ -427,14 +434,15 @@
 {
 	char *buf = NULL;
 	int ret = 0, i = 0;
-
+	unsigned int buf_size;
 	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
 	if (ZERO_OR_NULL_PTR(buf)) {
 		pr_err("diag: %s, Error allocating memory\n", __func__);
 		return -ENOMEM;
 	}
+	buf_size = ksize(buf);
 
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+	ret = scnprintf(buf, buf_size,
 		"POOL_TYPE_COPY: [0x%p : 0x%p] count = %d\n"
 		"POOL_TYPE_HDLC: [0x%p : 0x%p] count = %d\n"
 		"POOL_TYPE_USER: [0x%p : 0x%p] count = %d\n"
@@ -455,7 +463,7 @@
 	for (i = 0; i < MAX_HSIC_CH; i++) {
 		if (!diag_hsic[i].hsic_inited)
 			continue;
-		ret += scnprintf(buf+ret, DEBUG_BUF_SIZE-ret,
+		ret += scnprintf(buf+ret, buf_size-ret,
 				"POOL_TYPE_HSIC_%d: [0x%p : 0x%p] count = %d\n",
 				i+1,
 				diag_hsic[i].diag_hsic_pool,
@@ -466,7 +474,7 @@
 	for (i = 0; i < MAX_HSIC_CH; i++) {
 		if (!diag_hsic[i].hsic_inited)
 			continue;
-		ret += scnprintf(buf+ret, DEBUG_BUF_SIZE-ret,
+		ret += scnprintf(buf+ret, buf_size-ret,
 				"POOL_TYPE_HSIC_%d_WRITE: [0x%p : 0x%p] count = %d\n",
 				i+1,
 				diag_hsic[i].diag_hsic_write_pool,
@@ -485,6 +493,7 @@
 {
 	char *buf = NULL;
 	int ret = 0;
+	unsigned int buf_size;
 
 	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
 	if (ZERO_OR_NULL_PTR(buf)) {
@@ -492,7 +501,8 @@
 		return -ENOMEM;
 	}
 
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+	buf_size = ksize(buf);
+	ret = scnprintf(buf, buf_size,
 		"POOL_TYPE_COPY: [0x%p : 0x%p] count = %d\n"
 		"POOL_TYPE_HDLC: [0x%p : 0x%p] count = %d\n"
 		"POOL_TYPE_USER: [0x%p : 0x%p] count = %d\n"
@@ -524,13 +534,15 @@
 	char *buf;
 	int ret;
 	int i;
-	int bytes_remaining;
-	int bytes_in_buffer = 0;
-	int bytes_written;
-	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+	unsigned int bytes_remaining;
+	unsigned int bytes_in_buffer = 0;
+	unsigned int bytes_written;
+	unsigned int buf_size;
 	int bytes_hsic_inited = 45;
 	int bytes_hsic_not_inited = 410;
 
+	buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+
 	if (diag_dbgfs_finished) {
 		diag_dbgfs_finished = 0;
 		return 0;
@@ -542,6 +554,7 @@
 		return -ENOMEM;
 	}
 
+	buf_size = ksize(buf);
 	bytes_remaining = buf_size;
 
 	/* Only one smux for now */
@@ -583,8 +596,8 @@
 			"in_busy_hsic_write: %d\n"
 			"count_hsic_pool: %d\n"
 			"count_hsic_write_pool: %d\n"
-			"diag_hsic_pool: %x\n"
-			"diag_hsic_write_pool: %x\n"
+			"diag_hsic_pool: %p\n"
+			"diag_hsic_write_pool: %p\n"
 			"HSIC write_len: %d\n"
 			"num_hsic_buf_tbl_entries: %d\n"
 			"HSIC usb_connected: %d\n"
@@ -601,8 +614,8 @@
 			diag_hsic[i].in_busy_hsic_write,
 			diag_hsic[i].count_hsic_pool,
 			diag_hsic[i].count_hsic_write_pool,
-			(unsigned int)diag_hsic[i].diag_hsic_pool,
-			(unsigned int)diag_hsic[i].diag_hsic_write_pool,
+			diag_hsic[i].diag_hsic_pool,
+			diag_hsic[i].diag_hsic_write_pool,
 			diag_bridge[i].write_len,
 			diag_hsic[i].num_hsic_buf_tbl_entries,
 			diag_bridge[i].usb_connected,
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index c28b3bd..8b00ece 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 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
@@ -327,10 +327,10 @@
 	}
 
 	diag_send_feature_mask_update(smd_info);
-	diag_send_msg_mask_update(smd_info->ch, ALL_SSID, ALL_SSID,
+	diag_send_msg_mask_update(smd_info, ALL_SSID, ALL_SSID,
 						smd_info->peripheral);
-	diag_send_log_mask_update(smd_info->ch, ALL_EQUIP_ID);
-	diag_send_event_mask_update(smd_info->ch, diag_event_num_bytes);
+	diag_send_log_mask_update(smd_info, ALL_EQUIP_ID);
+	diag_send_event_mask_update(smd_info, diag_event_num_bytes);
 
 	if (smd_info->notify_context == SMD_EVENT_OPEN)
 		diag_send_diag_mode_update_by_smd(smd_info,
@@ -339,7 +339,7 @@
 	smd_info->notify_context = 0;
 }
 
-void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
+void diag_send_log_mask_update(struct diag_smd_info *smd_info, int equip_id)
 {
 	void *buf = driver->buf_log_mask_update;
 	struct diag_log_mask_t *log_item = NULL;
@@ -348,6 +348,12 @@
 	int wr_size = -ENOMEM, retry_count = 0;
 	int i, header_size, send_once = 0;
 
+	if (!smd_info) {
+		pr_err("diag: In %s, null smd info pointer\n",
+			__func__);
+		return;
+	}
+
 	header_size = sizeof(struct diag_ctrl_log_mask);
 	log_item = (struct diag_log_mask_t *)driver->log_masks;
 	mutex_lock(&driver->diag_cntl_mutex);
@@ -390,10 +396,12 @@
 			       log_mask_size);
 		}
 
-		if (ch) {
+		if (smd_info->ch) {
 			while (retry_count < 3) {
-				wr_size = smd_write(ch, buf,
+				mutex_lock(&smd_info->smd_ch_mutex);
+				wr_size = smd_write(smd_info->ch, buf,
 						header_size + log_mask_size);
+				mutex_unlock(&smd_info->smd_ch_mutex);
 				if (wr_size == -ENOMEM) {
 					retry_count++;
 					usleep_range(10000, 10100);
@@ -415,12 +423,18 @@
 	mutex_unlock(&driver->diag_cntl_mutex);
 }
 
-void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
+void diag_send_event_mask_update(struct diag_smd_info *smd_info, int num_bytes)
 {
 	void *buf = driver->buf_event_mask_update;
 	int header_size = sizeof(struct diag_ctrl_event_mask);
 	int wr_size = -ENOMEM, retry_count = 0;
 
+	if (!smd_info) {
+		pr_err("diag: In %s, null smd info pointer\n",
+			__func__);
+		return;
+	}
+
 	mutex_lock(&driver->diag_cntl_mutex);
 	if (num_bytes == 0) {
 		pr_debug("diag: event mask not set yet, so no update\n");
@@ -459,9 +473,12 @@
 		return;
 	}
 	memcpy(buf, driver->event_mask, header_size);
-	if (ch) {
+	if (smd_info->ch) {
 		while (retry_count < 3) {
-			wr_size = smd_write(ch, buf, header_size + num_bytes);
+			mutex_lock(&smd_info->smd_ch_mutex);
+			wr_size = smd_write(smd_info->ch, buf,
+						header_size + num_bytes);
+			mutex_unlock(&smd_info->smd_ch_mutex);
 			if (wr_size == -ENOMEM) {
 				retry_count++;
 				usleep_range(10000, 10100);
@@ -476,14 +493,20 @@
 	mutex_unlock(&driver->diag_cntl_mutex);
 }
 
-void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
-						int updated_ssid_last, int proc)
+void diag_send_msg_mask_update(struct diag_smd_info *smd_info,
+				int updated_ssid_first, int updated_ssid_last,
+				int proc)
 {
 	void *buf = driver->buf_msg_mask_update;
 	int first, last, actual_last, size = -ENOMEM, retry_count = 0;
 	int header_size = sizeof(struct diag_ctrl_msg_mask);
 	uint8_t *ptr = driver->msg_masks;
 
+	if (!smd_info) {
+		pr_err("diag: In %s, null smd info pointer\n",
+				__func__);
+		return;
+	}
 	mutex_lock(&driver->diag_cntl_mutex);
 	while (*(uint32_t *)(ptr + 4)) {
 		first = *(uint32_t *)ptr;
@@ -543,10 +566,12 @@
 		driver->msg_mask->ssid_first = first;
 		driver->msg_mask->ssid_last = actual_last;
 		memcpy(buf, driver->msg_mask, header_size);
-		if (ch) {
+		if (smd_info->ch) {
 			while (retry_count < 3) {
-				size = smd_write(ch, buf, header_size +
-				 4*(driver->msg_mask->msg_mask_size));
+				mutex_lock(&smd_info->smd_ch_mutex);
+				size = smd_write(smd_info->ch, buf, header_size
+					+ 4*(driver->msg_mask->msg_mask_size));
+				mutex_unlock(&smd_info->smd_ch_mutex);
 				if (size == -ENOMEM) {
 					retry_count++;
 					usleep_range(10000, 10100);
@@ -606,7 +631,9 @@
 	total_len = header_size + FEATURE_MASK_LEN_BYTES;
 
 	while (retry_count < 3) {
+		mutex_lock(&smd_info->smd_ch_mutex);
 		wr_size = smd_write(smd_info->ch, buf, total_len);
+		mutex_unlock(&smd_info->smd_ch_mutex);
 		if (wr_size == -ENOMEM) {
 			retry_count++;
 			/*
@@ -661,7 +688,7 @@
 			for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 				if (driver->smd_cntl[i].ch)
 					diag_send_log_mask_update(
-						driver->smd_cntl[i].ch,
+						&driver->smd_cntl[i],
 						*(int *)buf);
 			}
 			encode_rsp_and_send(12 + payload_length - 1);
@@ -703,7 +730,7 @@
 			for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 				if (driver->smd_cntl[i].ch)
 					diag_send_log_mask_update(
-						driver->smd_cntl[i].ch,
+						&driver->smd_cntl[i],
 						ALL_EQUIP_ID);
 
 			}
@@ -774,7 +801,7 @@
 			for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 				if (driver->smd_cntl[i].ch)
 					diag_send_msg_mask_update(
-						driver->smd_cntl[i].ch,
+						&driver->smd_cntl[i],
 						ssid_first, ssid_last,
 						driver->smd_cntl[i].peripheral);
 
@@ -799,7 +826,7 @@
 			for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 				if (driver->smd_cntl[i].ch)
 					diag_send_msg_mask_update(
-						driver->smd_cntl[i].ch,
+						&driver->smd_cntl[i],
 						ALL_SSID, ALL_SSID,
 						driver->smd_cntl[i].peripheral);
 
@@ -825,7 +852,7 @@
 			for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 				if (driver->smd_cntl[i].ch)
 					diag_send_event_mask_update(
-						driver->smd_cntl[i].ch,
+						&driver->smd_cntl[i],
 						diag_event_num_bytes);
 			}
 			encode_rsp_and_send(6 + EVENT_LAST_ID/8);
@@ -843,7 +870,7 @@
 			for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
 				if (driver->smd_cntl[i].ch)
 					diag_send_event_mask_update(
-						driver->smd_cntl[i].ch,
+						&driver->smd_cntl[i],
 						diag_event_num_bytes);
 			}
 			encode_rsp_and_send(2);
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index 856d4fc..3ec087d 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -21,10 +21,10 @@
 	uint8_t ptr[MAX_ITEMS_PER_EQUIP_ID];
 } __packed;
 
-void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
-void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
+void diag_send_event_mask_update(struct diag_smd_info *smd_info, int num_bytes);
+void diag_send_msg_mask_update(struct diag_smd_info *smd_info, int ssid_first,
 					 int ssid_last, int proc);
-void diag_send_log_mask_update(smd_channel_t *, int);
+void diag_send_log_mask_update(struct diag_smd_info *smd_info, int);
 void diag_mask_update_fn(struct work_struct *work);
 void diag_send_feature_mask_update(struct diag_smd_info *smd_info);
 int diag_process_apps_masks(unsigned char *buf, int len);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6ead0ad..0e475c9 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 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
@@ -51,6 +51,7 @@
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("1.0");
 
+#define MIN_SIZ_ALLOW 4
 #define INIT	1
 #define EXIT	-1
 struct diagchar_dev *driver;
@@ -341,6 +342,9 @@
 		else if (subsys_id == 0x32 && cmd_code_hi >= 0x03  &&
 			 cmd_code_lo <= 0x03)
 			return 1;
+		else if (subsys_id == 0x57 && cmd_code_hi >= 0x0E &&
+			 cmd_code_lo <= 0x0E)
+			return 1;
 	}
 	return 0;
 }
@@ -475,8 +479,8 @@
 
 		for (i = 0; i < diag_hsic[index].poolsize_hsic_write; i++) {
 			if (hsic_buf_tbl[i].length > 0) {
-				pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
-					i, (unsigned int)hsic_buf_tbl[i].buf,
+				pr_debug("diag: HSIC copy to user, i: %d, buf: %p, len: %d\n",
+					i, hsic_buf_tbl[i].buf,
 					hsic_buf_tbl[i].length);
 				num_data++;
 
@@ -939,6 +943,8 @@
 		for (i = 0; i < MAX_DCI_CLIENTS; i++) {
 			if (driver->dci_client_tbl[i].client == NULL) {
 				driver->dci_client_tbl[i].client = current;
+				driver->dci_client_tbl[i].client_id =
+							driver->dci_client_id;
 				driver->dci_client_tbl[i].list =
 							 dci_params->list;
 				driver->dci_client_tbl[i].signal_type =
@@ -978,7 +984,7 @@
 			clear_client_dci_cumulative_log_mask(i);
 			/* send updated log mask to peripherals */
 			result =
-			diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch);
+			diag_send_dci_log_mask(&driver->smd_cntl[MODEM_DATA]);
 			if (result != DIAG_DCI_NO_ERROR) {
 				mutex_unlock(&driver->dci_mutex);
 				return result;
@@ -988,7 +994,7 @@
 			/* send updated event mask to peripherals */
 			result =
 			diag_send_dci_event_mask(
-				driver->smd_cntl[MODEM_DATA].ch);
+				&driver->smd_cntl[MODEM_DATA]);
 			if (result != DIAG_DCI_NO_ERROR) {
 				mutex_unlock(&driver->dci_mutex);
 				return result;
@@ -1039,7 +1045,7 @@
 				 sizeof(struct diag_dci_health_stats)))
 			return -EFAULT;
 		mutex_lock(&dci_health_mutex);
-		i = diag_dci_find_client_index(current->tgid);
+		i = diag_dci_find_client_index_health(stats.client_id);
 		if (i != DCI_CLIENT_INDEX_INVALID) {
 			dci_params = &(driver->dci_client_tbl[i]);
 			stats.dropped_logs = dci_params->dropped_logs;
@@ -1117,7 +1123,7 @@
 	case DIAG_IOCTL_VOTE_REAL_TIME:
 		if (copy_from_user(&rt_vote, (void *)ioarg, sizeof(struct
 							real_time_vote_t)))
-			result = -EFAULT;
+			return -EFAULT;
 		driver->real_time_update_busy++;
 		if (rt_vote.proc == DIAG_PROC_DCI) {
 			diag_dci_set_real_time(current->tgid,
@@ -1194,10 +1200,9 @@
 		for (i = 0; i < driver->buf_tbl_size; i++) {
 			if (driver->buf_tbl[i].length > 0) {
 #ifdef DIAG_DEBUG
-				pr_debug("diag: WRITING the buf address "
-				       "and length is %x , %d\n", (unsigned int)
-					(driver->buf_tbl[i].buf),
-					driver->buf_tbl[i].length);
+				pr_debug("diag: WRITING the buf address and length is %p , %d\n",
+					 driver->buf_tbl[i].buf,
+					 driver->buf_tbl[i].length);
 #endif
 				num_data++;
 				/* Copy the length of data being passed */
@@ -1218,10 +1223,9 @@
 				ret += driver->buf_tbl[i].length;
 drop:
 #ifdef DIAG_DEBUG
-				pr_debug("diag: DEQUEUE buf address and"
-				       " length is %x,%d\n", (unsigned int)
-				       (driver->buf_tbl[i].buf), driver->
-				       buf_tbl[i].length);
+				pr_debug("diag: DEQUEUE buf address and length is %p, %d\n",
+					 driver->buf_tbl[i].buf,
+					 driver->buf_tbl[i].length);
 #endif
 				diagmem_free(driver, (unsigned char *)
 				(driver->buf_tbl[i].buf), POOL_TYPE_HDLC);
@@ -1452,6 +1456,10 @@
 	index = 0;
 	/* Get the packet type F3/log/event/Pkt response */
 	err = copy_from_user((&pkt_type), buf, 4);
+	if (err) {
+		pr_alert("diag: copy failed for pkt_type\n");
+		return -EAGAIN;
+	}
 	/* First 4 bytes indicate the type of payload - ignore these */
 	if (count < 4) {
 		pr_err("diag: Client sending short data\n");
@@ -1493,8 +1501,9 @@
 		return err;
 	}
 	if (pkt_type == CALLBACK_DATA_TYPE) {
-		if (payload_size > driver->itemsize) {
-			pr_err("diag: Dropping packet, packet payload size crosses 4KB limit. Current payload size %d\n",
+		if (payload_size > driver->itemsize ||
+				payload_size <= MIN_SIZ_ALLOW) {
+			pr_err("diag: Dropping packet, invalid packet size. Current payload size %d\n",
 				payload_size);
 			driver->dropped_count++;
 			return -EBADMSG;
@@ -1628,6 +1637,11 @@
 			diag_get_remote(*(int *)driver->user_space_data_buf);
 
 		if (remote_proc) {
+			if (payload_size <= MIN_SIZ_ALLOW) {
+				pr_err("diag: Integer underflow in %s, payload size: %d",
+							__func__, payload_size);
+				return -EBADMSG;
+			}
 			token_offset = 4;
 			payload_size -= 4;
 			buf += 4;
diff --git a/drivers/char/diag/diagchar_hdlc.c b/drivers/char/diag/diagchar_hdlc.c
index 3e38a3c..6f527a5 100644
--- a/drivers/char/diag/diagchar_hdlc.c
+++ b/drivers/char/diag/diagchar_hdlc.c
@@ -177,8 +177,8 @@
 	int msg_start;
 
 	if (hdlc && hdlc->src_ptr && hdlc->dest_ptr &&
-	    (hdlc->src_size - hdlc->src_idx > 0) &&
-	    (hdlc->dest_size - hdlc->dest_idx > 0)) {
+	    (hdlc->src_size > hdlc->src_idx) &&
+	    (hdlc->dest_size > hdlc->dest_idx)) {
 
 		msg_start = (hdlc->src_idx == 0) ? 1 : 0;
 
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 395bea0..028f045 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -825,10 +825,9 @@
 					driver->buf_tbl[i].length =
 								 driver->used;
 #ifdef DIAG_DEBUG
-					pr_debug("diag: ENQUEUE buf ptr"
-						   " and length is %x , %d\n",
-						   (unsigned int)(driver->buf_
-				tbl[i].buf), driver->buf_tbl[i].length);
+					pr_debug("diag: ENQUEUE buf ptr and length is %p , %d\n",
+						 driver->buf_tbl[i].buf,
+						 driver->buf_tbl[i].length);
 #endif
 					break;
 				}
@@ -860,9 +859,9 @@
 			if (foundIndex == -1)
 				err = -1;
 			else
-				pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d, ch %d\n",
-					(unsigned int)buf,
-					 diag_bridge[index].write_len, index);
+				pr_debug("diag: ENQUEUE HSIC buf ptr and length is %p , %d, ch %d\n",
+					 buf, diag_bridge[index].write_len,
+					 index);
 		}
 #endif
 		for (i = 0; i < driver->num_clients; i++)
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index d3c311d..a75f7f69 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -349,10 +349,19 @@
 	int wr_size = -ENOMEM, retry_count = 0, timer;
 	struct diag_smd_info *data = NULL;
 
-	/* For now only allow the modem to receive the message */
-	if (!smd_info || smd_info->type != SMD_CNTL_TYPE ||
-		(smd_info->peripheral != MODEM_DATA))
+	if (!smd_info || smd_info->type != SMD_CNTL_TYPE) {
+		pr_err("diag: In %s, invalid channel info, smd_info: %p type: %d\n",
+					__func__, smd_info,
+					((smd_info) ? smd_info->type : -1));
 		return;
+	}
+
+	if (smd_info->peripheral < MODEM_DATA ||
+					smd_info->peripheral > WCNSS_DATA) {
+		pr_err("diag: In %s, invalid peripheral %d\n", __func__,
+							smd_info->peripheral);
+		return;
+	}
 
 	data = &driver->smd_data[smd_info->peripheral];
 	if (!data)
@@ -380,7 +389,9 @@
 
 	if (smd_info->ch) {
 		while (retry_count < 3) {
+			mutex_lock(&smd_info->smd_ch_mutex);
 			wr_size = smd_write(smd_info->ch, buf, msg_size);
+			mutex_unlock(&smd_info->smd_ch_mutex);
 			if (wr_size == -ENOMEM) {
 				/*
 				 * The smd channel is full. Delay while
@@ -433,7 +444,9 @@
 		stm_msg.version = 1;
 		stm_msg.control_data = stm_control_data;
 		while (retry_count < 3) {
+			mutex_lock(&smd_info->smd_ch_mutex);
 			wr_size = smd_write(smd_info->ch, &stm_msg, msg_size);
+			mutex_unlock(&smd_info->smd_ch_mutex);
 			if (wr_size == -ENOMEM) {
 				/*
 				 * The smd channel is full. Delay while
diff --git a/drivers/cpufreq/cpu-boost.c b/drivers/cpufreq/cpu-boost.c
index 8cd5ef9..f20510d 100644
--- a/drivers/cpufreq/cpu-boost.c
+++ b/drivers/cpufreq/cpu-boost.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 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
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/notifier.h>
 #include <linux/cpufreq.h>
+#include <linux/cpu.h>
 #include <linux/sched.h>
 #include <linux/jiffies.h>
 #include <linux/kthread.h>
@@ -62,6 +63,12 @@
  * The CPUFREQ_ADJUST notifier is used to override the current policy min to
  * make sure policy min >= boost_min. The cpufreq framework then does the job
  * of enforcing the new policy.
+ *
+ * The sync kthread needs to run on the CPU in question to avoid deadlocks in
+ * the wake up code. Achieve this by binding the thread to the respective
+ * CPU. But a CPU going offline unbinds threads from that CPU. So, set it up
+ * again each time the CPU comes back up. We can use CPUFREQ_START to figure
+ * out a CPU is coming online instead of registering for hotplug notifiers.
  */
 static int boost_adjust_notify(struct notifier_block *nb, unsigned long val, void *data)
 {
@@ -72,22 +79,27 @@
 	unsigned int ib_min = s->input_boost_min;
 	unsigned int min;
 
-	if (val != CPUFREQ_ADJUST)
-		return NOTIFY_OK;
+	switch (val) {
+	case CPUFREQ_ADJUST:
+		if (!b_min && !ib_min)
+			break;
 
-	if (!b_min && !ib_min)
-		return NOTIFY_OK;
+		min = max(b_min, ib_min);
 
-	min = max(b_min, ib_min);
+		pr_debug("CPU%u policy min before boost: %u kHz\n",
+			 cpu, policy->min);
+		pr_debug("CPU%u boost min: %u kHz\n", cpu, min);
 
-	pr_debug("CPU%u policy min before boost: %u kHz\n",
-		 cpu, policy->min);
-	pr_debug("CPU%u boost min: %u kHz\n", cpu, min);
+		cpufreq_verify_within_limits(policy, min, UINT_MAX);
 
-	cpufreq_verify_within_limits(policy, min, UINT_MAX);
+		pr_debug("CPU%u policy min after boost: %u kHz\n",
+			 cpu, policy->min);
+		break;
 
-	pr_debug("CPU%u policy min after boost: %u kHz\n",
-		 cpu, policy->min);
+	case CPUFREQ_START:
+		set_cpus_allowed(s->thread, *cpumask_of(cpu));
+		break;
+	}
 
 	return NOTIFY_OK;
 }
@@ -165,9 +177,15 @@
 			s->boost_min = src_policy.cur;
 		}
 		/* Force policy re-evaluation to trigger adjust notifier. */
-		cpufreq_update_policy(dest_cpu);
-		queue_delayed_work_on(s->cpu, cpu_boost_wq,
-			&s->boost_rem, msecs_to_jiffies(boost_ms));
+		get_online_cpus();
+		if (cpu_online(dest_cpu)) {
+			cpufreq_update_policy(dest_cpu);
+			queue_delayed_work_on(dest_cpu, cpu_boost_wq,
+				&s->boost_rem, msecs_to_jiffies(boost_ms));
+		} else {
+			s->boost_min = 0;
+		}
+		put_online_cpus();
 	}
 
 	return 0;
@@ -202,6 +220,7 @@
 	struct cpu_sync *i_sync_info;
 	struct cpufreq_policy policy;
 
+	get_online_cpus();
 	for_each_online_cpu(i) {
 
 		i_sync_info = &per_cpu(sync_info, i);
@@ -218,6 +237,7 @@
 			&i_sync_info->input_boost_rem,
 			msecs_to_jiffies(input_boost_ms));
 	}
+	put_online_cpus();
 }
 
 static void cpuboost_input_event(struct input_handle *handle,
@@ -332,6 +352,7 @@
 		INIT_DELAYED_WORK(&s->input_boost_rem, do_input_boost_rem);
 		s->thread = kthread_run(boost_mig_sync_thread, (void *)cpu,
 					"boost_sync/%d", cpu);
+		set_cpus_allowed(s->thread, *cpumask_of(cpu));
 	}
 	atomic_notifier_chain_register(&migration_notifier_head,
 					&boost_migration_nb);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 975a42f..4605685 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1726,7 +1726,8 @@
 	memcpy(&policy->cpuinfo, &data->cpuinfo,
 				sizeof(struct cpufreq_cpuinfo));
 
-	if (policy->min > data->max || policy->max < data->min) {
+	if (policy->min > data->user_policy.max
+		|| policy->max < data->user_policy.min) {
 		ret = -EINVAL;
 		goto error_out;
 	}
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 45a41eb..e96d577 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -445,7 +445,7 @@
 					continue;
 
 				max_load = max(max_load, picpu->prev_load);
-				max_freq = max(max_freq, picpu->policy->cur);
+				max_freq = max(max_freq, picpu->target_freq);
 			}
 
 			if (max_freq > up_threshold_any_cpu_freq &&
@@ -1283,6 +1283,7 @@
 			pcpu = &per_cpu(cpuinfo, j);
 			down_write(&pcpu->enable_sem);
 			pcpu->governor_enabled = 0;
+			pcpu->target_freq = 0;
 			del_timer_sync(&pcpu->cpu_timer);
 			del_timer_sync(&pcpu->cpu_slack_timer);
 			up_write(&pcpu->enable_sem);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 8f7d39c..7f8b4cd 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -978,14 +978,8 @@
 			dbs_info->sample_type = DBS_SUB_SAMPLE;
 			delay = dbs_info->freq_hi_jiffies;
 		} else {
-			/* We want all CPUs to do sampling nearly on
-			 * same jiffy
-			 */
 			delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
 				* dbs_info->rate_mult);
-
-			if (num_online_cpus() > 1)
-				delay -= jiffies % delay;
 		}
 	} else {
 		__cpufreq_driver_target(dbs_info->cur_policy,
diff --git a/drivers/crypto/msm/qce.h b/drivers/crypto/msm/qce.h
index afd5141..73438d0 100644
--- a/drivers/crypto/msm/qce.h
+++ b/drivers/crypto/msm/qce.h
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver API
  *
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 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
@@ -116,6 +116,13 @@
 	bool bam;
 	bool is_shared;
 	bool hw_key;
+	bool use_sw_aes_cbc_ecb_ctr_algo;
+	bool use_sw_aead_algo;
+	bool use_sw_aes_xts_algo;
+	bool use_sw_ahash_algo;
+	bool use_sw_hmac_algo;
+	bool use_sw_aes_ccm_algo;
+	bool clk_mgmt_sus_res;
 };
 
 /* Sha operation parameters */
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index a4154c1..62fd948 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto Engine driver.
  *
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -38,6 +38,7 @@
 #include "qce.h"
 #include "qce50.h"
 #include "qcryptohw_50.h"
+#include "qce_ota.h"
 
 #define CRYPTO_CONFIG_RESET 0xE001F
 #define QCE_MAX_NUM_DSCR    0x500
@@ -72,6 +73,7 @@
 	int is_shared;			/* CE HW is shared */
 	bool support_cmd_dscr;
 	bool support_hw_key;
+	bool support_clk_mgmt_sus_res;
 
 	void __iomem *iobase;	    /* Virtual io base of CE HW  */
 	unsigned int phy_iobase;    /* Physical io base of CE HW    */
@@ -96,6 +98,17 @@
 	enum qce_cipher_mode_enum mode;
 	struct qce_ce_cfg_reg_setting reg;
 	struct ce_sps_data ce_sps;
+	uint32_t engines_avail;
+	dma_addr_t phy_ota_src;
+	dma_addr_t phy_ota_dst;
+	unsigned int ota_size;
+
+	bool use_sw_aes_cbc_ecb_ctr_algo;
+	bool use_sw_aead_algo;
+	bool use_sw_aes_xts_algo;
+	bool use_sw_ahash_algo;
+	bool use_sw_hmac_algo;
+	bool use_sw_aes_ccm_algo;
 };
 
 /* Standard initialization vector for SHA-1, source: FIPS 180-2 */
@@ -202,6 +215,8 @@
 	};
 	pce_dev->ce_sps.minor_version = min_rev;
 
+	pce_dev->engines_avail = readl_relaxed(pce_dev->iobase +
+					CRYPTO_ENGINES_AVAIL);
 	dev_info(pce_dev->pdev, "Qualcomm Crypto %d.%d.%d device found @0x%x\n",
 			maj_rev, min_rev, step_rev, pce_dev->phy_iobase);
 
@@ -212,12 +227,14 @@
 			"Consumer (IN) PIPE %d,    "
 			"Producer (OUT) PIPE %d\n"
 			"IO base BAM = 0x%x\n"
-			"BAM IRQ %d\n",
+			"BAM IRQ %d\n"
+			"Engines Availability = 0x%x\n",
 			(uint32_t) pce_dev->iobase,
 			pce_dev->ce_sps.dest_pipe_index,
 			pce_dev->ce_sps.src_pipe_index,
 			(uint32_t)pce_dev->ce_sps.bam_iobase,
-			pce_dev->ce_sps.bam_irq);
+			pce_dev->ce_sps.bam_irq,
+			pce_dev->engines_avail);
 	return 0;
 };
 
@@ -268,31 +285,38 @@
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 	bool sha1 = false;
 	struct sps_command_element *pce = NULL;
+	bool use_hw_key = false;
+	bool use_pipe_key = false;
+	uint32_t authk_size_in_word = sreq->authklen/sizeof(uint32_t);
+	uint32_t auth_cfg;
 
 	if ((sreq->alg == QCE_HASH_SHA1_HMAC) ||
 			(sreq->alg == QCE_HASH_SHA256_HMAC) ||
 			(sreq->alg ==  QCE_HASH_AES_CMAC)) {
-		uint32_t authk_size_in_word = sreq->authklen/sizeof(uint32_t);
 
-		_byte_stream_to_net_words(mackey32, sreq->authkey,
-						sreq->authklen);
 
-		/* check for null key. If null, use hw key*/
-		for (i = 0; i < authk_size_in_word; i++) {
-			if (mackey32[i] != 0)
-				break;
-		}
-
+		/* no more check for null key. use flag */
+		if ((sreq->flags & QCRYPTO_CTX_USE_HW_KEY)
+						== QCRYPTO_CTX_USE_HW_KEY)
+			use_hw_key = true;
+		else if ((sreq->flags & QCRYPTO_CTX_USE_PIPE_KEY) ==
+						QCRYPTO_CTX_USE_PIPE_KEY)
+			use_pipe_key = true;
 		pce = cmdlistinfo->go_proc;
-		if (i == authk_size_in_word) {
+		if (use_hw_key == true) {
 			pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
 							pce_dev->phy_iobase);
 		} else {
 			pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
 							pce_dev->phy_iobase);
 			pce = cmdlistinfo->auth_key;
-			for (i = 0; i < authk_size_in_word; i++, pce++)
-				pce->data = mackey32[i];
+			if (use_pipe_key == false) {
+				_byte_stream_to_net_words(mackey32,
+						sreq->authkey,
+						sreq->authklen);
+				for (i = 0; i < authk_size_in_word; i++, pce++)
+					pce->data = mackey32[i];
+			}
 		}
 	}
 
@@ -347,14 +371,19 @@
 
 	/* Set/reset  last bit in CFG register  */
 	pce = cmdlistinfo->auth_seg_cfg;
+	auth_cfg = pce->data & ~(1 << CRYPTO_LAST |
+				1 << CRYPTO_FIRST |
+				1 << CRYPTO_USE_PIPE_KEY_AUTH |
+				1 << CRYPTO_USE_HW_KEY_AUTH);
 	if (sreq->last_blk)
-		pce->data |= 1 << CRYPTO_LAST;
-	else
-		pce->data &= ~(1 << CRYPTO_LAST);
+		auth_cfg |= 1 << CRYPTO_LAST;
 	if (sreq->first_blk)
-		pce->data |= 1 << CRYPTO_FIRST;
-	else
-		pce->data &= ~(1 << CRYPTO_FIRST);
+		auth_cfg |= 1 << CRYPTO_FIRST;
+	if (use_hw_key)
+		auth_cfg |= 1 << CRYPTO_USE_HW_KEY_AUTH;
+	if (use_pipe_key)
+		auth_cfg |= 1 << CRYPTO_USE_PIPE_KEY_AUTH;
+	pce->data = auth_cfg;
 go_proc:
 	/* write auth seg size */
 	pce = cmdlistinfo->auth_seg_size;
@@ -443,7 +472,7 @@
 		uint32_t totallen_in, uint32_t coffset,
 		struct qce_cmdlist_info *cmdlistinfo)
 {
-	int32_t authk_size_in_word = q_req->authklen/sizeof(uint32_t);
+	int32_t authk_size_in_word = SHA_HMAC_KEY_SIZE/sizeof(uint32_t);
 	int i;
 	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {0};
 	struct sps_command_element *pce;
@@ -804,12 +833,20 @@
 			}
 			/* write xts du size */
 			pce = cmdlistinfo->encr_xts_du_size;
-			if (!(creq->flags & QCRYPTO_CTX_XTS_MASK))
-				pce->data = creq->cryptlen;
-			else
+			switch (creq->flags & QCRYPTO_CTX_XTS_MASK) {
+			case QCRYPTO_CTX_XTS_DU_SIZE_512B:
 				pce->data = min((unsigned int)QCE_SECTOR_SIZE,
 						creq->cryptlen);
-
+				break;
+			case QCRYPTO_CTX_XTS_DU_SIZE_1KB:
+				pce->data =
+					min((unsigned int)QCE_SECTOR_SIZE * 2,
+					creq->cryptlen);
+				break;
+			default:
+				pce->data = creq->cryptlen;
+				break;
+			}
 		}
 		if (creq->mode !=  QCE_MODE_ECB) {
 			if (creq->mode ==  QCE_MODE_XTS)
@@ -889,15 +926,141 @@
 	return 0;
 };
 
+static int _ce_f9_setup(struct qce_device *pce_dev, struct qce_f9_req *req,
+		struct qce_cmdlist_info *cmdlistinfo)
+{
+	uint32_t ikey32[OTA_KEY_SIZE/sizeof(uint32_t)];
+	uint32_t key_size_in_word = OTA_KEY_SIZE/sizeof(uint32_t);
+	uint32_t cfg;
+	struct sps_command_element *pce;
+	int i;
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		cfg = pce_dev->reg.auth_cfg_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+	default:
+		cfg = pce_dev->reg.auth_cfg_snow3g;
+		break;
+	};
+
+	/* write key in CRYPTO_AUTH_IV0-3_REG */
+	_byte_stream_to_net_words(ikey32, &req->ikey[0], OTA_KEY_SIZE);
+	pce = cmdlistinfo->auth_iv;
+	for (i = 0; i < key_size_in_word; i++, pce++)
+		pce->data = ikey32[i];
+
+	/* write last bits  in CRYPTO_AUTH_IV4_REG  */
+	pce->data = req->last_bits;
+
+	/* write fresh to CRYPTO_AUTH_BYTECNT0_REG */
+	pce = cmdlistinfo->auth_bytecount;
+	pce->data = req->fresh;
+
+	/* write count-i  to CRYPTO_AUTH_BYTECNT1_REG */
+	pce++;
+	pce->data = req->count_i;
+
+	/* write auth seg cfg */
+	pce = cmdlistinfo->auth_seg_cfg;
+	if (req->direction == QCE_OTA_DIR_DOWNLINK)
+		cfg |= BIT(CRYPTO_F9_DIRECTION);
+	pce->data = cfg;
+
+	/* write auth seg size */
+	pce = cmdlistinfo->auth_seg_size;
+	pce->data = req->msize;
+
+	/* write auth seg start*/
+	pce = cmdlistinfo->auth_seg_start;
+	pce->data = 0;
+
+	/* write seg size  */
+	pce = cmdlistinfo->seg_size;
+	pce->data = req->msize;
+
+
+	/* write go */
+	pce = cmdlistinfo->go_proc;
+	pce->addr = (uint32_t)(CRYPTO_GOPROC_REG + pce_dev->phy_iobase);
+	return 0;
+}
+
+static int _ce_f8_setup(struct qce_device *pce_dev, struct qce_f8_req *req,
+		bool key_stream_mode, uint16_t npkts, uint16_t cipher_offset,
+		uint16_t cipher_size,
+		struct qce_cmdlist_info *cmdlistinfo)
+{
+	uint32_t ckey32[OTA_KEY_SIZE/sizeof(uint32_t)];
+	uint32_t key_size_in_word = OTA_KEY_SIZE/sizeof(uint32_t);
+	uint32_t cfg;
+	struct sps_command_element *pce;
+	int i;
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		cfg = pce_dev->reg.encr_cfg_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+	default:
+		cfg = pce_dev->reg.encr_cfg_snow3g;
+		break;
+	};
+	/* write key */
+	_byte_stream_to_net_words(ckey32, &req->ckey[0], OTA_KEY_SIZE);
+	pce = cmdlistinfo->encr_key;
+	for (i = 0; i < key_size_in_word; i++, pce++)
+		pce->data = ckey32[i];
+
+	/* write encr seg cfg */
+	pce = cmdlistinfo->encr_seg_cfg;
+	if (key_stream_mode)
+		cfg |= BIT(CRYPTO_F8_KEYSTREAM_ENABLE);
+	if (req->direction == QCE_OTA_DIR_DOWNLINK)
+		cfg |= BIT(CRYPTO_F8_DIRECTION);
+	pce->data = cfg;
+
+	/* write encr seg start */
+	pce = cmdlistinfo->encr_seg_start;
+	pce->data = (cipher_offset & 0xffff);
+
+	/* write encr seg size  */
+	pce = cmdlistinfo->encr_seg_size;
+	pce->data = cipher_size;
+
+	/* write seg size  */
+	pce = cmdlistinfo->seg_size;
+	pce->data = req->data_len;
+
+	/* write cntr0_iv0 for countC */
+	pce = cmdlistinfo->encr_cntr_iv;
+	pce->data = req->count_c;
+	/* write cntr1_iv1 for nPkts, and bearer */
+	pce++;
+	if (npkts == 1)
+		npkts = 0;
+	pce->data = req->bearer << CRYPTO_CNTR1_IV1_REG_F8_BEARER |
+				npkts << CRYPTO_CNTR1_IV1_REG_F8_PKT_CNT;
+
+	/* write go */
+	pce = cmdlistinfo->go_proc;
+	pce->addr = (uint32_t)(CRYPTO_GOPROC_REG + pce_dev->phy_iobase);
+
+	return 0;
+}
+
 static int _ce_setup_hash_direct(struct qce_device *pce_dev,
 				struct qce_sha_req *sreq)
 {
 	uint32_t auth32[SHA256_DIGEST_SIZE / sizeof(uint32_t)];
 	uint32_t diglen;
 	bool use_hw_key = false;
+	bool use_pipe_key = false;
 	int i;
 	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {
 			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+	uint32_t authk_size_in_word = sreq->authklen/sizeof(uint32_t);
 	bool sha1 = false;
 	uint32_t auth_cfg = 0;
 
@@ -944,25 +1107,25 @@
 	if ((sreq->alg == QCE_HASH_SHA1_HMAC) ||
 			(sreq->alg == QCE_HASH_SHA256_HMAC) ||
 			(sreq->alg ==  QCE_HASH_AES_CMAC)) {
-		uint32_t authk_size_in_word = sreq->authklen/sizeof(uint32_t);
 
 		_byte_stream_to_net_words(mackey32, sreq->authkey,
 						sreq->authklen);
 
-		/* check for null key. If null, use hw key*/
-		for (i = 0; i < authk_size_in_word; i++) {
-			if (mackey32[i] != 0)
-				break;
-		}
+		/* no more check for null key. use flag to check*/
 
-		if (i == authk_size_in_word)
+		if ((sreq->flags & QCRYPTO_CTX_USE_HW_KEY) ==
+					QCRYPTO_CTX_USE_HW_KEY) {
 			use_hw_key = true;
-		else
-			/* Clear auth_ivn, auth_keyn registers  */
+		} else if ((sreq->flags & QCRYPTO_CTX_USE_PIPE_KEY) ==
+						QCRYPTO_CTX_USE_PIPE_KEY) {
+			use_pipe_key = true;
+		} else {
+			/* setup key */
 			for (i = 0; i < authk_size_in_word; i++)
 				writel_relaxed(mackey32[i], (pce_dev->iobase +
 					(CRYPTO_AUTH_KEY0_REG +
 							i*sizeof(uint32_t))));
+		}
 	}
 
 	if (sreq->alg ==  QCE_HASH_AES_CMAC)
@@ -1036,6 +1199,10 @@
 		auth_cfg |= 1 << CRYPTO_FIRST;
 	else
 		auth_cfg &= ~(1 << CRYPTO_FIRST);
+	if (use_hw_key)
+		auth_cfg |= 1 << CRYPTO_USE_HW_KEY_AUTH;
+	if (use_pipe_key)
+		auth_cfg |= 1 << CRYPTO_USE_PIPE_KEY_AUTH;
 go_proc:
 	 /* write seg_cfg */
 	writel_relaxed(auth_cfg, pce_dev->iobase + CRYPTO_AUTH_SEG_CFG_REG);
@@ -1071,7 +1238,7 @@
 static int _ce_setup_aead_direct(struct qce_device *pce_dev,
 		struct qce_req *q_req, uint32_t totallen_in, uint32_t coffset)
 {
-	int32_t authk_size_in_word = q_req->authklen/sizeof(uint32_t);
+	int32_t authk_size_in_word = SHA_HMAC_KEY_SIZE/sizeof(uint32_t);
 	int i;
 	uint32_t mackey32[SHA_HMAC_KEY_SIZE/sizeof(uint32_t)] = {0};
 	uint32_t a_cfg;
@@ -1454,15 +1621,25 @@
 						(i * sizeof(uint32_t)));
 			}
 			/* write xts du size */
-			if (use_pipe_key == true)
-				writel_relaxed(min((uint32_t)QCE_SECTOR_SIZE,
-						creq->cryptlen),
-						pce_dev->iobase +
-						CRYPTO_ENCR_XTS_DU_SIZE_REG);
-			else
-				writel_relaxed(creq->cryptlen ,
-						pce_dev->iobase +
-						CRYPTO_ENCR_XTS_DU_SIZE_REG);
+			switch (creq->flags & QCRYPTO_CTX_XTS_MASK) {
+			case QCRYPTO_CTX_XTS_DU_SIZE_512B:
+				writel_relaxed(
+					min((uint32_t)QCE_SECTOR_SIZE,
+					creq->cryptlen), pce_dev->iobase +
+					CRYPTO_ENCR_XTS_DU_SIZE_REG);
+				break;
+			case QCRYPTO_CTX_XTS_DU_SIZE_1KB:
+				writel_relaxed(
+					min((uint32_t)(QCE_SECTOR_SIZE * 2),
+					creq->cryptlen), pce_dev->iobase +
+					CRYPTO_ENCR_XTS_DU_SIZE_REG);
+				break;
+			default:
+				writel_relaxed(creq->cryptlen,
+					pce_dev->iobase +
+					CRYPTO_ENCR_XTS_DU_SIZE_REG);
+				break;
+			}
 		}
 		if (creq->mode !=  QCE_MODE_ECB) {
 			if (creq->mode ==  QCE_MODE_XTS)
@@ -1556,6 +1733,168 @@
 	return 0;
 };
 
+static int _ce_f9_setup_direct(struct qce_device *pce_dev,
+				 struct qce_f9_req *req)
+{
+	uint32_t ikey32[OTA_KEY_SIZE/sizeof(uint32_t)];
+	uint32_t key_size_in_word = OTA_KEY_SIZE/sizeof(uint32_t);
+	uint32_t auth_cfg;
+	int i;
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		auth_cfg = pce_dev->reg.auth_cfg_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+	default:
+		auth_cfg = pce_dev->reg.auth_cfg_snow3g;
+		break;
+	};
+
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
+	/* set big endian configuration */
+	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/*
+	 * Ensure previous instructions (setting the CONFIG register)
+	 * was completed before issuing starting to set other config register
+	 * This is to ensure the configurations are done in correct endian-ness
+	 * as set in the CONFIG registers
+	 */
+	mb();
+
+	/* write enc_seg_cfg */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_ENCR_SEG_CFG_REG);
+
+	/* write ecn_seg_size */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_ENCR_SEG_SIZE_REG);
+
+	/* write key in CRYPTO_AUTH_IV0-3_REG */
+	_byte_stream_to_net_words(ikey32, &req->ikey[0], OTA_KEY_SIZE);
+	for (i = 0; i < key_size_in_word; i++)
+		writel_relaxed(ikey32[i], (pce_dev->iobase +
+			(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t))));
+
+	/* write last bits  in CRYPTO_AUTH_IV4_REG  */
+	writel_relaxed(req->last_bits, (pce_dev->iobase +
+					CRYPTO_AUTH_IV4_REG));
+
+	/* write fresh to CRYPTO_AUTH_BYTECNT0_REG */
+	writel_relaxed(req->fresh, (pce_dev->iobase +
+					 CRYPTO_AUTH_BYTECNT0_REG));
+
+	/* write count-i  to CRYPTO_AUTH_BYTECNT1_REG */
+	writel_relaxed(req->count_i, (pce_dev->iobase +
+					 CRYPTO_AUTH_BYTECNT1_REG));
+
+	/* write auth seg cfg */
+	if (req->direction == QCE_OTA_DIR_DOWNLINK)
+		auth_cfg |= BIT(CRYPTO_F9_DIRECTION);
+	writel_relaxed(auth_cfg, pce_dev->iobase + CRYPTO_AUTH_SEG_CFG_REG);
+
+	/* write auth seg size */
+	writel_relaxed(req->msize, pce_dev->iobase + CRYPTO_AUTH_SEG_SIZE_REG);
+
+	/* write auth seg start*/
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_START_REG);
+
+	/* write seg size  */
+	writel_relaxed(req->msize, pce_dev->iobase + CRYPTO_SEG_SIZE_REG);
+
+	/* set little endian configuration before go*/
+	writel_relaxed(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/* write go */
+	writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase +  CRYPTO_GOPROC_REG);
+	/*
+	 * Ensure previous instructions (setting the GO register)
+	 * was completed before issuing a DMA transfer request
+	 */
+	mb();
+	return 0;
+}
+
+static int _ce_f8_setup_direct(struct qce_device *pce_dev,
+		struct qce_f8_req *req, bool key_stream_mode,
+		uint16_t npkts, uint16_t cipher_offset, uint16_t cipher_size)
+{
+	int i = 0;
+	uint32_t encr_cfg = 0;
+	uint32_t ckey32[OTA_KEY_SIZE/sizeof(uint32_t)];
+	uint32_t key_size_in_word = OTA_KEY_SIZE/sizeof(uint32_t);
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		encr_cfg = pce_dev->reg.encr_cfg_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+	default:
+		encr_cfg = pce_dev->reg.encr_cfg_snow3g;
+		break;
+	};
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+	/* set big endian configuration */
+	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/* write auth seg configuration */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_CFG_REG);
+	/* write auth seg size */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_AUTH_SEG_SIZE_REG);
+
+	/* write key */
+	_byte_stream_to_net_words(ckey32, &req->ckey[0], OTA_KEY_SIZE);
+
+	for (i = 0; i < key_size_in_word; i++)
+		writel_relaxed(ckey32[i], (pce_dev->iobase +
+			(CRYPTO_ENCR_KEY0_REG + i*sizeof(uint32_t))));
+	/* write encr seg cfg */
+	if (key_stream_mode)
+		encr_cfg |= BIT(CRYPTO_F8_KEYSTREAM_ENABLE);
+	if (req->direction == QCE_OTA_DIR_DOWNLINK)
+		encr_cfg |= BIT(CRYPTO_F8_DIRECTION);
+	writel_relaxed(encr_cfg, pce_dev->iobase +
+		CRYPTO_ENCR_SEG_CFG_REG);
+
+	/* write encr seg start */
+	writel_relaxed((cipher_offset & 0xffff), pce_dev->iobase +
+		CRYPTO_ENCR_SEG_START_REG);
+	/* write encr seg size  */
+	writel_relaxed(cipher_size, pce_dev->iobase +
+		CRYPTO_ENCR_SEG_SIZE_REG);
+
+	/* write seg size  */
+	writel_relaxed(req->data_len, pce_dev->iobase +
+		CRYPTO_SEG_SIZE_REG);
+
+	/* write cntr0_iv0 for countC */
+	writel_relaxed(req->count_c, pce_dev->iobase +
+		CRYPTO_CNTR0_IV0_REG);
+	/* write cntr1_iv1 for nPkts, and bearer */
+	if (npkts == 1)
+		npkts = 0;
+	writel_relaxed(req->bearer << CRYPTO_CNTR1_IV1_REG_F8_BEARER |
+				npkts << CRYPTO_CNTR1_IV1_REG_F8_PKT_CNT,
+			pce_dev->iobase + CRYPTO_CNTR1_IV1_REG);
+
+	/* set little endian configuration before go*/
+	writel_relaxed(pce_dev->reg.crypto_cfg_le, (pce_dev->iobase +
+							CRYPTO_CONFIG_REG));
+	/* write go */
+	writel_relaxed(((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+				pce_dev->iobase +  CRYPTO_GOPROC_REG);
+	/*
+	 * Ensure previous instructions (setting the GO register)
+	 * was completed before issuing a DMA transfer request
+	 */
+	mb();
+	return 0;
+}
+
+
 static int _qce_unlock_other_pipes(struct qce_device *pce_dev)
 {
 	int rc = 0;
@@ -1705,6 +2044,48 @@
 	return 0;
 };
 
+static int _f9_complete(struct qce_device *pce_dev)
+{
+	uint32_t mac_i;
+	uint32_t status;
+	int32_t result_status;
+
+	dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_src,
+				pce_dev->ota_size, DMA_TO_DEVICE);
+	_byte_stream_to_net_words(&mac_i,
+		(char *)(&pce_dev->ce_sps.result->auth_iv[0]),
+		CRYPTO_REG_SIZE);
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+	if (_qce_unlock_other_pipes(pce_dev)) {
+		pce_dev->qce_cb(pce_dev->areq, NULL, NULL, -ENXIO);
+		return -ENXIO;
+	}
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+				| (1 <<  CRYPTO_HSD_ERR))) {
+		pr_err("f9 operation error. Status %x\n", status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status |
+				pce_dev->ce_sps.producer_status)  {
+		pr_err("f9 sps operation error. sps status %x %x\n",
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("f9 operation not done? Status %x, sps status %x %x\n",
+			status,
+			pce_dev->ce_sps.consumer_status,
+			pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+	} else {
+		result_status = 0;
+	}
+	pce_dev->qce_cb(pce_dev->areq, (void *) mac_i, NULL,
+				result_status);
+
+	return 0;
+}
+
 static int _ablk_cipher_complete(struct qce_device *pce_dev)
 {
 	struct ablkcipher_request *areq;
@@ -1811,6 +2192,47 @@
 	return 0;
 };
 
+static int _f8_complete(struct qce_device *pce_dev)
+{
+	uint32_t status;
+	int32_t result_status;
+
+	if (pce_dev->phy_ota_dst != 0)
+		dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_dst,
+				pce_dev->ota_size, DMA_FROM_DEVICE);
+	if (pce_dev->phy_ota_src != 0)
+		dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_src,
+				pce_dev->ota_size, (pce_dev->phy_ota_dst) ?
+				DMA_TO_DEVICE : DMA_BIDIRECTIONAL);
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+	if (_qce_unlock_other_pipes(pce_dev)) {
+		pce_dev->qce_cb(pce_dev->areq, NULL, NULL, -ENXIO);
+		return -ENXIO;
+	}
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+				| (1 <<  CRYPTO_HSD_ERR))) {
+		pr_err("f8 operation error. Status %x\n", status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status |
+				pce_dev->ce_sps.producer_status)  {
+		pr_err("f8 sps operation error. sps status %x %x\n",
+				pce_dev->ce_sps.consumer_status,
+				pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("f8 operation not done? Status %x, sps status %x %x\n",
+			status,
+			pce_dev->ce_sps.consumer_status,
+			pce_dev->ce_sps.producer_status);
+		result_status = -ENXIO;
+	} else {
+		result_status = 0;
+	}
+	pce_dev->qce_cb(pce_dev->areq, NULL, NULL, result_status);
+	return 0;
+}
+
 #ifdef QCE_DEBUG
 static void _qce_dump_descr_fifos(struct qce_device *pce_dev)
 {
@@ -1903,8 +2325,11 @@
 
 static void _qce_set_flag(struct sps_transfer *sps_bam_pipe, uint32_t flag)
 {
-	struct sps_iovec *iovec = sps_bam_pipe->iovec +
-					(sps_bam_pipe->iovec_count - 1);
+	struct sps_iovec *iovec;
+
+	if (sps_bam_pipe->iovec_count == 0)
+		return;
+	iovec  = sps_bam_pipe->iovec + (sps_bam_pipe->iovec_count - 1);
 	iovec->flags |= flag;
 }
 
@@ -1913,16 +2338,26 @@
 {
 	struct sps_iovec *iovec = sps_bam_pipe->iovec +
 					sps_bam_pipe->iovec_count;
-	if (sps_bam_pipe->iovec_count == QCE_MAX_NUM_DSCR) {
-		pr_err("Num of descrptor %d exceed max (%d)",
-			sps_bam_pipe->iovec_count, (uint32_t)QCE_MAX_NUM_DSCR);
-		return -ENOMEM;
-	}
-	if (len) {
-		iovec->size = len;
+	uint32_t data_cnt;
+
+	while (len > 0) {
+		if (sps_bam_pipe->iovec_count == QCE_MAX_NUM_DSCR) {
+			pr_err("Num of descrptor %d exceed max (%d)",
+				sps_bam_pipe->iovec_count,
+				(uint32_t)QCE_MAX_NUM_DSCR);
+			return -ENOMEM;
+		}
+		if (len > SPS_MAX_PKT_SIZE)
+			data_cnt = SPS_MAX_PKT_SIZE;
+		else
+			data_cnt = len;
+		iovec->size = data_cnt;
 		iovec->addr = addr;
 		iovec->flags = 0;
 		sps_bam_pipe->iovec_count++;
+		iovec++;
+		addr += data_cnt;
+		len -= data_cnt;
 	}
 	return 0;
 }
@@ -1988,13 +2423,15 @@
 	int rc = 0;
 
 	_qce_dump_descr_fifos(pce_dev);
-	rc = sps_transfer(pce_dev->ce_sps.consumer.pipe,
+	if (pce_dev->ce_sps.in_transfer.iovec_count) {
+		rc = sps_transfer(pce_dev->ce_sps.consumer.pipe,
 					  &pce_dev->ce_sps.in_transfer);
-	if (rc) {
-		pr_err("sps_xfr() fail (consumer pipe=0x%x) rc = %d,",
+		if (rc) {
+			pr_err("sps_xfr() fail (consumer pipe=0x%x) rc = %d,",
 				(u32)pce_dev->ce_sps.consumer.pipe, rc);
-		_qce_dump_descr_fifos_fail(pce_dev);
-		return rc;
+			_qce_dump_descr_fifos_fail(pce_dev);
+			return rc;
+		}
 	}
 	rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
 					  &pce_dev->ce_sps.out_transfer);
@@ -2195,8 +2632,8 @@
 	list_del(&pbam->qlist);
 	kfree(pbam);
 
-	pce_dev->pbam = NULL;
 ret:
+	pce_dev->pbam = NULL;
 	mutex_unlock(&bam_register_lock);
 }
 
@@ -2255,6 +2692,10 @@
 					CRYPTO_BAM_CNFG_BITS_REG);
 	pbam->support_cmd_dscr =  (bam_cfg & CRYPTO_BAM_CD_ENABLE_MASK) ?
 					true : false;
+	if (pbam->support_cmd_dscr == false) {
+		pr_info("qce50 don't support command descriptor. bam_cfg%x\n",
+								 bam_cfg);
+	}
 	pce_dev->support_cmd_dscr = pbam->support_cmd_dscr;
 
 	bam.phys_addr = pce_dev->ce_sps.bam_mem;
@@ -2282,6 +2723,7 @@
 		bam.manage = SPS_BAM_MGR_DEVICE_REMOTE;
 	else
 		bam.manage = SPS_BAM_MGR_LOCAL;
+
 	bam.ee = 1;
 
 	pr_debug("bam physical base=0x%x\n", (u32)bam.phys_addr);
@@ -2419,6 +2861,55 @@
 	_sha_complete(pce_dev);
 };
 
+static void _f9_sps_producer_callback(struct sps_event_notify *notify)
+{
+	struct qce_device *pce_dev = (struct qce_device *)
+		((struct sps_event_notify *)notify)->user;
+
+	pce_dev->ce_sps.notify = *notify;
+	pr_debug("sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
+			notify->event_id,
+			notify->data.transfer.iovec.addr,
+			notify->data.transfer.iovec.size,
+			notify->data.transfer.iovec.flags);
+	/* done */
+	_f9_complete(pce_dev);
+}
+
+static void _f8_sps_producer_callback(struct sps_event_notify *notify)
+{
+	struct qce_device *pce_dev = (struct qce_device *)
+		((struct sps_event_notify *)notify)->user;
+
+	pce_dev->ce_sps.notify = *notify;
+	pr_debug("sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
+			notify->event_id,
+			notify->data.transfer.iovec.addr,
+			notify->data.transfer.iovec.size,
+			notify->data.transfer.iovec.flags);
+
+	if (pce_dev->ce_sps.producer_state == QCE_PIPE_STATE_COMP) {
+		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+		/* done */
+		_f8_complete(pce_dev);
+	} else {
+		int rc = 0;
+		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+		pce_dev->ce_sps.out_transfer.iovec_count = 0;
+		_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+					CRYPTO_RESULT_DUMP_SIZE,
+					  &pce_dev->ce_sps.out_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_INT);
+		rc = sps_transfer(pce_dev->ce_sps.producer.pipe,
+					  &pce_dev->ce_sps.out_transfer);
+		if (rc) {
+			pr_err("sps_xfr() fail (producer pipe=0x%x) rc = %d,",
+				(u32)pce_dev->ce_sps.producer.pipe, rc);
+		}
+	}
+}
+
 static void _ablk_cipher_sps_producer_callback(struct sps_event_notify *notify)
 {
 	struct qce_device *pce_dev = (struct qce_device *)
@@ -3251,6 +3742,172 @@
 	return 0;
 }
 
+static int _setup_f8_cmdlistptrs(struct qce_device *pdev,
+	unsigned char **pvaddr, enum qce_ota_algo_enum alg)
+{
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
+	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
+	struct qce_cmdlist_info *pcl_info = NULL;
+	int i = 0;
+	uint32_t encr_cfg = 0;
+	uint32_t key_reg = 4;
+
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
+	ce_vaddr_start = (uint32_t)(*pvaddr);
+
+	/*
+	 * Designate chunks of the allocated memory to various
+	 * command list pointers related to f8 cipher algorithm defined
+	 * in ce_cmdlistptrs_ops structure.
+	 */
+
+	switch (alg) {
+	case QCE_OTA_ALGO_KASUMI:
+		cmdlistptr->f8_kasumi.cmdlist = (uint32_t)ce_vaddr;
+		pcl_info = &(cmdlistptr->f8_kasumi);
+		encr_cfg = pdev->reg.encr_cfg_kasumi;
+		break;
+
+	case QCE_OTA_ALGO_SNOW3G:
+	default:
+		cmdlistptr->f8_snow3g.cmdlist = (uint32_t)ce_vaddr;
+		pcl_info = &(cmdlistptr->f8_snow3g);
+		encr_cfg = pdev->reg.encr_cfg_snow3g;
+		break;
+	}
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+							0, NULL);
+	/* set config to big endian */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_SEG_SIZE_REG, 0,
+						&pcl_info->seg_size);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, encr_cfg,
+						&pcl_info->encr_seg_cfg);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG, 0,
+						&pcl_info->encr_seg_size);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_START_REG, 0,
+						&pcl_info->encr_seg_start);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG, 0,
+						&pcl_info->auth_seg_cfg);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG,
+						0, &pcl_info->auth_seg_size);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG,
+						0, &pcl_info->auth_seg_start);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_KEY0_REG, 0,
+						 &pcl_info->encr_key);
+	for (i = 1; i < key_reg; i++)
+		qce_add_cmd_element(pdev, &ce_vaddr,
+				(CRYPTO_ENCR_KEY0_REG + i * sizeof(uint32_t)),
+				0, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR0_IV0_REG, 0,
+						&pcl_info->encr_cntr_iv);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR1_IV1_REG, 0,
+								NULL);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+					pdev->reg.crypto_cfg_le, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
+			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+			&pcl_info->go_proc);
+
+	pcl_info->size = (uint32_t)ce_vaddr - (uint32_t)ce_vaddr_start;
+	*pvaddr = (unsigned char *) ce_vaddr;
+
+	return 0;
+}
+
+static int _setup_f9_cmdlistptrs(struct qce_device *pdev,
+	unsigned char **pvaddr, enum qce_ota_algo_enum alg)
+{
+	struct sps_command_element *ce_vaddr;
+	uint32_t ce_vaddr_start;
+	struct qce_cmdlistptr_ops *cmdlistptr = &pdev->ce_sps.cmdlistptr;
+	struct qce_cmdlist_info *pcl_info = NULL;
+	int i = 0;
+	uint32_t auth_cfg = 0;
+	uint32_t iv_reg = 0;
+
+	*pvaddr = (unsigned char *) ALIGN(((unsigned int)(*pvaddr)),
+					pdev->ce_sps.ce_burst_size);
+	ce_vaddr_start = (uint32_t)(*pvaddr);
+	ce_vaddr = (struct sps_command_element *)(*pvaddr);
+
+	/*
+	 * Designate chunks of the allocated memory to various
+	 * command list pointers related to authentication operations
+	 * defined in ce_cmdlistptrs_ops structure.
+	 */
+	switch (alg) {
+	case QCE_OTA_ALGO_KASUMI:
+		cmdlistptr->f9_kasumi.cmdlist = (uint32_t)ce_vaddr;
+		pcl_info = &(cmdlistptr->f9_kasumi);
+		auth_cfg = pdev->reg.auth_cfg_kasumi;
+		break;
+
+	case QCE_OTA_ALGO_SNOW3G:
+	default:
+		cmdlistptr->f9_snow3g.cmdlist = (uint32_t)ce_vaddr;
+		pcl_info = &(cmdlistptr->f9_snow3g);
+		auth_cfg = pdev->reg.auth_cfg_snow3g;
+	};
+
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+							0, NULL);
+	/* set config to big endian */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
+
+	iv_reg = 5;
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_SEG_SIZE_REG, 0,
+						&pcl_info->seg_size);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, 0,
+						&pcl_info->encr_seg_cfg);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
+					auth_cfg, &pcl_info->auth_seg_cfg);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_SIZE_REG, 0,
+						&pcl_info->auth_seg_size);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG, 0,
+						&pcl_info->auth_seg_start);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_IV0_REG, 0,
+							&pcl_info->auth_iv);
+	for (i = 1; i < iv_reg; i++) {
+		qce_add_cmd_element(pdev, &ce_vaddr,
+				(CRYPTO_AUTH_IV0_REG + i*sizeof(uint32_t)),
+				0, NULL);
+	}
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT0_REG,
+					0, &pcl_info->auth_bytecount);
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_BYTECNT1_REG, 0, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
+					pdev->reg.crypto_cfg_le, NULL);
+
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_GOPROC_REG,
+			((1 << CRYPTO_GO) | (1 << CRYPTO_RESULTS_DUMP)),
+			&pcl_info->go_proc);
+
+	pcl_info->size = (uint32_t)ce_vaddr - (uint32_t)ce_vaddr_start;
+	*pvaddr = (unsigned char *) ce_vaddr;
+
+	return 0;
+}
+
 static int _setup_unlock_pipe_cmdlistptrs(struct qce_device *pdev,
 		unsigned char **pvaddr)
 {
@@ -3334,6 +3991,10 @@
 
 	_setup_aead_ccm_cmdlistptrs(pdev, pvaddr, true);
 	_setup_aead_ccm_cmdlistptrs(pdev, pvaddr, false);
+	_setup_f8_cmdlistptrs(pdev, pvaddr, QCE_OTA_ALGO_KASUMI);
+	_setup_f8_cmdlistptrs(pdev, pvaddr, QCE_OTA_ALGO_SNOW3G);
+	_setup_f9_cmdlistptrs(pdev, pvaddr, QCE_OTA_ALGO_KASUMI);
+	_setup_f9_cmdlistptrs(pdev, pvaddr, QCE_OTA_ALGO_SNOW3G);
 	_setup_unlock_pipe_cmdlistptrs(pdev, pvaddr);
 
 	return 0;
@@ -3461,6 +4122,13 @@
 		(CRYPTO_ENCR_ALG_DES << CRYPTO_ENCR_ALG) |
 		(CRYPTO_ENCR_MODE_CBC << CRYPTO_ENCR_MODE);
 
+	/* Initialize encr_cfg register for kasumi/snow3g  alg */
+	pce_dev->reg.encr_cfg_kasumi =
+		(CRYPTO_ENCR_ALG_KASUMI << CRYPTO_ENCR_ALG);
+
+	pce_dev->reg.encr_cfg_snow3g =
+		(CRYPTO_ENCR_ALG_SNOW_3G << CRYPTO_ENCR_ALG);
+
 	/* Initialize auth_cfg register for CMAC alg */
 	pce_dev->reg.auth_cfg_cmac_128 =
 		(1 << CRYPTO_LAST) | (1 << CRYPTO_FIRST) |
@@ -3531,6 +4199,13 @@
 		((MAX_NONCE/sizeof(uint32_t)) << CRYPTO_AUTH_NONCE_NUM_WORDS);
 	pce_dev->reg.auth_cfg_aes_ccm_256 &= ~(1 << CRYPTO_USE_HW_KEY_AUTH);
 
+	/* Initialize auth_cfg register for kasumi/snow3g */
+	pce_dev->reg.auth_cfg_kasumi =
+			(CRYPTO_AUTH_ALG_KASUMI << CRYPTO_AUTH_ALG) |
+				BIT(CRYPTO_FIRST) | BIT(CRYPTO_LAST);
+	pce_dev->reg.auth_cfg_snow3g =
+			(CRYPTO_AUTH_ALG_SNOW3G << CRYPTO_AUTH_ALG) |
+				BIT(CRYPTO_FIRST) | BIT(CRYPTO_LAST);
 	return 0;
 }
 
@@ -4105,6 +4780,302 @@
 }
 EXPORT_SYMBOL(qce_process_sha_req);
 
+int qce_f8_req(void *handle, struct qce_f8_req *req,
+			void *cookie, qce_comp_func_ptr_t qce_cb)
+{
+	struct qce_device *pce_dev = (struct qce_device *) handle;
+	bool key_stream_mode;
+	dma_addr_t dst;
+	int rc;
+	struct qce_cmdlist_info *cmdlistinfo;
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.f8_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+		cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.f8_snow3g;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	key_stream_mode = (req->data_in == NULL);
+
+	if ((key_stream_mode && (req->data_len & 0xf)) ||
+				(req->bearer >= QCE_OTA_MAX_BEARER))
+		return -EINVAL;
+
+	/* F8 cipher input       */
+	if (key_stream_mode)
+		pce_dev->phy_ota_src = 0;
+	else {
+		pce_dev->phy_ota_src = dma_map_single(pce_dev->pdev,
+					req->data_in, req->data_len,
+					(req->data_in == req->data_out) ?
+					DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+	}
+
+	/* F8 cipher output     */
+	if (req->data_in != req->data_out) {
+		dst = dma_map_single(pce_dev->pdev, req->data_out,
+				req->data_len, DMA_FROM_DEVICE);
+		pce_dev->phy_ota_dst = dst;
+	} else {
+		/* in place ciphering */
+		dst = pce_dev->phy_ota_src;
+		pce_dev->phy_ota_dst = 0;
+	}
+	pce_dev->ota_size = req->data_len;
+
+
+	/* set up crypto device */
+	if (pce_dev->support_cmd_dscr)
+		rc = _ce_f8_setup(pce_dev, req, key_stream_mode, 1, 0,
+				 req->data_len, cmdlistinfo);
+	else
+		rc = _ce_f8_setup_direct(pce_dev, req, key_stream_mode, 1, 0,
+				 req->data_len);
+	if (rc < 0)
+		goto bad;
+
+	/* setup for callback, and issue command to sps */
+	pce_dev->areq = cookie;
+	pce_dev->qce_cb = qce_cb;
+
+	/* Register producer callback event for DESC_DONE event. */
+	pce_dev->ce_sps.producer.event.callback =
+				_f8_sps_producer_callback;
+	pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
+	rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
+					&pce_dev->ce_sps.producer.event);
+	if (rc) {
+		pr_err("Producer callback registration failed rc = %d\n", rc);
+		goto bad;
+	}
+	_qce_sps_iovec_count_init(pce_dev);
+
+	if (pce_dev->support_cmd_dscr)
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+					&pce_dev->ce_sps.in_transfer);
+
+	if (!key_stream_mode) {
+		_qce_sps_add_data((uint32_t)pce_dev->phy_ota_src, req->data_len,
+					&pce_dev->ce_sps.in_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
+	}
+
+	_qce_sps_add_data((uint32_t)dst, req->data_len,
+					&pce_dev->ce_sps.out_transfer);
+
+	if (req->data_len > SPS_MAX_PKT_SIZE) {
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+	} else {
+		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+		_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+					CRYPTO_RESULT_DUMP_SIZE,
+					  &pce_dev->ce_sps.out_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+	}
+	rc = _qce_sps_transfer(pce_dev);
+	if (rc)
+		goto bad;
+	return 0;
+bad:
+	if (pce_dev->phy_ota_dst != 0)
+		dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_dst,
+				req->data_len, DMA_FROM_DEVICE);
+	if (pce_dev->phy_ota_src != 0)
+		dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_src,
+				req->data_len,
+				(req->data_in == req->data_out) ?
+					DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+	return rc;
+}
+EXPORT_SYMBOL(qce_f8_req);
+
+int qce_f8_multi_pkt_req(void *handle, struct qce_f8_multi_pkt_req *mreq,
+			void *cookie, qce_comp_func_ptr_t qce_cb)
+{
+	struct qce_device *pce_dev = (struct qce_device *) handle;
+	uint16_t num_pkt = mreq->num_pkt;
+	uint16_t cipher_start = mreq->cipher_start;
+	uint16_t cipher_size = mreq->cipher_size;
+	struct qce_f8_req *req = &mreq->qce_f8_req;
+	uint32_t total;
+	dma_addr_t dst = 0;
+	int rc = 0;
+	struct qce_cmdlist_info *cmdlistinfo;
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.f8_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+		cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.f8_snow3g;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	total = num_pkt *  req->data_len;
+
+	/* F8 cipher input       */
+	pce_dev->phy_ota_src = dma_map_single(pce_dev->pdev,
+				req->data_in, total,
+				(req->data_in == req->data_out) ?
+				DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+
+	/* F8 cipher output      */
+	if (req->data_in != req->data_out) {
+		dst = dma_map_single(pce_dev->pdev, req->data_out, total,
+						DMA_FROM_DEVICE);
+		pce_dev->phy_ota_dst = dst;
+	} else {
+		/* in place ciphering */
+		dst = pce_dev->phy_ota_src;
+		pce_dev->phy_ota_dst = 0;
+	}
+
+	pce_dev->ota_size = total;
+
+	/* set up crypto device */
+	if (pce_dev->support_cmd_dscr)
+		rc = _ce_f8_setup(pce_dev, req, false, num_pkt, cipher_start,
+			cipher_size, cmdlistinfo);
+	else
+		rc = _ce_f8_setup_direct(pce_dev, req, false, num_pkt,
+			cipher_start, cipher_size);
+	if (rc)
+		goto bad;
+
+	/* setup for callback, and issue command to sps */
+	pce_dev->areq = cookie;
+	pce_dev->qce_cb = qce_cb;
+
+	/* Register producer callback event for DESC_DONE event. */
+	pce_dev->ce_sps.producer.event.callback =
+				_f8_sps_producer_callback;
+	pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
+	rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
+					&pce_dev->ce_sps.producer.event);
+	if (rc) {
+		pr_err("Producer callback registration failed rc = %d\n", rc);
+		goto bad;
+	}
+	_qce_sps_iovec_count_init(pce_dev);
+
+	if (pce_dev->support_cmd_dscr)
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+					&pce_dev->ce_sps.in_transfer);
+
+	_qce_sps_add_data((uint32_t)pce_dev->phy_ota_src, total,
+					&pce_dev->ce_sps.in_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
+
+	_qce_sps_add_data((uint32_t)dst, total,
+					&pce_dev->ce_sps.out_transfer);
+
+	if (total > SPS_MAX_PKT_SIZE) {
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_IDLE;
+	} else {
+		pce_dev->ce_sps.producer_state = QCE_PIPE_STATE_COMP;
+		_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+					CRYPTO_RESULT_DUMP_SIZE,
+					  &pce_dev->ce_sps.out_transfer);
+		_qce_set_flag(&pce_dev->ce_sps.out_transfer,
+							SPS_IOVEC_FLAG_INT);
+	}
+	rc = _qce_sps_transfer(pce_dev);
+
+	if (rc == 0)
+		return 0;
+bad:
+	if (pce_dev->phy_ota_dst)
+		dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_dst, total,
+				DMA_FROM_DEVICE);
+	dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_src, total,
+				(req->data_in == req->data_out) ?
+				DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+	return rc;
+}
+EXPORT_SYMBOL(qce_f8_multi_pkt_req);
+
+int qce_f9_req(void *handle, struct qce_f9_req *req, void *cookie,
+			qce_comp_func_ptr_t qce_cb)
+{
+	struct qce_device *pce_dev = (struct qce_device *) handle;
+	int rc;
+	struct qce_cmdlist_info *cmdlistinfo;
+
+	switch (req->algorithm) {
+	case QCE_OTA_ALGO_KASUMI:
+		cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.f9_kasumi;
+		break;
+	case QCE_OTA_ALGO_SNOW3G:
+		cmdlistinfo = &pce_dev->ce_sps.cmdlistptr.f9_snow3g;
+		break;
+	default:
+		return -EINVAL;
+	};
+
+	pce_dev->phy_ota_src = dma_map_single(pce_dev->pdev, req->message,
+			req->msize, DMA_TO_DEVICE);
+
+	pce_dev->ota_size = req->msize;
+
+	if (pce_dev->support_cmd_dscr)
+		rc = _ce_f9_setup(pce_dev, req, cmdlistinfo);
+	else
+		rc = _ce_f9_setup_direct(pce_dev, req);
+	if (rc < 0)
+		goto bad;
+
+	/* setup for callback, and issue command to sps */
+	pce_dev->areq = cookie;
+	pce_dev->qce_cb = qce_cb;
+
+	/* Register producer callback event for DESC_DONE event. */
+	pce_dev->ce_sps.producer.event.callback = _f9_sps_producer_callback;
+	pce_dev->ce_sps.producer.event.options = SPS_O_DESC_DONE;
+	rc = sps_register_event(pce_dev->ce_sps.producer.pipe,
+					&pce_dev->ce_sps.producer.event);
+	if (rc) {
+		pr_err("Producer callback registration failed rc = %d\n", rc);
+		goto bad;
+	}
+
+	_qce_sps_iovec_count_init(pce_dev);
+	if (pce_dev->support_cmd_dscr)
+		_qce_sps_add_cmd(pce_dev, SPS_IOVEC_FLAG_LOCK, cmdlistinfo,
+					&pce_dev->ce_sps.in_transfer);
+	_qce_sps_add_data((uint32_t)pce_dev->phy_ota_src, req->msize,
+					&pce_dev->ce_sps.in_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.in_transfer,
+				SPS_IOVEC_FLAG_EOT|SPS_IOVEC_FLAG_NWD);
+
+	_qce_sps_add_data(GET_PHYS_ADDR(pce_dev->ce_sps.result_dump),
+					CRYPTO_RESULT_DUMP_SIZE,
+					  &pce_dev->ce_sps.out_transfer);
+	_qce_set_flag(&pce_dev->ce_sps.out_transfer, SPS_IOVEC_FLAG_INT);
+	rc = _qce_sps_transfer(pce_dev);
+	if (rc)
+		goto bad;
+	return 0;
+bad:
+	dma_unmap_single(pce_dev->pdev, pce_dev->phy_ota_src,
+				req->msize, DMA_TO_DEVICE);
+	return rc;
+}
+EXPORT_SYMBOL(qce_f9_req);
+
 static int __qce_get_device_tree_data(struct platform_device *pdev,
 		struct qce_device *pce_dev)
 {
@@ -4115,6 +5086,28 @@
 				"qcom,ce-hw-shared");
 	pce_dev->support_hw_key = of_property_read_bool((&pdev->dev)->of_node,
 				"qcom,ce-hw-key");
+
+	pce_dev->use_sw_aes_cbc_ecb_ctr_algo =
+				of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-sw-aes-cbc-ecb-ctr-algo");
+	pce_dev->use_sw_aead_algo =
+				of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-sw-aead-algo");
+	pce_dev->use_sw_aes_xts_algo =
+				of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-sw-aes-xts-algo");
+	pce_dev->use_sw_ahash_algo =
+				of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-sw-ahash-algo");
+	pce_dev->use_sw_hmac_algo =
+				of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-sw-hmac-algo");
+	pce_dev->use_sw_aes_ccm_algo =
+				of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-sw-aes-ccm-algo");
+	pce_dev->support_clk_mgmt_sus_res = of_property_read_bool(
+		(&pdev->dev)->of_node, "qcom,clk-mgmt-sus-res");
+
 	if (of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,bam-pipe-pair",
 				&pce_dev->ce_sps.pipe_pair_index)) {
@@ -4339,7 +5332,7 @@
 		goto err_pce_dev;
 	}
 
-	pce_dev->memsize = 9 * PAGE_SIZE;
+	pce_dev->memsize = 10 * PAGE_SIZE;
 	pce_dev->coh_vmem = dma_alloc_coherent(pce_dev->pdev,
 			pce_dev->memsize, &pce_dev->coh_pmem, GFP_KERNEL);
 	if (pce_dev->coh_vmem == NULL) {
@@ -4354,7 +5347,7 @@
 
 	*rc = qce_enable_clk(pce_dev);
 	if (*rc)
-		goto err;
+		goto err_enable_clk;
 
 	if (_probe_ce_engine(pce_dev)) {
 		*rc = -ENXIO;
@@ -4363,12 +5356,17 @@
 	*rc = 0;
 
 	qce_init_ce_cfg_val(pce_dev);
-	qce_sps_init(pce_dev);
+	*rc  = qce_sps_init(pce_dev);
+	if (*rc)
+		goto err;
 	qce_setup_ce_sps_data(pce_dev);
 	qce_disable_clk(pce_dev);
 
 	return pce_dev;
 err:
+	qce_disable_clk(pce_dev);
+
+err_enable_clk:
 	__qce_deinit_clk(pce_dev);
 
 err_mem:
@@ -4410,6 +5408,11 @@
 }
 EXPORT_SYMBOL(qce_close);
 
+#define OTA_SUPPORT_MASK (1 << CRYPTO_ENCR_SNOW3G_SEL |\
+				1 << CRYPTO_ENCR_KASUMI_SEL |\
+				1 << CRYPTO_AUTH_SNOW3G_SEL |\
+				1 << CRYPTO_AUTH_KASUMI_SEL)
+
 int qce_hw_support(void *handle, struct ce_hw_support *ce_support)
 {
 	struct qce_device *pce_dev = (struct qce_device *)handle;
@@ -4424,15 +5427,32 @@
 	ce_support->cmac  = true;
 	ce_support->aes_key_192 = false;
 	ce_support->aes_xts = true;
-	ce_support->ota = false;
+	if ((pce_dev->engines_avail & OTA_SUPPORT_MASK) == OTA_SUPPORT_MASK)
+		ce_support->ota = true;
+	else
+		ce_support->ota = false;
 	ce_support->bam = true;
 	ce_support->is_shared = (pce_dev->is_shared == 1) ? true : false;
 	ce_support->hw_key = pce_dev->support_hw_key;
 	ce_support->aes_ccm = true;
+	ce_support->clk_mgmt_sus_res = pce_dev->support_clk_mgmt_sus_res;
 	if (pce_dev->ce_sps.minor_version)
 		ce_support->aligned_only = false;
 	else
 		ce_support->aligned_only = true;
+
+	ce_support->use_sw_aes_cbc_ecb_ctr_algo =
+				pce_dev->use_sw_aes_cbc_ecb_ctr_algo;
+	ce_support->use_sw_aead_algo =
+				pce_dev->use_sw_aead_algo;
+	ce_support->use_sw_aes_xts_algo =
+				pce_dev->use_sw_aes_xts_algo;
+	ce_support->use_sw_ahash_algo =
+				pce_dev->use_sw_ahash_algo;
+	ce_support->use_sw_hmac_algo =
+				pce_dev->use_sw_hmac_algo;
+	ce_support->use_sw_aes_ccm_algo =
+				pce_dev->use_sw_aes_ccm_algo;
 	return 0;
 }
 EXPORT_SYMBOL(qce_hw_support);
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index adab5d4..fc387aa 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -113,6 +113,10 @@
 	struct qce_cmdlist_info aead_hmac_sha1_ecb_3des;
 	struct qce_cmdlist_info aead_aes_128_ccm;
 	struct qce_cmdlist_info aead_aes_256_ccm;
+	struct qce_cmdlist_info f8_kasumi;
+	struct qce_cmdlist_info f8_snow3g;
+	struct qce_cmdlist_info f9_kasumi;
+	struct qce_cmdlist_info f9_snow3g;
 	struct qce_cmdlist_info unlock_all_pipes;
 };
 
@@ -140,6 +144,8 @@
 
 	uint32_t encr_cfg_3des_cbc;
 	uint32_t encr_cfg_3des_ecb;
+	uint32_t encr_cfg_kasumi;
+	uint32_t encr_cfg_snow3g;
 
 	uint32_t auth_cfg_cmac_128;
 	uint32_t auth_cfg_cmac_256;
@@ -154,7 +160,8 @@
 	uint32_t auth_cfg_aes_ccm_256;
 	uint32_t auth_cfg_aead_sha1_hmac;
 	uint32_t auth_cfg_aead_sha256_hmac;
-
+	uint32_t auth_cfg_kasumi;
+	uint32_t auth_cfg_snow3g;
 };
 
 /* DM data structure with buffers, commandlists & commmand pointer lists */
diff --git a/drivers/crypto/msm/qcrypto.c b/drivers/crypto/msm/qcrypto.c
index 6606706..3aebaf0 100644
--- a/drivers/crypto/msm/qcrypto.c
+++ b/drivers/crypto/msm/qcrypto.c
@@ -1,6 +1,6 @@
 /* Qualcomm Crypto driver
  *
- * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2014, 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
@@ -24,6 +24,10 @@
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/debugfs.h>
+#include <linux/workqueue.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/cache.h>
 
 #include <crypto/ctr.h>
 #include <crypto/des.h>
@@ -51,6 +55,8 @@
  */
 #define MAX_ALIGN_SIZE  0x40
 
+#define QCRYPTO_HIGH_BANDWIDTH_TIMEOUT 1000
+
 struct crypto_stat {
 	u32 aead_sha1_aes_enc;
 	u32 aead_sha1_aes_dec;
@@ -83,6 +89,30 @@
 static struct crypto_stat _qcrypto_stat;
 static struct dentry *_debug_dent;
 static char _debug_read_buf[DEBUG_MAX_RW_BUF];
+struct crypto_priv;
+struct crypto_engine {
+	struct list_head elist;
+	void *qce; /* qce handle */
+	struct platform_device *pdev; /* platform device */
+	struct crypto_async_request *req; /* current active request */
+	struct crypto_priv *pcp;
+	struct tasklet_struct done_tasklet;
+	uint32_t  bus_scale_handle;
+	struct crypto_queue req_queue;	/*
+					 * request queue for those requests
+					 * that have this engine assgined
+					 * waiting to be executed
+					 */
+	u32 total_req;
+	u32 err_req;
+	u32 unit;
+	int res; /* execution result */
+	unsigned int signature;
+	uint32_t high_bw_req_count;
+	bool     high_bw_req;
+	struct timer_list bw_scale_down_timer;
+	struct work_struct low_bw_req_ws;
+};
 
 struct crypto_priv {
 	/* CE features supported by target device*/
@@ -91,34 +121,25 @@
 	/* CE features/algorithms supported by HW engine*/
 	struct ce_hw_support ce_support;
 
-	uint32_t  bus_scale_handle;
 	/* the lock protects queue and req*/
 	spinlock_t lock;
 
-	/* qce handle */
-	void *qce;
-
 	/* list of  registered algorithms */
 	struct list_head alg_list;
 
-	/* platform device */
-	struct platform_device *pdev;
-
 	/* current active request */
 	struct crypto_async_request *req;
-	int res;
-
-	/* request queue */
-	struct crypto_queue queue;
 
 	uint32_t ce_lock_count;
-	uint32_t high_bw_req_count;
-
 	struct work_struct unlock_ce_ws;
-
-	struct tasklet_struct done_tasklet;
+	struct list_head engine_list; /* list of  qcrypto engines */
+	int32_t total_units;   /* total units of engines */
+	struct mutex engine_lock;
+	struct crypto_engine *next_engine; /* next assign engine */
 };
-
+static struct crypto_priv qcrypto_dev;
+static struct crypto_engine *_qcrypto_static_assign_engine(
+					struct crypto_priv *cp);
 
 /*-------------------------------------------------------------------------
 * Resource Locking Service
@@ -129,8 +150,6 @@
 #define NUM_RETRY				1000
 #define CE_BUSY				        55
 
-static DEFINE_MUTEX(qcrypto_sent_bw_req);
-
 static int qcrypto_scm_cmd(int resource, int cmd, int *response)
 {
 #ifdef CONFIG_MSM_SCM
@@ -224,6 +243,7 @@
 
 	struct crypto_priv *cp;
 	unsigned int flags;
+	struct crypto_engine *pengine;  /* fixed engine assigned */
 };
 
 struct qcrypto_cipher_req_ctx {
@@ -266,30 +286,18 @@
 
 struct qcrypto_sha_ctx {
 	enum qce_hash_alg_enum  alg;
-	uint32_t		byte_count[4];
-	uint8_t			digest[SHA_MAX_DIGEST_SIZE];
 	uint32_t		diglen;
-	uint8_t			*tmp_tbuf;
-	uint8_t			*trailing_buf;
-	uint8_t			*in_buf;
 	uint32_t		authkey_in_len;
-	uint32_t		trailing_buf_len;
-	uint8_t			first_blk;
-	uint8_t			last_blk;
 	uint8_t			authkey[SHA_MAX_BLOCK_SIZE];
 	struct ahash_request *ahash_req;
 	struct completion ahash_req_complete;
-	struct scatterlist *sg;
-	struct scatterlist tmp_sg;
 	struct crypto_priv *cp;
 	unsigned int flags;
+	struct crypto_engine *pengine;  /* fixed engine assigned */
 };
 
 struct qcrypto_sha_req_ctx {
-	union {
-		struct sha1_state sha1_state_ctx;
-		struct sha256_state sha256_state_ctx;
-	};
+
 	struct scatterlist *src;
 	uint32_t nbytes;
 
@@ -297,6 +305,20 @@
 	struct scatterlist dsg;		/* Data sg */
 	unsigned char *data;		/* Incoming data pointer*/
 	unsigned char *data2;		/* Updated data pointer*/
+
+	uint32_t byte_count[4];
+	u64 count;
+	uint8_t	first_blk;
+	uint8_t	last_blk;
+	uint8_t	 trailing_buf[SHA_MAX_BLOCK_SIZE];
+	uint32_t trailing_buf_len;
+
+	/* dma buffer, Internal use */
+	uint8_t	staging_dmabuf
+		[SHA_MAX_BLOCK_SIZE+SHA_MAX_DIGEST_SIZE+MAX_ALIGN_SIZE];
+
+	uint8_t	digest[SHA_MAX_DIGEST_SIZE];
+	struct scatterlist sg[2];
 };
 
 static void _byte_stream_to_words(uint32_t *iv, unsigned char *b,
@@ -304,7 +326,7 @@
 {
 	unsigned n;
 
-	n = len  / sizeof(uint32_t) ;
+	n = len  / sizeof(uint32_t);
 	for (; n > 0; n--) {
 		*iv =  ((*b << 24)      & 0xff000000) |
 				(((*(b+1)) << 16) & 0xff0000)   |
@@ -318,12 +340,12 @@
 	if (n == 3) {
 		*iv = ((*b << 24) & 0xff000000) |
 				(((*(b+1)) << 16) & 0xff0000)   |
-				(((*(b+2)) << 8) & 0xff00)     ;
+				(((*(b+2)) << 8) & 0xff00);
 	} else if (n == 2) {
 		*iv = ((*b << 24) & 0xff000000) |
-				(((*(b+1)) << 16) & 0xff0000)   ;
+				(((*(b+1)) << 16) & 0xff0000);
 	} else if (n == 1) {
-		*iv = ((*b << 24) & 0xff000000) ;
+		*iv = ((*b << 24) & 0xff000000);
 	}
 }
 
@@ -352,58 +374,103 @@
 	}
 }
 
-static void qcrypto_ce_high_bw_req(struct crypto_priv *cp, bool high_bw_req)
+static void qcrypto_ce_set_bus(struct crypto_engine *pengine,
+				 bool high_bw_req)
 {
 	int ret = 0;
 
-	mutex_lock(&qcrypto_sent_bw_req);
-	if (high_bw_req) {
-		if (cp->high_bw_req_count == 0) {
-			ret = qce_enable_clk(cp->qce);
-			if (ret) {
-				pr_err("%s Unable enable clk\n", __func__);
-				mutex_unlock(&qcrypto_sent_bw_req);
-				return;
-			}
+	if (high_bw_req && pengine->high_bw_req == false) {
+		pm_stay_awake(&pengine->pdev->dev);
+		ret = qce_enable_clk(pengine->qce);
+		if (ret) {
+			pr_err("%s Unable enable clk\n", __func__);
+			goto clk_err;
+		}
+		ret = msm_bus_scale_client_update_request(
+				pengine->bus_scale_handle, 1);
+		if (ret) {
+			pr_err("%s Unable to set to high bandwidth\n",
+						__func__);
+			qce_disable_clk(pengine->qce);
+			goto clk_err;
+		}
+		pengine->high_bw_req = true;
+	} else if (high_bw_req == false && pengine->high_bw_req == true) {
+		ret = msm_bus_scale_client_update_request(
+				pengine->bus_scale_handle, 0);
+		if (ret) {
+			pr_err("%s Unable to set to low bandwidth\n",
+						__func__);
+			goto clk_err;
+		}
+		ret = qce_disable_clk(pengine->qce);
+		if (ret) {
+			pr_err("%s Unable disable clk\n", __func__);
 			ret = msm_bus_scale_client_update_request(
-					cp->bus_scale_handle, 1);
-			if (ret) {
+				pengine->bus_scale_handle, 1);
+			if (ret)
 				pr_err("%s Unable to set to high bandwidth\n",
-							__func__);
-				qce_disable_clk(cp->qce);
-				mutex_unlock(&qcrypto_sent_bw_req);
-				return;
-			}
+						__func__);
+			goto clk_err;
 		}
-		cp->high_bw_req_count++;
-	} else {
-		if (cp->high_bw_req_count == 1) {
-			ret = msm_bus_scale_client_update_request(
-					cp->bus_scale_handle, 0);
-			if (ret) {
-				pr_err("%s Unable to set to low bandwidth\n",
-							__func__);
-				mutex_unlock(&qcrypto_sent_bw_req);
-				return;
-			}
-			ret = qce_disable_clk(cp->qce);
-			if (ret) {
-				pr_err("%s Unable disable clk\n", __func__);
-				ret = msm_bus_scale_client_update_request(
-					cp->bus_scale_handle, 1);
-				if (ret)
-					pr_err("%s Unable to set to high bandwidth\n",
-							__func__);
-				mutex_unlock(&qcrypto_sent_bw_req);
-				return;
-			}
-		}
-		cp->high_bw_req_count--;
+		pengine->high_bw_req = false;
+		pm_relax(&pengine->pdev->dev);
 	}
-	mutex_unlock(&qcrypto_sent_bw_req);
+	return;
+clk_err:
+	pm_relax(&pengine->pdev->dev);
+	return;
+
 }
 
-static int _start_qcrypto_process(struct crypto_priv *cp);
+static void qcrypto_bw_scale_down_timer_callback(unsigned long data)
+{
+	struct crypto_engine *pengine = (struct crypto_engine *)data;
+
+	schedule_work(&pengine->low_bw_req_ws);
+
+	return;
+}
+
+static void qcrypto_bw_set_timeout(struct crypto_engine *pengine)
+{
+	del_timer_sync(&(pengine->bw_scale_down_timer));
+	pengine->bw_scale_down_timer.data =
+			(unsigned long)(pengine);
+	pengine->bw_scale_down_timer.expires = jiffies +
+			msecs_to_jiffies(QCRYPTO_HIGH_BANDWIDTH_TIMEOUT);
+	add_timer(&(pengine->bw_scale_down_timer));
+}
+
+static void qcrypto_ce_bw_scaling_req(struct crypto_engine *pengine,
+				 bool high_bw_req)
+{
+	mutex_lock(&pengine->pcp->engine_lock);
+	if (high_bw_req) {
+		if (pengine->high_bw_req_count == 0)
+			qcrypto_ce_set_bus(pengine, true);
+		pengine->high_bw_req_count++;
+	} else {
+		pengine->high_bw_req_count--;
+		if (pengine->high_bw_req_count == 0)
+			qcrypto_bw_set_timeout(pengine);
+	}
+	mutex_unlock(&pengine->pcp->engine_lock);
+}
+
+static void qcrypto_low_bw_req_work(struct work_struct *work)
+{
+	struct crypto_engine *pengine = container_of(work,
+				struct crypto_engine, low_bw_req_ws);
+
+	mutex_lock(&pengine->pcp->engine_lock);
+	if (pengine->high_bw_req_count == 0)
+		qcrypto_ce_set_bus(pengine, false);
+	mutex_unlock(&pengine->pcp->engine_lock);
+}
+
+static int _start_qcrypto_process(struct crypto_priv *cp,
+					struct crypto_engine *pengine);
 
 static int qcrypto_count_sg(struct scatterlist *sg, int nbytes)
 {
@@ -499,9 +566,11 @@
 
 	/* random first IV */
 	get_random_bytes(ctx->iv, QCRYPTO_MAX_IV_LENGTH);
+	ctx->pengine = _qcrypto_static_assign_engine(ctx->cp);
+	if (ctx->pengine == NULL)
+		return -ENODEV;
 	if (ctx->cp->platform_support.bus_scale_table != NULL)
-		qcrypto_ce_high_bw_req(ctx->cp, true);
-
+		qcrypto_ce_bw_scaling_req(ctx->pengine, true);
 	return 0;
 };
 
@@ -517,30 +586,13 @@
 	crypto_ahash_set_reqsize(ahash, sizeof(struct qcrypto_sha_req_ctx));
 	/* update context with ptr to cp */
 	sha_ctx->cp = q_alg->cp;
-	sha_ctx->sg = NULL;
 	sha_ctx->flags = 0;
-
-	sha_ctx->tmp_tbuf = kzalloc(SHA_MAX_BLOCK_SIZE +
-					SHA_MAX_DIGEST_SIZE, GFP_KERNEL);
-	if (sha_ctx->tmp_tbuf == NULL) {
-		pr_err("qcrypto Can't Allocate mem: sha_ctx->tmp_tbuf, error %ld\n",
-			PTR_ERR(sha_ctx->tmp_tbuf));
-		return -ENOMEM;
-	}
-
-	sha_ctx->trailing_buf = kzalloc(SHA_MAX_BLOCK_SIZE, GFP_KERNEL);
-	if (sha_ctx->trailing_buf == NULL) {
-		kfree(sha_ctx->tmp_tbuf);
-		sha_ctx->tmp_tbuf = NULL;
-		pr_err("qcrypto Can't Allocate mem: sha_ctx->trailing_buf, error %ld\n",
-			PTR_ERR(sha_ctx->trailing_buf));
-		return -ENOMEM;
-	}
-
 	sha_ctx->ahash_req = NULL;
+	sha_ctx->pengine = _qcrypto_static_assign_engine(sha_ctx->cp);
+	if (sha_ctx->pengine == NULL)
+		return -ENODEV;
 	if (sha_ctx->cp->platform_support.bus_scale_table != NULL)
-		qcrypto_ce_high_bw_req(sha_ctx->cp, true);
-
+		qcrypto_ce_bw_scaling_req(sha_ctx->pengine, true);
 	return 0;
 };
 
@@ -548,20 +600,13 @@
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(tfm);
 
-	kfree(sha_ctx->tmp_tbuf);
-	sha_ctx->tmp_tbuf = NULL;
-	kfree(sha_ctx->trailing_buf);
-	sha_ctx->trailing_buf = NULL;
-	if (sha_ctx->sg != NULL) {
-		kfree(sha_ctx->sg);
-		sha_ctx->sg = NULL;
-	}
 	if (sha_ctx->ahash_req != NULL) {
 		ahash_request_free(sha_ctx->ahash_req);
 		sha_ctx->ahash_req = NULL;
 	}
-	if (sha_ctx->cp->platform_support.bus_scale_table != NULL)
-		qcrypto_ce_high_bw_req(sha_ctx->cp, false);
+	if (sha_ctx->pengine &&
+			sha_ctx->cp->platform_support.bus_scale_table != NULL)
+		qcrypto_ce_bw_scaling_req(sha_ctx->pengine, false);
 };
 
 
@@ -610,22 +655,25 @@
 {
 	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	if (ctx->cp->platform_support.bus_scale_table != NULL)
-		qcrypto_ce_high_bw_req(ctx->cp, false);
+	if (ctx->pengine && ctx->cp->platform_support.bus_scale_table != NULL)
+		qcrypto_ce_bw_scaling_req(ctx->pengine, false);
 };
 
 static void _qcrypto_cra_aead_exit(struct crypto_tfm *tfm)
 {
 	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(tfm);
 
-	if (ctx->cp->platform_support.bus_scale_table != NULL)
-		qcrypto_ce_high_bw_req(ctx->cp, false);
+	if (ctx->pengine && ctx->cp->platform_support.bus_scale_table != NULL)
+		qcrypto_ce_bw_scaling_req(ctx->pengine, false);
 };
 
 static int _disp_stats(int id)
 {
 	struct crypto_stat *pstat;
 	int len = 0;
+	unsigned long flags;
+	struct crypto_priv *cp = &qcrypto_dev;
+	struct crypto_engine *pe;
 
 	pstat = &_qcrypto_stat;
 	len = scnprintf(_debug_read_buf, DEBUG_MAX_RW_BUF - 1,
@@ -722,22 +770,55 @@
 	len += scnprintf(_debug_read_buf + len, DEBUG_MAX_RW_BUF - len - 1,
 			"   SHA HMAC operation success          : %d\n",
 					pstat->sha_hmac_op_success);
+	spin_lock_irqsave(&cp->lock, flags);
+	list_for_each_entry(pe, &cp->engine_list, elist) {
+		len += snprintf(
+			_debug_read_buf + len,
+			DEBUG_MAX_RW_BUF - len - 1,
+			"   Engine %d Req                : %d\n",
+			pe->unit,
+			pe->total_req
+		);
+		len += snprintf(
+			_debug_read_buf + len,
+			DEBUG_MAX_RW_BUF - len - 1,
+			"   Engine %d Req Error          : %d\n",
+			pe->unit,
+			pe->err_req
+		);
+	}
+	spin_unlock_irqrestore(&cp->lock, flags);
 	return len;
 }
 
-static int _qcrypto_remove(struct platform_device *pdev)
+static void _qcrypto_remove_engine(struct crypto_engine *pengine)
 {
 	struct crypto_priv *cp;
 	struct qcrypto_alg *q_alg;
 	struct qcrypto_alg *n;
+	unsigned long flags;
 
-	cp = platform_get_drvdata(pdev);
+	cp = pengine->pcp;
 
-	if (!cp)
-		return 0;
+	spin_lock_irqsave(&cp->lock, flags);
+	list_del(&pengine->elist);
+	if (cp->next_engine == pengine)
+		cp->next_engine = NULL;
+	spin_unlock_irqrestore(&cp->lock, flags);
 
-	if (cp->platform_support.bus_scale_table != NULL)
-		msm_bus_scale_unregister_client(cp->bus_scale_handle);
+	cp->total_units--;
+
+	tasklet_kill(&pengine->done_tasklet);
+	cancel_work_sync(&pengine->low_bw_req_ws);
+	del_timer_sync(&pengine->bw_scale_down_timer);
+	device_init_wakeup(&pengine->pdev->dev, false);
+
+	if (pengine->bus_scale_handle != 0)
+		msm_bus_scale_unregister_client(pengine->bus_scale_handle);
+	pengine->bus_scale_handle = 0;
+
+	if (cp->total_units)
+		return;
 
 	list_for_each_entry_safe(q_alg, n, &cp->alg_list, entry) {
 		if (q_alg->alg_type == QCRYPTO_ALG_CIPHER)
@@ -747,14 +828,26 @@
 		list_del(&q_alg->entry);
 		kfree(q_alg);
 	}
+}
 
-	if (cp->qce)
-		qce_close(cp->qce);
-	tasklet_kill(&cp->done_tasklet);
-	kfree(cp);
+static int _qcrypto_remove(struct platform_device *pdev)
+{
+	struct crypto_engine *pengine;
+	struct crypto_priv *cp;
+
+	pengine = platform_get_drvdata(pdev);
+
+	if (!pengine)
+		return 0;
+	cp = pengine->pcp;
+	mutex_lock(&cp->engine_lock);
+	_qcrypto_remove_engine(pengine);
+	mutex_unlock(&cp->engine_lock);
+	if (pengine->qce)
+		qce_close(pengine->qce);
+	kfree(pengine);
 	return 0;
-};
-
+}
 
 static int _qcrypto_check_aes_keylen(struct crypto_ablkcipher *cipher,
 		struct crypto_priv *cp, unsigned int len)
@@ -894,54 +987,24 @@
 static void req_done(unsigned long data)
 {
 	struct crypto_async_request *areq;
-	struct crypto_priv *cp = (struct crypto_priv *)data;
+	struct crypto_engine *pengine = (struct crypto_engine *)data;
+	struct crypto_priv *cp;
 	unsigned long flags;
+	int res;
 
+	cp = pengine->pcp;
 	spin_lock_irqsave(&cp->lock, flags);
-	areq = cp->req;
-	cp->req = NULL;
+	areq = pengine->req;
+	pengine->req = NULL;
+	res = pengine->res;
 	spin_unlock_irqrestore(&cp->lock, flags);
-
 	if (areq)
-		areq->complete(areq, cp->res);
-	_start_qcrypto_process(cp);
+		areq->complete(areq, res);
+	if (res)
+		pengine->err_req++;
+	_start_qcrypto_process(cp, pengine);
 };
 
-static void _update_sha1_ctx(struct ahash_request  *req)
-{
-	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha1_state *sha_state_ctx = &rctx->sha1_state_ctx;
-	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-
-	if (sha_ctx->last_blk == 1)
-		memset(sha_state_ctx, 0x00, sizeof(struct sha1_state));
-	else {
-		memset(sha_state_ctx->buffer, 0x00, SHA1_BLOCK_SIZE);
-		memcpy(sha_state_ctx->buffer, sha_ctx->trailing_buf,
-						sha_ctx->trailing_buf_len);
-		_byte_stream_to_words(sha_state_ctx->state , sha_ctx->digest,
-					SHA1_DIGEST_SIZE);
-	}
-	return;
-}
-
-static void _update_sha256_ctx(struct ahash_request  *req)
-{
-	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha256_state *sha_state_ctx = &rctx->sha256_state_ctx;
-	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-
-	if (sha_ctx->last_blk == 1)
-		memset(sha_state_ctx, 0x00, sizeof(struct sha256_state));
-	else {
-		memset(sha_state_ctx->buf, 0x00, SHA256_BLOCK_SIZE);
-		memcpy(sha_state_ctx->buf, sha_ctx->trailing_buf,
-						sha_ctx->trailing_buf_len);
-		_byte_stream_to_words(sha_state_ctx->state, sha_ctx->digest,
-					SHA256_DIGEST_SIZE);
-	}
-	return;
-}
 
 static void _qce_ahash_complete(void *cookie, unsigned char *digest,
 		unsigned char *authdata, int ret)
@@ -954,44 +1017,36 @@
 	struct crypto_stat *pstat;
 	uint32_t diglen = crypto_ahash_digestsize(ahash);
 	uint32_t *auth32 = (uint32_t *)authdata;
+	struct crypto_engine *pengine;
 
 	pstat = &_qcrypto_stat;
 
+	pengine = sha_ctx->pengine;
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qce_ahash_complete: %p ret %d\n",
+	dev_info(&pengine->pdev->dev, "_qce_ahash_complete: %p ret %d\n",
 				areq, ret);
 #endif
 	if (digest) {
-		memcpy(sha_ctx->digest, digest, diglen);
+		memcpy(rctx->digest, digest, diglen);
 		memcpy(areq->result, digest, diglen);
 	}
 	if (authdata) {
-		sha_ctx->byte_count[0] = auth32[0];
-		sha_ctx->byte_count[1] = auth32[1];
-		sha_ctx->byte_count[2] = auth32[2];
-		sha_ctx->byte_count[3] = auth32[3];
+		rctx->byte_count[0] = auth32[0];
+		rctx->byte_count[1] = auth32[1];
+		rctx->byte_count[2] = auth32[2];
+		rctx->byte_count[3] = auth32[3];
 	}
 	areq->src = rctx->src;
 	areq->nbytes = rctx->nbytes;
 
-	if (sha_ctx->sg != NULL) {
-		kfree(sha_ctx->sg);
-		sha_ctx->sg = NULL;
-	}
-
-	if (sha_ctx->alg == QCE_HASH_SHA1)
-		_update_sha1_ctx(areq);
-	if (sha_ctx->alg == QCE_HASH_SHA256)
-		_update_sha256_ctx(areq);
-
-	sha_ctx->last_blk = 0;
-	sha_ctx->first_blk = 0;
+	rctx->last_blk = 0;
+	rctx->first_blk = 0;
 
 	if (ret) {
-		cp->res = -ENXIO;
+		pengine->res = -ENXIO;
 		pstat->sha_op_fail++;
 	} else {
-		cp->res = 0;
+		pengine->res = 0;
 		pstat->sha_op_success++;
 	}
 	if (cp->ce_support.aligned_only)  {
@@ -1001,7 +1056,7 @@
 
 	if (cp->platform_support.ce_shared)
 		schedule_work(&cp->unlock_ce_ws);
-	tasklet_schedule(&cp->done_tasklet);
+	tasklet_schedule(&pengine->done_tasklet);
 };
 
 static void _qce_ablk_cipher_complete(void *cookie, unsigned char *icb,
@@ -1012,21 +1067,22 @@
 	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(areq->base.tfm);
 	struct crypto_priv *cp = ctx->cp;
 	struct crypto_stat *pstat;
+	struct crypto_engine *pengine;
 
 	pstat = &_qcrypto_stat;
-
+	pengine = ctx->pengine;
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qce_ablk_cipher_complete: %p ret %d\n",
+	dev_info(&pengine->pdev->dev, "_qce_ablk_cipher_complete: %p ret %d\n",
 				areq, ret);
 #endif
 	if (iv)
 		memcpy(ctx->iv, iv, crypto_ablkcipher_ivsize(ablk));
 
 	if (ret) {
-		cp->res = -ENXIO;
+		pengine->res = -ENXIO;
 		pstat->ablk_cipher_op_fail++;
 	} else {
-		cp->res = 0;
+		pengine->res = 0;
 		pstat->ablk_cipher_op_success++;
 	}
 
@@ -1050,7 +1106,7 @@
 
 	if (cp->platform_support.ce_shared)
 		schedule_work(&cp->unlock_ce_ws);
-	tasklet_schedule(&cp->done_tasklet);
+	tasklet_schedule(&pengine->done_tasklet);
 };
 
 
@@ -1063,9 +1119,10 @@
 	struct crypto_priv *cp = ctx->cp;
 	struct qcrypto_cipher_req_ctx *rctx;
 	struct crypto_stat *pstat;
+	struct crypto_engine *pengine;
 
 	pstat = &_qcrypto_stat;
-
+	pengine = ctx->pengine;
 	rctx = aead_request_ctx(areq);
 
 	if (rctx->mode == QCE_MODE_CCM) {
@@ -1162,11 +1219,11 @@
 	else
 		pstat->aead_op_success++;
 
-	cp->res = ret;
+	pengine->res = ret;
 
 	if (cp->platform_support.ce_shared)
 		schedule_work(&cp->unlock_ce_ws);
-	tasklet_schedule(&cp->done_tasklet);
+	tasklet_schedule(&pengine->done_tasklet);
 }
 
 static int aead_ccm_set_msg_len(u8 *block, unsigned int msglen, int csize)
@@ -1251,7 +1308,7 @@
 	return 0;
 }
 
-static int _qcrypto_process_ablkcipher(struct crypto_priv *cp,
+static int _qcrypto_process_ablkcipher(struct crypto_engine *pengine,
 				struct crypto_async_request *async_req)
 {
 	struct qce_req qreq;
@@ -1265,7 +1322,7 @@
 	cipher_ctx = crypto_tfm_ctx(async_req->tfm);
 	rctx = ablkcipher_request_ctx(req);
 	tfm = crypto_ablkcipher_reqtfm(req);
-	if (cp->ce_support.aligned_only) {
+	if (pengine->pcp->ce_support.aligned_only) {
 		uint32_t bytes = 0;
 		uint32_t num_sg = 0;
 
@@ -1306,35 +1363,37 @@
 	qreq.flags = cipher_ctx->flags;
 
 	if ((cipher_ctx->enc_key_len == 0) &&
-			(cp->platform_support.hw_key_support == 0))
+			(pengine->pcp->platform_support.hw_key_support == 0))
 		ret = -EINVAL;
 	else
-		ret =  qce_ablk_cipher_req(cp->qce, &qreq);
+		ret =  qce_ablk_cipher_req(pengine->qce, &qreq);
 
 	return ret;
 }
 
-static int _qcrypto_process_ahash(struct crypto_priv *cp,
+static int _qcrypto_process_ahash(struct crypto_engine *pengine,
 				struct crypto_async_request *async_req)
 {
 	struct ahash_request *req;
 	struct qce_sha_req sreq;
+	struct qcrypto_sha_req_ctx *rctx;
 	struct qcrypto_sha_ctx *sha_ctx;
 	int ret = 0;
 
 	req = container_of(async_req,
 				struct ahash_request, base);
+	rctx = ahash_request_ctx(req);
 	sha_ctx = crypto_tfm_ctx(async_req->tfm);
 
 	sreq.qce_cb = _qce_ahash_complete;
-	sreq.digest =  &sha_ctx->digest[0];
+	sreq.digest =  &rctx->digest[0];
 	sreq.src = req->src;
-	sreq.auth_data[0] = sha_ctx->byte_count[0];
-	sreq.auth_data[1] = sha_ctx->byte_count[1];
-	sreq.auth_data[2] = sha_ctx->byte_count[2];
-	sreq.auth_data[3] = sha_ctx->byte_count[3];
-	sreq.first_blk = sha_ctx->first_blk;
-	sreq.last_blk = sha_ctx->last_blk;
+	sreq.auth_data[0] = rctx->byte_count[0];
+	sreq.auth_data[1] = rctx->byte_count[1];
+	sreq.auth_data[2] = rctx->byte_count[2];
+	sreq.auth_data[3] = rctx->byte_count[3];
+	sreq.first_blk = rctx->first_blk;
+	sreq.last_blk = rctx->last_blk;
 	sreq.size = req->nbytes;
 	sreq.areq = req;
 	sreq.flags = sha_ctx->flags;
@@ -1363,12 +1422,12 @@
 		ret = -1;
 		break;
 	};
-	ret =  qce_process_sha_req(cp->qce, &sreq);
+	ret =  qce_process_sha_req(pengine->qce, &sreq);
 
 	return ret;
 }
 
-static int _qcrypto_process_aead(struct crypto_priv *cp,
+static int _qcrypto_process_aead(struct  crypto_engine *pengine,
 				struct crypto_async_request *async_req)
 {
 	struct qce_req qreq;
@@ -1417,7 +1476,7 @@
 		if (ret)
 			return ret;
 
-		if (cp->ce_support.aligned_only) {
+		if (pengine->pcp->ce_support.aligned_only) {
 			uint32_t bytes = 0;
 			uint32_t num_sg = 0;
 
@@ -1487,7 +1546,7 @@
 		sg_mark_end(req->assoc);
 	} else {
 		/* for aead operations, other than aes(ccm) */
-		if (cp->ce_support.aligned_only) {
+		if (pengine->pcp->ce_support.aligned_only) {
 			uint32_t bytes = 0;
 			uint32_t num_sg = 0;
 
@@ -1558,12 +1617,36 @@
 			req->dst = &rctx->dsg;
 		}
 	}
-	ret =  qce_aead_req(cp->qce, &qreq);
+	ret =  qce_aead_req(pengine->qce, &qreq);
 
 	return ret;
 }
+#define list_next_entry(pos, member) \
+		list_entry(pos->member.next, typeof(*pos), member)
+static struct crypto_engine *_qcrypto_static_assign_engine(
+					struct crypto_priv *cp)
+{
+	struct crypto_engine *pengine;
+	unsigned long flags;
 
-static int _start_qcrypto_process(struct crypto_priv *cp)
+	spin_lock_irqsave(&cp->lock, flags);
+	if (cp->next_engine)
+		pengine = cp->next_engine;
+	else
+		pengine = list_first_entry(&cp->engine_list,
+				struct crypto_engine, elist);
+
+	if (list_is_last(&pengine->elist, &cp->engine_list))
+		cp->next_engine = list_first_entry(
+			&cp->engine_list, struct crypto_engine, elist);
+	else
+		cp->next_engine = list_next_entry(pengine, elist);
+	spin_unlock_irqrestore(&cp->lock, flags);
+	return pengine;
+}
+
+static int _start_qcrypto_process(struct crypto_priv *cp,
+				struct crypto_engine *pengine)
 {
 	struct crypto_async_request *async_req = NULL;
 	struct crypto_async_request *backlog = NULL;
@@ -1576,10 +1659,10 @@
 
 again:
 	spin_lock_irqsave(&cp->lock, flags);
-	if (cp->req == NULL) {
-		backlog = crypto_get_backlog(&cp->queue);
-		async_req = crypto_dequeue_request(&cp->queue);
-		cp->req = async_req;
+	if (pengine->req == NULL) {
+		backlog = crypto_get_backlog(&pengine->req_queue);
+		async_req = crypto_dequeue_request(&pengine->req_queue);
+		pengine->req = async_req;
 	}
 	spin_unlock_irqrestore(&cp->lock, flags);
 	if (!async_req)
@@ -1590,21 +1673,22 @@
 
 	switch (type) {
 	case CRYPTO_ALG_TYPE_ABLKCIPHER:
-		ret = _qcrypto_process_ablkcipher(cp, async_req);
+		ret = _qcrypto_process_ablkcipher(pengine, async_req);
 		break;
 	case CRYPTO_ALG_TYPE_AHASH:
-		ret = _qcrypto_process_ahash(cp, async_req);
+		ret = _qcrypto_process_ahash(pengine, async_req);
 		break;
 	case CRYPTO_ALG_TYPE_AEAD:
-		ret = _qcrypto_process_aead(cp, async_req);
+		ret = _qcrypto_process_aead(pengine, async_req);
 		break;
 	default:
 		ret = -EINVAL;
 	};
-
+	pengine->total_req++;
 	if (ret) {
+		pengine->err_req++;
 		spin_lock_irqsave(&cp->lock, flags);
-		cp->req = NULL;
+		pengine->req = NULL;
 		spin_unlock_irqrestore(&cp->lock, flags);
 
 		if (type == CRYPTO_ALG_TYPE_ABLKCIPHER)
@@ -1622,6 +1706,7 @@
 };
 
 static int _qcrypto_queue_req(struct crypto_priv *cp,
+				struct crypto_engine *pengine,
 				struct crypto_async_request *req)
 {
 	int ret;
@@ -1634,9 +1719,9 @@
 	}
 
 	spin_lock_irqsave(&cp->lock, flags);
-	ret = crypto_enqueue_request(&cp->queue, req);
+	ret = crypto_enqueue_request(&pengine->req_queue, req);
 	spin_unlock_irqrestore(&cp->lock, flags);
-	_start_qcrypto_process(cp);
+	_start_qcrypto_process(cp, pengine);
 
 	return ret;
 }
@@ -1653,7 +1738,7 @@
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_enc_aes_ecb: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_ecb: %p\n", req);
 #endif
 	rctx = ablkcipher_request_ctx(req);
 	rctx->aead = 0;
@@ -1662,7 +1747,7 @@
 	rctx->mode = QCE_MODE_ECB;
 
 	pstat->ablk_cipher_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_enc_aes_cbc(struct ablkcipher_request *req)
@@ -1677,7 +1762,7 @@
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_enc_aes_cbc: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_cbc: %p\n", req);
 #endif
 	rctx = ablkcipher_request_ctx(req);
 	rctx->aead = 0;
@@ -1686,7 +1771,7 @@
 	rctx->mode = QCE_MODE_CBC;
 
 	pstat->ablk_cipher_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_enc_aes_ctr(struct ablkcipher_request *req)
@@ -1701,7 +1786,7 @@
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_enc_aes_ctr: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_enc_aes_ctr: %p\n", req);
 #endif
 	rctx = ablkcipher_request_ctx(req);
 	rctx->aead = 0;
@@ -1710,7 +1795,7 @@
 	rctx->mode = QCE_MODE_CTR;
 
 	pstat->ablk_cipher_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_enc_aes_xts(struct ablkcipher_request *req)
@@ -1731,7 +1816,7 @@
 	rctx->mode = QCE_MODE_XTS;
 
 	pstat->ablk_cipher_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_aead_encrypt_aes_ccm(struct aead_request *req)
@@ -1757,7 +1842,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_ccm_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_enc_des_ecb(struct ablkcipher_request *req)
@@ -1778,7 +1863,7 @@
 	rctx->mode = QCE_MODE_ECB;
 
 	pstat->ablk_cipher_des_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_enc_des_cbc(struct ablkcipher_request *req)
@@ -1799,7 +1884,7 @@
 	rctx->mode = QCE_MODE_CBC;
 
 	pstat->ablk_cipher_des_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_enc_3des_ecb(struct ablkcipher_request *req)
@@ -1820,7 +1905,7 @@
 	rctx->mode = QCE_MODE_ECB;
 
 	pstat->ablk_cipher_3des_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_enc_3des_cbc(struct ablkcipher_request *req)
@@ -1841,7 +1926,7 @@
 	rctx->mode = QCE_MODE_CBC;
 
 	pstat->ablk_cipher_3des_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_aes_ecb(struct ablkcipher_request *req)
@@ -1856,7 +1941,7 @@
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_dec_aes_ecb: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_ecb: %p\n", req);
 #endif
 	rctx = ablkcipher_request_ctx(req);
 	rctx->aead = 0;
@@ -1865,7 +1950,7 @@
 	rctx->mode = QCE_MODE_ECB;
 
 	pstat->ablk_cipher_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_aes_cbc(struct ablkcipher_request *req)
@@ -1880,7 +1965,7 @@
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 				CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_dec_aes_cbc: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_cbc: %p\n", req);
 #endif
 
 	rctx = ablkcipher_request_ctx(req);
@@ -1890,7 +1975,7 @@
 	rctx->mode = QCE_MODE_CBC;
 
 	pstat->ablk_cipher_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_aes_ctr(struct ablkcipher_request *req)
@@ -1905,7 +1990,7 @@
 	BUG_ON(crypto_tfm_alg_type(req->base.tfm) !=
 					CRYPTO_ALG_TYPE_ABLKCIPHER);
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_dec_aes_ctr: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev, "_qcrypto_dec_aes_ctr: %p\n", req);
 #endif
 	rctx = ablkcipher_request_ctx(req);
 	rctx->aead = 0;
@@ -1916,7 +2001,7 @@
 	rctx->dir = QCE_ENCRYPT;
 
 	pstat->ablk_cipher_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_des_ecb(struct ablkcipher_request *req)
@@ -1937,7 +2022,7 @@
 	rctx->mode = QCE_MODE_ECB;
 
 	pstat->ablk_cipher_des_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_des_cbc(struct ablkcipher_request *req)
@@ -1958,7 +2043,7 @@
 	rctx->mode = QCE_MODE_CBC;
 
 	pstat->ablk_cipher_des_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_3des_ecb(struct ablkcipher_request *req)
@@ -1979,7 +2064,7 @@
 	rctx->mode = QCE_MODE_ECB;
 
 	pstat->ablk_cipher_3des_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_3des_cbc(struct ablkcipher_request *req)
@@ -2000,7 +2085,7 @@
 	rctx->mode = QCE_MODE_CBC;
 
 	pstat->ablk_cipher_3des_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 static int _qcrypto_dec_aes_xts(struct ablkcipher_request *req)
@@ -2021,7 +2106,7 @@
 	rctx->dir = QCE_DECRYPT;
 
 	pstat->ablk_cipher_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 };
 
 
@@ -2048,7 +2133,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_ccm_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_setauthsize(struct crypto_aead *authenc,
@@ -2156,7 +2241,8 @@
 	pstat = &_qcrypto_stat;
 
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_aead_encrypt_aes_cbc: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev,
+			 "_qcrypto_aead_encrypt_aes_cbc: %p\n", req);
 #endif
 
 	rctx = aead_request_ctx(req);
@@ -2167,7 +2253,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_decrypt_aes_cbc(struct aead_request *req)
@@ -2180,7 +2266,8 @@
 	pstat = &_qcrypto_stat;
 
 #ifdef QCRYPTO_DEBUG
-	dev_info(&cp->pdev->dev, "_qcrypto_aead_decrypt_aes_cbc: %p\n", req);
+	dev_info(&ctx->pengine->pdev->dev,
+			 "_qcrypto_aead_decrypt_aes_cbc: %p\n", req);
 #endif
 	rctx = aead_request_ctx(req);
 	rctx->aead = 1;
@@ -2190,7 +2277,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_givencrypt_aes_cbc(struct aead_givcrypt_request *req)
@@ -2215,7 +2302,7 @@
 	 /* avoid consecutive packets going out with same IV */
 	*(__be64 *)req->giv ^= cpu_to_be64(req->seq);
 	pstat->aead_sha1_aes_enc++;
-	return _qcrypto_queue_req(cp, &areq->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &areq->base);
 }
 
 #ifdef QCRYPTO_AEAD_AES_CTR
@@ -2236,7 +2323,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_aes_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_decrypt_aes_ctr(struct aead_request *req)
@@ -2259,7 +2346,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_aes_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_givencrypt_aes_ctr(struct aead_givcrypt_request *req)
@@ -2284,7 +2371,7 @@
 	 /* avoid consecutive packets going out with same IV */
 	*(__be64 *)req->giv ^= cpu_to_be64(req->seq);
 	pstat->aead_sha1_aes_enc++;
-	return _qcrypto_queue_req(cp, &areq->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &areq->base);
 };
 #endif /* QCRYPTO_AEAD_AES_CTR */
 
@@ -2305,7 +2392,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_des_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_decrypt_des_cbc(struct aead_request *req)
@@ -2325,7 +2412,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_des_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_givencrypt_des_cbc(struct aead_givcrypt_request *req)
@@ -2350,7 +2437,7 @@
 	 /* avoid consecutive packets going out with same IV */
 	*(__be64 *)req->giv ^= cpu_to_be64(req->seq);
 	pstat->aead_sha1_des_enc++;
-	return _qcrypto_queue_req(cp, &areq->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &areq->base);
 }
 
 static int _qcrypto_aead_encrypt_3des_cbc(struct aead_request *req)
@@ -2370,7 +2457,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_3des_enc++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_decrypt_3des_cbc(struct aead_request *req)
@@ -2390,7 +2477,7 @@
 	rctx->iv = req->iv;
 
 	pstat->aead_sha1_3des_dec++;
-	return _qcrypto_queue_req(cp, &req->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &req->base);
 }
 
 static int _qcrypto_aead_givencrypt_3des_cbc(struct aead_givcrypt_request *req)
@@ -2415,18 +2502,21 @@
 	 /* avoid consecutive packets going out with same IV */
 	*(__be64 *)req->giv ^= cpu_to_be64(req->seq);
 	pstat->aead_sha1_3des_enc++;
-	return _qcrypto_queue_req(cp, &areq->base);
+	return _qcrypto_queue_req(cp, ctx->pengine, &areq->base);
 }
 
-static int _sha_init(struct qcrypto_sha_ctx *ctx)
+static int _sha_init(struct ahash_request *req)
 {
-	ctx->first_blk = 1;
-	ctx->last_blk = 0;
-	ctx->byte_count[0] = 0;
-	ctx->byte_count[1] = 0;
-	ctx->byte_count[2] = 0;
-	ctx->byte_count[3] = 0;
-	ctx->trailing_buf_len = 0;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
+
+	rctx->first_blk = 1;
+	rctx->last_blk = 0;
+	rctx->byte_count[0] = 0;
+	rctx->byte_count[1] = 0;
+	rctx->byte_count[2] = 0;
+	rctx->byte_count[3] = 0;
+	rctx->trailing_buf_len = 0;
+	rctx->count = 0;
 
 	return 0;
 };
@@ -2435,18 +2525,17 @@
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_stat *pstat;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 
 	pstat = &_qcrypto_stat;
 
-	_sha_init(sha_ctx);
+	_sha_init(req);
 	sha_ctx->alg = QCE_HASH_SHA1;
 
-	memset(&sha_ctx->trailing_buf[0], 0x00, SHA1_BLOCK_SIZE);
-	memcpy(&sha_ctx->digest[0], &_std_init_vector_sha1_uint8[0],
+	memset(&rctx->trailing_buf[0], 0x00, SHA1_BLOCK_SIZE);
+	memcpy(&rctx->digest[0], &_std_init_vector_sha1_uint8[0],
 						SHA1_DIGEST_SIZE);
 	sha_ctx->diglen = SHA1_DIGEST_SIZE;
-	_update_sha1_ctx(req);
-
 	pstat->sha1_digest++;
 	return 0;
 };
@@ -2455,18 +2544,17 @@
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_stat *pstat;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 
 	pstat = &_qcrypto_stat;
 
-	_sha_init(sha_ctx);
+	_sha_init(req);
 	sha_ctx->alg = QCE_HASH_SHA256;
 
-	memset(&sha_ctx->trailing_buf[0], 0x00, SHA256_BLOCK_SIZE);
-	memcpy(&sha_ctx->digest[0], &_std_init_vector_sha256_uint8[0],
+	memset(&rctx->trailing_buf[0], 0x00, SHA256_BLOCK_SIZE);
+	memcpy(&rctx->digest[0], &_std_init_vector_sha256_uint8[0],
 						SHA256_DIGEST_SIZE);
 	sha_ctx->diglen = SHA256_DIGEST_SIZE;
-	_update_sha256_ctx(req);
-
 	pstat->sha256_digest++;
 	return 0;
 };
@@ -2475,82 +2563,126 @@
 static int _sha1_export(struct ahash_request  *req, void *out)
 {
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha1_state *sha_state_ctx = &rctx->sha1_state_ctx;
 	struct sha1_state *out_ctx = (struct sha1_state *)out;
 
-	out_ctx->count = sha_state_ctx->count;
-	memcpy(out_ctx->state, sha_state_ctx->state, sizeof(out_ctx->state));
-	memcpy(out_ctx->buffer, sha_state_ctx->buffer, SHA1_BLOCK_SIZE);
+	out_ctx->count = rctx->count;
+	_byte_stream_to_words(out_ctx->state, rctx->digest, SHA1_DIGEST_SIZE);
+	memcpy(out_ctx->buffer, rctx->trailing_buf, SHA1_BLOCK_SIZE);
 
 	return 0;
 };
 
+static int _sha1_hmac_export(struct ahash_request  *req, void *out)
+{
+	return _sha1_export(req, out);
+}
+
+/* crypto hw padding constant for hmac first operation */
+#define HMAC_PADDING 64
+
+static int __sha1_import_common(struct ahash_request  *req, const void *in,
+				bool hmac)
+{
+	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
+	struct sha1_state *in_ctx = (struct sha1_state *)in;
+	u64 hw_count = in_ctx->count;
+
+	rctx->count = in_ctx->count;
+	memcpy(rctx->trailing_buf, in_ctx->buffer, SHA1_BLOCK_SIZE);
+	if (in_ctx->count <= SHA1_BLOCK_SIZE) {
+		rctx->first_blk = 1;
+	} else {
+		rctx->first_blk = 0;
+		/*
+		 * For hmac, there is a hardware padding done
+		 * when first is set. So the byte_count will be
+		 * incremened by 64 after the operstion of first
+		 */
+		if (hmac)
+			hw_count += HMAC_PADDING;
+	}
+	rctx->byte_count[0] =  (uint32_t)(hw_count & 0xFFFFFFC0);
+	rctx->byte_count[1] =  (uint32_t)(hw_count >> 32);
+	_words_to_byte_stream(in_ctx->state, rctx->digest, sha_ctx->diglen);
+
+	rctx->trailing_buf_len = (uint32_t)(in_ctx->count &
+						(SHA1_BLOCK_SIZE-1));
+	return 0;
+}
+
 static int _sha1_import(struct ahash_request  *req, const void *in)
 {
-	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
-	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha1_state *sha_state_ctx = &rctx->sha1_state_ctx;
-	struct sha1_state *in_ctx = (struct sha1_state *)in;
-
-	sha_state_ctx->count = in_ctx->count;
-	memcpy(sha_state_ctx->state, in_ctx->state, sizeof(in_ctx->state));
-	memcpy(sha_state_ctx->buffer, in_ctx->buffer, SHA1_BLOCK_SIZE);
-	memcpy(sha_ctx->trailing_buf, in_ctx->buffer, SHA1_BLOCK_SIZE);
-
-	sha_ctx->byte_count[0] =  (uint32_t)(in_ctx->count & 0xFFFFFFC0);
-	sha_ctx->byte_count[1] =  (uint32_t)(in_ctx->count >> 32);
-	_words_to_byte_stream(in_ctx->state, sha_ctx->digest, sha_ctx->diglen);
-
-	sha_ctx->trailing_buf_len = (uint32_t)(in_ctx->count &
-						(SHA1_BLOCK_SIZE-1));
-
-	if (!(in_ctx->count))
-		sha_ctx->first_blk = 1;
-	else
-		sha_ctx->first_blk = 0;
-
-	return 0;
+	return __sha1_import_common(req, in, false);
 }
+
+static int _sha1_hmac_import(struct ahash_request  *req, const void *in)
+{
+	return __sha1_import_common(req, in, true);
+}
+
 static int _sha256_export(struct ahash_request  *req, void *out)
 {
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha256_state *sha_state_ctx = &rctx->sha256_state_ctx;
 	struct sha256_state *out_ctx = (struct sha256_state *)out;
 
-	out_ctx->count = sha_state_ctx->count;
-	memcpy(out_ctx->state, sha_state_ctx->state, sizeof(out_ctx->state));
-	memcpy(out_ctx->buf, sha_state_ctx->buf, SHA256_BLOCK_SIZE);
+	out_ctx->count = rctx->count;
+	_byte_stream_to_words(out_ctx->state, rctx->digest, SHA256_DIGEST_SIZE);
+	memcpy(out_ctx->buf, rctx->trailing_buf, SHA256_BLOCK_SIZE);
 
 	return 0;
 };
 
-static int _sha256_import(struct ahash_request  *req, const void *in)
+static int _sha256_hmac_export(struct ahash_request  *req, void *out)
+{
+	return _sha256_export(req, out);
+}
+
+static int __sha256_import_common(struct ahash_request  *req, const void *in,
+			bool hmac)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha256_state *sha_state_ctx = &rctx->sha256_state_ctx;
 	struct sha256_state *in_ctx = (struct sha256_state *)in;
+	u64 hw_count = in_ctx->count;
 
-	sha_state_ctx->count = in_ctx->count;
-	memcpy(sha_state_ctx->state, in_ctx->state, sizeof(in_ctx->state));
-	memcpy(sha_state_ctx->buf, in_ctx->buf, SHA256_BLOCK_SIZE);
-	memcpy(sha_ctx->trailing_buf, in_ctx->buf, SHA256_BLOCK_SIZE);
+	rctx->count = in_ctx->count;
+	memcpy(rctx->trailing_buf, in_ctx->buf, SHA256_BLOCK_SIZE);
 
-	sha_ctx->byte_count[0] =  (uint32_t)(in_ctx->count & 0xFFFFFFC0);
-	sha_ctx->byte_count[1] =  (uint32_t)(in_ctx->count >> 32);
-	_words_to_byte_stream(in_ctx->state, sha_ctx->digest, sha_ctx->diglen);
+	if (in_ctx->count <= SHA256_BLOCK_SIZE) {
+		rctx->first_blk = 1;
+	} else {
+		rctx->first_blk = 0;
+		/*
+		 * for hmac, there is a hardware padding done
+		 * when first is set. So the byte_count will be
+		 * incremened by 64 after the operstion of first
+		 */
+		if (hmac)
+			hw_count += HMAC_PADDING;
+	}
 
-	sha_ctx->trailing_buf_len = (uint32_t)(in_ctx->count &
+	rctx->byte_count[0] =  (uint32_t)(hw_count & 0xFFFFFFC0);
+	rctx->byte_count[1] =  (uint32_t)(hw_count >> 32);
+	_words_to_byte_stream(in_ctx->state, rctx->digest, sha_ctx->diglen);
+
+	rctx->trailing_buf_len = (uint32_t)(in_ctx->count &
 						(SHA256_BLOCK_SIZE-1));
 
-	if (!(in_ctx->count))
-		sha_ctx->first_blk = 1;
-	else
-		sha_ctx->first_blk = 0;
 
 	return 0;
 }
 
+static int _sha256_import(struct ahash_request  *req, const void *in)
+{
+	return __sha256_import_common(req, in, false);
+}
+
+static int _sha256_hmac_import(struct ahash_request  *req, const void *in)
+{
+	return __sha256_import_common(req, in, true);
+}
+
 static int _copy_source(struct ahash_request  *req)
 {
 	struct qcrypto_sha_req_ctx *srctx = NULL;
@@ -2593,23 +2725,19 @@
 	uint32_t nbytes;
 	uint32_t offset = 0;
 	uint32_t bytes = 0;
-
+	uint8_t  *staging;
 	int ret = 0;
 
 	/* check for trailing buffer from previous updates and append it */
-	total = req->nbytes + sha_ctx->trailing_buf_len;
+	total = req->nbytes + rctx->trailing_buf_len;
 	len = req->nbytes;
 
 	if (total <= sha_block_size) {
-		k_src = &sha_ctx->trailing_buf[sha_ctx->trailing_buf_len];
+		k_src = &rctx->trailing_buf[rctx->trailing_buf_len];
 		num_sg = qcrypto_count_sg(req->src, len);
 		bytes = qcrypto_sg_copy_to_buffer(req->src, num_sg, k_src, len);
 
-		sha_ctx->trailing_buf_len = total;
-		if (sha_ctx->alg == QCE_HASH_SHA1)
-			_update_sha1_ctx(req);
-		if (sha_ctx->alg == QCE_HASH_SHA256)
-			_update_sha256_ctx(req);
+		rctx->trailing_buf_len = total;
 		return 0;
 	}
 
@@ -2617,9 +2745,10 @@
 	rctx->src = req->src;
 	rctx->nbytes = req->nbytes;
 
-	memcpy(sha_ctx->tmp_tbuf, sha_ctx->trailing_buf,
-					sha_ctx->trailing_buf_len);
-	k_src = &sha_ctx->trailing_buf[0];
+	staging = (uint8_t *) ALIGN(((unsigned int)rctx->staging_dmabuf),
+							L1_CACHE_BYTES);
+	memcpy(staging, rctx->trailing_buf, rctx->trailing_buf_len);
+	k_src = &rctx->trailing_buf[0];
 	/*  get new trailing buffer */
 	sha_pad_len = ALIGN(total, sha_block_size) - total;
 	trailing_buf_len =  sha_block_size - sha_pad_len;
@@ -2632,7 +2761,7 @@
 	nbytes = total - trailing_buf_len;
 	num_sg = qcrypto_count_sg(req->src, req->nbytes);
 
-	len = sha_ctx->trailing_buf_len;
+	len = rctx->trailing_buf_len;
 	sg_last = req->src;
 
 	while (len < nbytes) {
@@ -2641,56 +2770,41 @@
 		len += sg_last->length;
 		sg_last = scatterwalk_sg_next(sg_last);
 	}
-	if (sha_ctx->trailing_buf_len) {
+	if (rctx->trailing_buf_len) {
 		if (cp->ce_support.aligned_only)  {
-			sha_ctx->sg = kzalloc(sizeof(struct scatterlist),
-								GFP_ATOMIC);
-			if (sha_ctx->sg == NULL) {
-				pr_err("MemAlloc fail sha_ctx->sg, error %ld\n",
-						PTR_ERR(sha_ctx->sg));
-				return -ENOMEM;
-			}
 			rctx->data2 = kzalloc((req->nbytes + 64), GFP_ATOMIC);
 			if (rctx->data2 == NULL) {
 				pr_err("Mem Alloc fail srctx->data2, err %ld\n",
 							PTR_ERR(rctx->data2));
-				kfree(sha_ctx->sg);
 				return -ENOMEM;
 			}
-			memcpy(rctx->data2, sha_ctx->tmp_tbuf,
-						sha_ctx->trailing_buf_len);
-			memcpy((rctx->data2 + sha_ctx->trailing_buf_len),
+			memcpy(rctx->data2, staging,
+						rctx->trailing_buf_len);
+			memcpy((rctx->data2 + rctx->trailing_buf_len),
 					rctx->data, req->src->length);
 			kfree(rctx->data);
 			rctx->data = rctx->data2;
-			sg_set_buf(&sha_ctx->sg[0], rctx->data,
-					(sha_ctx->trailing_buf_len +
+			sg_set_buf(&rctx->sg[0], rctx->data,
+					(rctx->trailing_buf_len +
 							req->src->length));
-			req->src = sha_ctx->sg;
-			sg_mark_end(&sha_ctx->sg[0]);
+			req->src = rctx->sg;
+			sg_mark_end(&rctx->sg[0]);
 		} else {
 			sg_mark_end(sg_last);
-			sha_ctx->sg = kzalloc(2 * (sizeof(struct scatterlist)),
-								GFP_ATOMIC);
-			if (sha_ctx->sg == NULL) {
-				pr_err("MEMalloc fail sha_ctx->sg, error %ld\n",
-							PTR_ERR(sha_ctx->sg));
-				return -ENOMEM;
-			}
-
-			sg_set_buf(&sha_ctx->sg[0], sha_ctx->tmp_tbuf,
-						sha_ctx->trailing_buf_len);
-			sg_mark_end(&sha_ctx->sg[1]);
-			sg_chain(sha_ctx->sg, 2, req->src);
-			req->src = sha_ctx->sg;
+			memset(rctx->sg, 0, sizeof(rctx->sg));
+			sg_set_buf(&rctx->sg[0], staging,
+						rctx->trailing_buf_len);
+			sg_mark_end(&rctx->sg[1]);
+			sg_chain(rctx->sg, 2, req->src);
+			req->src = rctx->sg;
 		}
 	} else
 		sg_mark_end(sg_last);
 
 	req->nbytes = nbytes;
-	sha_ctx->trailing_buf_len = trailing_buf_len;
+	rctx->trailing_buf_len = trailing_buf_len;
 
-	ret =  _qcrypto_queue_req(cp, &req->base);
+	ret =  _qcrypto_queue_req(cp, sha_ctx->pengine, &req->base);
 
 	return ret;
 };
@@ -2698,7 +2812,6 @@
 static int _sha1_update(struct ahash_request  *req)
 {
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha1_state *sha_state_ctx = &rctx->sha1_state_ctx;
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_priv *cp = sha_ctx->cp;
 
@@ -2706,14 +2819,13 @@
 		if (_copy_source(req))
 			return -ENOMEM;
 	}
-	sha_state_ctx->count += req->nbytes;
+	rctx->count += req->nbytes;
 	return _sha_update(req, SHA1_BLOCK_SIZE);
 }
 
 static int _sha256_update(struct ahash_request  *req)
 {
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
-	struct sha256_state *sha_state_ctx = &rctx->sha256_state_ctx;
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_priv *cp = sha_ctx->cp;
 
@@ -2722,7 +2834,7 @@
 			return -ENOMEM;
 	}
 
-	sha_state_ctx->count += req->nbytes;
+	rctx->count += req->nbytes;
 	return _sha_update(req, SHA256_BLOCK_SIZE);
 }
 
@@ -2732,26 +2844,29 @@
 	struct crypto_priv *cp = sha_ctx->cp;
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 	int ret = 0;
+	uint8_t  *staging;
 
 	if (cp->ce_support.aligned_only) {
 		if (_copy_source(req))
 			return -ENOMEM;
 	}
 
-	sha_ctx->last_blk = 1;
+	rctx->last_blk = 1;
 
 	/* save the original req structure fields*/
 	rctx->src = req->src;
 	rctx->nbytes = req->nbytes;
 
-	sg_set_buf(&sha_ctx->tmp_sg, sha_ctx->trailing_buf,
-					sha_ctx->trailing_buf_len);
-	sg_mark_end(&sha_ctx->tmp_sg);
+	staging = (uint8_t *) ALIGN(((unsigned int)rctx->staging_dmabuf),
+							L1_CACHE_BYTES);
+	memcpy(staging, rctx->trailing_buf, rctx->trailing_buf_len);
+	sg_set_buf(&rctx->sg[0], staging, rctx->trailing_buf_len);
+	sg_mark_end(&rctx->sg[0]);
 
-	req->src = &sha_ctx->tmp_sg;
-	req->nbytes = sha_ctx->trailing_buf_len;
+	req->src = &rctx->sg[0];
+	req->nbytes = rctx->trailing_buf_len;
 
-	ret =  _qcrypto_queue_req(cp, &req->base);
+	ret =  _qcrypto_queue_req(cp, sha_ctx->pengine, &req->base);
 
 	return ret;
 };
@@ -2781,9 +2896,9 @@
 	/* save the original req structure fields*/
 	rctx->src = req->src;
 	rctx->nbytes = req->nbytes;
-	sha_ctx->first_blk = 1;
-	sha_ctx->last_blk = 1;
-	ret =  _qcrypto_queue_req(cp, &req->base);
+	rctx->first_blk = 1;
+	rctx->last_blk = 1;
+	ret =  _qcrypto_queue_req(cp, sha_ctx->pengine, &req->base);
 
 	return ret;
 }
@@ -2814,32 +2929,49 @@
 		unsigned int len)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base);
+	uint8_t	*in_buf;
 	int ret = 0;
+	struct scatterlist sg;
+	struct ahash_request *ahash_req;
+	struct completion ahash_req_complete;
 
-	sha_ctx->in_buf = kzalloc(len + 64, GFP_KERNEL);
-	if (sha_ctx->in_buf == NULL) {
-		pr_err("qcrypto Can't Allocate mem: sha_ctx->in_buf, error %ld\n",
-		PTR_ERR(sha_ctx->in_buf));
+	ahash_req = ahash_request_alloc(tfm, GFP_KERNEL);
+	if (ahash_req == NULL)
+		return -ENOMEM;
+	init_completion(&ahash_req_complete);
+	ahash_request_set_callback(ahash_req,
+				CRYPTO_TFM_REQ_MAY_BACKLOG,
+				_crypto_sha_hmac_ahash_req_complete,
+				&ahash_req_complete);
+	crypto_ahash_clear_flags(tfm, ~0);
+
+	in_buf = kzalloc(len + 64, GFP_KERNEL);
+	if (in_buf == NULL) {
+		pr_err("qcrypto Can't Allocate mem: in_buf, error %ld\n",
+			PTR_ERR(in_buf));
+		ahash_request_free(ahash_req);
 		return -ENOMEM;
 	}
-	memcpy(sha_ctx->in_buf, key, len);
-	sg_set_buf(&sha_ctx->tmp_sg, sha_ctx->in_buf, len);
-	sg_mark_end(&sha_ctx->tmp_sg);
+	memcpy(in_buf, key, len);
+	sg_set_buf(&sg, in_buf, len);
+	sg_mark_end(&sg);
 
-	ahash_request_set_crypt(sha_ctx->ahash_req, &sha_ctx->tmp_sg,
+	ahash_request_set_crypt(ahash_req, &sg,
 				&sha_ctx->authkey[0], len);
 
-	ret = _sha_digest(sha_ctx->ahash_req);
+	if (sha_ctx->alg == QCE_HASH_SHA1)
+		ret = _sha1_digest(ahash_req);
+	else
+		ret = _sha256_digest(ahash_req);
 	if (ret == -EINPROGRESS || ret == -EBUSY) {
 		ret =
 			wait_for_completion_interruptible(
-						&sha_ctx->ahash_req_complete);
+						&ahash_req_complete);
 		INIT_COMPLETION(sha_ctx->ahash_req_complete);
 	}
 
-	sha_ctx->authkey_in_len = len;
-	kfree(sha_ctx->in_buf);
-	sha_ctx->in_buf = NULL;
+	kfree(in_buf);
+	ahash_request_free(ahash_req);
 
 	return ret;
 }
@@ -2848,16 +2980,15 @@
 							unsigned int len)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base);
-
-	if (len <= SHA1_BLOCK_SIZE)
+	memset(&sha_ctx->authkey[0], 0, SHA1_BLOCK_SIZE);
+	if (len <= SHA1_BLOCK_SIZE) {
 		memcpy(&sha_ctx->authkey[0], key, len);
-	else {
-		_sha_init(sha_ctx);
+		sha_ctx->authkey_in_len = len;
+	} else {
 		sha_ctx->alg = QCE_HASH_SHA1;
-		memcpy(&sha_ctx->digest[0], &_std_init_vector_sha1_uint8[0],
-						SHA1_DIGEST_SIZE);
 		sha_ctx->diglen = SHA1_DIGEST_SIZE;
 		_sha_hmac_setkey(tfm, key, len);
+		sha_ctx->authkey_in_len = SHA1_BLOCK_SIZE;
 	}
 	return 0;
 }
@@ -2867,15 +2998,15 @@
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(&tfm->base);
 
-	if (len <= SHA256_BLOCK_SIZE)
+	memset(&sha_ctx->authkey[0], 0, SHA256_BLOCK_SIZE);
+	if (len <= SHA256_BLOCK_SIZE) {
 		memcpy(&sha_ctx->authkey[0], key, len);
-	else {
-		_sha_init(sha_ctx);
+		sha_ctx->authkey_in_len = len;
+	} else {
 		sha_ctx->alg = QCE_HASH_SHA256;
-		memcpy(&sha_ctx->digest[0], &_std_init_vector_sha256_uint8[0],
-						SHA256_DIGEST_SIZE);
 		sha_ctx->diglen = SHA256_DIGEST_SIZE;
 		_sha_hmac_setkey(tfm, key, len);
+		sha_ctx->authkey_in_len = SHA256_BLOCK_SIZE;
 	}
 
 	return 0;
@@ -2885,11 +3016,12 @@
 						uint32_t sha_block_size)
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 	int i;
 
 	for (i = 0; i < sha_block_size; i++)
-		sha_ctx->trailing_buf[i] = sha_ctx->authkey[i] ^ 0x36;
-	sha_ctx->trailing_buf_len = sha_block_size;
+		rctx->trailing_buf[i] = sha_ctx->authkey[i] ^ 0x36;
+	rctx->trailing_buf_len = sha_block_size;
 
 	return 0;
 }
@@ -2900,16 +3032,16 @@
 	struct crypto_priv *cp = sha_ctx->cp;
 	struct crypto_stat *pstat;
 	int ret = 0;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 
 	pstat = &_qcrypto_stat;
 	pstat->sha1_hmac_digest++;
 
-	_sha_init(sha_ctx);
-	memset(&sha_ctx->trailing_buf[0], 0x00, SHA1_BLOCK_SIZE);
-	memcpy(&sha_ctx->digest[0], &_std_init_vector_sha1_uint8[0],
+	_sha_init(req);
+	memset(&rctx->trailing_buf[0], 0x00, SHA1_BLOCK_SIZE);
+	memcpy(&rctx->digest[0], &_std_init_vector_sha1_uint8[0],
 						SHA1_DIGEST_SIZE);
 	sha_ctx->diglen = SHA1_DIGEST_SIZE;
-	_update_sha1_ctx(req);
 
 	if (cp->ce_support.sha_hmac)
 			sha_ctx->alg = QCE_HASH_SHA1_HMAC;
@@ -2927,16 +3059,17 @@
 	struct crypto_priv *cp = sha_ctx->cp;
 	struct crypto_stat *pstat;
 	int ret = 0;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 
 	pstat = &_qcrypto_stat;
 	pstat->sha256_hmac_digest++;
 
-	_sha_init(sha_ctx);
-	memset(&sha_ctx->trailing_buf[0], 0x00, SHA256_BLOCK_SIZE);
-	memcpy(&sha_ctx->digest[0], &_std_init_vector_sha256_uint8[0],
+	_sha_init(req);
+
+	memset(&rctx->trailing_buf[0], 0x00, SHA256_BLOCK_SIZE);
+	memcpy(&rctx->digest[0], &_std_init_vector_sha256_uint8[0],
 						SHA256_DIGEST_SIZE);
 	sha_ctx->diglen = SHA256_DIGEST_SIZE;
-	_update_sha256_ctx(req);
 
 	if (cp->ce_support.sha_hmac)
 		sha_ctx->alg = QCE_HASH_SHA256_HMAC;
@@ -2965,36 +3098,39 @@
 	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 	struct crypto_priv *cp = sha_ctx->cp;
 	int i;
+	uint8_t  *staging;
+	uint8_t *p;
 
+	staging = (uint8_t *) ALIGN(((unsigned int)rctx->staging_dmabuf),
+							L1_CACHE_BYTES);
+	p = staging;
 	for (i = 0; i < sha_block_size; i++)
-		sha_ctx->tmp_tbuf[i] = sha_ctx->authkey[i] ^ 0x5c;
+		*p++ = sha_ctx->authkey[i] ^ 0x5c;
+	memcpy(p, &rctx->digest[0], sha_digest_size);
+	sg_set_buf(&rctx->sg[0], staging, sha_block_size +
+							sha_digest_size);
+	sg_mark_end(&rctx->sg[0]);
 
 	/* save the original req structure fields*/
 	rctx->src = req->src;
 	rctx->nbytes = req->nbytes;
 
-	memcpy(&sha_ctx->tmp_tbuf[sha_block_size], &sha_ctx->digest[0],
-						 sha_digest_size);
-
-	sg_set_buf(&sha_ctx->tmp_sg, sha_ctx->tmp_tbuf, sha_block_size +
-							sha_digest_size);
-	sg_mark_end(&sha_ctx->tmp_sg);
-	req->src = &sha_ctx->tmp_sg;
+	req->src = &rctx->sg[0];
 	req->nbytes = sha_block_size + sha_digest_size;
 
-	_sha_init(sha_ctx);
+	_sha_init(req);
 	if (sha_ctx->alg == QCE_HASH_SHA1) {
-		memcpy(&sha_ctx->digest[0], &_std_init_vector_sha1_uint8[0],
+		memcpy(&rctx->digest[0], &_std_init_vector_sha1_uint8[0],
 							SHA1_DIGEST_SIZE);
 		sha_ctx->diglen = SHA1_DIGEST_SIZE;
 	} else {
-		memcpy(&sha_ctx->digest[0], &_std_init_vector_sha256_uint8[0],
+		memcpy(&rctx->digest[0], &_std_init_vector_sha256_uint8[0],
 							SHA256_DIGEST_SIZE);
 		sha_ctx->diglen = SHA256_DIGEST_SIZE;
 	}
 
-	sha_ctx->last_blk = 1;
-	return  _qcrypto_queue_req(cp, &req->base);
+	rctx->last_blk = 1;
+	return  _qcrypto_queue_req(cp, sha_ctx->pengine, &req->base);
 }
 
 static int _sha_hmac_inner_hash(struct ahash_request *req,
@@ -3004,17 +3140,19 @@
 	struct ahash_request *areq = sha_ctx->ahash_req;
 	struct crypto_priv *cp = sha_ctx->cp;
 	int ret = 0;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
+	uint8_t  *staging;
 
-	sha_ctx->last_blk = 1;
+	staging = (uint8_t *) ALIGN(((unsigned int)rctx->staging_dmabuf),
+							L1_CACHE_BYTES);
+	memcpy(staging, rctx->trailing_buf, rctx->trailing_buf_len);
+	sg_set_buf(&rctx->sg[0], staging, rctx->trailing_buf_len);
+	sg_mark_end(&rctx->sg[0]);
 
-	sg_set_buf(&sha_ctx->tmp_sg, sha_ctx->trailing_buf,
-					sha_ctx->trailing_buf_len);
-	sg_mark_end(&sha_ctx->tmp_sg);
-
-	ahash_request_set_crypt(areq, &sha_ctx->tmp_sg, &sha_ctx->digest[0],
-						sha_ctx->trailing_buf_len);
-	sha_ctx->last_blk = 1;
-	ret =  _qcrypto_queue_req(cp, &areq->base);
+	ahash_request_set_crypt(areq, &rctx->sg[0], &rctx->digest[0],
+						rctx->trailing_buf_len);
+	rctx->last_blk = 1;
+	ret =  _qcrypto_queue_req(cp, sha_ctx->pengine, &areq->base);
 
 	if (ret == -EINPROGRESS || ret == -EBUSY) {
 		ret =
@@ -3067,12 +3205,13 @@
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_stat *pstat;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 
 	pstat = &_qcrypto_stat;
 	pstat->sha1_hmac_digest++;
 
-	_sha_init(sha_ctx);
-	memcpy(&sha_ctx->digest[0], &_std_init_vector_sha1_uint8[0],
+	_sha_init(req);
+	memcpy(&rctx->digest[0], &_std_init_vector_sha1_uint8[0],
 							SHA1_DIGEST_SIZE);
 	sha_ctx->diglen = SHA1_DIGEST_SIZE;
 	sha_ctx->alg = QCE_HASH_SHA1_HMAC;
@@ -3084,12 +3223,13 @@
 {
 	struct qcrypto_sha_ctx *sha_ctx = crypto_tfm_ctx(req->base.tfm);
 	struct crypto_stat *pstat;
+	struct qcrypto_sha_req_ctx *rctx = ahash_request_ctx(req);
 
 	pstat = &_qcrypto_stat;
 	pstat->sha256_hmac_digest++;
 
-	_sha_init(sha_ctx);
-	memcpy(&sha_ctx->digest[0], &_std_init_vector_sha256_uint8[0],
+	_sha_init(req);
+	memcpy(&rctx->digest[0], &_std_init_vector_sha256_uint8[0],
 						SHA256_DIGEST_SIZE);
 	sha_ctx->diglen = SHA256_DIGEST_SIZE;
 	sha_ctx->alg = QCE_HASH_SHA256_HMAC;
@@ -3097,6 +3237,16 @@
 	return _sha_digest(req);
 }
 
+static int _qcrypto_prefix_alg_cra_name(char cra_name[], unsigned int size)
+{
+	char new_cra_name[CRYPTO_MAX_ALG_NAME] = "qcom-";
+	if (CRYPTO_MAX_ALG_NAME < size + 5)
+		return -EINVAL;
+	strlcat(new_cra_name, cra_name, CRYPTO_MAX_ALG_NAME);
+	strlcpy(cra_name, new_cra_name, CRYPTO_MAX_ALG_NAME);
+	return 0;
+}
+
 int qcrypto_cipher_set_flag(struct ablkcipher_request *req, unsigned int flags)
 {
 	struct qcrypto_cipher_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
@@ -3252,8 +3402,8 @@
 		.init		=	_sha1_hmac_init,
 		.update		=	_sha1_hmac_update,
 		.final		=	_sha1_hmac_final,
-		.export		=	_sha1_export,
-		.import		=	_sha1_import,
+		.export		=	_sha1_hmac_export,
+		.import		=	_sha1_hmac_import,
 		.digest		=	_sha1_hmac_digest,
 		.setkey		=	_sha1_hmac_setkey,
 		.halg		= {
@@ -3280,8 +3430,8 @@
 		.init		=	_sha256_hmac_init,
 		.update		=	_sha256_hmac_update,
 		.final		=	_sha256_hmac_final,
-		.export		=	_sha256_export,
-		.import		=	_sha256_import,
+		.export		=	_sha256_hmac_export,
+		.import		=	_sha256_hmac_import,
 		.digest		=	_sha256_hmac_digest,
 		.setkey		=	_sha256_hmac_setkey,
 		.halg		= {
@@ -3627,38 +3777,59 @@
 {
 	int rc = 0;
 	void *handle;
-	struct crypto_priv *cp;
+	struct crypto_priv *cp = &qcrypto_dev;
 	int i;
 	struct msm_ce_hw_support *platform_support;
+	struct crypto_engine *pengine;
+	unsigned long flags;
 
-	cp = kzalloc(sizeof(*cp), GFP_KERNEL);
-	if (!cp) {
+	pengine = kzalloc(sizeof(*pengine), GFP_KERNEL);
+	if (!pengine) {
 		pr_err("qcrypto Memory allocation of q_alg FAIL, error %ld\n",
-				PTR_ERR(cp));
+				PTR_ERR(pengine));
 		return -ENOMEM;
 	}
 
 	/* open qce */
 	handle = qce_open(pdev, &rc);
 	if (handle == NULL) {
-		kfree(cp);
+		kfree(pengine);
 		platform_set_drvdata(pdev, NULL);
 		return rc;
 	}
 
-	INIT_LIST_HEAD(&cp->alg_list);
-	platform_set_drvdata(pdev, cp);
-	spin_lock_init(&cp->lock);
-	tasklet_init(&cp->done_tasklet, req_done, (unsigned long)cp);
-	crypto_init_queue(&cp->queue, 50);
-	cp->qce = handle;
-	cp->pdev = pdev;
-	qce_hw_support(cp->qce, &cp->ce_support);
+	platform_set_drvdata(pdev, pengine);
+	pengine->qce = handle;
+	pengine->pcp = cp;
+	pengine->pdev = pdev;
+	pengine->req = NULL;
+
+	pengine->high_bw_req_count = 0;
+	pengine->high_bw_req = false;
+	init_timer(&(pengine->bw_scale_down_timer));
+	INIT_WORK(&pengine->low_bw_req_ws, qcrypto_low_bw_req_work);
+	pengine->bw_scale_down_timer.function =
+			qcrypto_bw_scale_down_timer_callback;
+
+	device_init_wakeup(&pengine->pdev->dev, true);
+
+	tasklet_init(&pengine->done_tasklet, req_done, (unsigned long)pengine);
+	crypto_init_queue(&pengine->req_queue, 50);
+
+	mutex_lock(&cp->engine_lock);
+	cp->total_units++;
+	pengine->unit = cp->total_units;
+
+	spin_lock_irqsave(&cp->lock, flags);
+	list_add_tail(&pengine->elist, &cp->engine_list);
+	cp->next_engine = pengine;
+	spin_unlock_irqrestore(&cp->lock, flags);
+
+	qce_hw_support(pengine->qce, &cp->ce_support);
 	if (cp->ce_support.bam)	 {
 		cp->platform_support.ce_shared = cp->ce_support.is_shared;
 		cp->platform_support.shared_ce_resource = 0;
 		cp->platform_support.hw_key_support = cp->ce_support.hw_key;
-		cp->platform_support.bus_scale_table =	NULL;
 		cp->platform_support.sha_hmac = 1;
 
 		cp->platform_support.bus_scale_table =
@@ -3678,26 +3849,25 @@
 				platform_support->bus_scale_table;
 		cp->platform_support.sha_hmac = platform_support->sha_hmac;
 	}
-	cp->high_bw_req_count = 0;
-	cp->ce_lock_count = 0;
-
-
-	if (cp->platform_support.ce_shared)
-		INIT_WORK(&cp->unlock_ce_ws, qcrypto_unlock_ce);
-
+	pengine->bus_scale_handle = 0;
 	if (cp->platform_support.bus_scale_table != NULL) {
-		cp->bus_scale_handle =
+		pengine->bus_scale_handle =
 			msm_bus_scale_register_client(
 				(struct msm_bus_scale_pdata *)
 					cp->platform_support.bus_scale_table);
-		if (!cp->bus_scale_handle) {
-			printk(KERN_ERR "%s not able to get bus scale\n",
+		if (!pengine->bus_scale_handle) {
+			pr_err("%s not able to get bus scale\n",
 				__func__);
 			rc =  -ENOMEM;
 			goto err;
 		}
 	}
 
+	if (cp->total_units != 1) {
+		mutex_unlock(&cp->engine_lock);
+		return 0;
+	}
+
 	/* register crypto cipher algorithms the device supports */
 	for (i = 0; i < ARRAY_SIZE(_qcrypto_ablk_cipher_algos); i++) {
 		struct qcrypto_alg *q_alg;
@@ -3708,6 +3878,17 @@
 			rc = PTR_ERR(q_alg);
 			goto err;
 		}
+		if (cp->ce_support.use_sw_aes_cbc_ecb_ctr_algo) {
+			rc = _qcrypto_prefix_alg_cra_name(
+					q_alg->cipher_alg.cra_name,
+					strlen(q_alg->cipher_alg.cra_name));
+			if (rc) {
+				dev_err(&pdev->dev,
+					"The algorithm name %s is too long.\n",
+					q_alg->cipher_alg.cra_name);
+				goto err;
+			}
+		}
 		rc = crypto_register_alg(&q_alg->cipher_alg);
 		if (rc) {
 			dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3730,6 +3911,17 @@
 			rc = PTR_ERR(q_alg);
 			goto err;
 		}
+		if (cp->ce_support.use_sw_aes_xts_algo) {
+			rc = _qcrypto_prefix_alg_cra_name(
+					q_alg->cipher_alg.cra_name,
+					strlen(q_alg->cipher_alg.cra_name));
+			if (rc) {
+				dev_err(&pdev->dev,
+					"The algorithm name %s is too long.\n",
+					q_alg->cipher_alg.cra_name);
+				goto err;
+			}
+		}
 		rc = crypto_register_alg(&q_alg->cipher_alg);
 		if (rc) {
 			dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3755,7 +3947,17 @@
 			rc = PTR_ERR(q_alg);
 			goto err;
 		}
-
+		if (cp->ce_support.use_sw_ahash_algo) {
+			rc = _qcrypto_prefix_alg_cra_name(
+				q_alg->sha_alg.halg.base.cra_name,
+				strlen(q_alg->sha_alg.halg.base.cra_name));
+			if (rc) {
+				dev_err(&pdev->dev,
+					"The algorithm name %s is too long.\n",
+					q_alg->sha_alg.halg.base.cra_name);
+				goto err;
+			}
+		}
 		rc = crypto_register_ahash(&q_alg->sha_alg);
 		if (rc) {
 			dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3781,7 +3983,17 @@
 				rc = PTR_ERR(q_alg);
 				goto err;
 			}
-
+			if (cp->ce_support.use_sw_aead_algo) {
+				rc = _qcrypto_prefix_alg_cra_name(
+					q_alg->cipher_alg.cra_name,
+					strlen(q_alg->cipher_alg.cra_name));
+				if (rc) {
+					dev_err(&pdev->dev,
+						"The algorithm name %s is too long.\n",
+						q_alg->cipher_alg.cra_name);
+					goto err;
+				}
+			}
 			rc = crypto_register_alg(&q_alg->cipher_alg);
 			if (rc) {
 				dev_err(&pdev->dev,
@@ -3808,7 +4020,18 @@
 				rc = PTR_ERR(q_alg);
 				goto err;
 			}
-
+			if (cp->ce_support.use_sw_hmac_algo) {
+				rc = _qcrypto_prefix_alg_cra_name(
+					q_alg->sha_alg.halg.base.cra_name,
+					strlen(
+					q_alg->sha_alg.halg.base.cra_name));
+				if (rc) {
+					dev_err(&pdev->dev,
+					     "The algorithm name %s is too long.\n",
+					     q_alg->sha_alg.halg.base.cra_name);
+					goto err;
+				}
+			}
 			rc = crypto_register_ahash(&q_alg->sha_alg);
 			if (rc) {
 				dev_err(&pdev->dev,
@@ -3834,6 +4057,17 @@
 			rc = PTR_ERR(q_alg);
 			goto err;
 		}
+		if (cp->ce_support.use_sw_aes_ccm_algo) {
+			rc = _qcrypto_prefix_alg_cra_name(
+					q_alg->cipher_alg.cra_name,
+					strlen(q_alg->cipher_alg.cra_name));
+			if (rc) {
+				dev_err(&pdev->dev,
+						"The algorithm name %s is too long.\n",
+						q_alg->cipher_alg.cra_name);
+				goto err;
+			}
+		}
 		rc = crypto_register_alg(&q_alg->cipher_alg);
 		if (rc) {
 			dev_err(&pdev->dev, "%s alg registration failed\n",
@@ -3846,13 +4080,112 @@
 		}
 	}
 
+	mutex_unlock(&cp->engine_lock);
 	return 0;
 err:
-	_qcrypto_remove(pdev);
+	_qcrypto_remove_engine(pengine);
+	mutex_unlock(&cp->engine_lock);
+	if (pengine->qce)
+		qce_close(pengine->qce);
+	kfree(pengine);
 	return rc;
 };
 
 
+static int  _qcrypto_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int ret = 0;
+	struct crypto_engine *pengine;
+	struct crypto_priv *cp;
+
+	pengine = platform_get_drvdata(pdev);
+	if (!pengine)
+		return -EINVAL;
+
+	/*
+	 * Check if this platform supports clock management in suspend/resume
+	 * If not, just simply return 0.
+	 */
+	cp = pengine->pcp;
+	if (!cp->ce_support.clk_mgmt_sus_res)
+		return 0;
+
+	mutex_lock(&cp->engine_lock);
+
+	if (pengine->high_bw_req) {
+		del_timer_sync(&(pengine->bw_scale_down_timer));
+		ret = msm_bus_scale_client_update_request(
+				pengine->bus_scale_handle, 0);
+		if (ret) {
+			dev_err(&pdev->dev, "%s Unable to set to low bandwidth\n",
+					__func__);
+			mutex_unlock(&cp->engine_lock);
+			return ret;
+		}
+		ret = qce_disable_clk(pengine->qce);
+		if (ret) {
+			pr_err("%s Unable disable clk\n", __func__);
+			ret = msm_bus_scale_client_update_request(
+				pengine->bus_scale_handle, 1);
+			if (ret)
+				dev_err(&pdev->dev,
+					"%s Unable to set to high bandwidth\n",
+					__func__);
+			mutex_unlock(&cp->engine_lock);
+			return ret;
+		}
+	}
+
+	mutex_unlock(&cp->engine_lock);
+	return 0;
+}
+
+static int  _qcrypto_resume(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct crypto_engine *pengine;
+	struct crypto_priv *cp;
+
+	pengine = platform_get_drvdata(pdev);
+
+	if (!pengine)
+		return -EINVAL;
+
+	cp = pengine->pcp;
+	if (!cp->ce_support.clk_mgmt_sus_res)
+		return 0;
+
+	mutex_lock(&cp->engine_lock);
+	if (pengine->high_bw_req) {
+		ret = qce_enable_clk(pengine->qce);
+		if (ret) {
+			dev_err(&pdev->dev, "%s Unable to enable clk\n",
+				__func__);
+			mutex_unlock(&cp->engine_lock);
+			return ret;
+		}
+		ret = msm_bus_scale_client_update_request(
+				pengine->bus_scale_handle, 1);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"%s Unable to set to high bandwidth\n",
+				__func__);
+			qce_disable_clk(pengine->qce);
+			mutex_unlock(&cp->engine_lock);
+			return ret;
+		}
+		pengine->bw_scale_down_timer.data =
+					(unsigned long)(pengine);
+		pengine->bw_scale_down_timer.expires = jiffies +
+			msecs_to_jiffies(QCRYPTO_HIGH_BANDWIDTH_TIMEOUT);
+		add_timer(&(pengine->bw_scale_down_timer));
+	}
+
+	mutex_unlock(&cp->engine_lock);
+
+	return 0;
+}
+
 static struct of_device_id qcrypto_match[] = {
 	{	.compatible = "qcom,qcrypto",
 	},
@@ -3862,6 +4195,8 @@
 static struct platform_driver _qualcomm_crypto = {
 	.probe          = _qcrypto_probe,
 	.remove         = _qcrypto_remove,
+	.suspend        = _qcrypto_suspend,
+	.resume         = _qcrypto_resume,
 	.driver         = {
 		.owner  = THIS_MODULE,
 		.name   = "qcrypto",
@@ -3895,10 +4230,19 @@
 static ssize_t _debug_stats_write(struct file *file, const char __user *buf,
 			size_t count, loff_t *ppos)
 {
+	unsigned long flags;
+	struct crypto_priv *cp = &qcrypto_dev;
+	struct crypto_engine *pe;
 
 	memset((char *)&_qcrypto_stat, 0, sizeof(struct crypto_stat));
+	spin_lock_irqsave(&cp->lock, flags);
+	list_for_each_entry(pe, &cp->engine_list, elist) {
+		pe->total_req = 0;
+		pe->err_req = 0;
+	}
+	spin_unlock_irqrestore(&cp->lock, flags);
 	return count;
-};
+}
 
 static const struct file_operations _debug_stats_ops = {
 	.open =         _debug_stats_open,
@@ -3938,11 +4282,20 @@
 static int __init _qcrypto_init(void)
 {
 	int rc;
+	struct crypto_priv *pcp = &qcrypto_dev;
 
 	rc = _qcrypto_debug_init();
 	if (rc)
 		return rc;
-
+	INIT_LIST_HEAD(&pcp->alg_list);
+	INIT_LIST_HEAD(&pcp->engine_list);
+	INIT_WORK(&pcp->unlock_ce_ws, qcrypto_unlock_ce);
+	spin_lock_init(&pcp->lock);
+	mutex_init(&pcp->engine_lock);
+	pcp->total_units = 0;
+	pcp->ce_lock_count = 0;
+	pcp->platform_support.bus_scale_table = NULL;
+	pcp->next_engine = NULL;
 	return platform_driver_register(&_qualcomm_crypto);
 }
 
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index 17bbe19..ca7953d 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -71,6 +71,25 @@
 	  Sets the frequency using a "on-demand" algorithm.
 	  This governor is unlikely to be useful for other devices.
 
+config DEVFREQ_GOV_MSM_CPUFREQ
+	bool "MSM CPUfreq"
+	depends on CPU_FREQ_MSM
+	help
+	  MSM CPUfreq based governor for CPU bandwidth voting.  Sets the CPU
+	  to DDR BW vote based on the current CPU frequency.  This governor
+	  is unlikely to be useful for non-MSM devices.
+
+config DEVFREQ_GOV_MSM_CPUBW_HWMON
+	tristate "HW monitor based governor for CPUBW"
+	depends on ARCH_MSM_KRAIT
+	help
+	  HW monitor based governor for CPU to DDR bandwidth voting. This
+	  goveror currently supports only Krait L2 PM counters.  Sets the CPU
+	  BW vote by using L2 PM counters to monitor the Krait's use of DDR.
+	  Since this governor uses some of the PM counters it can conflict
+	  with existing profiling tools.  This governor is unlikely to be
+	  useful for other devices.
+
 comment "DEVFREQ Drivers"
 
 config ARM_EXYNOS4_BUS_DEVFREQ
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 29b48ff..e06ed9f 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -4,6 +4,8 @@
 obj-$(CONFIG_DEVFREQ_GOV_POWERSAVE)	+= governor_powersave.o
 obj-$(CONFIG_DEVFREQ_GOV_USERSPACE)	+= governor_userspace.o
 obj-$(CONFIG_DEVFREQ_GOV_MSM_ADRENO_TZ)	+= governor_msm_adreno_tz.o
+obj-$(CONFIG_DEVFREQ_GOV_MSM_CPUFREQ)	+= governor_msm_cpufreq.o
+obj-$(CONFIG_DEVFREQ_GOV_MSM_CPUBW_HWMON)	+= governor_cpubw_hwmon.o
 
 # DEVFREQ Drivers
 obj-$(CONFIG_ARM_EXYNOS4_BUS_DEVFREQ)	+= exynos4_bus.o
diff --git a/drivers/devfreq/governor_cpubw_hwmon.c b/drivers/devfreq/governor_cpubw_hwmon.c
new file mode 100644
index 0000000..e7d373b
--- /dev/null
+++ b/drivers/devfreq/governor_cpubw_hwmon.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2013-2014, 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.
+ */
+
+#define pr_fmt(fmt) "cpubw-hwmon: " fmt
+
+#include <linux/kernel.h>
+#include <asm/sizes.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/ktime.h>
+#include <linux/time.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/devfreq.h>
+#include "governor.h"
+
+#include <mach/msm-krait-l2-accessors.h>
+
+#define L2PMRESR2		0x412
+#define L2PMCR			0x400
+#define L2PMCNTENCLR		0x402
+#define L2PMCNTENSET		0x403
+#define L2PMINTENCLR		0x404
+#define L2PMINTENSET		0x405
+#define L2PMOVSR		0x406
+#define L2PMOVSSET		0x407
+#define L2PMnEVCNTCR(n)		(0x420 + n * 0x10)
+#define L2PMnEVCNTR(n)		(0x421 + n * 0x10)
+#define L2PMnEVCNTSR(n)		(0x422 + n * 0x10)
+#define L2PMnEVFILTER(n)	(0x423 + n * 0x10)
+#define L2PMnEVTYPER(n)		(0x424 + n * 0x10)
+
+#define show_attr(name) \
+static ssize_t show_##name(struct device *dev,				\
+			struct device_attribute *attr, char *buf)	\
+{									\
+	return sprintf(buf, "%u\n", name);				\
+}
+
+#define store_attr(name, _min, _max) \
+static ssize_t store_##name(struct device *dev,				\
+			struct device_attribute *attr, const char *buf,	\
+			size_t count)					\
+{									\
+	int ret;							\
+	unsigned int val;						\
+	ret = sscanf(buf, "%u", &val);					\
+	if (ret != 1)							\
+		return -EINVAL;						\
+	val = max(val, _min);				\
+	val = min(val, _max);				\
+	name = val;							\
+	return count;							\
+}
+
+#define gov_attr(__attr, min, max)	\
+show_attr(__attr)			\
+store_attr(__attr, min, max)		\
+static DEVICE_ATTR(__attr, 0644, show_##__attr, store_##__attr)
+
+
+static int l2pm_irq;
+static unsigned int bytes_per_beat;
+static unsigned int tolerance_percent = 10;
+static unsigned int guard_band_mbps = 100;
+static unsigned int decay_rate = 90;
+static unsigned int io_percent = 16;
+static unsigned int bw_step = 190;
+
+#define MIN_MS	10U
+#define MAX_MS	500U
+static unsigned int sample_ms = 50;
+static u32 prev_r_start_val;
+static u32 prev_w_start_val;
+static unsigned long prev_ab;
+static ktime_t prev_ts;
+
+#define RD_MON	0
+#define WR_MON	1
+static void mon_init(void)
+{
+	/* Set up counters 0/1 to count write/read beats */
+	set_l2_indirect_reg(L2PMRESR2, 0x8B0B0000);
+	set_l2_indirect_reg(L2PMnEVCNTCR(RD_MON), 0x0);
+	set_l2_indirect_reg(L2PMnEVCNTCR(WR_MON), 0x0);
+	set_l2_indirect_reg(L2PMnEVCNTR(RD_MON), 0xFFFFFFFF);
+	set_l2_indirect_reg(L2PMnEVCNTR(WR_MON), 0xFFFFFFFF);
+	set_l2_indirect_reg(L2PMnEVFILTER(RD_MON), 0xF003F);
+	set_l2_indirect_reg(L2PMnEVFILTER(WR_MON), 0xF003F);
+	set_l2_indirect_reg(L2PMnEVTYPER(RD_MON), 0xA);
+	set_l2_indirect_reg(L2PMnEVTYPER(WR_MON), 0xB);
+}
+
+static void global_mon_enable(bool en)
+{
+	u32 regval;
+
+	/* Global counter enable */
+	regval = get_l2_indirect_reg(L2PMCR);
+	if (en)
+		regval |= BIT(0);
+	else
+		regval &= ~BIT(0);
+	set_l2_indirect_reg(L2PMCR, regval);
+}
+
+static void mon_enable(int n)
+{
+	/* Clear previous overflow state for event counter n */
+	set_l2_indirect_reg(L2PMOVSR, BIT(n));
+
+	/* Enable event counter n */
+	set_l2_indirect_reg(L2PMCNTENSET, BIT(n));
+}
+
+static void mon_disable(int n)
+{
+	/* Disable event counter n */
+	set_l2_indirect_reg(L2PMCNTENCLR, BIT(n));
+}
+
+static void mon_irq_enable(int n, bool en)
+{
+	if (en)
+		set_l2_indirect_reg(L2PMINTENSET, BIT(n));
+	else
+		set_l2_indirect_reg(L2PMINTENCLR, BIT(n));
+}
+
+/* Returns start counter value to be used with mon_get_mbps() */
+static u32 mon_set_limit_mbyte(int n, unsigned int mbytes)
+{
+	u32 regval, beats;
+
+	beats = mult_frac(mbytes, SZ_1M, bytes_per_beat);
+	regval = 0xFFFFFFFF - beats;
+	set_l2_indirect_reg(L2PMnEVCNTR(n), regval);
+	pr_debug("EV%d MB: %d, start val: %x\n", n, mbytes, regval);
+
+	return regval;
+}
+
+long mon_get_count(int n, u32 start_val)
+{
+	u32 overflow, count;
+
+	count = get_l2_indirect_reg(L2PMnEVCNTR(n));
+	overflow = get_l2_indirect_reg(L2PMOVSR);
+
+	pr_debug("EV%d ov: %x, cnt: %x\n", n, overflow, count);
+
+	if (overflow & BIT(n))
+		return 0xFFFFFFFF - start_val + count;
+	else
+		return count - start_val;
+}
+
+/* Returns MBps of read/writes for the sampling window. */
+unsigned int beats_to_mbps(long long beats, unsigned int us)
+{
+	beats *= USEC_PER_SEC;
+	beats *= bytes_per_beat;
+	do_div(beats, us);
+	beats = DIV_ROUND_UP_ULL(beats, SZ_1M);
+
+	return beats;
+}
+
+static int to_limit(int mbps)
+{
+	mbps *= (100 + tolerance_percent) * sample_ms;
+	mbps /= 100;
+	mbps = DIV_ROUND_UP(mbps, MSEC_PER_SEC);
+	return mbps;
+}
+
+unsigned long measure_bw_and_set_irq(void)
+{
+	long r_mbps, w_mbps, mbps;
+	ktime_t ts;
+	unsigned int us;
+
+	/*
+	 * Since we are stopping the counters, we don't want this short work
+	 * to be interrupted by other tasks and cause the measurements to be
+	 * wrong. Not blocking interrupts to avoid affecting interrupt
+	 * latency and since they should be short anyway because they run in
+	 * atomic context.
+	 */
+	preempt_disable();
+
+	ts = ktime_get();
+	us = ktime_to_us(ktime_sub(ts, prev_ts));
+	if (!us)
+		us = 1;
+
+	mon_disable(RD_MON);
+	mon_disable(WR_MON);
+
+	r_mbps = mon_get_count(RD_MON, prev_r_start_val);
+	r_mbps = beats_to_mbps(r_mbps, us);
+	w_mbps = mon_get_count(WR_MON, prev_w_start_val);
+	w_mbps = beats_to_mbps(w_mbps, us);
+
+	prev_r_start_val = mon_set_limit_mbyte(RD_MON, to_limit(r_mbps));
+	prev_w_start_val = mon_set_limit_mbyte(WR_MON, to_limit(w_mbps));
+	prev_ts = ts;
+
+	mon_enable(RD_MON);
+	mon_enable(WR_MON);
+
+	preempt_enable();
+
+	mbps = r_mbps + w_mbps;
+	pr_debug("R/W/BW/us = %ld/%ld/%ld/%d\n", r_mbps, w_mbps, mbps, us);
+
+	return mbps;
+}
+
+static void compute_bw(int mbps, unsigned long *freq, unsigned long *ab)
+{
+	int new_bw;
+
+	mbps += guard_band_mbps;
+
+	if (mbps > prev_ab) {
+		new_bw = mbps;
+	} else {
+		new_bw = mbps * decay_rate + prev_ab * (100 - decay_rate);
+		new_bw /= 100;
+	}
+
+	*ab = roundup(mbps, bw_step);
+	*freq = (mbps * 100) / io_percent;
+}
+
+#define TOO_SOON_US	(1 * USEC_PER_MSEC)
+static irqreturn_t mon_intr_handler(int irq, void *dev)
+{
+	struct devfreq *df = dev;
+	ktime_t ts;
+	unsigned int us;
+	u32 regval;
+	int ret;
+
+	regval = get_l2_indirect_reg(L2PMOVSR);
+	pr_debug("Got interrupt: %x\n", regval);
+
+	devfreq_monitor_stop(df);
+
+	/*
+	 * Don't recalc bandwidth if the interrupt comes right after a
+	 * previous bandwidth calculation.  This is done for two reasons:
+	 *
+	 * 1. Sampling the BW during a very short duration can result in a
+	 *    very inaccurate measurement due to very short bursts.
+	 * 2. This can only happen if the limit was hit very close to the end
+	 *    of the previous sample period. Which means the current BW
+	 *    estimate is not very off and doesn't need to be readjusted.
+	 */
+	ts = ktime_get();
+	us = ktime_to_us(ktime_sub(ts, prev_ts));
+	if (us > TOO_SOON_US) {
+		mutex_lock(&df->lock);
+		ret = update_devfreq(df);
+		if (ret)
+			pr_err("Unable to update freq on IRQ!\n");
+		mutex_unlock(&df->lock);
+	}
+
+	devfreq_monitor_start(df);
+
+	return IRQ_HANDLED;
+}
+
+static int start_monitoring(struct devfreq *df)
+{
+	int ret, mbyte;
+
+	ret = request_threaded_irq(l2pm_irq, NULL, mon_intr_handler,
+			  IRQF_ONESHOT | IRQF_SHARED,
+			  "cpubw_hwmon", df);
+	if (ret) {
+		pr_err("Unable to register interrupt handler\n");
+		return ret;
+	}
+
+	mon_init();
+	mon_disable(RD_MON);
+	mon_disable(WR_MON);
+
+	mbyte = (df->previous_freq * io_percent) / (2 * 100);
+	prev_r_start_val = mon_set_limit_mbyte(RD_MON, mbyte);
+	prev_w_start_val = mon_set_limit_mbyte(WR_MON, mbyte);
+	prev_ts = ktime_get();
+	prev_ab = 0;
+
+	mon_irq_enable(RD_MON, true);
+	mon_irq_enable(WR_MON, true);
+	mon_enable(RD_MON);
+	mon_enable(WR_MON);
+	global_mon_enable(true);
+
+	return 0;
+}
+
+static void stop_monitoring(struct devfreq *df)
+{
+	global_mon_enable(false);
+	mon_disable(RD_MON);
+	mon_disable(WR_MON);
+	mon_irq_enable(RD_MON, false);
+	mon_irq_enable(WR_MON, false);
+
+	disable_irq(l2pm_irq);
+	free_irq(l2pm_irq, df);
+}
+
+static int devfreq_cpubw_hwmon_get_freq(struct devfreq *df,
+					unsigned long *freq,
+					u32 *flag)
+{
+	unsigned long mbps;
+
+	mbps = measure_bw_and_set_irq();
+	compute_bw(mbps, freq, df->data);
+	prev_ab = *(unsigned long *) df->data;
+
+	return 0;
+}
+
+gov_attr(tolerance_percent, 0U, 30U);
+gov_attr(guard_band_mbps, 0U, 2000U);
+gov_attr(decay_rate, 0U, 100U);
+gov_attr(io_percent, 1U, 100U);
+gov_attr(bw_step, 50U, 1000U);
+
+static struct attribute *dev_attr[] = {
+	&dev_attr_tolerance_percent.attr,
+	&dev_attr_guard_band_mbps.attr,
+	&dev_attr_decay_rate.attr,
+	&dev_attr_io_percent.attr,
+	&dev_attr_bw_step.attr,
+	NULL,
+};
+
+static struct attribute_group dev_attr_group = {
+	.name = "cpubw_hwmon",
+	.attrs = dev_attr,
+};
+
+static int devfreq_cpubw_hwmon_ev_handler(struct devfreq *df,
+					unsigned int event, void *data)
+{
+	int ret;
+
+	switch (event) {
+	case DEVFREQ_GOV_START:
+		ret = start_monitoring(df);
+		if (ret)
+			return ret;
+		ret = sysfs_create_group(&df->dev.kobj, &dev_attr_group);
+		if (ret)
+			return ret;
+
+		sample_ms = df->profile->polling_ms;
+		sample_ms = max(MIN_MS, sample_ms);
+		sample_ms = min(MAX_MS, sample_ms);
+		df->profile->polling_ms = sample_ms;
+		devfreq_monitor_start(df);
+
+		pr_debug("Enabled CPU BW HW monitor governor\n");
+		break;
+
+	case DEVFREQ_GOV_STOP:
+		sysfs_remove_group(&df->dev.kobj, &dev_attr_group);
+		devfreq_monitor_stop(df);
+		*(unsigned long *)df->data = 0;
+		stop_monitoring(df);
+		pr_debug("Disabled CPU BW HW monitor governor\n");
+		break;
+
+	case DEVFREQ_GOV_INTERVAL:
+		sample_ms = *(unsigned int *)data;
+		sample_ms = max(MIN_MS, sample_ms);
+		sample_ms = min(MAX_MS, sample_ms);
+		devfreq_interval_update(df, &sample_ms);
+		break;
+	}
+
+	return 0;
+}
+
+static struct devfreq_governor devfreq_cpubw_hwmon = {
+	.name = "cpubw_hwmon",
+	.get_target_freq = devfreq_cpubw_hwmon_get_freq,
+	.event_handler = devfreq_cpubw_hwmon_ev_handler,
+};
+
+static int cpubw_hwmon_driver_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	l2pm_irq = platform_get_irq(pdev, 0);
+	if (l2pm_irq < 0) {
+		pr_err("Unable to get IRQ number\n");
+		return l2pm_irq;
+	}
+
+	ret = of_property_read_u32(dev->of_node, "qcom,bytes-per-beat",
+			     &bytes_per_beat);
+	if (ret) {
+		pr_err("Unable to read bytes per beat\n");
+		return ret;
+	}
+
+	ret = devfreq_add_governor(&devfreq_cpubw_hwmon);
+	if (ret) {
+		pr_err("devfreq governor registration failed\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct of_device_id match_table[] = {
+	{ .compatible = "qcom,kraitbw-l2pm" },
+	{}
+};
+
+static struct platform_driver cpubw_hwmon_driver = {
+	.probe = cpubw_hwmon_driver_probe,
+	.driver = {
+		.name = "kraitbw-l2pm",
+		.of_match_table = match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init cpubw_hwmon_init(void)
+{
+	return platform_driver_register(&cpubw_hwmon_driver);
+}
+module_init(cpubw_hwmon_init);
+
+static void __exit cpubw_hwmon_exit(void)
+{
+	platform_driver_unregister(&cpubw_hwmon_driver);
+}
+module_exit(cpubw_hwmon_exit);
+
+MODULE_DESCRIPTION("HW monitor based CPU DDR bandwidth voting driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/devfreq/governor_msm_cpufreq.c b/drivers/devfreq/governor_msm_cpufreq.c
new file mode 100644
index 0000000..9b13e26
--- /dev/null
+++ b/drivers/devfreq/governor_msm_cpufreq.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/devfreq.h>
+#include <mach/cpufreq.h>
+#include "governor.h"
+
+DEFINE_MUTEX(df_lock);
+static struct devfreq *df;
+
+static int devfreq_msm_cpufreq_get_freq(struct devfreq *df,
+					unsigned long *freq,
+					u32 *flag)
+{
+	*freq = msm_cpufreq_get_bw();
+	return 0;
+}
+
+int devfreq_msm_cpufreq_update_bw(void)
+{
+	int ret = 0;
+
+	mutex_lock(&df_lock);
+	if (df) {
+		mutex_lock(&df->lock);
+		ret = update_devfreq(df);
+		mutex_unlock(&df->lock);
+	}
+	mutex_unlock(&df_lock);
+	return ret;
+}
+
+static int devfreq_msm_cpufreq_ev_handler(struct devfreq *devfreq,
+					unsigned int event, void *data)
+{
+	int ret;
+
+	switch (event) {
+	case DEVFREQ_GOV_START:
+		mutex_lock(&df_lock);
+		df = devfreq;
+		mutex_unlock(&df_lock);
+
+		ret = devfreq_msm_cpufreq_update_bw();
+		if (ret) {
+			pr_err("Unable to update BW! Gov start failed!\n");
+			return ret;
+		}
+
+		devfreq_monitor_stop(df);
+		pr_debug("Enabled MSM CPUfreq governor\n");
+		break;
+
+	case DEVFREQ_GOV_STOP:
+		mutex_lock(&df_lock);
+		df = NULL;
+		mutex_unlock(&df_lock);
+
+		pr_debug("Disabled MSM CPUfreq governor\n");
+		break;
+	}
+
+	return 0;
+}
+
+static struct devfreq_governor devfreq_msm_cpufreq = {
+	.name = "msm_cpufreq",
+	.get_target_freq = devfreq_msm_cpufreq_get_freq,
+	.event_handler = devfreq_msm_cpufreq_ev_handler,
+};
+
+int register_devfreq_msm_cpufreq(void)
+{
+	return devfreq_add_governor(&devfreq_msm_cpufreq);
+}
diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c
index af2edc2..74ae3bb 100644
--- a/drivers/devfreq/governor_performance.c
+++ b/drivers/devfreq/governor_performance.c
@@ -32,13 +32,26 @@
 				unsigned int event, void *data)
 {
 	int ret = 0;
+	unsigned long freq;
 
-	if (event == DEVFREQ_GOV_START || event == DEVFREQ_GOV_RESUME) {
-		mutex_lock(&devfreq->lock);
+	mutex_lock(&devfreq->lock);
+	freq = devfreq->previous_freq;
+	switch (event) {
+	case DEVFREQ_GOV_START:
+		devfreq->profile->target(devfreq->dev.parent,
+				&freq,
+				DEVFREQ_FLAG_WAKEUP_MAXFREQ);
+		/* fall through */
+	case DEVFREQ_GOV_RESUME:
 		ret = update_devfreq(devfreq);
-		mutex_unlock(&devfreq->lock);
+		break;
+	case DEVFREQ_GOV_SUSPEND:
+		devfreq->profile->target(devfreq->dev.parent,
+				&freq,
+				DEVFREQ_FLAG_WAKEUP_MAXFREQ);
+		break;
 	}
-
+	mutex_unlock(&devfreq->lock);
 	return ret;
 }
 
diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c
index bb29360..d37997d 100644
--- a/drivers/devfreq/governor_simpleondemand.c
+++ b/drivers/devfreq/governor_simpleondemand.c
@@ -29,6 +29,7 @@
 	unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL;
 	struct devfreq_simple_ondemand_data *data = df->data;
 	unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX;
+	unsigned long min = (df->min_freq) ? df->min_freq : 0;
 
 	if (err)
 		return err;
@@ -43,18 +44,30 @@
 	    dfso_upthreshold < dfso_downdifferential)
 		return -EINVAL;
 
-	/* Assume MAX if it is going to be divided by zero */
-	if (stat.total_time == 0) {
-		*freq = max;
-		return 0;
-	}
-
 	/* Prevent overflow */
 	if (stat.busy_time >= (1 << 24) || stat.total_time >= (1 << 24)) {
 		stat.busy_time >>= 7;
 		stat.total_time >>= 7;
 	}
 
+	if (data && data->simple_scaling) {
+		if (stat.busy_time * 100 >
+		    stat.total_time * dfso_upthreshold)
+			*freq = max;
+		else if (stat.busy_time * 100 <
+		    stat.total_time * dfso_downdifferential)
+			*freq = min;
+		else
+			*freq = df->previous_freq;
+		return 0;
+	}
+
+	/* Assume MAX if it is going to be divided by zero */
+	if (stat.total_time == 0) {
+		*freq = max;
+		return 0;
+	}
+
 	/* Set MAX if it's busy enough */
 	if (stat.busy_time * 100 >
 	    stat.total_time * dfso_upthreshold) {
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index ed001f0..8d934df 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -55,11 +55,13 @@
 #define Q_GPIO_SUBTYPE_GPIOC_8CH	0xD
 
 /* mpp peripheral type and subtype values */
-#define Q_MPP_TYPE			0x11
-#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT	0x3
-#define Q_MPP_SUBTYPE_4CH_NO_SINK	0x5
-#define Q_MPP_SUBTYPE_4CH_FULL_FUNC	0x7
-#define Q_MPP_SUBTYPE_8CH_FULL_FUNC	0xF
+#define Q_MPP_TYPE				0x11
+#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT		0x3
+#define Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT	0x4
+#define Q_MPP_SUBTYPE_4CH_NO_SINK		0x5
+#define Q_MPP_SUBTYPE_ULT_4CH_NO_SINK		0x6
+#define Q_MPP_SUBTYPE_4CH_FULL_FUNC		0x7
+#define Q_MPP_SUBTYPE_8CH_FULL_FUNC		0xF
 
 /* control register base address offsets */
 #define Q_REG_MODE_CTL			0x40
@@ -235,22 +237,29 @@
 static int qpnp_pin_check_config(enum qpnp_pin_param_type idx,
 				 struct qpnp_pin_spec *q_spec, uint32_t val)
 {
+	u8 subtype = q_spec->subtype;
+
 	switch (idx) {
 	case Q_PIN_CFG_MODE:
 		if (q_spec->type == Q_GPIO_TYPE &&
 		    val >= QPNP_PIN_GPIO_MODE_INVALID)
 				return -EINVAL;
-		else if (q_spec->type == Q_MPP_TYPE &&
-			 val >= QPNP_PIN_MPP_MODE_INVALID)
+		else if (q_spec->type == Q_MPP_TYPE) {
+			if (val >= QPNP_PIN_MPP_MODE_INVALID)
 				return -EINVAL;
+			if ((subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT ||
+			     subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_SINK) &&
+			     (val == QPNP_PIN_MODE_BIDIR))
+				return -ENXIO;
+		}
 		break;
 	case Q_PIN_CFG_OUTPUT_TYPE:
 		if (q_spec->type != Q_GPIO_TYPE)
 			return -ENXIO;
 		if ((val == QPNP_PIN_OUT_BUF_OPEN_DRAIN_NMOS ||
 		    val == QPNP_PIN_OUT_BUF_OPEN_DRAIN_PMOS) &&
-		    (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
-		    (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH)))
+		    (subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
+		    (subtype == Q_GPIO_SUBTYPE_GPIOC_8CH)))
 			return -EINVAL;
 		else if (val >= QPNP_PIN_OUT_BUF_INVALID)
 			return -EINVAL;
@@ -263,22 +272,28 @@
 		if (q_spec->type == Q_GPIO_TYPE &&
 		    val >= QPNP_PIN_GPIO_PULL_INVALID)
 			return -EINVAL;
-		if (q_spec->type == Q_MPP_TYPE &&
-		    val >= QPNP_PIN_MPP_PULL_INVALID)
-			return -EINVAL;
+		if (q_spec->type == Q_MPP_TYPE) {
+			if (val >= QPNP_PIN_MPP_PULL_INVALID)
+				return -EINVAL;
+			if (subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT ||
+			    subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_SINK)
+				return -ENXIO;
+		}
 		break;
 	case Q_PIN_CFG_VIN_SEL:
 		if (val >= QPNP_PIN_VIN_8CH_INVALID)
 			return -EINVAL;
 		else if (val >= QPNP_PIN_VIN_4CH_INVALID) {
 			if (q_spec->type == Q_GPIO_TYPE &&
-			   (q_spec->subtype == Q_GPIO_SUBTYPE_GPIO_4CH ||
-			    q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH))
+			   (subtype == Q_GPIO_SUBTYPE_GPIO_4CH ||
+			    subtype == Q_GPIO_SUBTYPE_GPIOC_4CH))
 				return -EINVAL;
 			if (q_spec->type == Q_MPP_TYPE &&
-			   (q_spec->subtype == Q_MPP_SUBTYPE_4CH_NO_ANA_OUT ||
-			    q_spec->subtype == Q_MPP_SUBTYPE_4CH_NO_SINK ||
-			    q_spec->subtype == Q_MPP_SUBTYPE_4CH_FULL_FUNC))
+			   (subtype == Q_MPP_SUBTYPE_4CH_NO_ANA_OUT ||
+			    subtype == Q_MPP_SUBTYPE_4CH_NO_SINK ||
+			    subtype == Q_MPP_SUBTYPE_4CH_FULL_FUNC ||
+			    subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT ||
+			    subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_SINK))
 				return -EINVAL;
 		}
 		break;
@@ -304,7 +319,8 @@
 	case Q_PIN_CFG_AOUT_REF:
 		if (q_spec->type != Q_MPP_TYPE)
 			return -ENXIO;
-		if (q_spec->subtype == Q_MPP_SUBTYPE_4CH_NO_ANA_OUT)
+		if (subtype == Q_MPP_SUBTYPE_4CH_NO_ANA_OUT ||
+		    subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT)
 			return -ENXIO;
 		if (val >= QPNP_PIN_AOUT_REF_INVALID)
 			return -EINVAL;
@@ -318,7 +334,8 @@
 	case Q_PIN_CFG_CS_OUT:
 		if (q_spec->type != Q_MPP_TYPE)
 			return -ENXIO;
-		if (q_spec->subtype == Q_MPP_SUBTYPE_4CH_NO_SINK)
+		if (subtype == Q_MPP_SUBTYPE_4CH_NO_SINK ||
+		    subtype == Q_MPP_SUBTYPE_ULT_4CH_NO_SINK)
 			return -ENXIO;
 		if (val >= QPNP_PIN_CS_OUT_INVALID)
 			return -EINVAL;
@@ -410,9 +427,11 @@
 	else if (q_spec->type == Q_MPP_TYPE)
 		switch (q_spec->subtype) {
 		case Q_MPP_SUBTYPE_4CH_NO_SINK:
+		case Q_MPP_SUBTYPE_ULT_4CH_NO_SINK:
 			q_spec->num_ctl_regs = 12;
 			break;
 		case Q_MPP_SUBTYPE_4CH_NO_ANA_OUT:
+		case Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT:
 		case Q_MPP_SUBTYPE_4CH_FULL_FUNC:
 		case Q_MPP_SUBTYPE_8CH_FULL_FUNC:
 			q_spec->num_ctl_regs = 13;
@@ -627,11 +646,28 @@
 {
 	struct qpnp_pin_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
 	struct qpnp_pin_spec *q_spec;
+	u32 intspec[3];
 
 	q_spec = qpnp_chip_gpio_get_spec(q_chip, offset);
 	if (!q_spec)
 		return -EINVAL;
 
+	/* if we have mapped this pin previously return the virq */
+	if (q_spec->irq)
+		return q_spec->irq;
+
+	/* call into irq_domain to get irq mapping */
+	intspec[0] = q_chip->spmi->sid;
+	intspec[1] = (q_spec->offset >> 8) & 0xFF;
+	intspec[2] = 0;
+	q_spec->irq = irq_create_of_mapping(q_chip->int_ctrl, intspec, 3);
+	if (!q_spec->irq) {
+		dev_err(&q_chip->spmi->dev, "%s: invalid irq for gpio %u\n",
+						__func__, q_spec->pmic_pin);
+		WARN_ON(1);
+		return -EINVAL;
+	}
+
 	return q_spec->irq;
 }
 
@@ -1127,7 +1163,9 @@
 	else if (q_spec->type == Q_MPP_TYPE)
 		switch (q_spec->subtype) {
 		case Q_MPP_SUBTYPE_4CH_NO_ANA_OUT:
+		case Q_MPP_SUBTYPE_ULT_4CH_NO_ANA_OUT:
 		case Q_MPP_SUBTYPE_4CH_NO_SINK:
+		case Q_MPP_SUBTYPE_ULT_4CH_NO_SINK:
 		case Q_MPP_SUBTYPE_4CH_FULL_FUNC:
 		case Q_MPP_SUBTYPE_8CH_FULL_FUNC:
 			return 1;
@@ -1144,7 +1182,7 @@
 	struct spmi_resource *d_node;
 	int i, rc;
 	int lowest_gpio = UINT_MAX, highest_gpio = 0;
-	u32 intspec[3], gpio;
+	u32 gpio;
 	char version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV + 1];
 	const char *dev_name;
 
@@ -1279,18 +1317,6 @@
 		if (rc)
 			goto err_probe;
 
-		/* call into irq_domain to get irq mapping */
-		intspec[0] = q_chip->spmi->sid;
-		intspec[1] = (q_spec->offset >> 8) & 0xFF;
-		intspec[2] = 0;
-		q_spec->irq = irq_create_of_mapping(q_chip->int_ctrl,
-							intspec, 3);
-		if (!q_spec->irq) {
-			dev_err(&spmi->dev, "%s: invalid irq for gpio %u\n",
-								__func__, gpio);
-			rc = -EINVAL;
-			goto err_probe;
-		}
 		/* initialize lookup table params */
 		qpnp_pmic_pin_set_spec(q_chip, gpio, q_spec);
 		qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 9d33bf4..6261d89 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -108,8 +108,7 @@
  *
  * Note that the `pages' array should be composed of all 4K pages.
  */
-int ion_heap_pages_zero(struct page **pages, int num_pages,
-				bool should_invalidate)
+int ion_heap_pages_zero(struct page **pages, int num_pages)
 {
 	int i, j, k, npages_to_vmap;
 	void *ptr = NULL;
@@ -143,19 +142,17 @@
 			return -ENOMEM;
 
 		memset(ptr, 0, npages_to_vmap * PAGE_SIZE);
-		if (should_invalidate) {
-			/*
-			 * invalidate the cache to pick up the zeroing
-			 */
-			for (k = 0; k < npages_to_vmap; k++) {
-				void *p = kmap_atomic(pages[i + k]);
-				phys_addr_t phys = page_to_phys(
-							pages[i + k]);
+		/*
+		 * invalidate the cache to pick up the zeroing
+		 */
+		for (k = 0; k < npages_to_vmap; k++) {
+			void *p = kmap_atomic(pages[i + k]);
+			phys_addr_t phys = page_to_phys(
+				pages[i + k]);
 
-				dmac_inv_range(p, p + PAGE_SIZE);
-				outer_inv_range(phys, phys + PAGE_SIZE);
-				kunmap_atomic(p);
-			}
+			dmac_inv_range(p, p + PAGE_SIZE);
+			outer_inv_range(phys, phys + PAGE_SIZE);
+			kunmap_atomic(p);
 		}
 		vunmap(ptr);
 	}
@@ -196,8 +193,7 @@
 	pages_mem->free_fn(pages_mem->pages);
 }
 
-int ion_heap_high_order_page_zero(struct page *page,
-				int order, bool should_invalidate)
+int ion_heap_high_order_page_zero(struct page *page, int order)
 {
 	int i, ret;
 	struct pages_mem pages_mem;
@@ -210,8 +206,7 @@
 	for (i = 0; i < (1 << order); ++i)
 		pages_mem.pages[i] = page + i;
 
-	ret = ion_heap_pages_zero(pages_mem.pages, npages,
-				should_invalidate);
+	ret = ion_heap_pages_zero(pages_mem.pages, npages);
 	ion_heap_free_pages_mem(&pages_mem);
 	return ret;
 }
@@ -240,49 +235,11 @@
 			pages_mem.pages[npages++] = page + j;
 	}
 
-	ret = ion_heap_pages_zero(pages_mem.pages, npages,
-				ion_buffer_cached(buffer));
+	ret = ion_heap_pages_zero(pages_mem.pages, npages);
 	ion_heap_free_pages_mem(&pages_mem);
 	return ret;
 }
 
-int ion_heap_buffer_zero_old(struct ion_buffer *buffer)
-{
-	struct sg_table *table = buffer->sg_table;
-	pgprot_t pgprot;
-	struct scatterlist *sg;
-	struct vm_struct *vm_struct;
-	int i, j, ret = 0;
-
-	if (buffer->flags & ION_FLAG_CACHED)
-		pgprot = PAGE_KERNEL;
-	else
-		pgprot = pgprot_writecombine(PAGE_KERNEL);
-
-	vm_struct = get_vm_area(PAGE_SIZE, VM_ALLOC);
-	if (!vm_struct)
-		return -ENOMEM;
-
-	for_each_sg(table->sgl, sg, table->nents, i) {
-		struct page *page = sg_page(sg);
-		unsigned long len = sg_dma_len(sg);
-
-		for (j = 0; j < len / PAGE_SIZE; j++) {
-			struct page *sub_page = page + j;
-			struct page **pages = &sub_page;
-			ret = map_vm_area(vm_struct, pgprot, &pages);
-			if (ret)
-				goto end;
-			memset(vm_struct->addr, 0, PAGE_SIZE);
-			unmap_kernel_range((unsigned long)vm_struct->addr,
-					   PAGE_SIZE);
-		}
-	}
-end:
-	free_vm_area(vm_struct);
-	return ret;
-}
-
 void ion_heap_free_page(struct ion_buffer *buffer, struct page *page,
 		       unsigned int order)
 {
@@ -333,11 +290,11 @@
 		if (total_drained >= size)
 			break;
 		list_del(&buffer->list);
-		ion_buffer_destroy(buffer);
 		heap->free_list_size -= buffer->size;
 		if (skip_pools)
 			buffer->flags |= ION_FLAG_FREED_FROM_SHRINKER;
 		total_drained += buffer->size;
+		ion_buffer_destroy(buffer);
 	}
 	rt_mutex_unlock(&heap->lock);
 
diff --git a/drivers/gpu/ion/ion_page_pool.c b/drivers/gpu/ion/ion_page_pool.c
index 94f9445..cc2a36d 100644
--- a/drivers/gpu/ion/ion_page_pool.c
+++ b/drivers/gpu/ion/ion_page_pool.c
@@ -40,8 +40,7 @@
 		return NULL;
 
 	if (pool->gfp_mask & __GFP_ZERO)
-		if (ion_heap_high_order_page_zero(
-				page, pool->order, pool->should_invalidate))
+		if (ion_heap_high_order_page_zero(page, pool->order))
 			goto error_free_pages;
 
 	sg_init_table(&sg, 1);
@@ -175,8 +174,7 @@
 	return nr_freed;
 }
 
-struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
-	bool should_invalidate)
+struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order)
 {
 	struct ion_page_pool *pool = kmalloc(sizeof(struct ion_page_pool),
 					     GFP_KERNEL);
@@ -188,7 +186,6 @@
 	INIT_LIST_HEAD(&pool->high_items);
 	pool->gfp_mask = gfp_mask;
 	pool->order = order;
-	pool->should_invalidate = should_invalidate;
 	mutex_init(&pool->mutex);
 	plist_node_init(&pool->list, order);
 
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index aa0a9e2..c57efc1 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -234,11 +234,9 @@
 void ion_heap_unmap_kernel(struct ion_heap *, struct ion_buffer *);
 int ion_heap_map_user(struct ion_heap *, struct ion_buffer *,
 			struct vm_area_struct *);
-int ion_heap_pages_zero(struct page **pages, int num_pages,
-			bool should_invalidate);
+int ion_heap_pages_zero(struct page **pages, int num_pages);
 int ion_heap_buffer_zero(struct ion_buffer *buffer);
-int ion_heap_high_order_page_zero(struct page *page,
-				int order, bool should_invalidate);
+int ion_heap_high_order_page_zero(struct page *page, int order);
 
 /**
  * ion_heap_init_deferred_free -- initialize deferred free functionality
@@ -357,8 +355,6 @@
  * @gfp_mask:		gfp_mask to use from alloc
  * @order:		order of pages in the pool
  * @list:		plist node for list of pools
- * @should_invalidate:	whether or not the cache needs to be invalidated at
- *			page allocation time.
  *
  * Allows you to keep a pool of pre allocated pages to use from your heap.
  * Keeping a pool of pages that is ready for dma, ie any cached mapping have
@@ -374,11 +370,9 @@
 	gfp_t gfp_mask;
 	unsigned int order;
 	struct plist_node list;
-	bool should_invalidate;
 };
 
-struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order,
-	bool should_invalidate);
+struct ion_page_pool *ion_page_pool_create(gfp_t gfp_mask, unsigned int order);
 void ion_page_pool_destroy(struct ion_page_pool *);
 void *ion_page_pool_alloc(struct ion_page_pool *);
 void ion_page_pool_free(struct ion_page_pool *, struct page *);
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 8e885b2..be1a89c 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -355,8 +355,7 @@
  * nothing. If it succeeds you'll eventually need to use
  * ion_system_heap_destroy_pools to destroy the pools.
  */
-static int ion_system_heap_create_pools(struct ion_page_pool **pools,
-					bool should_invalidate)
+static int ion_system_heap_create_pools(struct ion_page_pool **pools)
 {
 	int i;
 	for (i = 0; i < num_orders; i++) {
@@ -365,8 +364,7 @@
 
 		if (orders[i] > 4)
 			gfp_flags = high_order_gfp_flags;
-		pool = ion_page_pool_create(gfp_flags, orders[i],
-					should_invalidate);
+		pool = ion_page_pool_create(gfp_flags, orders[i]);
 		if (!pool)
 			goto err_create_pool;
 		pools[i] = pool;
@@ -397,10 +395,10 @@
 	if (!heap->cached_pools)
 		goto err_alloc_cached_pools;
 
-	if (ion_system_heap_create_pools(heap->uncached_pools, false))
+	if (ion_system_heap_create_pools(heap->uncached_pools))
 		goto err_create_uncached_pools;
 
-	if (ion_system_heap_create_pools(heap->cached_pools, true))
+	if (ion_system_heap_create_pools(heap->cached_pools))
 		goto err_create_cached_pools;
 
 	heap->heap.shrinker.shrink = ion_system_heap_shrink;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index eba60ea..0d88689 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2336,15 +2336,33 @@
 				     const char *buf, size_t count)
 {
 	struct adreno_device *adreno_dev = _get_adreno_dev(dev);
-	int ret;
+	int ret = 0;
+	unsigned int policy = 0;
 	if (adreno_dev == NULL)
 		return 0;
 
 	mutex_lock(&adreno_dev->dev.mutex);
-	ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy);
+
+	/* MMU option changed call function to reset MMU options */
+	if (count != _ft_sysfs_store(buf, count, &policy))
+		ret = -EINVAL;
+
+	if (!ret) {
+		policy &= (KGSL_FT_PAGEFAULT_INT_ENABLE |
+				KGSL_FT_PAGEFAULT_GPUHALT_ENABLE |
+				KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE |
+				KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT);
+		ret = kgsl_mmu_set_pagefault_policy(&(adreno_dev->dev.mmu),
+				adreno_dev->ft_pf_policy);
+		if (!ret)
+			adreno_dev->ft_pf_policy = policy;
+	}
 	mutex_unlock(&adreno_dev->dev.mutex);
 
-	return ret;
+	if (!ret)
+		return count;
+	else
+		return 0;
 }
 
 /**
@@ -2635,12 +2653,56 @@
 	return status;
 }
 
-static int adreno_setproperty(struct kgsl_device *device,
+static int adreno_set_constraint(struct kgsl_device *device,
+				struct kgsl_context *context,
+				struct kgsl_device_constraint *constraint)
+{
+	int status = 0;
+
+	switch (constraint->type) {
+	case KGSL_CONSTRAINT_PWRLEVEL: {
+		struct kgsl_device_constraint_pwrlevel pwr;
+
+		if (constraint->size != sizeof(pwr)) {
+			status = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(&pwr,
+				(void __user *)constraint->data,
+				sizeof(pwr))) {
+			status = -EFAULT;
+			break;
+		}
+		if (pwr.level >= KGSL_CONSTRAINT_PWR_MAXLEVELS) {
+			status = -EINVAL;
+			break;
+		}
+
+		context->pwr_constraint.type =
+				KGSL_CONSTRAINT_PWRLEVEL;
+		context->pwr_constraint.sub_type = pwr.level;
+		}
+		break;
+	case KGSL_CONSTRAINT_NONE:
+		context->pwr_constraint.type = KGSL_CONSTRAINT_NONE;
+		break;
+
+	default:
+		status = -EINVAL;
+		break;
+	}
+
+	return status;
+}
+
+static int adreno_setproperty(struct kgsl_device_private *dev_priv,
 				enum kgsl_property_type type,
 				void *value,
 				unsigned int sizebytes)
 {
 	int status = -EINVAL;
+	struct kgsl_device *device = dev_priv->device;
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 
 	switch (type) {
@@ -2678,6 +2740,28 @@
 			status = 0;
 		}
 		break;
+	case KGSL_PROP_PWR_CONSTRAINT: {
+			struct kgsl_device_constraint constraint;
+			struct kgsl_context *context;
+
+			if (sizebytes != sizeof(constraint))
+				break;
+
+			if (copy_from_user(&constraint, value,
+				sizeof(constraint))) {
+				status = -EFAULT;
+				break;
+			}
+
+			context = kgsl_context_get_owner(dev_priv,
+							constraint.context_id);
+			if (context == NULL)
+				break;
+			status = adreno_set_constraint(device, context,
+								&constraint);
+			kgsl_context_put(context);
+		}
+		break;
 	default:
 		break;
 	}
@@ -3069,7 +3153,7 @@
 		return -EINVAL;
 
 	ret = adreno_drawctxt_wait(ADRENO_DEVICE(device), context,
-		timestamp, msecs_to_jiffies(msecs));
+		timestamp, msecs);
 
 	/* If the context got invalidated then return a specific error */
 	drawctxt = ADRENO_CONTEXT(context);
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index 56c4305..9f5765d 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -492,6 +492,22 @@
 	/* Reading these will hang the GPU if it isn't already hung */
 
 	if (hang) {
+		unsigned int reg;
+
+		/*
+		 * Reading the microcode while the CP will is running will
+		 * basically basically move the CP instruction pointer to
+		 * whatever address we read. Big badaboom ensues. Stop the CP
+		 * (if it isn't already stopped) to ensure that we are safe.
+		 * We do this here and not earlier to avoid corrupting the RBBM
+		 * status and CP registers - by the time we get here we don't
+		 * care about the contents of the CP anymore.
+		 */
+
+		adreno_readreg(adreno_dev, ADRENO_REG_CP_ME_CNTL, &reg);
+		reg |= (1 << 27) | (1 << 28);
+		adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, reg);
+
 		snapshot = kgsl_snapshot_add_section(device,
 			KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain,
 			a3xx_snapshot_cp_pfp_ram, NULL);
diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c
index 1b827ff..d0ba145 100644
--- a/drivers/gpu/msm/adreno_coresight.c
+++ b/drivers/gpu/msm/adreno_coresight.c
@@ -55,7 +55,12 @@
 int adreno_coresight_enable(struct coresight_device *csdev)
 {
 	struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device *adreno_dev;
+
+	if (device == NULL)
+		return -ENODEV;
+
+	adreno_dev = ADRENO_DEVICE(device);
 
 	/* Check if coresight compatible device, return error otherwise */
 	if (adreno_dev->gpudev->coresight_enable)
@@ -80,7 +85,12 @@
 void adreno_coresight_disable(struct coresight_device *csdev)
 {
 	struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device *adreno_dev;
+
+	if (device == NULL)
+		return;
+
+	adreno_dev = ADRENO_DEVICE(device);
 
 	/* Check if coresight compatible device, bail otherwise */
 	if (adreno_dev->gpudev->coresight_disable)
@@ -134,6 +144,10 @@
 	struct kgsl_device *device = dev_get_drvdata(dev->parent);
 	struct coresight_attr *csight_attr = container_of(attr,
 			struct coresight_attr, attr);
+
+	if (device == NULL)
+		return -ENODEV;
+
 	return coresight_read_reg(device, csight_attr->regname, buf);
 }
 
@@ -142,11 +156,16 @@
 		const char *buf, size_t size)
 {
 	struct kgsl_device *device = dev_get_drvdata(dev->parent);
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device *adreno_dev;
 	struct coresight_attr *csight_attr = container_of(attr,
 			struct coresight_attr, attr);
 	unsigned int regval = 0;
 
+	if (device == NULL)
+		return -ENODEV;
+
+	adreno_dev = ADRENO_DEVICE(device);
+
 	regval = coresight_convert_reg(buf);
 
 	if (adreno_dev->gpudev->coresight_config_debug_reg)
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 2da36b6..95e4017 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -397,7 +397,7 @@
 	 */
 
 	if (count)
-		wake_up_interruptible_all(&drawctxt->wq);
+		wake_up_all(&drawctxt->wq);
 
 	/*
 	 * Return positive if the context submitted commands or if we figured
@@ -1515,8 +1515,14 @@
  */
 void adreno_dispatcher_start(struct kgsl_device *device)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
 	complete_all(&device->cmdbatch_gate);
 
+	/* a305b & a305c GPUs are slower than a330 and needs a larger timer */
+	if (adreno_is_a305b(adreno_dev) || adreno_is_a305c(adreno_dev))
+		_fault_timer_interval = 200;
+
 	/* Schedule the work loop to get things going */
 	adreno_dispatcher_schedule(device);
 }
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 6007a3f..4db045a 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2014, 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
@@ -138,7 +138,7 @@
 		u32 timestamp, u32 type)
 {
 	struct adreno_context *drawctxt = priv;
-	wake_up_interruptible_all(&drawctxt->waiting);
+	wake_up_all(&drawctxt->waiting);
 }
 
 #define adreno_wait_event_interruptible_timeout(wq, condition, timeout, io)   \
@@ -266,20 +266,18 @@
 {
 	struct adreno_context *drawctxt = priv;
 
-	wake_up_interruptible_all(&drawctxt->waiting);
+	wake_up_all(&drawctxt->waiting);
 	kgsl_context_put(&drawctxt->base);
 }
 
 static int _check_global_timestamp(struct kgsl_device *device,
-		unsigned int timestamp)
+		struct adreno_context *drawctxt, unsigned int timestamp)
 {
-	int ret;
+	/* Stop waiting if the context is invalidated */
+	if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID)
+		return 1;
 
-	mutex_lock(&device->mutex);
-	ret = kgsl_check_timestamp(device, NULL, timestamp);
-	mutex_unlock(&device->mutex);
-
-	return ret;
+	return kgsl_check_timestamp(device, NULL, timestamp);
 }
 
 int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev,
@@ -288,7 +286,7 @@
 {
 	struct kgsl_device *device = &adreno_dev->dev;
 	struct adreno_context *drawctxt = ADRENO_CONTEXT(context);
-	int ret;
+	int ret = 0;
 
 	/* Needs to hold the device mutex */
 	BUG_ON(!mutex_is_locked(&device->mutex));
@@ -298,6 +296,15 @@
 		goto done;
 	}
 
+	/*
+	 * If the context is invalid then return immediately - we may end up
+	 * waiting for a timestamp that will never come
+	 */
+	if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
+		kgsl_context_put(context);
+		goto done;
+	}
+
 	trace_adreno_drawctxt_wait_start(KGSL_MEMSTORE_GLOBAL, timestamp);
 
 	ret = kgsl_add_event(device, KGSL_MEMSTORE_GLOBAL, timestamp,
@@ -310,8 +317,8 @@
 	mutex_unlock(&device->mutex);
 
 	if (timeout) {
-		ret = (int) wait_event_interruptible_timeout(drawctxt->waiting,
-			_check_global_timestamp(device, timestamp),
+		ret = (int) wait_event_timeout(drawctxt->waiting,
+			_check_global_timestamp(device, drawctxt, timestamp),
 			msecs_to_jiffies(timeout));
 
 		if (ret == 0)
@@ -319,8 +326,8 @@
 		else if (ret > 0)
 			ret = 0;
 	} else {
-		ret = (int) wait_event_interruptible(drawctxt->waiting,
-			_check_global_timestamp(device, timestamp));
+		wait_event(drawctxt->waiting,
+			_check_global_timestamp(device, drawctxt, timestamp));
 	}
 
 	mutex_lock(&device->mutex);
@@ -386,8 +393,8 @@
 	mutex_unlock(&drawctxt->mutex);
 
 	/* Give the bad news to everybody waiting around */
-	wake_up_interruptible_all(&drawctxt->waiting);
-	wake_up_interruptible_all(&drawctxt->wq);
+	wake_up_all(&drawctxt->waiting);
+	wake_up_all(&drawctxt->wq);
 }
 
 /**
@@ -425,11 +432,13 @@
 		KGSL_CONTEXT_PER_CONTEXT_TS |
 		KGSL_CONTEXT_USER_GENERATED_TS |
 		KGSL_CONTEXT_NO_FAULT_TOLERANCE |
-		KGSL_CONTEXT_TYPE_MASK);
+		KGSL_CONTEXT_TYPE_MASK |
+		KGSL_CONTEXT_PWR_CONSTRAINT);
 
 	/* Always enable per-context timestamps */
 	drawctxt->base.flags |= KGSL_CONTEXT_PER_CONTEXT_TS;
-
+	drawctxt->type = (drawctxt->base.flags & KGSL_CONTEXT_TYPE_MASK)
+	>> KGSL_CONTEXT_TYPE_SHIFT;
 	mutex_init(&drawctxt->mutex);
 	init_waitqueue_head(&drawctxt->wq);
 	init_waitqueue_head(&drawctxt->waiting);
@@ -543,6 +552,14 @@
 	ret = adreno_drawctxt_wait_global(adreno_dev, context,
 		drawctxt->internal_timestamp, 10 * 1000);
 
+	/*
+	 * If the wait for global fails then nothing after this point is likely
+	 * to work very well - BUG_ON() so we can take advantage of the debug
+	 * tools to figure out what the h - e - double hockey sticks happened
+	 */
+
+	BUG_ON(ret);
+
 	kgsl_sharedmem_writel(device, &device->memstore,
 			KGSL_MEMSTORE_OFFSET(context->id, soptimestamp),
 			drawctxt->timestamp);
@@ -557,8 +574,8 @@
 		drawctxt->ops->detach(drawctxt);
 
 	/* wake threads waiting to submit commands from this context */
-	wake_up_interruptible_all(&drawctxt->waiting);
-	wake_up_interruptible_all(&drawctxt->wq);
+	wake_up_all(&drawctxt->waiting);
+	wake_up_all(&drawctxt->wq);
 
 	return ret;
 }
diff --git a/drivers/gpu/msm/adreno_profile.c b/drivers/gpu/msm/adreno_profile.c
index 28fd6d6..079e120 100644
--- a/drivers/gpu/msm/adreno_profile.c
+++ b/drivers/gpu/msm/adreno_profile.c
@@ -1106,7 +1106,7 @@
 	if (SIZE_SHARED_ENTRY(count) >= shared_buf_available(profile))
 		goto done;
 
-	if (entry_head + SIZE_SHARED_ENTRY(count) > profile->shared_size) {
+	if (entry_head + SIZE_SHARED_ENTRY(count) >= profile->shared_size) {
 		/* entry_head would wrap, start entry_head at 0 in buffer */
 		entry_head = 0;
 		profile->shared_size = profile->shared_head;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1383a20..8d7b803 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2014, 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
@@ -665,7 +665,8 @@
 	total_sizedwords += (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) ? 2 : 0;
 
 	/* Add two dwords for the CP_INTERRUPT */
-	total_sizedwords += drawctxt ? 2 : 0;
+	total_sizedwords +=
+		(drawctxt || (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) ?  2 : 0;
 
 	if (adreno_is_a3xx(adreno_dev))
 		total_sizedwords += 7;
@@ -1131,6 +1132,65 @@
 	return ret;
 }
 
+unsigned int adreno_ringbuffer_get_constraint(struct kgsl_device *device,
+				struct kgsl_context *context)
+{
+	unsigned int pwrlevel = device->pwrctrl.active_pwrlevel;
+
+	switch (context->pwr_constraint.type) {
+	case KGSL_CONSTRAINT_PWRLEVEL: {
+		switch (context->pwr_constraint.sub_type) {
+		case KGSL_CONSTRAINT_PWR_MAX:
+			pwrlevel = device->pwrctrl.max_pwrlevel;
+			break;
+		case KGSL_CONSTRAINT_PWR_MIN:
+			pwrlevel = device->pwrctrl.min_pwrlevel;
+			break;
+		default:
+			break;
+		}
+	}
+	break;
+
+	}
+
+	return pwrlevel;
+}
+
+void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
+			struct kgsl_cmdbatch *cmdbatch)
+{
+	unsigned int constraint;
+	struct kgsl_context *context = cmdbatch->context;
+	/*
+	 * Check if the context has a constraint and constraint flags are
+	 * set.
+	 */
+	if (context->pwr_constraint.type &&
+		((context->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
+			(cmdbatch->flags & KGSL_CONTEXT_PWR_CONSTRAINT))) {
+
+		constraint = adreno_ringbuffer_get_constraint(device, context);
+
+		/*
+		 * If a constraint is already set, set a new
+		 * constraint only if it is faster
+		 */
+		if ((device->pwrctrl.constraint.type ==
+			KGSL_CONSTRAINT_NONE) || (constraint <
+			device->pwrctrl.constraint.hint.pwrlevel.level)) {
+
+			kgsl_pwrctrl_pwrlevel_change(device, constraint);
+			device->pwrctrl.constraint.type =
+					context->pwr_constraint.type;
+			device->pwrctrl.constraint.hint.
+					pwrlevel.level = constraint;
+		}
+
+	}
+
+}
+
 /* adreno_rindbuffer_submitcmd - submit userspace IBs to the GPU */
 int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
 		struct kgsl_cmdbatch *cmdbatch)
@@ -1241,6 +1301,9 @@
 		test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv))
 		flags |= KGSL_CMD_FLAGS_PWRON_FIXUP;
 
+	/* Set the constraints before adding to ringbuffer */
+	adreno_ringbuffer_set_constraint(device, cmdbatch);
+
 	ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
 					drawctxt,
 					flags,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 9aefda6..11b7429 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -45,6 +45,10 @@
 #undef MODULE_PARAM_PREFIX
 #define MODULE_PARAM_PREFIX "kgsl."
 
+#ifndef arch_mmap_check
+#define arch_mmap_check(addr, len, flags)	(0)
+#endif
+
 static int kgsl_pagetable_count = KGSL_PAGETABLE_COUNT;
 static char *ksgl_mmu_type;
 module_param_named(ptcount, kgsl_pagetable_count, int, 0);
@@ -1113,7 +1117,7 @@
 	if (device->open_count == 0) {
 		/* make sure power is on to stop the device */
 		kgsl_pwrctrl_enable(device);
-		result = device->ftbl->stop(device);
+		device->ftbl->stop(device);
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
 		atomic_dec(&device->active_cnt);
 	}
@@ -1375,8 +1379,8 @@
 
 	if (dev_priv->device->ftbl->setproperty)
 		result = dev_priv->device->ftbl->setproperty(
-			dev_priv->device, param->type,
-			param->value, param->sizebytes);
+			dev_priv, param->type, param->value,
+			param->sizebytes);
 
 	return result;
 }
@@ -1458,7 +1462,7 @@
  * @timestamp: Pending timestamp for the event
  * @handle: Pointer to a sync fence handle
  * @device: Pointer to the KGSL device
- * @lock: Spin lock to protect the sync event list
+ * @refcount: Allow event to be destroyed asynchronously
  */
 struct kgsl_cmdbatch_sync_event {
 	int type;
@@ -1468,10 +1472,37 @@
 	unsigned int timestamp;
 	struct kgsl_sync_fence_waiter *handle;
 	struct kgsl_device *device;
-	spinlock_t lock;
+	struct kref refcount;
 };
 
 /**
+ * kgsl_cmdbatch_sync_event_destroy() - Destroy a sync event object
+ * @kref: Pointer to the kref structure for this object
+ *
+ * Actually destroy a sync event object.  Called from
+ * kgsl_cmdbatch_sync_event_put.
+ */
+static void kgsl_cmdbatch_sync_event_destroy(struct kref *kref)
+{
+	struct kgsl_cmdbatch_sync_event *event = container_of(kref,
+		struct kgsl_cmdbatch_sync_event, refcount);
+
+	kgsl_cmdbatch_put(event->cmdbatch);
+	kfree(event);
+}
+
+/**
+ * kgsl_cmdbatch_sync_event_put() - Decrement the refcount for a
+ *                                  sync event object
+ * @event: Pointer to the sync event object
+ */
+static inline void kgsl_cmdbatch_sync_event_put(
+	struct kgsl_cmdbatch_sync_event *event)
+{
+	kref_put(&event->refcount, kgsl_cmdbatch_sync_event_destroy);
+}
+
+/**
  * kgsl_cmdbatch_destroy_object() - Destroy a cmdbatch object
  * @kref: Pointer to the kref structure for this object
  *
@@ -1496,10 +1527,25 @@
 static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device,
 	struct kgsl_cmdbatch_sync_event *event)
 {
+	struct kgsl_cmdbatch_sync_event *e, *tmp;
 	int sched = 0;
+	int removed = 0;
 
 	spin_lock(&event->cmdbatch->lock);
-	list_del(&event->node);
+
+	/*
+	 * sync events that are contained by a cmdbatch which has been
+	 * destroyed may have already been removed from the synclist
+	 */
+
+	list_for_each_entry_safe(e, tmp, &event->cmdbatch->synclist, node) {
+		if (e == event) {
+			list_del_init(&event->node);
+			removed = 1;
+			break;
+		}
+	}
+
 	sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0;
 	spin_unlock(&event->cmdbatch->lock);
 
@@ -1510,6 +1556,10 @@
 
 	if (sched && device->ftbl->drawctxt_sched)
 		device->ftbl->drawctxt_sched(device, event->cmdbatch->context);
+
+	/* Put events that have been removed from the synclist */
+	if (removed)
+		kgsl_cmdbatch_sync_event_put(event);
 }
 
 
@@ -1523,11 +1573,9 @@
 	struct kgsl_cmdbatch_sync_event *event = priv;
 
 	kgsl_cmdbatch_sync_expire(device, event);
-
 	kgsl_context_put(event->context);
-	kgsl_cmdbatch_put(event->cmdbatch);
-
-	kfree(event);
+	/* Put events that have signaled */
+	kgsl_cmdbatch_sync_event_put(event);
 }
 
 /**
@@ -1535,32 +1583,48 @@
  * @cmdbatch: Pointer to the command batch object to destroy
  *
  * Start the process of destroying a command batch.  Cancel any pending events
- * and decrement the refcount.
+ * and decrement the refcount.  Asynchronous events can still signal after
+ * kgsl_cmdbatch_destroy has returned.
  */
 void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch)
 {
 	struct kgsl_cmdbatch_sync_event *event, *tmp;
+	LIST_HEAD(cancel_synclist);
 
+	/*
+	 * Empty the synclist before canceling events
+	 */
 	spin_lock(&cmdbatch->lock);
+	list_splice_init(&cmdbatch->synclist, &cancel_synclist);
+	spin_unlock(&cmdbatch->lock);
 
-	/* Delete any pending sync points for this command batch */
-	list_for_each_entry_safe(event, tmp, &cmdbatch->synclist, node) {
+	/*
+	 * Finish canceling events outside the cmdbatch spinlock and
+	 * require the cancel function to return if the event was
+	 * successfully canceled meaning that the event is guaranteed
+	 * not to signal the callback. This guarantee ensures that
+	 * the reference count for the event and cmdbatch is correct.
+	 */
+	list_for_each_entry_safe(event, tmp, &cancel_synclist, node) {
 
 		if (event->type == KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP) {
-			/* Cancel the event if it still exists */
+			/*
+			 * Timestamp events are guaranteed to signal
+			 * when canceled
+			 */
 			kgsl_cancel_event(cmdbatch->device, event->context,
 				event->timestamp, kgsl_cmdbatch_sync_func,
 				event);
 		} else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) {
-			if (kgsl_sync_fence_async_cancel(event->handle)) {
-				list_del(&event->node);
-				kfree(event);
-				kgsl_cmdbatch_put(cmdbatch);
-			}
+			/* Put events that are successfully canceled */
+			if (kgsl_sync_fence_async_cancel(event->handle))
+				kgsl_cmdbatch_sync_event_put(event);
 		}
-	}
 
-	spin_unlock(&cmdbatch->lock);
+		/* Put events that have been removed from the synclist */
+		list_del_init(&event->node);
+		kgsl_cmdbatch_sync_event_put(event);
+	}
 	kgsl_cmdbatch_put(cmdbatch);
 }
 EXPORT_SYMBOL(kgsl_cmdbatch_destroy);
@@ -1573,11 +1637,9 @@
 {
 	struct kgsl_cmdbatch_sync_event *event = priv;
 
-	spin_lock(&event->lock);
 	kgsl_cmdbatch_sync_expire(event->device, event);
-	kgsl_cmdbatch_put(event->cmdbatch);
-	spin_unlock(&event->lock);
-	kfree(event);
+	/* Put events that have signaled */
+	kgsl_cmdbatch_sync_event_put(event);
 }
 
 /* kgsl_cmdbatch_add_sync_fence() - Add a new sync fence syncpoint
@@ -1603,28 +1665,33 @@
 	event->type = KGSL_CMD_SYNCPOINT_TYPE_FENCE;
 	event->cmdbatch = cmdbatch;
 	event->device = device;
-	spin_lock_init(&event->lock);
+	event->context = NULL;
+
+	/*
+	 * Initial kref is to ensure async callback does not free the
+	 * event before this function sets the event handle
+	 */
+	kref_init(&event->refcount);
 
 	/*
 	 * Add it to the list first to account for the possiblity that the
 	 * callback will happen immediately after the call to
-	 * kgsl_sync_fence_async_wait
+	 * kgsl_sync_fence_async_wait. Decrement the event refcount when
+	 * removing from the synclist.
 	 */
 
 	spin_lock(&cmdbatch->lock);
+	kref_get(&event->refcount);
 	list_add(&event->node, &cmdbatch->synclist);
 	spin_unlock(&cmdbatch->lock);
 
 	/*
-	 * There is a distinct race condition that can occur if the fence
-	 * callback is fired before the function has a chance to return.  The
-	 * event struct would be freed before we could write event->handle and
-	 * hilarity ensued.  Protect against this by protecting the call to
-	 * kgsl_sync_fence_async_wait and the kfree in the callback with a lock.
+	 * Increment the reference count for the async callback.
+	 * Decrement when the callback is successfully canceled, when
+	 * the callback is signaled or if the async wait fails.
 	 */
 
-	spin_lock(&event->lock);
-
+	kref_get(&event->refcount);
 	event->handle = kgsl_sync_fence_async_wait(sync->fd,
 		kgsl_cmdbatch_sync_fence_func, event);
 
@@ -1632,18 +1699,27 @@
 	if (IS_ERR_OR_NULL(event->handle)) {
 		int ret = PTR_ERR(event->handle);
 
+		/* Failed to add the event to the async callback */
+		kgsl_cmdbatch_sync_event_put(event);
+
+		/* Remove event from the synclist */
 		spin_lock(&cmdbatch->lock);
 		list_del(&event->node);
+		kgsl_cmdbatch_sync_event_put(event);
 		spin_unlock(&cmdbatch->lock);
 
-		kgsl_cmdbatch_put(cmdbatch);
-		spin_unlock(&event->lock);
-		kfree(event);
+		/* Event no longer needed by this function */
+		kgsl_cmdbatch_sync_event_put(event);
 
 		return ret;
 	}
 
-	spin_unlock(&event->lock);
+	/*
+	 * Event was successfully added to the synclist, the async
+	 * callback and handle to cancel event has been set.
+	 */
+	kgsl_cmdbatch_sync_event_put(event);
+
 	return 0;
 }
 
@@ -1698,6 +1774,17 @@
 	event->context = context;
 	event->timestamp = sync->timestamp;
 
+	/*
+	 * Two krefs are required to support events. The first kref is for
+	 * the synclist which holds the event in the cmdbatch. The second
+	 * kref is for the callback which can be asynchronous and be called
+	 * after kgsl_cmdbatch_destroy. The kref should be put when the event
+	 * is removed from the synclist, if the callback is successfully
+	 * canceled or when the callback is signaled.
+	 */
+	kref_init(&event->refcount);
+	kref_get(&event->refcount);
+
 	spin_lock(&cmdbatch->lock);
 	list_add(&event->node, &cmdbatch->synclist);
 	spin_unlock(&cmdbatch->lock);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 7fc6fae..7d009ce 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2014, 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
@@ -129,7 +129,7 @@
 	void (*drawctxt_destroy) (struct kgsl_context *context);
 	long (*ioctl) (struct kgsl_device_private *dev_priv,
 		unsigned int cmd, void *data);
-	int (*setproperty) (struct kgsl_device *device,
+	int (*setproperty) (struct kgsl_device_private *dev_priv,
 		enum kgsl_property_type type, void *value,
 		unsigned int sizebytes);
 	int (*postmortem_dump) (struct kgsl_device *device, int manual);
@@ -349,6 +349,7 @@
  * @pagefault_ts: global timestamp of the pagefault, if KGSL_CONTEXT_PAGEFAULT
  * is set.
  * @flags: flags from userspace controlling the behavior of this context
+ * @pwr_constraint: power constraint from userspace for this context
  */
 struct kgsl_context {
 	struct kref refcount;
@@ -366,6 +367,7 @@
 	struct list_head events_list;
 	unsigned int pagefault_ts;
 	unsigned int flags;
+	struct kgsl_pwr_constraint pwr_constraint;
 };
 
 /**
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
old mode 100644
new mode 100755
index 246295b..0a7ba30
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -72,6 +72,11 @@
 
 static struct iommu_access_ops *iommu_access_ops;
 
+static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu,
+		uint32_t flags);
+static phys_addr_t
+kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu);
+
 static void _iommu_lock(struct kgsl_iommu const *iommu)
 {
 	if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire)
@@ -1485,7 +1490,7 @@
 
 	/* If chip is not 8960 then we use the 2nd context bank for pagetable
 	 * switching on the 3D side for which a separate table is allocated */
-	if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v0()) {
+	if (msm_soc_version_supports_iommu_v0()) {
 		mmu->priv_bank_table =
 			kgsl_mmu_getpagetable(mmu,
 					KGSL_MMU_PRIV_BANK_TABLE_NAME);
@@ -1739,9 +1744,11 @@
 		struct kgsl_memdesc *memdesc,
 		unsigned int *tlb_flags)
 {
-	int ret;
+	int ret = 0, lock_taken = 0;
 	unsigned int range = memdesc->size;
 	struct kgsl_iommu_pt *iommu_pt = pt->priv;
+	struct kgsl_device *device = pt->mmu->device;
+	struct kgsl_iommu *iommu = pt->mmu->priv;
 
 	/* All GPU addresses as assigned are page aligned, but some
 	   functions purturb the gpuaddr with an offset, so apply the
@@ -1756,18 +1763,38 @@
 		range += PAGE_SIZE;
 
 	ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range);
-	if (ret)
+	if (ret) {
 		KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed "
 			"with err: %d\n", iommu_pt->domain, gpuaddr,
 			range, ret);
+		return ret;
+	}
 
 	/*
-	 * Flushing only required if per process pagetables are used. With
-	 * global case, flushing will happen inside iommu_map function
+	 * Check to see if the current thread already holds the device mutex.
+	 * If it does not, then take the device mutex which is required for
+	 * flushing the tlb
 	 */
-	if (!ret && kgsl_mmu_is_perprocess(pt->mmu))
-		*tlb_flags = UINT_MAX;
-	return 0;
+	if (!mutex_is_locked(&device->mutex) ||
+		device->mutex.owner != current) {
+		mutex_lock(&device->mutex);
+		lock_taken = 1;
+	}
+
+	/*
+	 * Flush the tlb only if the iommu device is attached and the pagetable
+	 * hasn't been switched yet
+	 */
+	if (kgsl_mmu_is_perprocess(pt->mmu) &&
+		iommu->iommu_units[0].dev[KGSL_IOMMU_CONTEXT_USER].attached &&
+		kgsl_iommu_pt_equal(pt->mmu, pt,
+		kgsl_iommu_get_current_ptbase(pt->mmu)))
+		kgsl_iommu_default_setstate(pt->mmu, KGSL_MMUFLAGS_TLBFLUSH);
+
+	if (lock_taken)
+		mutex_unlock(&device->mutex);
+
+	return ret;
 }
 
 static int
@@ -2076,6 +2103,72 @@
 	return iommu->unit_count;
 }
 
+/*
+ * kgsl_iommu_set_pf_policy() - Set the pagefault policy for IOMMU
+ * @mmu: Pointer to mmu structure
+ * @pf_policy: The pagefault polict to set
+ *
+ * Check if the new policy indicated by pf_policy is same as current
+ * policy, if same then return else set the policy
+ */
+static int kgsl_iommu_set_pf_policy(struct kgsl_mmu *mmu,
+				unsigned int pf_policy)
+{
+	int i, j;
+	struct kgsl_iommu *iommu = mmu->priv;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device);
+	int ret = 0;
+	unsigned int sctlr_val;
+
+	if ((adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) ==
+		(pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE))
+		return ret;
+	if (msm_soc_version_supports_iommu_v0())
+		return ret;
+
+	ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER);
+
+	if (ret) {
+		KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n");
+		return ret;
+	}
+	ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_PRIV);
+
+	if (ret) {
+		KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n");
+		kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
+		return ret;
+	}
+	/* Need to idle device before changing options */
+	ret = mmu->device->ftbl->idle(mmu->device);
+	if (ret) {
+		kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
+		return ret;
+	}
+
+	for (i = 0; i < iommu->unit_count; i++) {
+		struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
+		for (j = 0; j < iommu_unit->dev_count; j++) {
+			sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu,
+					iommu_unit,
+					iommu_unit->dev[j].ctx_id,
+					SCTLR);
+			if (pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE)
+				sctlr_val &= ~(0x1 <<
+					KGSL_IOMMU_SCTLR_HUPCF_SHIFT);
+			else
+				sctlr_val |= (0x1 <<
+					KGSL_IOMMU_SCTLR_HUPCF_SHIFT);
+			KGSL_IOMMU_SET_CTX_REG(iommu,
+					iommu_unit,
+					iommu_unit->dev[j].ctx_id,
+					SCTLR, sctlr_val);
+		}
+	}
+	kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
+	return ret;
+}
+
 struct kgsl_mmu_ops iommu_ops = {
 	.mmu_init = kgsl_iommu_init,
 	.mmu_close = kgsl_iommu_close,
@@ -2101,6 +2194,7 @@
 	.mmu_cleanup_pt = NULL,
 	.mmu_sync_lock = kgsl_iommu_sync_lock,
 	.mmu_sync_unlock = kgsl_iommu_sync_unlock,
+	.mmu_set_pf_policy = kgsl_iommu_set_pf_policy,
 };
 
 struct kgsl_mmu_pt_ops iommu_pt_ops = {
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 8bc9962..040a3a7 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-2014, 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
@@ -173,6 +173,7 @@
 	unsigned int (*mmu_sync_unlock)
 			(struct kgsl_mmu *mmu, unsigned int *cmds);
 	int (*mmu_hw_halt_supported)(struct kgsl_mmu *mmu, int iommu_unit_num);
+	int (*mmu_set_pf_policy)(struct kgsl_mmu *mmu, unsigned int pf_policy);
 };
 
 struct kgsl_mmu_pt_ops {
@@ -477,4 +478,13 @@
 		return 0;
 }
 
+static inline int kgsl_mmu_set_pagefault_policy(struct kgsl_mmu *mmu,
+						unsigned int pf_policy)
+{
+	if (mmu->mmu_ops && mmu->mmu_ops->mmu_set_pf_policy)
+		return mmu->mmu_ops->mmu_set_pf_policy(mmu, pf_policy);
+	else
+		return 0;
+}
+
 #endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 3e15580..96ff1b8 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -132,6 +132,9 @@
 	int buslevel = 0;
 	if (!pwr->pcl)
 		return;
+	/* the bus should be ON to update the active frequency */
+	if (on && !(test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)))
+		return;
 	/*
 	 * If the bus should remain on calculate our request and submit it,
 	 * otherwise request bus level 0, off.
@@ -175,11 +178,10 @@
 	pwr->bus_mod = 0;
 	pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel];
 
-	if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) {
-		kgsl_pwrctrl_buslevel_update(device, true);
+	kgsl_pwrctrl_buslevel_update(device, true);
+	if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags))
 		if (pwr->ebi1_clk)
 			clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq);
-	}
 
 	if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) ||
 		(device->state == KGSL_STATE_NAP)) {
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 6ec809d..c811b78 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -27,6 +27,9 @@
 
 #define KGSL_MAX_CLKS 6
 
+/* Only two supported levels, min & max */
+#define KGSL_CONSTRAINT_PWR_MAXLEVELS 2
+
 struct platform_device;
 
 struct kgsl_clk_stats {
@@ -40,6 +43,16 @@
 	unsigned int elapsed_old;
 };
 
+struct kgsl_pwr_constraint {
+	unsigned int type;
+	unsigned int sub_type;
+	union {
+		struct {
+			unsigned int level;
+		} pwrlevel;
+	} hint;
+};
+
 /**
  * struct kgsl_pwrctrl - Power control settings for a KGSL device
  * @interrupt_num - The interrupt number for the device
@@ -67,6 +80,7 @@
  * @bus_control - true if the bus calculation is independent
  * @bus_index - default bus index into the bus_ib table
  * @bus_ib - the set of unique ib requests needed for the bus calculation
+ * @constraint - currently active power constraint
  */
 
 struct kgsl_pwrctrl {
@@ -98,6 +112,7 @@
 	int bus_mod;
 	unsigned int bus_index[KGSL_MAX_PWRLEVELS];
 	uint64_t bus_ib[KGSL_MAX_PWRLEVELS];
+	struct kgsl_pwr_constraint constraint;
 };
 
 void kgsl_pwrctrl_irq(struct kgsl_device *device, int state);
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index 52732cf..acee4d4 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -228,6 +228,10 @@
 	}
 
 	kgsl_pwrctrl_pwrlevel_change(device, level);
+
+	/*Invalidate the constraint set */
+	pwr->constraint.type = KGSL_CONSTRAINT_NONE;
+
 	*freq = kgsl_pwrctrl_active_freq(pwr);
 
 	mutex_unlock(&device->mutex);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index d031d5e..d3adf84 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -591,7 +591,6 @@
 
 	sglen_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT;
 
-	memdesc->size = size;
 	memdesc->pagetable = pagetable;
 	memdesc->ops = &kgsl_page_alloc_ops;
 
@@ -654,6 +653,14 @@
 				continue;
 			}
 
+			/*
+			 * Update sglen and memdesc size,as requested allocation
+			 * not served fully. So that they can be correctly freed
+			 * in kgsl_sharedmem_free().
+			 */
+			memdesc->sglen = sglen;
+			memdesc->size = (size - len);
+
 			KGSL_CORE_ERR(
 				"Out of memory: only allocated %dKB of %dKB requested\n",
 				(size - len) >> 10, size >> 10);
@@ -670,6 +677,7 @@
 	}
 
 	memdesc->sglen = sglen;
+	memdesc->size = size;
 
 	/*
 	 * All memory that goes to the user has to be zeroed out before it gets
@@ -716,15 +724,15 @@
 	outer_cache_range_op_sg(memdesc->sg, memdesc->sglen,
 				KGSL_CACHE_OP_FLUSH);
 
-	KGSL_STATS_ADD(size, kgsl_driver.stats.page_alloc,
-		kgsl_driver.stats.page_alloc_max);
-
 	order = get_order(size);
 
 	if (order < 16)
 		kgsl_driver.stats.histogram[order]++;
 
 done:
+	KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.page_alloc,
+		kgsl_driver.stats.page_alloc_max);
+
 	if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE)
 		vfree(pages);
 	else
diff --git a/drivers/hwmon/epm_adc.c b/drivers/hwmon/epm_adc.c
index f7cf2df..2f5ed9d 100644
--- a/drivers/hwmon/epm_adc.c
+++ b/drivers/hwmon/epm_adc.c
@@ -888,6 +888,12 @@
 	init_resp->num_dev		= rx_buf[6];
 	init_resp->num_channel		= rx_buf[7];
 
+	pr_debug("EPM PSOC response for hello command: resp_cmd:0x%x\n",
+							rx_buf[0]);
+	pr_debug("EPM PSOC version:0x%x\n", rx_buf[1]);
+	pr_debug("EPM PSOC firmware version:0x%x\n",
+			rx_buf[6] | rx_buf[5] | rx_buf[4] | rx_buf[3]);
+
 	return rc;
 }
 
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 9e0be59..7bc8773 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -238,6 +238,60 @@
 	{800,	549},
 };
 
+static const struct qpnp_vadc_map_pt adcmap_qrd_skug_btm_threshold[] = {
+	{-200,	1338},
+	{-180,	1307},
+	{-160,	1276},
+	{-140,	1244},
+	{-120,	1213},
+	{-100,	1182},
+	{-80,	1151},
+	{-60,	1121},
+	{-40,	1092},
+	{-20,	1063},
+	{0,	1035},
+	{20,	1008},
+	{40,	982},
+	{60,	957},
+	{80,	933},
+	{100,	910},
+	{120,	889},
+	{140,	868},
+	{160,	848},
+	{180,	830},
+	{200,	812},
+	{220,	795},
+	{240,	780},
+	{260,	765},
+	{280,	751},
+	{300,	738},
+	{320,	726},
+	{340,	714},
+	{360,	704},
+	{380,	694},
+	{400,	684},
+	{420,	675},
+	{440,	667},
+	{460,	659},
+	{480,	652},
+	{500,	645},
+	{520,	639},
+	{540,	633},
+	{560,	627},
+	{580,	622},
+	{600,	617},
+	{620,	613},
+	{640,	608},
+	{660,	604},
+	{680,	600},
+	{700,	597},
+	{720,	593},
+	{740,	590},
+	{760,	587},
+	{780,	585},
+	{800,	582},
+};
+
 /* Voltage to temperature */
 static const struct qpnp_vadc_map_pt adcmap_100k_104ef_104fb[] = {
 	{1758,	-40},
@@ -442,7 +496,8 @@
 
 	if (!chan_properties || !chan_properties->offset_gain_numerator ||
 		!chan_properties->offset_gain_denominator || !adc_properties
-		|| !adc_chan_result)
+		|| !adc_chan_result
+		|| !chan_properties->adc_graph[CALIB_ABSOLUTE].dy)
 		return -EINVAL;
 
 	pmic_voltage = (adc_code -
@@ -612,6 +667,24 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_qrd_skuaa_batt_therm);
 
+int32_t qpnp_adc_scale_qrd_skug_batt_therm(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int64_t bat_voltage = 0;
+
+	bat_voltage = qpnp_adc_scale_ratiometric_calib(adc_code,
+			adc_properties, chan_properties);
+
+	return qpnp_adc_map_temp_voltage(
+			adcmap_qrd_skug_btm_threshold,
+			ARRAY_SIZE(adcmap_qrd_skug_btm_threshold),
+			bat_voltage,
+			&adc_chan_result->physical);
+}
+EXPORT_SYMBOL(qpnp_adc_scale_qrd_skug_batt_therm);
 int32_t qpnp_adc_scale_therm_pu1(struct qpnp_vadc_chip *chip,
 		int32_t adc_code,
 		const struct qpnp_adc_properties *adc_properties,
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 9839595..32c94dc 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -1011,6 +1011,11 @@
 	if (qpnp_iadc_is_valid(iadc) < 0)
 		return -EPROBE_DEFER;
 
+	if ((iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw) == 0) {
+		pr_err("raw offset errors! run iadc calibration again\n");
+		return -EINVAL;
+	}
+
 	rc = qpnp_check_pmic_temp(iadc);
 	if (rc) {
 		pr_err("Error checking pmic therm temp\n");
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index b2b846a..d462fb3 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -129,6 +129,7 @@
 	[SCALE_THERM_150K_PULLUP] = {qpnp_adc_scale_therm_pu1},
 	[SCALE_QRD_BATT_THERM] = {qpnp_adc_scale_qrd_batt_therm},
 	[SCALE_QRD_SKUAA_BATT_THERM] = {qpnp_adc_scale_qrd_skuaa_batt_therm},
+	[SCALE_QRD_SKUG_BATT_THERM] = {qpnp_adc_scale_qrd_skug_batt_therm},
 };
 
 static int32_t qpnp_vadc_read_reg(struct qpnp_vadc_chip *vadc, int16_t reg,
@@ -808,7 +809,14 @@
 	}
 
 	pr_debug("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
-				calib_read_1, calib_read_2);
+				calib_read_2, calib_read_1);
+
+	if (calib_read_1 == calib_read_2) {
+		pr_err("absolute reference raw: 625mV:0x%x 1.25V:0x%x\n",
+				calib_read_2, calib_read_1);
+		rc = -EINVAL;
+		goto calib_fail;
+	}
 
 	vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_ABSOLUTE].dy =
 					(calib_read_1 - calib_read_2);
@@ -888,6 +896,14 @@
 
 	pr_debug("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
 				calib_read_1, calib_read_2);
+
+	if (calib_read_1 == calib_read_2) {
+		pr_err("ratiometric reference raw: VDD:0x%x GND:0x%x\n",
+				calib_read_1, calib_read_2);
+		rc = -EINVAL;
+		goto calib_fail;
+	}
+
 	vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dy =
 					(calib_read_1 - calib_read_2);
 	vadc->adc->amux_prop->chan_prop->adc_graph[CALIB_RATIOMETRIC].dx =
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 57aa835..1704105 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2014, 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
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/i2c/i2c-qup.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
@@ -85,10 +86,11 @@
 	QUP_MX_INPUT_DONE       = 1U << 11,
 };
 
-/* I2C mini core related values */
+/* QUP_CONFIG values and flags */
 enum {
 	I2C_MINI_CORE           = 2U << 8,
 	I2C_N_VAL               = 0xF,
+	I2C_CORE_CLK_ON_EN      = BIT(13),
 
 };
 
@@ -129,6 +131,12 @@
 	I2C_CLK_FORCED_LOW_STATE	= 5,
 };
 
+enum msm_i2c_state {
+	MSM_I2C_PM_ACTIVE,
+	MSM_I2C_PM_SUSPENDED,
+	MSM_I2C_SYS_SUSPENDING,
+	MSM_I2C_SYS_SUSPENDED,
+};
 #define QUP_MAX_CLK_STATE_RETRIES	300
 #define DEFAULT_CLK_RATE		(19200000)
 #define I2C_STATUS_CLK_STATE		13
@@ -184,8 +192,7 @@
 	int                          in_blk_sz;
 	int                          wr_sz;
 	struct msm_i2c_platform_data *pdata;
-	int                          suspended;
-	int                          pwr_state;
+	enum msm_i2c_state           pwr_state;
 	struct mutex                 mlock;
 	void                         *complete;
 	int                          i2c_gpios[ARRAY_SIZE(i2c_rsrcs)];
@@ -339,22 +346,6 @@
 	return 0;
 }
 
-/*
- * Before calling qup_config_core_on_en(), please make
- * sure that QuPE core is in RESET state.
- */
-static void
-qup_config_core_on_en(struct qup_i2c_dev *dev)
-{
-	uint32_t status;
-
-	status = readl_relaxed(dev->base + QUP_CONFIG);
-	status |= BIT(13);
-	writel_relaxed(status, dev->base + QUP_CONFIG);
-	/* making sure that write has really gone through */
-	mb();
-}
-
 #define MSM_I2C_CLK_PATH_SUSPEND (0)
 #define MSM_I2C_CLK_PATH_RESUME  (1)
 #define MSM_I2C_CLK_PATH_MAX_BW(dev) ((dev->pdata->src_clk_rate * 8) / 1000)
@@ -500,27 +491,97 @@
 	}
 }
 
-static void
-qup_i2c_pwr_mgmt(struct qup_i2c_dev *dev, unsigned int state)
+static int i2c_qup_gpio_request(struct qup_i2c_dev *dev)
 {
-	dev->pwr_state = state;
-	if (state != 0) {
-		i2c_qup_clk_path_postponed_register(dev);
-		if (!dev->pdata->active_only)
-			i2c_qup_clk_path_vote(dev);
+	int i;
+	int result = 0;
 
-		clk_prepare_enable(dev->clk);
-		if (!dev->pdata->keep_ahb_clk_on)
-			clk_prepare_enable(dev->pclk);
-	} else {
-		qup_update_state(dev, QUP_RESET_STATE);
-		clk_disable_unprepare(dev->clk);
-		qup_config_core_on_en(dev);
-		if (!dev->pdata->keep_ahb_clk_on)
-			clk_disable_unprepare(dev->pclk);
-		if (!dev->pdata->active_only)
-			i2c_qup_clk_path_unvote(dev);
+	for (i = 0; i < ARRAY_SIZE(i2c_rsrcs); ++i) {
+		if (dev->i2c_gpios[i] >= 0) {
+			result = gpio_request(dev->i2c_gpios[i], i2c_rsrcs[i]);
+			if (result) {
+				dev_err(dev->dev,
+					"gpio_request for pin %d failed with error %d\n",
+					dev->i2c_gpios[i], result);
+				goto error;
+			}
+		}
 	}
+	return 0;
+
+error:
+	for (; --i >= 0;) {
+		if (dev->i2c_gpios[i] >= 0)
+			gpio_free(dev->i2c_gpios[i]);
+	}
+	return result;
+}
+
+static void i2c_qup_gpio_free(struct qup_i2c_dev *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(i2c_rsrcs); ++i) {
+		if (dev->i2c_gpios[i] >= 0)
+			gpio_free(dev->i2c_gpios[i]);
+	}
+}
+
+static void i2c_qup_pm_suspend_clk(struct qup_i2c_dev *dev)
+{
+	uint32_t status;
+
+	/* reset core and enable conditional dynamic clock gating */
+	qup_update_state(dev, QUP_RESET_STATE);
+	status = readl_relaxed(dev->base + QUP_CONFIG);
+	status |= I2C_CORE_CLK_ON_EN;
+	writel_relaxed(status, dev->base + QUP_CONFIG);
+	/* ensure that write has really gone through */
+	mb();
+
+	clk_disable_unprepare(dev->clk);
+	if (!dev->pdata->keep_ahb_clk_on)
+		clk_disable_unprepare(dev->pclk);
+}
+
+static void i2c_qup_pm_resume_clk(struct qup_i2c_dev *dev)
+{
+	clk_prepare_enable(dev->clk);
+	if (!dev->pdata->keep_ahb_clk_on)
+		clk_prepare_enable(dev->pclk);
+}
+
+static void i2c_qup_pm_suspend(struct qup_i2c_dev *dev)
+{
+	if (dev->pwr_state == MSM_I2C_PM_SUSPENDED) {
+		dev_err(dev->dev, "attempt to suspend when suspended\n");
+		return;
+	}
+
+	if (!dev->pdata->clk_ctl_xfer)
+		i2c_qup_pm_suspend_clk(dev);
+
+	if (!dev->pdata->active_only)
+		i2c_qup_clk_path_unvote(dev);
+
+	i2c_qup_gpio_free(dev);
+	dev->pwr_state = MSM_I2C_PM_SUSPENDED;
+}
+
+static void i2c_qup_pm_resume(struct qup_i2c_dev *dev)
+{
+	if (dev->pwr_state == MSM_I2C_PM_ACTIVE)
+		return;
+
+	i2c_qup_gpio_request(dev);
+
+	i2c_qup_clk_path_postponed_register(dev);
+	if (!dev->pdata->active_only)
+		i2c_qup_clk_path_vote(dev);
+
+	if (!dev->pdata->clk_ctl_xfer)
+		i2c_qup_pm_resume_clk(dev);
+	dev->pwr_state = MSM_I2C_PM_ACTIVE;
 }
 
 static int
@@ -595,43 +656,6 @@
 	return -ETIMEDOUT;
 }
 
-static inline int qup_i2c_request_gpios(struct qup_i2c_dev *dev)
-{
-	int i;
-	int result = 0;
-
-	for (i = 0; i < ARRAY_SIZE(i2c_rsrcs); ++i) {
-		if (dev->i2c_gpios[i] >= 0) {
-			result = gpio_request(dev->i2c_gpios[i], i2c_rsrcs[i]);
-			if (result) {
-				dev_err(dev->dev,
-					"gpio_request for pin %d failed\
-					with error %d\n", dev->i2c_gpios[i],
-					result);
-				goto error;
-			}
-		}
-	}
-	return 0;
-
-error:
-	for (; --i >= 0;) {
-		if (dev->i2c_gpios[i] >= 0)
-			gpio_free(dev->i2c_gpios[i]);
-	}
-	return result;
-}
-
-static inline void qup_i2c_free_gpios(struct qup_i2c_dev *dev)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(i2c_rsrcs); ++i) {
-		if (dev->i2c_gpios[i] >= 0)
-			gpio_free(dev->i2c_gpios[i]);
-	}
-}
-
 #ifdef DEBUG
 static void qup_verify_fifo(struct qup_i2c_dev *dev, uint32_t val,
 				uint32_t addr, int rdwr)
@@ -948,19 +972,35 @@
 	long timeout;
 	int err;
 
-	/* Alternate if runtime power management is disabled */
-	if (!pm_runtime_enabled(dev->dev)) {
-		dev_dbg(dev->dev, "Runtime PM is disabled\n");
-		i2c_qup_pm_resume_runtime(dev->dev);
-	} else {
-		pm_runtime_get_sync(dev->dev);
-	}
+	/*
+	 * If all slaves of this controller behave as expected, they will
+	 * implement suspend and won't call any transaction if they are
+	 * suspended. Since controller is its parent, controller's suspend
+	 * will be called only AFTER alls slaves are suspended.
+	 * However reality is differe and some slave don't implement suspend
+	 * If a slave tries to initiate transfer when we are suspended,
+	 * pm_runtime_enabled is set to false by system-pm.
+	 * Make sure we return error when transaction is initiated while
+	 * we are in suspended state
+	 */
 	mutex_lock(&dev->mlock);
-
-	if (dev->suspended) {
+	if (dev->pwr_state >= MSM_I2C_SYS_SUSPENDING) {
+		dev_err(dev->dev,
+			"xfer not allowed when ctrl is suspended addr:0x%x\n",
+			msgs->addr);
 		mutex_unlock(&dev->mlock);
 		return -EIO;
 	}
+	if (!pm_runtime_enabled(dev->dev)) {
+		dev_dbg(dev->dev, "Runtime PM FEATURE is disabled\n");
+		i2c_qup_pm_resume(dev);
+	} else {
+		pm_runtime_get_sync(dev->dev);
+	}
+
+
+	if (dev->pdata->clk_ctl_xfer)
+		i2c_qup_pm_resume_clk(dev);
 
 	/* Initialize QUP registers during first transfer */
 	if (dev->clk_ctl == 0) {
@@ -1263,6 +1303,8 @@
 	dev->pos = 0;
 	dev->err = 0;
 	dev->cnt = 0;
+	if (dev->pdata->clk_ctl_xfer)
+		i2c_qup_pm_suspend_clk(dev);
 	mutex_unlock(&dev->mlock);
 	pm_runtime_mark_last_busy(dev->dev);
 	pm_runtime_put_autosuspend(dev->dev);
@@ -1296,14 +1338,15 @@
 	struct device_node *node = pdev->dev.of_node;
 	struct msm_i2c_dt_to_pdata_map *itr;
 	struct msm_i2c_dt_to_pdata_map  map[] = {
-	{"qcom,i2c-bus-freq", &pdata->clk_freq    , DT_REQUIRED , DT_U32 ,  0},
-	{"cell-index"       , &pdev->id           , DT_REQUIRED , DT_U32 , -1},
+	{"qcom,i2c-bus-freq", &pdata->clk_freq,     DT_REQUIRED,  DT_U32,   0},
+	{"cell-index",        &pdev->id,            DT_REQUIRED,  DT_U32,  -1},
 	{"qcom,i2c-src-freq", &pdata->src_clk_rate, DT_SUGGESTED, DT_U32,   0},
-	{"qcom,master-id"   , &pdata->master_id   , DT_SUGGESTED, DT_U32,   0},
-	{"qcom,scl-gpio"    , gpios               , DT_OPTIONAL , DT_GPIO, -1},
-	{"qcom,sda-gpio"    , gpios + 1           , DT_OPTIONAL , DT_GPIO, -1},
-	{"qcom,active-only" , &pdata->active_only , DT_OPTIONAL , DT_BOOL,  0},
-	{NULL               , NULL                , 0           , 0      ,  0},
+	{"qcom,master-id",    &pdata->master_id,    DT_SUGGESTED, DT_U32,   0},
+	{"qcom,scl-gpio",      gpios,               DT_OPTIONAL,  DT_GPIO, -1},
+	{"qcom,sda-gpio",      gpios + 1,           DT_OPTIONAL,  DT_GPIO, -1},
+	{"qcom,clk-ctl-xfer", &pdata->clk_ctl_xfer, DT_OPTIONAL,  DT_BOOL, -1},
+	{"qcom,active-only",  &pdata->active_only,  DT_OPTIONAL,  DT_BOOL,  0},
+	{NULL,                 NULL,                0,            0,        0},
 	};
 
 	for (itr = map; itr->dt_name ; ++itr) {
@@ -1611,7 +1654,7 @@
 		pdata->msm_i2c_config_gpio(dev->adapter.nr, 1);
 
 	mutex_init(&dev->mlock);
-	dev->pwr_state = 0;
+	dev->pwr_state = MSM_I2C_PM_SUSPENDED;
 	/* If the same AHB clock is used on Modem side
 	 * switch it on here itself and don't switch it
 	 * on and off during suspend and resume.
@@ -1685,13 +1728,11 @@
 
 	/* Grab mutex to ensure ongoing transaction is over */
 	mutex_lock(&dev->mlock);
-	dev->suspended = 1;
+	dev->pwr_state = MSM_I2C_SYS_SUSPENDING;
 	mutex_unlock(&dev->mlock);
+	i2c_qup_pm_suspend(dev);
+	dev->pwr_state = MSM_I2C_SYS_SUSPENDED;
 	mutex_destroy(&dev->mlock);
-	if (dev->pwr_state != 0) {
-		qup_i2c_pwr_mgmt(dev, 0);
-		qup_i2c_free_gpios(dev);
-	}
 	platform_set_drvdata(pdev, NULL);
 	if (dev->num_irqs == 3) {
 		free_irq(dev->out_irq, dev);
@@ -1732,14 +1773,7 @@
 	struct platform_device *pdev = to_platform_device(device);
 	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
 	dev_dbg(device, "pm_runtime: suspending...\n");
-	/* Grab mutex to ensure ongoing transaction is over */
-	mutex_lock(&dev->mlock);
-	dev->suspended = 1;
-	mutex_unlock(&dev->mlock);
-	if (dev->pwr_state != 0) {
-		qup_i2c_pwr_mgmt(dev, 0);
-		qup_i2c_free_gpios(dev);
-	}
+	i2c_qup_pm_suspend(dev);
 	return 0;
 }
 
@@ -1747,23 +1781,22 @@
 {
 	struct platform_device *pdev = to_platform_device(device);
 	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
-	int ret = 0;
 	dev_dbg(device, "pm_runtime: resuming...\n");
-	if (dev->pwr_state == 0) {
-		ret = qup_i2c_request_gpios(dev);
-		if (ret != 0)
-			return ret;
-		qup_i2c_pwr_mgmt(dev, 1);
-	}
-	dev->suspended = 0;
+	i2c_qup_pm_resume(dev);
 	return 0;
 }
 
-static int qup_i2c_suspend(struct device *device)
+static int i2c_qup_pm_suspend_sys(struct device *device)
 {
+	struct platform_device *pdev = to_platform_device(device);
+	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
+	/* Acquire mutex to ensure current transaction is over */
+	mutex_lock(&dev->mlock);
+	dev->pwr_state = MSM_I2C_SYS_SUSPENDING;
+	mutex_unlock(&dev->mlock);
 	if (!pm_runtime_enabled(device) || !pm_runtime_suspended(device)) {
-		dev_dbg(device, "system suspend");
-		i2c_qup_pm_suspend_runtime(device);
+		dev_dbg(device, "system suspend\n");
+		i2c_qup_pm_suspend(dev);
 		/*
 		 * set the device's runtime PM status to 'suspended'
 		 */
@@ -1771,25 +1804,29 @@
 		pm_runtime_set_suspended(device);
 		pm_runtime_enable(device);
 	}
+	dev->pwr_state = MSM_I2C_SYS_SUSPENDED;
 	return 0;
 }
 
-static int qup_i2c_resume(struct device *device)
+static int i2c_qup_pm_resume_sys(struct device *device)
 {
+	struct platform_device *pdev = to_platform_device(device);
+	struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
 	/*
 	 * Rely on runtime-PM to call resume in case it is enabled
 	 * Even if it's not enabled, rely on 1st client transaction to do
 	 * clock ON and gpio configuration
 	 */
-	dev_dbg(device, "system resume");
+	dev_dbg(device, "system resume\n");
+	dev->pwr_state = MSM_I2C_PM_SUSPENDED;
 	return 0;
 }
 #endif /* CONFIG_PM */
 
 static const struct dev_pm_ops i2c_qup_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(
-		qup_i2c_suspend,
-		qup_i2c_resume
+		i2c_qup_pm_suspend_sys,
+		i2c_qup_pm_resume_sys
 	)
 	SET_RUNTIME_PM_OPS(
 		i2c_qup_pm_suspend_runtime,
@@ -1817,11 +1854,18 @@
 };
 
 /* QUP may be needed to bring up other drivers */
-static int __init
-qup_i2c_init_driver(void)
+int __init qup_i2c_init_driver(void)
 {
+	static bool initialized;
+
+	if (initialized)
+		return 0;
+	else
+		initialized = true;
+
 	return platform_driver_register(&qup_i2c_driver);
 }
+EXPORT_SYMBOL(qup_i2c_init_driver);
 arch_initcall(qup_i2c_init_driver);
 
 static void __exit qup_i2c_exit_driver(void)
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 716ea0d..0c22694 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -73,6 +73,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called bma150.
 
+config INPUT_HBTP_INPUT
+	tristate "HBTP input driver support"
+	help
+	  Say Y to enable HBTP input driver.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hbtp_input.
+
+endif
+
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
 	depends on PCSPKR_PLATFORM
@@ -714,4 +724,3 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called CM36283.
-endif
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index c927e0e..c9a65fc 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -26,6 +26,7 @@
 obj-$(CONFIG_INPUT_GP2A)		+= gp2ap002a00f.o
 obj-$(CONFIG_INPUT_GPIO_TILT_POLLED)	+= gpio_tilt_polled.o
 obj-$(CONFIG_INPUT_GPIO)		+= gpio_event.o gpio_matrix.o gpio_input.o gpio_output.o gpio_axis.o
+obj-$(CONFIG_INPUT_HBTP_INPUT)		+= hbtp_input.o
 obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
 obj-$(CONFIG_INPUT_IXP4XX_BEEPER)	+= ixp4xx-beeper.o
 obj-$(CONFIG_INPUT_KEYCHORD)		+= keychord.o
diff --git a/drivers/input/misc/bmp18x-core.c b/drivers/input/misc/bmp18x-core.c
index 001a804..6f82277 100644
--- a/drivers/input/misc/bmp18x-core.c
+++ b/drivers/input/misc/bmp18x-core.c
@@ -75,35 +75,6 @@
 #define ABS_MAX_PRESSURE	120000
 #define BMP_DELAY_DEFAULT   200
 
-struct bmp18x_calibration_data {
-	s16 AC1, AC2, AC3;
-	u16 AC4, AC5, AC6;
-	s16 B1, B2;
-	s16 MB, MC, MD;
-};
-
-/* Each client has this additional data */
-struct bmp18x_data {
-	struct	bmp18x_data_bus data_bus;
-	struct	device *dev;
-	struct	mutex lock;
-	struct	bmp18x_calibration_data calibration;
-	u8	oversampling_setting;
-	u8	sw_oversampling_setting;
-	u32	raw_temperature;
-	u32	raw_pressure;
-	u32	temp_measurement_period;
-	u32	last_temp_measurement;
-	s32	b6; /* calculated temperature correction coefficient */
-#ifdef CONFIG_HAS_EARLYSUSPEND
-	struct early_suspend early_suspend;
-#endif
-	struct input_dev	*input;
-	struct delayed_work work;
-	u32					delay;
-	u32					enable;
-};
-
 static struct sensors_classdev sensors_cdev = {
 	.name = "bmp18x-pressure",
 	.vendor = "Bosch",
@@ -113,9 +84,13 @@
 	.max_range = "1100.0",
 	.resolution = "0.01",
 	.sensor_power = "0.67",
-	.min_delay = 20000,
+	.min_delay = 20000,	/* microsecond */
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = 200,	/* millisecond */
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
@@ -403,6 +378,19 @@
 static DEVICE_ATTR(sw_oversampling, S_IWUSR | S_IRUGO,
 				show_sw_oversampling, set_sw_oversampling);
 
+static ssize_t bmp18x_poll_delay_set(struct sensors_classdev *sensors_cdev,
+						unsigned int delay_msec)
+{
+	struct bmp18x_data *data = container_of(sensors_cdev,
+					struct bmp18x_data, cdev);
+	mutex_lock(&data->lock);
+	data->delay = delay_msec;
+	mutex_unlock(&data->lock);
+
+	return 0;
+}
+
+
 static ssize_t show_delay(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
@@ -416,17 +404,51 @@
 {
 	struct bmp18x_data *data = dev_get_drvdata(dev);
 	unsigned long delay;
-	int success = kstrtoul(buf, 10, &delay);
-	if (success == 0) {
-		mutex_lock(&data->lock);
-		data->delay = delay;
-		mutex_unlock(&data->lock);
-	}
-	return success;
+	int err = kstrtoul(buf, 10, &delay);
+	if (err < 0)
+		return err;
+
+	err = bmp18x_poll_delay_set(&data->cdev, delay);
+	if (err < 0)
+		return err;
+
+	return count;
 }
-static DEVICE_ATTR(delay, S_IWUSR | S_IRUGO,
+
+static DEVICE_ATTR(poll_delay, S_IWUSR | S_IRUGO,
 				show_delay, set_delay);
 
+static ssize_t bmp18x_enable_set(struct sensors_classdev *sensors_cdev,
+						unsigned int enabled)
+{
+	struct bmp18x_data *data = container_of(sensors_cdev,
+					struct bmp18x_data, cdev);
+	struct device *dev = data->dev;
+
+	enabled = enabled ? 1 : 0;
+	mutex_lock(&data->lock);
+
+	if (data->enable == enabled) {
+		dev_warn(dev, "already %s\n", enabled ? "enabled" : "disabled");
+		goto out;
+	}
+
+	data->enable = enabled;
+
+	if (data->enable) {
+		bmp18x_enable(dev);
+		schedule_delayed_work(&data->work,
+					msecs_to_jiffies(data->delay));
+	} else {
+		cancel_delayed_work_sync(&data->work);
+		bmp18x_disable(dev);
+	}
+
+out:
+	mutex_unlock(&data->lock);
+	return 0;
+}
+
 static ssize_t show_enable(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
@@ -440,24 +462,17 @@
 {
 	struct bmp18x_data *data = dev_get_drvdata(dev);
 	unsigned long enable;
-	int success = kstrtoul(buf, 10, &enable);
-	if (success == 0) {
-		mutex_lock(&data->lock);
-		data->enable = enable ? 1 : 0;
+	int err = kstrtoul(buf, 10, &enable);
+	if (err < 0)
+		return err;
 
-		if (data->enable) {
-			bmp18x_enable(dev);
-			schedule_delayed_work(&data->work,
-						msecs_to_jiffies(data->delay));
-		} else {
-			cancel_delayed_work_sync(&data->work);
-			bmp18x_disable(dev);
-		}
-		mutex_unlock(&data->lock);
+	err = bmp18x_enable_set(&data->cdev, enable);
+	if (err < 0)
+		return err;
 
-	}
 	return count;
 }
+
 static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
 				show_enable, set_enable);
 
@@ -499,7 +514,7 @@
 	&dev_attr_pressure0_input.attr,
 	&dev_attr_oversampling.attr,
 	&dev_attr_sw_oversampling.attr,
-	&dev_attr_delay.attr,
+	&dev_attr_poll_delay.attr,
 	&dev_attr_enable.attr,
 	NULL
 };
@@ -628,7 +643,10 @@
 	if (err)
 		goto error_sysfs;
 
-	err = sensors_classdev_register(&data->input->dev, &sensors_cdev);
+	data->cdev = sensors_cdev;
+	data->cdev.sensors_enable = bmp18x_enable_set;
+	data->cdev.sensors_poll_delay = bmp18x_poll_delay_set;
+	err = sensors_classdev_register(&data->input->dev, &data->cdev);
 	if (err) {
 		pr_err("class device create failed: %d\n", err);
 		goto error_class_sysfs;
@@ -646,6 +664,8 @@
 	register_early_suspend(&data->early_suspend);
 #endif
 
+	pdata->set_power(data, 0);
+	data->power_enabled = 0;
 	dev_info(dev, "Succesfully initialized bmp18x!\n");
 	return 0;
 
@@ -680,10 +700,12 @@
 {
 	struct bmp18x_platform_data *pdata = dev->platform_data;
 	struct bmp18x_data *data = dev_get_drvdata(dev);
-	if (pdata && pdata->deinit_hw)
-		pdata->deinit_hw(&data->data_bus);
+	int ret = 0;
 
-	return 0;
+	if (pdata && pdata->set_power)
+		ret = pdata->set_power(data, 0);
+
+	return ret;
 }
 EXPORT_SYMBOL(bmp18x_disable);
 
@@ -691,10 +713,12 @@
 {
 	struct bmp18x_platform_data *pdata = dev->platform_data;
 	struct bmp18x_data *data = dev_get_drvdata(dev);
-	if (pdata && pdata->init_hw)
-		return pdata->init_hw(&data->data_bus);
+	int ret = 0;
 
-	return 0;
+	if (pdata && pdata->set_power)
+		ret = pdata->set_power(data, 1);
+
+	return ret;
 }
 EXPORT_SYMBOL(bmp18x_enable);
 #endif
diff --git a/drivers/input/misc/bmp18x-i2c.c b/drivers/input/misc/bmp18x-i2c.c
index abbe6e5..75edd0b 100644
--- a/drivers/input/misc/bmp18x-i2c.c
+++ b/drivers/input/misc/bmp18x-i2c.c
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/err.h>
 #include <linux/regulator/consumer.h>
+#include <linux/delay.h>
 #include "bmp18x.h"
 
 struct sensor_regulator {
@@ -102,9 +103,13 @@
 
 static int bmp18x_init_hw(struct bmp18x_data_bus *data_bus)
 {
-	if (data_bus->client)
-		return bmp18x_config_regulator(data_bus->client, 1);
-	return 0;
+	int ret = 0;
+	if (data_bus->client) {
+		ret = bmp18x_config_regulator(data_bus->client, 1);
+		/* The minimum start up time of bmp18x is 10ms */
+		usleep_range(15000, 20000);
+	}
+	return ret;
 }
 
 static void bmp18x_deinit_hw(struct bmp18x_data_bus *data_bus)
@@ -113,6 +118,43 @@
 		bmp18x_config_regulator(data_bus->client, 0);
 }
 
+static int bmp18x_set_power(struct bmp18x_data *data, int on)
+{
+	int rc = 0;
+	int num_vreg = ARRAY_SIZE(bmp_vreg);
+	int i;
+
+	if (!on && data->power_enabled) {
+		for (i = 0; i < num_vreg; i++) {
+			rc = regulator_disable(bmp_vreg[i].vreg);
+			if (rc) {
+				dev_err(data->dev, "Regulator vdd disable failed rc=%d\n",
+						rc);
+				return rc;
+			}
+		}
+		data->power_enabled = false;
+	} else if (on && !data->power_enabled) {
+		for (i = 0; i < num_vreg; i++) {
+			rc = regulator_enable(bmp_vreg[i].vreg);
+			if (rc) {
+				dev_err(data->dev, "Regulator vdd enable failed rc=%d\n",
+						rc);
+				return rc;
+			}
+		}
+		/* The minimum start up time of bmp18x is 10ms */
+		usleep_range(15000, 20000);
+		data->power_enabled = true;
+	} else {
+		dev_warn(data->dev,
+				"Power on=%d. enabled=%d\n",
+				on, data->power_enabled);
+	}
+
+	return rc;
+}
+
 #ifdef CONFIG_OF
 static int bmp18x_parse_dt(struct device *dev,
 			struct bmp18x_platform_data *pdata)
@@ -198,6 +240,7 @@
 		}
 		pdata->init_hw = bmp18x_init_hw;
 		pdata->deinit_hw = bmp18x_deinit_hw;
+		pdata->set_power = bmp18x_set_power;
 		client->dev.platform_data = pdata;
 	}
 	return bmp18x_probe(&client->dev, &data_bus);
@@ -216,12 +259,24 @@
 #ifdef CONFIG_PM
 static int bmp18x_i2c_suspend(struct device *dev)
 {
-	return bmp18x_disable(dev);
+	int ret = 0;
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	if (data->enable)
+		ret = bmp18x_disable(dev);
+
+	return ret;
 }
 
 static int bmp18x_i2c_resume(struct device *dev)
 {
-	return bmp18x_enable(dev);
+	int ret = 0;
+	struct bmp18x_data *data = dev_get_drvdata(dev);
+
+	if (data->enable)
+		ret = bmp18x_enable(dev);
+
+	return ret;
 }
 
 static const struct dev_pm_ops bmp18x_i2c_pm_ops = {
diff --git a/drivers/input/misc/bmp18x.h b/drivers/input/misc/bmp18x.h
index d1b1ee7..6b6c4b1 100644
--- a/drivers/input/misc/bmp18x.h
+++ b/drivers/input/misc/bmp18x.h
@@ -18,6 +18,7 @@
 */
 #ifndef _BMP18X_H
 #define _BMP18X_H
+#include <linux/sensors.h>
 
 #define BMP18X_NAME "bmp18x"
 
@@ -46,13 +47,47 @@
 	void	*client;
 };
 
+struct bmp18x_calibration_data {
+	s16 AC1, AC2, AC3;
+	u16 AC4, AC5, AC6;
+	s16 B1, B2;
+	s16 MB, MC, MD;
+};
+
+/* Each client has this additional data */
+struct bmp18x_data {
+	struct	bmp18x_data_bus data_bus;
+	struct	device *dev;
+	struct	mutex lock;
+	struct	bmp18x_calibration_data calibration;
+	struct	sensors_classdev cdev;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+	struct	early_suspend early_suspend;
+#endif
+	struct	input_dev	*input;
+	struct	delayed_work work;
+
+	u8	oversampling_setting;
+	u8	sw_oversampling_setting;
+	u32	raw_temperature;
+	u32	raw_pressure;
+	u32	temp_measurement_period;
+	u32	last_temp_measurement;
+	s32	b6; /* calculated temperature correction coefficient */
+	u32	delay;
+	u32	enable;
+	u32	power_enabled;
+};
+
 struct bmp18x_platform_data {
 	u8	chip_id;
 	u8	default_oversampling;
 	u8	default_sw_oversampling;
 	u32	temp_measurement_period;
+	u32	power_enabled;
 	int	(*init_hw)(struct bmp18x_data_bus *);
 	void	(*deinit_hw)(struct bmp18x_data_bus *);
+	int	(*set_power)(struct bmp18x_data*, int);
 };
 
 int bmp18x_probe(struct device *dev, struct bmp18x_data_bus *data_bus);
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index 5c89c0c..a7b4735 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -3,7 +3,7 @@
  * Copyright (C) 2012 Capella Microsystems Inc.
  * Author: Frank Hsieh <pengyueh@gmail.com>
  *
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -75,6 +75,10 @@
 	.min_delay = 0,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = CM36283_LS_DEFAULT_POLL_DELAY,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 static struct sensors_classdev sensors_proximity_cdev = {
@@ -89,6 +93,10 @@
 	.min_delay = 0,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = CM36283_PS_DEFAULT_POLL_DELAY,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 
@@ -159,6 +167,8 @@
 	struct regulator *vio;
 	struct delayed_work ldwork;
 	struct delayed_work pdwork;
+	struct sensors_classdev als_cdev;
+	struct sensors_classdev ps_cdev;
 };
 struct cm36283_info *lp_info;
 int fLevel=-1;
@@ -640,12 +650,6 @@
 	.unlocked_ioctl = psensor_ioctl
 };
 
-struct miscdevice psensor_misc = {
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "proximity",
-	.fops = &psensor_fops
-};
-
 void lightsensor_set_kvalue(struct cm36283_info *lpi)
 {
 	if (!lpi) {
@@ -793,13 +797,6 @@
 	.unlocked_ioctl = lightsensor_ioctl
 };
 
-static struct miscdevice lightsensor_misc = {
-	.minor = MISC_DYNAMIC_MINOR,
-	.name = "lightsensor",
-	.fops = &lightsensor_fops
-};
-
-
 static ssize_t ps_adc_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
@@ -819,6 +816,21 @@
 	return ret;
 }
 
+static int ps_enable_set(struct sensors_classdev *sensors_cdev,
+		unsigned int enable)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, ps_cdev);
+	int ret;
+
+	if (enable)
+		ret = psensor_enable(lpi);
+	else
+		ret = psensor_disable(lpi);
+
+	return ret;
+}
+
 static ssize_t ps_enable_store(struct device *dev,
 				struct device_attribute *attr,
 				const char *buf, size_t count)
@@ -844,7 +856,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(ps_adc, 0664, ps_adc_show, ps_enable_store);
 
 static ssize_t ps_parameters_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
@@ -888,10 +899,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(ps_parameters, 0664,
-	ps_parameters_show, ps_parameters_store);
-
-
 static ssize_t ps_conf_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
 {
@@ -917,7 +924,6 @@
 
 	return count;
 }
-static DEVICE_ATTR(ps_conf, 0664, ps_conf_show, ps_conf_store);
 
 static ssize_t ps_thd_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
@@ -946,7 +952,6 @@
 
 	return count;
 }
-static DEVICE_ATTR(ps_thd, 0664, ps_thd_show, ps_thd_store);
 
 static ssize_t ps_hw_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
@@ -969,7 +974,6 @@
 
 	return count;
 }
-static DEVICE_ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store);
 
 static ssize_t ls_adc_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
@@ -983,7 +987,26 @@
 	return ret;
 }
 
-static DEVICE_ATTR(ls_adc, 0664, ls_adc_show, NULL);
+static int ls_enable_set(struct sensors_classdev *sensors_cdev,
+		unsigned int enable)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, als_cdev);
+	int ret;
+
+	if (enable)
+		ret = lightsensor_enable(lpi);
+	else
+		ret = lightsensor_disable(lpi);
+
+	if (ret < 0) {
+		dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
+				__func__);
+		return -EIO;
+	}
+
+	return 0;
+}
 
 static ssize_t ls_enable_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
@@ -1026,15 +1049,15 @@
 			lpi->ls_calibrate);
 	dev_dbg(&lpi->i2c_client->dev, "ls_auto:0x%x\n", ls_auto);
 
-	if (ret < 0)
+	if (ret < 0) {
 		dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
 		__func__);
+		return ret;
+	}
 
 	return count;
 }
 
-static DEVICE_ATTR(ls_auto, 0664,
-	ls_enable_show, ls_enable_store);
 
 static ssize_t ls_kadc_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
@@ -1077,7 +1100,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(ls_kadc, 0664, ls_kadc_show, ls_kadc_store);
 
 static ssize_t ls_gadc_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
@@ -1117,7 +1139,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(ls_gadc, 0664, ls_gadc_show, ls_gadc_store);
 
 static ssize_t ls_adc_table_show(struct device *dev,
 			struct device_attribute *attr, char *buf)
@@ -1168,9 +1189,6 @@
 	return count;
 }
 
-static DEVICE_ATTR(ls_adc_table, 0664,
-	ls_adc_table_show, ls_adc_table_store);
-
 static ssize_t ls_conf_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
@@ -1192,7 +1210,6 @@
 	_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
 	return count;
 }
-static DEVICE_ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store);
 
 static ssize_t ls_poll_delay_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -1219,8 +1236,20 @@
 	return count;
 }
 
-static DEVICE_ATTR(ls_poll_delay, 0664, ls_poll_delay_show,
-		ls_poll_delay_store);
+static int ls_poll_delay_set(struct sensors_classdev *sensors_cdev,
+		unsigned int delay_msec)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, als_cdev);
+
+	if ((delay_msec < CM36283_LS_MIN_POLL_DELAY) ||
+			(delay_msec > CM36283_LS_MAX_POLL_DELAY))
+		return -EINVAL;
+
+	atomic_set(&lpi->ls_poll_delay, delay_msec);
+
+	return 0;
+}
 
 static ssize_t ps_poll_delay_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -1247,8 +1276,19 @@
 	return count;
 }
 
-static DEVICE_ATTR(ps_poll_delay, 0664, ps_poll_delay_show,
-		ps_poll_delay_store);
+static int ps_poll_delay_set(struct sensors_classdev *sensors_cdev,
+		unsigned int delay_msec)
+{
+	struct cm36283_info *lpi = container_of(sensors_cdev,
+			struct cm36283_info, als_cdev);
+
+	if ((delay_msec < CM36283_PS_MIN_POLL_DELAY) ||
+			(delay_msec > CM36283_PS_MAX_POLL_DELAY))
+		return -EINVAL;
+
+	atomic_set(&lpi->ps_poll_delay, delay_msec);
+	return 0;
+}
 
 static ssize_t ls_fLevel_show(struct device *dev,
 				  struct device_attribute *attr, char *buf)
@@ -1271,7 +1311,6 @@
 	fLevel=-1;
 	return count;
 }
-static DEVICE_ATTR(ls_flevel, 0664, ls_fLevel_show, ls_fLevel_store);
 
 static int lightsensor_setup(struct cm36283_info *lpi)
 {
@@ -1286,6 +1325,7 @@
 		return -ENOMEM;
 	}
 	lpi->ls_input_dev->name = "cm36283-ls";
+	lpi->ls_input_dev->id.bustype = BUS_I2C;
 	set_bit(EV_ABS, lpi->ls_input_dev->evbit);
 
 	range = get_als_range();
@@ -1298,17 +1338,8 @@
 		goto err_free_ls_input_device;
 	}
 
-	ret = misc_register(&lightsensor_misc);
-	if (ret < 0) {
-		pr_err("[LS][CM36283 error]%s: can not register ls misc device\n",
-				__func__);
-		goto err_unregister_ls_input_device;
-	}
-
 	return ret;
 
-err_unregister_ls_input_device:
-	input_unregister_device(lpi->ls_input_dev);
 err_free_ls_input_device:
 	input_free_device(lpi->ls_input_dev);
 	return ret;
@@ -1326,6 +1357,7 @@
 		return -ENOMEM;
 	}
 	lpi->ps_input_dev->name = "cm36283-ps";
+	lpi->ps_input_dev->id.bustype = BUS_I2C;
 	set_bit(EV_ABS, lpi->ps_input_dev->evbit);
 	input_set_abs_params(lpi->ps_input_dev, ABS_DISTANCE, 0, 1, 0, 0);
 
@@ -1337,18 +1369,8 @@
 		goto err_free_ps_input_device;
 	}
 
-	ret = misc_register(&psensor_misc);
-	if (ret < 0) {
-		pr_err(
-			"[PS][CM36283 error]%s: could not register ps misc device\n",
-			__func__);
-		goto err_unregister_ps_input_device;
-	}
-
 	return ret;
 
-err_unregister_ps_input_device:
-	input_unregister_device(lpi->ps_input_dev);
 err_free_ps_input_device:
 	input_free_device(lpi->ps_input_dev);
 	return ret;
@@ -1496,6 +1518,59 @@
 	return 0;
 }
 
+static int create_sysfs_interfaces(struct device *dev,
+		struct device_attribute *attributes, int len)
+{
+	int i;
+	int err;
+	for (i = 0; i < len; i++) {
+		err = device_create_file(dev, attributes + i);
+		if (err)
+			goto error;
+	}
+	return 0;
+
+error:
+	for (; i >= 0; i--)
+		device_remove_file(dev, attributes + i);
+	dev_err(dev, "%s:Unable to create interface\n", __func__);
+	return err;
+}
+
+static int remove_sysfs_interfaces(struct device *dev,
+		struct device_attribute *attributes, int len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		device_remove_file(dev, attributes + i);
+	return 0;
+}
+
+static struct device_attribute light_attr[] = {
+	__ATTR(ls_adc, 0664, ls_adc_show, NULL),
+	__ATTR(ls_kadc, 0664, ls_kadc_show, ls_kadc_store),
+	__ATTR(ls_gadc, 0664, ls_gadc_show, ls_gadc_store),
+	__ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store),
+	__ATTR(ls_adc_table, 0664,
+			ls_adc_table_show, ls_adc_table_store),
+	__ATTR(poll_delay, 0664, ls_poll_delay_show,
+			ls_poll_delay_store),
+	__ATTR(enable, 0664,
+			ls_enable_show, ls_enable_store),
+};
+
+static struct device_attribute proximity_attr[] = {
+	__ATTR(enable, 0664, ps_adc_show, ps_enable_store),
+	__ATTR(ps_parameters, 0664,
+			ps_parameters_show, ps_parameters_store),
+	__ATTR(ps_conf, 0664, ps_conf_show, ps_conf_store),
+	__ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store),
+	__ATTR(ps_thd, 0664, ps_thd_show, ps_thd_store),
+	__ATTR(poll_delay, 0664, ps_poll_delay_show,
+			ps_poll_delay_store),
+	__ATTR(ls_flevel, 0664, ls_fLevel_show, ls_fLevel_store),
+};
+
 static int cm36283_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
@@ -1633,97 +1708,35 @@
 		goto err_psensor_setup;
 	}
 
-	lpi->cm36283_class = class_create(THIS_MODULE, "optical_sensors");
-	if (IS_ERR(lpi->cm36283_class)) {
-		ret = PTR_ERR(lpi->cm36283_class);
-		lpi->cm36283_class = NULL;
-		goto err_create_class;
+	ret = create_sysfs_interfaces(&lpi->ls_input_dev->dev, light_attr,
+			ARRAY_SIZE(light_attr));
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to create sysfs\n");
+		goto err_input_cleanup;
 	}
 
-	lpi->ls_dev = device_create(lpi->cm36283_class,
-				NULL, 0, "%s", "lightsensor");
-	if (unlikely(IS_ERR(lpi->ls_dev))) {
-		ret = PTR_ERR(lpi->ls_dev);
-		lpi->ls_dev = NULL;
-		goto err_create_ls_device;
+	ret = create_sysfs_interfaces(&lpi->ps_input_dev->dev, proximity_attr,
+			ARRAY_SIZE(proximity_attr));
+	if (ret < 0) {
+		dev_err(&client->dev, "failed to create sysfs\n");
+		goto err_light_sysfs_cleanup;
 	}
 
-	/* register the attributes */
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_adc);
+	lpi->als_cdev = sensors_light_cdev;
+	lpi->als_cdev.sensors_enable = ls_enable_set;
+	lpi->als_cdev.sensors_poll_delay = ls_poll_delay_set;
+	lpi->als_cdev.min_delay = CM36283_LS_MIN_POLL_DELAY * 1000;
+
+	lpi->ps_cdev = sensors_proximity_cdev;
+	lpi->ps_cdev.sensors_enable = ps_enable_set;
+	lpi->ps_cdev.sensors_poll_delay = ps_poll_delay_set;
+	lpi->ps_cdev.min_delay = CM36283_PS_MIN_POLL_DELAY * 1000;
+
+	ret = sensors_classdev_register(&client->dev, &lpi->als_cdev);
 	if (ret)
-		goto err_create_ls_device_file;
+		goto err_proximity_sysfs_cleanup;
 
-	/* register the attributes */
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_auto);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	/* register the attributes */
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_kadc);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_gadc);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_adc_table);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_conf);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_flevel);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	ret = device_create_file(lpi->ls_dev, &dev_attr_ls_poll_delay);
-	if (ret)
-		goto err_create_ls_device_file;
-
-	lpi->ps_dev = device_create(lpi->cm36283_class,
-				NULL, 0, "%s", "proximity");
-	if (unlikely(IS_ERR(lpi->ps_dev))) {
-		ret = PTR_ERR(lpi->ps_dev);
-		lpi->ps_dev = NULL;
-		goto err_create_ps_device;
-	}
-
-	/* register the attributes */
-	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_adc);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	ret = device_create_file(lpi->ps_dev,
-		&dev_attr_ps_parameters);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	/* register the attributes */
-	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_conf);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	/* register the attributes */
-	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_thd);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_hw);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	ret = device_create_file(lpi->ps_dev, &dev_attr_ps_poll_delay);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	ret = sensors_classdev_register(&client->dev, &sensors_light_cdev);
-	if (ret)
-		goto err_create_ps_device_file;
-
-	ret = sensors_classdev_register(&client->dev, &sensors_proximity_cdev);
+	ret = sensors_classdev_register(&client->dev, &lpi->ps_cdev);
 	if (ret)
 		goto err_create_class_sysfs;
 
@@ -1734,20 +1747,17 @@
 
 	return ret;
 err_create_class_sysfs:
-	sensors_classdev_unregister(&sensors_light_cdev);
-err_create_ps_device_file:
-	device_unregister(lpi->ps_dev);
-err_create_ps_device:
-err_create_ls_device_file:
-	device_unregister(lpi->ls_dev);
-err_create_ls_device:
-	class_destroy(lpi->cm36283_class);
-err_create_class:
-	misc_deregister(&psensor_misc);
+	sensors_classdev_unregister(&lpi->als_cdev);
+err_proximity_sysfs_cleanup:
+	remove_sysfs_interfaces(&lpi->ps_input_dev->dev, proximity_attr,
+			ARRAY_SIZE(proximity_attr));
+err_light_sysfs_cleanup:
+	remove_sysfs_interfaces(&lpi->ls_input_dev->dev, light_attr,
+			ARRAY_SIZE(light_attr));
+err_input_cleanup:
 	input_unregister_device(lpi->ps_input_dev);
 	input_free_device(lpi->ps_input_dev);
 err_psensor_setup:
-	misc_deregister(&lightsensor_misc);
 	input_unregister_device(lpi->ls_input_dev);
 	input_free_device(lpi->ls_input_dev);
 err_lightsensor_setup:
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
new file mode 100644
index 0000000..83ba652
--- /dev/null
+++ b/drivers/input/misc/hbtp_input.c
@@ -0,0 +1,477 @@
+
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/hbtp_input.h>
+#include <linux/input/mt.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include "../input-compat.h"
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#endif
+
+#define HBTP_INPUT_NAME			"hbtp_input"
+#define HBTP_AFE_LOAD_UA		150000
+#define HBTP_AFE_VTG_MIN_UV		2700000
+#define HBTP_AFE_VTG_MAX_UV		3300000
+
+struct hbtp_data {
+	struct platform_device *pdev;
+	struct input_dev *input_dev;
+	s32 count;
+	bool touch_status[HBTP_MAX_FINGER];
+#if defined(CONFIG_FB)
+	struct notifier_block fb_notif;
+#endif
+	struct regulator *vcc_ana;
+};
+
+static struct hbtp_data *hbtp;
+
+#if defined(CONFIG_FB)
+static int fb_notifier_callback(struct notifier_block *self,
+				 unsigned long event, void *data)
+{
+	int blank;
+	struct fb_event *evdata = data;
+	struct hbtp_data *hbtp_data =
+		container_of(self, struct hbtp_data, fb_notif);
+
+	if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+		hbtp_data && hbtp_data->input_dev) {
+		blank = *(int *)(evdata->data);
+		if (blank == FB_BLANK_UNBLANK)
+			kobject_uevent(&hbtp_data->input_dev->dev.kobj,
+					KOBJ_ONLINE);
+		else if (blank == FB_BLANK_POWERDOWN)
+			kobject_uevent(&hbtp_data->input_dev->dev.kobj,
+					KOBJ_OFFLINE);
+	}
+
+	return 0;
+}
+#endif
+
+static int hbtp_input_open(struct inode *inode, struct file *file)
+{
+	if (hbtp->count) {
+		pr_err("%s is busy\n", HBTP_INPUT_NAME);
+		return -EBUSY;
+	}
+	hbtp->count++;
+
+	return 0;
+}
+
+static int hbtp_input_release(struct inode *inode, struct file *file)
+{
+	if (!hbtp->count) {
+		pr_err("%s wasn't opened\n", HBTP_INPUT_NAME);
+		return -ENOTTY;
+	}
+	hbtp->count--;
+
+	return 0;
+}
+
+static int hbtp_input_create_input_dev(struct hbtp_input_absinfo *absinfo)
+{
+	struct input_dev *input_dev;
+	struct hbtp_input_absinfo *abs;
+	int error;
+	int i;
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		pr_err("%s: input_allocate_device failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	kfree(input_dev->name);
+	input_dev->name = kstrndup(HBTP_INPUT_NAME, sizeof(HBTP_INPUT_NAME),
+					GFP_KERNEL);
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+	/* For multi touch */
+	input_mt_init_slots(input_dev, HBTP_MAX_FINGER);
+	for (i = 0; i <= ABS_MT_LAST - ABS_MT_FIRST; i++) {
+		abs = absinfo + i;
+		if (abs->active)
+			input_set_abs_params(input_dev, abs->code,
+					abs->minimum, abs->maximum, 0, 0);
+	}
+
+	error = input_register_device(input_dev);
+	if (error) {
+		pr_err("%s: input_register_device failed\n", __func__);
+		goto err_input_reg_dev;
+	}
+
+	hbtp->input_dev = input_dev;
+	return 0;
+
+err_input_reg_dev:
+	input_free_device(input_dev);
+
+	return error;
+}
+
+static int hbtp_input_report_events(struct hbtp_data *hbtp_data,
+				struct hbtp_input_mt *mt_data)
+{
+	int i;
+	struct hbtp_input_touch *tch;
+
+	for (i = 0; i < HBTP_MAX_FINGER; i++) {
+		tch = &(mt_data->touches[i]);
+		if (tch->active || hbtp_data->touch_status[i]) {
+			input_mt_slot(hbtp_data->input_dev, i);
+			input_mt_report_slot_state(hbtp_data->input_dev,
+					MT_TOOL_FINGER, tch->active);
+
+			if (tch->active) {
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_TOOL_TYPE,
+						tch->tool);
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_TOUCH_MAJOR,
+						tch->major);
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_TOUCH_MINOR,
+						tch->minor);
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_ORIENTATION,
+						tch->orientation);
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_PRESSURE,
+						tch->pressure);
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_POSITION_X,
+						tch->x);
+				input_report_abs(hbtp_data->input_dev,
+						ABS_MT_POSITION_Y,
+						tch->y);
+			}
+			hbtp_data->touch_status[i] = tch->active;
+		}
+	}
+
+	input_report_key(hbtp->input_dev, BTN_TOUCH, mt_data->num_touches > 0);
+	input_sync(hbtp->input_dev);
+
+	return 0;
+}
+
+static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
+{
+	return (regulator_count_voltages(reg) > 0) ?
+		regulator_set_optimum_mode(reg, load_uA) : 0;
+}
+
+static int hbtp_pdev_power_on(struct hbtp_data *hbtp, bool on)
+{
+	int ret, error;
+
+	if (!hbtp->vcc_ana) {
+		pr_err("%s: regulator is not available\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!on)
+		goto reg_off;
+
+	ret = reg_set_optimum_mode_check(hbtp->vcc_ana, HBTP_AFE_LOAD_UA);
+	if (ret < 0) {
+		pr_err("%s: Regulator vcc_ana set_opt failed rc=%d\n",
+			__func__, ret);
+		return -EINVAL;
+	}
+
+	ret = regulator_enable(hbtp->vcc_ana);
+	if (ret) {
+		pr_err("%s: Regulator vcc_ana enable failed rc=%d\n",
+			__func__, ret);
+		error = -EINVAL;
+		goto error_reg_en_vcc_ana;
+	}
+
+	return 0;
+
+error_reg_en_vcc_ana:
+	reg_set_optimum_mode_check(hbtp->vcc_ana, 0);
+	return error;
+
+reg_off:
+	reg_set_optimum_mode_check(hbtp->vcc_ana, 0);
+	regulator_disable(hbtp->vcc_ana);
+	return 0;
+}
+
+static long hbtp_input_ioctl_handler(struct file *file, unsigned int cmd,
+				 unsigned long arg, void __user *p)
+{
+	int error;
+	struct hbtp_input_mt mt_data;
+	struct hbtp_input_absinfo absinfo[ABS_MT_LAST - ABS_MT_FIRST + 1];
+	enum hbtp_afe_power_cmd power_cmd;
+
+	switch (cmd) {
+	case HBTP_SET_ABSPARAM:
+		if (hbtp && hbtp->input_dev) {
+			pr_err("%s: The input device is already created\n",
+				__func__);
+			return 0;
+		}
+
+		if (copy_from_user(absinfo, (void *)arg,
+					sizeof(struct hbtp_input_absinfo) *
+					(ABS_MT_LAST - ABS_MT_FIRST + 1))) {
+			pr_err("%s: Error copying data for ABS param\n",
+				__func__);
+			return -EFAULT;
+		}
+
+		error = hbtp_input_create_input_dev(absinfo);
+		if (error)
+			pr_err("%s, hbtp_input_create_input_dev failed (%d)\n",
+				__func__, error);
+		break;
+
+	case HBTP_SET_TOUCHDATA:
+		if (!hbtp || !hbtp->input_dev) {
+			pr_err("%s: The input device hasn't been created\n",
+				__func__);
+			return -EFAULT;
+		}
+
+		if (copy_from_user(&mt_data, (void *)arg,
+					sizeof(struct hbtp_input_mt))) {
+			pr_err("%s: Error copying data\n", __func__);
+			return -EFAULT;
+		}
+
+		hbtp_input_report_events(hbtp, &mt_data);
+		error = 0;
+		break;
+
+	case HBTP_SET_POWERSTATE:
+		if (!hbtp || !hbtp->input_dev) {
+			pr_err("%s: The input device hasn't been created\n",
+				__func__);
+			return -EFAULT;
+		}
+
+		if (copy_from_user(&power_cmd, (void *)arg,
+					sizeof(enum hbtp_afe_power_cmd))) {
+			pr_err("%s: Error copying data\n", __func__);
+			return -EFAULT;
+		}
+
+		switch (power_cmd) {
+		case HBTP_AFE_POWER_ON:
+			error = hbtp_pdev_power_on(hbtp, true);
+			if (error)
+				pr_err("%s: failed to power on\n", __func__);
+			break;
+		case HBTP_AFE_POWER_OFF:
+			error = hbtp_pdev_power_on(hbtp, false);
+			if (error)
+				pr_err("%s: failed to power off\n", __func__);
+			break;
+		default:
+			pr_err("%s: Unsupported command for power state, %d\n",
+				__func__, power_cmd);
+			return -EINVAL;
+		}
+		break;
+
+	default:
+		pr_err("%s: Unsupported ioctl command %u\n", __func__, cmd);
+		error = -EINVAL;
+		break;
+	}
+
+	return error;
+}
+
+static long hbtp_input_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	return hbtp_input_ioctl_handler(file, cmd, arg, (void __user *)arg);
+}
+
+#ifdef CONFIG_COMPAT
+static long hbtp_input_compat_ioctl(struct file *file, unsigned int cmd,
+					unsigned long arg)
+{
+	return hbtp_input_ioctl_handler(file, cmd, arg, compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations hbtp_input_fops = {
+	.owner		= THIS_MODULE,
+	.open		= hbtp_input_open,
+	.release	= hbtp_input_release,
+	.unlocked_ioctl	= hbtp_input_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= hbtp_input_compat_ioctl,
+#endif
+};
+
+static struct miscdevice hbtp_input_misc = {
+	.fops		= &hbtp_input_fops,
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= HBTP_INPUT_NAME,
+};
+MODULE_ALIAS_MISCDEV(MISC_DYNAMIC_MINOR);
+MODULE_ALIAS("devname:" HBTP_INPUT_NAME);
+
+static int __devinit hbtp_pdev_probe(struct platform_device *pdev)
+{
+	int ret, error;
+	struct regulator *vcc_ana;
+
+	vcc_ana = regulator_get(&pdev->dev, "vcc_ana");
+	if (IS_ERR(vcc_ana)) {
+		ret = PTR_ERR(vcc_ana);
+		pr_err("%s: Regulator get failed vcc_ana rc=%d\n",
+			__func__, ret);
+		return -EINVAL;
+	}
+
+	if (regulator_count_voltages(vcc_ana) > 0) {
+		ret = regulator_set_voltage(vcc_ana,
+				HBTP_AFE_VTG_MIN_UV, HBTP_AFE_VTG_MAX_UV);
+		if (ret) {
+			pr_err("%s: regulator set_vtg failed rc=%d\n",
+				__func__, ret);
+			error = -EINVAL;
+			goto error_set_vtg_vcc_ana;
+		}
+	}
+
+	hbtp->vcc_ana = vcc_ana;
+	hbtp->pdev = pdev;
+	return 0;
+
+error_set_vtg_vcc_ana:
+	regulator_put(vcc_ana);
+
+	return error;
+};
+
+static int __devexit hbtp_pdev_remove(struct platform_device *pdev)
+{
+	if (hbtp->vcc_ana) {
+		hbtp_pdev_power_on(hbtp, false);
+		regulator_put(hbtp->vcc_ana);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id hbtp_match_table[] = {
+	{ .compatible = "qcom,hbtp",},
+	{ },
+};
+#else
+#define hbtp_match_table NULL
+#endif
+
+static struct platform_driver hbtp_pdev_driver = {
+	.probe		= hbtp_pdev_probe,
+	.remove		= __devexit_p(hbtp_pdev_remove),
+	.driver		= {
+		.name		= "hbtp",
+		.owner		= THIS_MODULE,
+		.of_match_table = hbtp_match_table,
+	},
+};
+
+static int __init hbtp_init(void)
+{
+	int error;
+
+	hbtp = kzalloc(sizeof(struct hbtp_data), GFP_KERNEL);
+	if (!hbtp)
+		return -ENOMEM;
+
+	error = misc_register(&hbtp_input_misc);
+	if (error) {
+		pr_err("%s: misc_register failed\n", HBTP_INPUT_NAME);
+		goto err_misc_reg;
+	}
+
+#if defined(CONFIG_FB)
+	hbtp->fb_notif.notifier_call = fb_notifier_callback;
+	error = fb_register_client(&hbtp->fb_notif);
+	if (error) {
+		pr_err("%s: Unable to register fb_notifier: %d\n",
+			HBTP_INPUT_NAME, error);
+		goto err_fb_reg;
+	}
+#endif
+
+	error = platform_driver_register(&hbtp_pdev_driver);
+	if (error) {
+		pr_err("Failed to register platform driver: %d\n", error);
+		goto err_platform_drv_reg;
+	}
+
+	return 0;
+
+err_platform_drv_reg:
+#if defined(CONFIG_FB)
+	fb_unregister_client(&hbtp->fb_notif);
+err_fb_reg:
+#endif
+	misc_deregister(&hbtp_input_misc);
+err_misc_reg:
+	kfree(hbtp);
+
+	return error;
+}
+
+static void __exit hbtp_exit(void)
+{
+	misc_deregister(&hbtp_input_misc);
+	if (hbtp->input_dev)
+		input_unregister_device(hbtp->input_dev);
+
+#if defined(CONFIG_FB)
+	fb_unregister_client(&hbtp->fb_notif);
+#endif
+
+	platform_driver_unregister(&hbtp_pdev_driver);
+
+	kfree(hbtp);
+}
+
+MODULE_DESCRIPTION("Kernel driver to support host based touch processing");
+MODULE_LICENSE("GPLv2");
+
+module_init(hbtp_init);
+module_exit(hbtp_exit);
diff --git a/drivers/input/misc/kxtj9.c b/drivers/input/misc/kxtj9.c
index f5d8441..0883ac5 100644
--- a/drivers/input/misc/kxtj9.c
+++ b/drivers/input/misc/kxtj9.c
@@ -90,9 +90,13 @@
 	.max_range = "19.6",
 	.resolution = "0.01",
 	.sensor_power = "0.2",
-	.min_delay = 2000,
+	.min_delay = 2000,	/* microsecond */
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = 200,	/* millisecond */
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 static const struct {
@@ -124,6 +128,7 @@
 	bool	power_enabled;
 	struct regulator *vdd;
 	struct regulator *vio;
+	struct sensors_classdev cdev;
 };
 
 static int kxtj9_i2c_read(struct kxtj9_data *tj9, u8 addr, u8 *data, int len)
@@ -486,6 +491,36 @@
 	return 0;
 }
 
+static int kxtj9_enable_set(struct sensors_classdev *sensors_cdev,
+					unsigned int enabled)
+{
+	struct kxtj9_data *tj9 = container_of(sensors_cdev,
+					struct kxtj9_data, cdev);
+	struct input_dev *input_dev = tj9->input_dev;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (enabled == 0) {
+		disable_irq(tj9->client->irq);
+		kxtj9_disable(tj9);
+		tj9->enable = false;
+	} else if (enabled == 1) {
+		if (!kxtj9_enable(tj9)) {
+			enable_irq(tj9->client->irq);
+			tj9->enable = true;
+		}
+	} else {
+		dev_err(&tj9->client->dev,
+			"Invalid value of input, input=%d\n", enabled);
+		mutex_unlock(&input_dev->mutex);
+		return -EINVAL;
+	}
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
 static ssize_t kxtj9_enable_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -501,31 +536,16 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
-	struct input_dev *input_dev = tj9->input_dev;
 	unsigned long data;
 	int error;
 
 	error = kstrtoul(buf, 10, &data);
-	if (error)
+	if (error < 0)
 		return error;
-	mutex_lock(&input_dev->mutex);
 
-	if (data == 0) {
-		disable_irq(client->irq);
-		kxtj9_disable(tj9);
-		tj9->enable = false;
-	} else if (data == 1) {
-		if (!kxtj9_enable(tj9)) {
-			enable_irq(client->irq);
-			tj9->enable = true;
-		}
-	} else {
-		dev_err(&tj9->client->dev,
-			"Invalid value of input, input=%ld\n", data);
-	}
-
-	mutex_unlock(&input_dev->mutex);
-
+	error = kxtj9_enable_set(&tj9->cdev, data);
+	if (error < 0)
+		return error;
 	return count;
 }
 
@@ -542,6 +562,29 @@
  * will be responsible for retrieving data from the input node at the desired
  * interval.
  */
+static int kxtj9_poll_delay_set(struct sensors_classdev *sensors_cdev,
+					unsigned int delay_msec)
+{
+	struct kxtj9_data *tj9 = container_of(sensors_cdev,
+					struct kxtj9_data, cdev);
+	struct input_dev *input_dev = tj9->input_dev;
+
+	/* Lock the device to prevent races with open/close (and itself) */
+	mutex_lock(&input_dev->mutex);
+
+	if (tj9->enable)
+		disable_irq(tj9->client->irq);
+
+	tj9->last_poll_interval = max(delay_msec, tj9->pdata.min_interval);
+
+	if (tj9->enable) {
+		kxtj9_update_odr(tj9, tj9->last_poll_interval);
+		enable_irq(tj9->client->irq);
+	}
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
 
 /* Returns currently selected poll interval (in ms) */
 static ssize_t kxtj9_get_poll_delay(struct device *dev,
@@ -560,7 +603,6 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct kxtj9_data *tj9 = i2c_get_clientdata(client);
-	struct input_dev *input_dev = tj9->input_dev;
 	unsigned int interval;
 	int error;
 
@@ -568,24 +610,9 @@
 	if (error < 0)
 		return error;
 
-	/* Lock the device to prevent races with open/close (and itself) */
-	mutex_lock(&input_dev->mutex);
-
-	if (tj9->enable)
-		disable_irq(client->irq);
-
-	/*
-	 * Set current interval to the greater of the minimum interval or
-	 * the requested interval
-	 */
-	tj9->last_poll_interval = max(interval, tj9->pdata.min_interval);
-
-	if (tj9->enable) {
-		kxtj9_update_odr(tj9, tj9->last_poll_interval);
-		enable_irq(client->irq);
-	}
-	mutex_unlock(&input_dev->mutex);
-
+	error = kxtj9_poll_delay_set(&tj9->cdev, interval);
+	if (error < 0)
+		return error;
 	return count;
 }
 
@@ -602,7 +629,6 @@
 	.attrs = kxtj9_attributes
 };
 
-
 #ifdef CONFIG_INPUT_KXTJ9_POLLED_MODE
 static void kxtj9_poll(struct input_polled_dev *dev)
 {
@@ -858,7 +884,13 @@
 	tj9->ctrl_reg1 = tj9->pdata.res_ctl | tj9->pdata.g_range;
 	tj9->last_poll_interval = tj9->pdata.init_interval;
 
-	err = sensors_classdev_register(&client->dev, &sensors_cdev);
+	tj9->cdev = sensors_cdev;
+	/* The min_delay is used by userspace and the unit is microsecond. */
+	tj9->cdev.min_delay = tj9->pdata.min_interval * 1000;
+	tj9->cdev.delay_msec = tj9->pdata.init_interval;
+	tj9->cdev.sensors_enable = kxtj9_enable_set;
+	tj9->cdev.sensors_poll_delay = kxtj9_poll_delay_set;
+	err = sensors_classdev_register(&client->dev, &tj9->cdev);
 	if (err) {
 		dev_err(&client->dev, "class device create failed: %d\n", err);
 		goto err_power_off;
@@ -871,7 +903,7 @@
 
 		err = kxtj9_setup_input_device(tj9);
 		if (err)
-			goto err_power_off;
+			goto err_class_sysfs;
 
 		err = request_threaded_irq(client->irq, NULL, kxtj9_isr,
 					   IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -892,7 +924,7 @@
 	} else {
 		err = kxtj9_setup_polled_device(tj9);
 		if (err)
-			goto err_power_off;
+			goto err_class_sysfs;
 	}
 
 	dev_dbg(&client->dev, "%s: kxtj9_probe OK.\n", __func__);
@@ -903,6 +935,8 @@
 	free_irq(client->irq, tj9);
 err_destroy_input:
 	input_unregister_device(tj9->input_dev);
+err_class_sysfs:
+	sensors_classdev_unregister(&tj9->cdev);
 err_power_off:
 	kxtj9_device_power_off(tj9);
 err_power_deinit:
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index d5053eb..d708d94 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -2,7 +2,7 @@
  *  mma8x5x.c - Linux kernel modules for 3-Axis Orientation/Motion
  *  Detection Sensor MMA8451/MMA8452/MMA8453
  *
- *  Copyright (c) 2013, The Linux Foundation. All Rights Reserved.
+ *  Copyright (c) 2013-2014, The Linux Foundation. All Rights Reserved.
  *  Linux Foundation chooses to take subject only to the GPLv2 license
  *  terms, and distributes only under these terms.
  *  Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
@@ -30,6 +30,7 @@
 #include <linux/sensors.h>
 #include <linux/regulator/consumer.h>
 #include <linux/of_gpio.h>
+#include <linux/irq.h>
 
 #define ACCEL_INPUT_DEV_NAME		"accelerometer"
 #define MMA8451_ID			0x1A
@@ -38,9 +39,9 @@
 #define MMA8652_ID			0x4A
 #define MMA8653_ID			0x5A
 
-
+/* Polling delay in msecs */
 #define POLL_INTERVAL_MIN	1
-#define POLL_INTERVAL_MAX	500
+#define POLL_INTERVAL_MAX	10000
 #define POLL_INTERVAL		100 /* msecs */
 
 /* if sensor is standby ,set POLL_STOP_TIME to slow down the poll */
@@ -68,8 +69,19 @@
 	.min_delay = 2000,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = POLL_INTERVAL,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
+#define MMA_WAKE_CFG		0x02
+#define MMA_INT_EN_DRDY		0x01
+#define MMA_INT_EN_FF_MT	0x04
+#define MMA_INT_ROUTING_CFG	0x01
+
+#define MMA_POWER_CFG_MASK	0xFE
+
 struct sensor_regulator {
 	struct regulator *vreg;
 	const char *name;
@@ -82,6 +94,23 @@
 	{NULL, "vio", 1800000, 1800000},
 };
 
+struct mma_odr_selection_table {
+	u32 odr_cfg;
+	u32 delay_bottom;
+	u32 delay_top;
+};
+
+static struct mma_odr_selection_table mma_odr_table[] = {
+	{0x00, 0, 1500},
+	{0x08, 1501, 3500},
+	{0x10, 3501, 7500},
+	{0x18, 7501, 15000},
+	{0x20, 15001, 50000},
+	{0x28, 50001, 120000},
+	{0x30, 120001, 400000},
+	{0x38, 400001, 10000000},
+};
+
 /* register enum for mma8x5x registers */
 enum {
 	MMA8X5X_STATUS = 0x00,
@@ -161,13 +190,17 @@
 struct mma8x5x_data {
 	struct i2c_client *client;
 	struct input_polled_dev *poll_dev;
+	struct input_dev *idev;
 	struct mutex data_lock;
+	struct sensors_classdev cdev;
 	int active;
 	int position;
 	u8 chip_id;
 	int mode;
 	int int_pin;
 	u32 int_flags;
+	int poll_delay;
+	bool use_int;
 };
 /* Addresses scanned */
 static const unsigned short normal_i2c[] = {0x1c, 0x1d, I2C_CLIENT_END};
@@ -196,7 +229,7 @@
 	{{ 0,  1,  0}, { 1,  0,	0}, {0, 0,  -1} },
 	{{ 1,  0,  0}, { 0, -1,	0}, {0, 0,  -1} },
 };
-
+static struct mma8x5x_data *drv_data;
 static int mma8x5x_config_regulator(struct i2c_client *client, bool on)
 {
 	int rc = 0, i;
@@ -342,6 +375,98 @@
 	return -EIO;
 }
 
+static int mma8x5x_delay2odr(u32 delay_ms)
+{
+	int i;
+	u32 delay_us;
+
+	delay_us = delay_ms * 1000;
+	for (i = 0; i < sizeof(mma_odr_table) /
+		sizeof(struct mma_odr_selection_table); i++) {
+		if ((delay_us <= mma_odr_table[i].delay_top) &&
+			(delay_us > mma_odr_table[i].delay_bottom))
+			break;
+	}
+	if (i < sizeof(mma_odr_table) /
+		sizeof(struct mma_odr_selection_table))
+		return mma_odr_table[i].odr_cfg;
+	else
+		return -EINVAL;
+}
+
+static int mma8x5x_device_set_odr(struct i2c_client *client, u32 delay_ms)
+{
+	int result;
+	u8 val;
+
+	result = mma8x5x_delay2odr(delay_ms);
+	if (result < 0)
+		goto out;
+	val = (u8)result;
+
+	result = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
+	if (result < 0)
+		goto out;
+
+	val = (u8)result | val;
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,
+					   (val & MMA_POWER_CFG_MASK));
+	if (result < 0)
+		goto out;
+
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG4,
+					   MMA_INT_EN_DRDY);
+	if (result < 0)
+		goto out;
+
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG5,
+					   MMA_INT_ROUTING_CFG);
+	if (result < 0)
+		goto out;
+
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1,
+					   val);
+	if (result < 0)
+		goto out;
+
+	return 0;
+out:
+	dev_err(&client->dev, "error when set ODR mma8x5x:(%d)", result);
+	return result;
+}
+static int mma8x5x_device_int_init(struct i2c_client *client)
+{
+	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+	int result;
+	int val;
+
+	result = mma8x5x_device_set_odr(client, pdata->poll_delay);
+	if (result < 0)
+		goto out;
+
+	val = MMA_WAKE_CFG;
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG3,
+					   val);
+	if (result < 0)
+		goto out;
+
+	val = MMA_INT_EN_DRDY;
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG4,
+					   val);
+	if (result < 0)
+		goto out;
+
+	val = MMA_INT_ROUTING_CFG;
+	result = i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG5,
+					   val);
+	if (result < 0)
+		goto out;
+
+	return 0;
+out:
+	dev_err(&client->dev, "error when int init mma8x5x:(%d)", result);
+	return result;
+}
 static int mma8x5x_read_data(struct i2c_client *client,
 		struct mma8x5x_data_axis *data)
 {
@@ -349,7 +474,7 @@
 	int ret;
 
 	ret = i2c_smbus_read_i2c_block_data(client,
-					    MMA8X5X_OUT_X_MSB, 7, tmp_data);
+					MMA8X5X_OUT_X_MSB, 7, tmp_data);
 	if (ret < MMA8X5X_BUF_SIZE) {
 		dev_err(&client->dev, "i2c block read failed\n");
 		return -EIO;
@@ -371,7 +496,7 @@
 		goto out;
 	} else {
 		if (poll_dev->poll_interval == POLL_STOP_TIME)
-			poll_dev->poll_interval = POLL_INTERVAL;
+			poll_dev->poll_interval = pdata->poll_delay;
 	}
 	if (mma8x5x_read_data(pdata->client, &data) != 0)
 		goto out;
@@ -390,15 +515,118 @@
 	mma8x5x_report_data(pdata);
 }
 
+static irqreturn_t mma8x5x_interrupt(int vec, void *data)
+{
+	struct i2c_client *client = (struct i2c_client *)data;
+	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+	struct input_dev *idev = pdata->idev;
+	struct mma8x5x_data_axis data_axis;
+
+	mutex_lock(&pdata->data_lock);
+
+	if (mma8x5x_read_data(pdata->client, &data_axis) != 0)
+		goto out;
+	mma8x5x_data_convert(pdata, &data_axis);
+	input_report_abs(idev, ABS_X, data_axis.x);
+	input_report_abs(idev, ABS_Y, data_axis.y);
+	input_report_abs(idev, ABS_Z, data_axis.z);
+	input_sync(idev);
+out:
+	mutex_unlock(&pdata->data_lock);
+
+	return IRQ_HANDLED;
+}
+
+static int mma8x5x_enable_set(struct sensors_classdev *sensors_cdev,
+		unsigned int enable)
+{
+	struct mma8x5x_data *pdata = container_of(sensors_cdev,
+			struct mma8x5x_data, cdev);
+	struct i2c_client *client = pdata->client;
+	int ret;
+	u8 val = 0;
+
+	mutex_lock(&pdata->data_lock);
+	if (enable) {
+		if (pdata->active & MMA_SHUTTEDDOWN) {
+			ret = mma8x5x_config_regulator(client, 1);
+			if (ret)
+				goto err_failed;
+
+			ret = mma8x5x_device_start(client);
+			if (ret)
+				goto err_failed;
+
+			ret = mma8x5x_device_set_odr(client, pdata->poll_delay);
+			if (ret)
+				goto err_failed;
+			pdata->active &= ~MMA_SHUTTEDDOWN;
+		}
+		if (pdata->active == MMA_STANDBY) {
+			val = i2c_smbus_read_byte_data(client,
+					MMA8X5X_CTRL_REG1);
+			if (val < 0) {
+				dev_err(&client->dev, "read device state failed!");
+				ret = val;
+				goto err_failed;
+			}
+
+			ret = i2c_smbus_write_byte_data(client,
+					MMA8X5X_CTRL_REG1, val | 0x01);
+			if (ret) {
+				dev_err(&client->dev, "change device state failed!");
+				goto err_failed;
+			}
+			pdata->active = MMA_ACTIVED;
+			dev_dbg(&client->dev, "%s:mma enable setting active.\n",
+					__func__);
+		}
+	} else if (enable == 0) {
+		if (pdata->active == MMA_ACTIVED) {
+			val = i2c_smbus_read_byte_data(client,
+					MMA8X5X_CTRL_REG1);
+			if (val < 0) {
+				dev_err(&client->dev, "read device state failed!");
+				ret = val;
+				goto err_failed;
+			}
+
+			ret = i2c_smbus_write_byte_data(client,
+				MMA8X5X_CTRL_REG1, val & 0xFE);
+			if (ret) {
+				dev_err(&client->dev, "change device state failed!");
+				goto err_failed;
+			}
+
+			pdata->active = MMA_STANDBY;
+			dev_dbg(&client->dev, "%s:mma enable setting inactive.\n",
+					__func__);
+		}
+		if (!mma8x5x_config_regulator(client, 0))
+			pdata->active |= MMA_SHUTTEDDOWN;
+	}
+	mutex_unlock(&pdata->data_lock);
+	return 0;
+
+err_failed:
+	mutex_unlock(&pdata->data_lock);
+	return ret;
+}
+
 static ssize_t mma8x5x_enable_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
-	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
-	struct i2c_client *client = pdata->client;
+	struct mma8x5x_data *pdata = drv_data;
+	struct i2c_client *client;
 	u8 val;
 	int enable;
 
+	if (!pdata) {
+		dev_err(dev, "Invalid driver private data!");
+		return -EINVAL;
+	}
+	client = pdata->client;
+
 	mutex_lock(&pdata->data_lock);
 	val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
 	if ((val & 0x01) && pdata->active == MMA_ACTIVED)
@@ -413,86 +641,35 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
-	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
-	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
-	struct i2c_client *client = pdata->client;
+	struct mma8x5x_data *pdata = drv_data;
+	struct i2c_client *client;
 	int ret;
 	unsigned long enable;
-	u8 val = 0;
 
+	if (!pdata) {
+		dev_err(dev, "Invalid driver private data!");
+		return -EINVAL;
+	}
+	client = pdata->client;
 	ret = kstrtoul(buf, 10, &enable);
 	if (ret)
 		return ret;
-	mutex_lock(&pdata->data_lock);
 	enable = (enable > 0) ? 1 : 0;
-	if (enable) {
-		if (pdata->active & MMA_SHUTTEDDOWN) {
-			ret = mma8x5x_config_regulator(client, 1);
-			if (ret)
-				goto err_failed;
-
-			ret = mma8x5x_device_start(client);
-			if (ret)
-				goto err_failed;
-
-			pdata->active &= ~MMA_SHUTTEDDOWN;
-		}
-		if (pdata->active == MMA_STANDBY) {
-			val = i2c_smbus_read_byte_data(client,
-					MMA8X5X_CTRL_REG1);
-			if (val < 0) {
-				dev_err(dev, "read device state failed!");
-				ret = val;
-				goto err_failed;
-			}
-
-			ret = i2c_smbus_write_byte_data(client,
-					MMA8X5X_CTRL_REG1, val | 0x01);
-			if (ret) {
-				dev_err(dev, "change device state failed!");
-				goto err_failed;
-			}
-			pdata->active = MMA_ACTIVED;
-			dev_dbg(dev, "%s:mma enable setting active.\n",
-					__func__);
-		}
-	} else if (enable == 0) {
-		if (pdata->active == MMA_ACTIVED) {
-			val = i2c_smbus_read_byte_data(client,
-					MMA8X5X_CTRL_REG1);
-			if (val < 0) {
-				dev_err(dev, "read device state failed!");
-				ret = val;
-				goto err_failed;
-			}
-
-			ret = i2c_smbus_write_byte_data(client,
-				MMA8X5X_CTRL_REG1, val & 0xFE);
-			if (ret) {
-				dev_err(dev, "change device state failed!");
-				goto err_failed;
-			}
-
-			pdata->active = MMA_STANDBY;
-			dev_dbg(dev, "%s:mma enable setting inactive.\n",
-					__func__);
-		}
-		if (!mma8x5x_config_regulator(client, 0))
-			pdata->active |= MMA_SHUTTEDDOWN;
-	}
-	mutex_unlock(&pdata->data_lock);
+	ret = mma8x5x_enable_set(&pdata->cdev, enable);
+	if (ret < 0)
+		return ret;
 	return count;
-
-err_failed:
-	mutex_unlock(&pdata->data_lock);
-	return ret;
 }
 static ssize_t mma8x5x_position_show(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
-	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
-	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+	struct mma8x5x_data *pdata = drv_data;
 	int position = 0;
+
+	if (!pdata) {
+		dev_err(dev, "Invalid driver private data!");
+		return -EINVAL;
+	}
 	mutex_lock(&pdata->data_lock);
 	position = pdata->position ;
 	mutex_unlock(&pdata->data_lock);
@@ -503,10 +680,14 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t count)
 {
-	struct input_polled_dev *poll_dev = dev_get_drvdata(dev);
-	struct mma8x5x_data *pdata = (struct mma8x5x_data *)(poll_dev->private);
+	struct mma8x5x_data *pdata = drv_data;
 	int position;
 	int ret;
+
+	if (!pdata) {
+		dev_err(dev, "Invalid driver private data!");
+		return -EINVAL;
+	}
 	ret = kstrtoint(buf, 10, &position);
 	if (ret)
 		return ret;
@@ -516,14 +697,79 @@
 	return count;
 }
 
+static int mma8x5x_poll_delay_set(struct sensors_classdev *sensors_cdev,
+		unsigned int delay_ms)
+{
+	struct mma8x5x_data *pdata = container_of(sensors_cdev,
+			struct mma8x5x_data, cdev);
+	int ret;
+
+	if (pdata->use_int) {
+		mutex_lock(&pdata->data_lock);
+		pdata->poll_delay = delay_ms;
+		ret = mma8x5x_device_set_odr(pdata->client, delay_ms);
+		mutex_unlock(&pdata->data_lock);
+		if (ret < 0)
+			return ret;
+	} else {
+		mutex_lock(&pdata->data_lock);
+		pdata->poll_delay = delay_ms;
+		pdata->poll_dev->poll_interval = pdata->poll_delay;
+		mutex_unlock(&pdata->data_lock);
+	}
+
+	return 0;
+}
+
+static ssize_t mma8x5x_poll_delay_show(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct mma8x5x_data *pdata = drv_data;
+
+	if (!pdata) {
+		dev_err(dev, "Invalid driver private data!");
+		return -EINVAL;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", pdata->poll_delay);
+}
+
+static ssize_t mma8x5x_poll_delay_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct mma8x5x_data *pdata = drv_data;
+	int delay;
+	int ret;
+
+	if (!pdata) {
+		dev_err(dev, "Invalid driver private data!");
+		return -EINVAL;
+	}
+	ret = kstrtoint(buf, 10, &delay);
+	if (ret)
+		return ret;
+	if (delay <= POLL_INTERVAL_MIN)
+		delay = POLL_INTERVAL_MIN;
+	if (delay > POLL_INTERVAL_MAX)
+		delay = POLL_INTERVAL_MAX;
+
+	mma8x5x_poll_delay_set(&pdata->cdev, delay);
+
+	return count;
+}
+
 static DEVICE_ATTR(enable, S_IWUSR | S_IRUGO,
 		   mma8x5x_enable_show, mma8x5x_enable_store);
 static DEVICE_ATTR(position, S_IWUSR | S_IRUGO,
 		   mma8x5x_position_show, mma8x5x_position_store);
+static DEVICE_ATTR(poll_delay, S_IWUSR | S_IRUGO,
+		   mma8x5x_poll_delay_show, mma8x5x_poll_delay_store);
 
 static struct attribute *mma8x5x_attributes[] = {
 	&dev_attr_enable.attr,
 	&dev_attr_position.attr,
+	&dev_attr_poll_delay.attr,
 	NULL
 };
 
@@ -567,6 +813,8 @@
 		return rc;
 	}
 
+	data->use_int = of_property_read_bool(np, "fsl,use-interrupt");
+
 	return 0;
 }
 
@@ -611,7 +859,7 @@
 	if (client->dev.of_node) {
 		result = mma8x5x_parse_dt(&client->dev, pdata);
 		if (result)
-			return result;
+			goto err_parse_dt;
 	} else {
 		pdata->position = CONFIG_SENSORS_MMA_POSITION;
 		pdata->int_pin = -1;
@@ -619,39 +867,96 @@
 	}
 
 	/* Initialize the MMA8X5X chip */
+	drv_data = pdata;
 	pdata->client = client;
 	pdata->chip_id = chip_id;
 	pdata->mode = MODE_2G;
+	pdata->poll_delay = POLL_STOP_TIME;
+	pdata->poll_dev = NULL;
 
 	mutex_init(&pdata->data_lock);
 	i2c_set_clientdata(client, pdata);
 	/* Initialize the MMA8X5X chip */
 	mma8x5x_device_init(client);
-	/* create the input poll device */
-	poll_dev = input_allocate_polled_device();
-	if (!poll_dev) {
-		result = -ENOMEM;
-		dev_err(&client->dev, "alloc poll device failed!\n");
-		goto err_alloc_poll_device;
-	}
-	poll_dev->poll = mma8x5x_dev_poll;
-	poll_dev->poll_interval = POLL_STOP_TIME;
-	poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
-	poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
-	poll_dev->private = pdata;
-	idev = poll_dev->input;
-	idev->name = ACCEL_INPUT_DEV_NAME;
-	idev->uniq = mma8x5x_id2name(pdata->chip_id);
-	idev->id.bustype = BUS_I2C;
-	idev->evbit[0] = BIT_MASK(EV_ABS);
-	input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
-	input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
-	input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
-	pdata->poll_dev = poll_dev;
-	result = input_register_polled_device(pdata->poll_dev);
-	if (result) {
-		dev_err(&client->dev, "register poll device failed!\n");
-		goto err_register_polled_device;
+	if (pdata->use_int) {
+		if (pdata->int_pin >= 0)
+			client->irq = gpio_to_irq(pdata->int_pin);
+
+		if (gpio_is_valid(pdata->int_pin)) {
+			result = gpio_request(pdata->int_pin,
+				"mma8x5x_irq_gpio");
+			if (result) {
+				dev_err(&client->dev, "irq gpio(%d) request failed",
+					pdata->int_pin);
+				goto err_request_gpio;
+			}
+			result = gpio_direction_input(pdata->int_pin);
+			if (result) {
+				dev_err(&client->dev,
+					"set_direction for irq gpio failed\n");
+				goto err_set_direction;
+			}
+		}
+		idev = input_allocate_device();
+		if (!idev) {
+			result = -ENOMEM;
+			dev_err(&client->dev, "alloc input device failed!\n");
+			goto err_alloc_poll_device;
+		}
+		input_set_drvdata(idev, pdata);
+		idev->name = ACCEL_INPUT_DEV_NAME;
+		idev->uniq = mma8x5x_id2name(pdata->chip_id);
+		idev->id.bustype = BUS_I2C;
+		idev->evbit[0] = BIT_MASK(EV_ABS);
+		input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
+		input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
+		input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
+		result = input_register_device(idev);
+		if (result) {
+			dev_err(&client->dev, "register input device failed!\n");
+			goto err_register_device;
+		}
+		pdata->idev = idev;
+		device_init_wakeup(&client->dev, true);
+		enable_irq_wake(client->irq);
+		result = request_threaded_irq(client->irq, NULL,
+			mma8x5x_interrupt,
+			IRQ_TYPE_EDGE_RISING | IRQF_ONESHOT | IRQF_NO_SUSPEND,
+			ACCEL_INPUT_DEV_NAME, (void *)client);
+		if (result) {
+			dev_err(&client->dev, "Could not allocate irq(%d) !\n",
+				client->irq);
+			goto err_register_irq;
+		}
+		mma8x5x_device_int_init(client);
+	} else {
+		/* create the input poll device */
+		poll_dev = input_allocate_polled_device();
+		if (!poll_dev) {
+			result = -ENOMEM;
+			dev_err(&client->dev, "alloc poll device failed!\n");
+			goto err_alloc_poll_device;
+		}
+		pdata->poll_dev = poll_dev;
+		pdata->idev = NULL;
+		poll_dev->poll = mma8x5x_dev_poll;
+		poll_dev->poll_interval = POLL_STOP_TIME;
+		poll_dev->poll_interval_min = POLL_INTERVAL_MIN;
+		poll_dev->poll_interval_max = POLL_INTERVAL_MAX;
+		poll_dev->private = pdata;
+		idev = poll_dev->input;
+		idev->name = ACCEL_INPUT_DEV_NAME;
+		idev->uniq = mma8x5x_id2name(pdata->chip_id);
+		idev->id.bustype = BUS_I2C;
+		idev->evbit[0] = BIT_MASK(EV_ABS);
+		input_set_abs_params(idev, ABS_X, -0x7fff, 0x7fff, 0, 0);
+		input_set_abs_params(idev, ABS_Y, -0x7fff, 0x7fff, 0, 0);
+		input_set_abs_params(idev, ABS_Z, -0x7fff, 0x7fff, 0, 0);
+		result = input_register_polled_device(pdata->poll_dev);
+		if (result) {
+			dev_err(&client->dev, "register poll device failed!\n");
+			goto err_register_device;
+		}
 	}
 	result = sysfs_create_group(&idev->dev.kobj, &mma8x5x_attr_group);
 	if (result) {
@@ -659,7 +964,12 @@
 		result = -EINVAL;
 		goto err_create_sysfs;
 	}
-	result = sensors_classdev_register(&client->dev, &sensors_cdev);
+	pdata->cdev = sensors_cdev;
+	pdata->cdev.min_delay = POLL_INTERVAL_MIN * 1000;
+	pdata->cdev.delay_msec = pdata->poll_delay;
+	pdata->cdev.sensors_enable = mma8x5x_enable_set;
+	pdata->cdev.sensors_poll_delay = mma8x5x_poll_delay_set;
+	result = sensors_classdev_register(&client->dev, &pdata->cdev);
 	if (result) {
 		dev_err(&client->dev, "create class device file failed!\n");
 		result = -EINVAL;
@@ -674,9 +984,20 @@
 	sysfs_remove_group(&idev->dev.kobj, &mma8x5x_attr_group);
 err_create_sysfs:
 	input_unregister_polled_device(pdata->poll_dev);
-err_register_polled_device:
-	input_free_polled_device(poll_dev);
+err_register_irq:
+	if (pdata->use_int)
+		device_init_wakeup(&client->dev, false);
+err_register_device:
+	if (pdata->use_int)
+		input_free_device(idev);
+	else
+		input_free_polled_device(pdata->poll_dev);
 err_alloc_poll_device:
+err_set_direction:
+	if (gpio_is_valid(pdata->int_pin) && pdata->use_int)
+		gpio_free(pdata->int_pin);
+err_request_gpio:
+err_parse_dt:
 	kfree(pdata);
 err_out:
 	mma8x5x_config_regulator(client, 0);
@@ -702,6 +1023,9 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+
+	if (pdata->use_int && pdata->active == MMA_ACTIVED)
+		return 0;
 	if (pdata->active == MMA_ACTIVED)
 		mma8x5x_device_stop(client);
 	if (pdata->active & MMA_SHUTTEDDOWN)
@@ -718,6 +1042,8 @@
 	struct i2c_client *client = to_i2c_client(dev);
 	struct mma8x5x_data *pdata = i2c_get_clientdata(client);
 
+	if (pdata->use_int && pdata->active == MMA_ACTIVED)
+		return 0;
 	/* No need to power on while device is shutdowned from standby state */
 	if (pdata->active == (MMA_SHUTTEDDOWN | MMA_STANDBY))
 		return 0;
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index fab209e..9629aae 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -122,6 +122,7 @@
 	struct input_dev *idev;
 	struct mpu3050_gyro_platform_data *platform_data;
 	struct delayed_work input_work;
+	struct sensors_classdev cdev;
 	u32    use_poll;
 	u32    poll_interval;
 	u32    dlpf_index;
@@ -141,6 +142,10 @@
 	.min_delay = 2000,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = MPU3050_DEFAULT_POLL_INTERVAL,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 struct sensor_regulator {
@@ -258,6 +263,40 @@
 	return rc;
 }
 
+static int mpu3050_poll_delay_set(struct sensors_classdev *sensors_cdev,
+		unsigned int delay_msec)
+{
+	struct mpu3050_sensor *sensor = container_of(sensors_cdev,
+			struct mpu3050_sensor, cdev);
+	unsigned int  dlpf_index;
+	u8  divider, reg;
+	int ret;
+
+	dlpf_index = interval_to_dlpf_cfg(delay_msec);
+	divider = delay_msec * dlpf_table[dlpf_index].sample_rate - 1;
+
+	if (sensor->dlpf_index != dlpf_index) {
+		/* Set low pass filter and full scale */
+		reg = dlpf_table[dlpf_index].cfg;
+		reg |= MPU3050_DEFAULT_FS_RANGE << 3;
+		reg |= MPU3050_EXT_SYNC_NONE << 5;
+		ret = i2c_smbus_write_byte_data(sensor->client,
+				MPU3050_DLPF_FS_SYNC, reg);
+		if (!ret)
+			sensor->dlpf_index = dlpf_index;
+	}
+
+	if (sensor->poll_interval != delay_msec) {
+		/* Output frequency divider. The poll interval */
+		ret = i2c_smbus_write_byte_data(sensor->client,
+				MPU3050_SMPLRT_DIV, divider);
+		if (!ret)
+			sensor->poll_interval = delay_msec;
+	}
+
+	return 0;
+}
+
 /**
  *	mpu3050_attr_get_polling_rate	-	get the sampling rate
  */
@@ -280,8 +319,6 @@
 {
 	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
 	unsigned long interval_ms;
-	unsigned int  dlpf_index;
-	u8  divider, reg;
 	int ret;
 
 	if (kstrtoul(buf, 10, &interval_ms))
@@ -290,29 +327,39 @@
 		(interval_ms > MPU3050_MAX_POLL_INTERVAL))
 		return -EINVAL;
 
-	dlpf_index = interval_to_dlpf_cfg(interval_ms);
-	divider = interval_ms * dlpf_table[dlpf_index].sample_rate - 1;
+	ret = mpu3050_poll_delay_set(&sensor->cdev, interval_ms);
 
-	if (sensor->dlpf_index != dlpf_index) {
-		/* Set low pass filter and full scale */
-		reg = dlpf_table[dlpf_index].cfg;
-		reg |= MPU3050_DEFAULT_FS_RANGE << 3;
-		reg |= MPU3050_EXT_SYNC_NONE << 5;
-		ret = i2c_smbus_write_byte_data(sensor->client,
-				MPU3050_DLPF_FS_SYNC, reg);
-		if (ret == 0)
-			sensor->dlpf_index = dlpf_index;
+	return ret < 0 ? ret : size;
+}
+static int mpu3050_enable_set(struct sensors_classdev *sensors_cdev,
+		unsigned int enabled)
+{
+	struct mpu3050_sensor *sensor = container_of(sensors_cdev,
+			struct mpu3050_sensor, cdev);
+
+
+	if (enabled && (!sensor->enable)) {
+		sensor->enable = enabled;
+		pm_runtime_get_sync(sensor->dev);
+		if (sensor->use_poll)
+			schedule_delayed_work(&sensor->input_work,
+				msecs_to_jiffies(sensor->poll_interval));
+		else
+			enable_irq(sensor->client->irq);
+	} else if (!enabled && sensor->enable) {
+		if (sensor->use_poll)
+			cancel_delayed_work_sync(&sensor->input_work);
+		else
+			disable_irq(sensor->client->irq);
+		pm_runtime_put_sync(sensor->dev);
+		sensor->enable = enabled;
+	} else {
+		dev_warn(&sensor->client->dev,
+				"ignore enable state change from %d to %d\n",
+				sensor->enable, enabled);
 	}
 
-	if (sensor->poll_interval != interval_ms) {
-		/* Output frequency divider. The poll interval */
-		ret = i2c_smbus_write_byte_data(sensor->client,
-				MPU3050_SMPLRT_DIV, divider);
-		if (ret == 0)
-			sensor->poll_interval = interval_ms;
-	}
-
-	return size;
+	return 0;
 }
 
 /**
@@ -325,31 +372,13 @@
 {
 	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
 	unsigned long val;
-	u32 enable;
+	int err;
 
 	if (kstrtoul(buf, 10, &val))
 		return -EINVAL;
-	enable = (u32)val == 0 ? 0 : 1;
-	if (enable && (!sensor->enable)) {
-		sensor->enable = enable;
-		pm_runtime_get_sync(sensor->dev);
-		if (sensor->use_poll)
-			schedule_delayed_work(&sensor->input_work,
-				msecs_to_jiffies(sensor->poll_interval));
-		else
-			enable_irq(sensor->client->irq);
-	} else if (!enable && sensor->enable) {
-		if (sensor->use_poll)
-			cancel_delayed_work_sync(&sensor->input_work);
-		else
-			disable_irq(sensor->client->irq);
-		pm_runtime_put_sync(sensor->dev);
-		sensor->enable = enable;
-	} else {
-		dev_warn(&sensor->client->dev,
-				"ignore enable state change from %d to %d\n",
-				sensor->enable, enable);
-	}
+	err = mpu3050_enable_set(&sensor->cdev, val);
+	if (err < 0)
+		return err;
 
 	return count;
 }
@@ -679,6 +708,19 @@
 		sensor->enable_gpio = -EINVAL;
 	}
 
+	sensor->cdev = sensors_cdev;
+	sensor->cdev.min_delay = MPU3050_MIN_POLL_INTERVAL * 1000;
+	sensor->cdev.delay_msec = sensor->poll_interval;
+	sensor->cdev.sensors_enable = mpu3050_enable_set;
+	sensor->cdev.sensors_poll_delay = mpu3050_poll_delay_set;
+	ret = sensors_classdev_register(&client->dev, &sensor->cdev);
+
+	if (ret) {
+		dev_err(&client->dev, "class device create failed: %d\n", ret);
+		error = -EINVAL;
+		goto err_free_mem;
+	}
+
 	if (gpio_is_valid(sensor->enable_gpio)) {
 		ret = gpio_request(sensor->enable_gpio, "GYRO_EN_PM");
 		gpio_direction_output(sensor->enable_gpio, 1);
@@ -690,7 +732,7 @@
 	if (ret < 0) {
 		dev_err(&client->dev, "failed to detect device\n");
 		error = -ENXIO;
-		goto err_free_mem;
+		goto err_class_sysfs;
 	}
 
 	for (i = 0; i < ARRAY_SIZE(mpu3050_chip_ids); i++)
@@ -700,7 +742,7 @@
 	if (i == ARRAY_SIZE(mpu3050_chip_ids)) {
 		dev_err(&client->dev, "unsupported chip id\n");
 		error = -ENXIO;
-		goto err_free_mem;
+		goto err_class_sysfs;
 	}
 
 	idev->name = "MPU3050";
@@ -775,16 +817,10 @@
 		goto err_free_irq;
 	}
 
-	error = sensors_classdev_register(&client->dev, &sensors_cdev);
-	if (error < 0) {
-		dev_err(&client->dev, "failed to create class device\n");
-		goto err_input_cleanup;
-	}
-
 	error = create_sysfs_interfaces(&idev->dev);
 	if (error < 0) {
 		dev_err(&client->dev, "failed to create sysfs\n");
-		goto err_class_sysfs;
+		goto err_input_cleanup;
 	}
 
 	pm_runtime_enable(&client->dev);
@@ -792,8 +828,6 @@
 
 	return 0;
 
-err_class_sysfs:
-	sensors_classdev_unregister(&sensors_cdev);
 err_input_cleanup:
 	input_unregister_device(idev);
 err_free_irq:
@@ -805,6 +839,8 @@
 		gpio_free(sensor->platform_data->gpio_int);
 err_pm_set_suspended:
 	pm_runtime_set_suspended(&client->dev);
+err_class_sysfs:
+	sensors_classdev_unregister(&sensor->cdev);
 err_free_mem:
 	input_free_device(idev);
 	kfree(sensor);
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index 39349bf..f9d3478 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -190,9 +190,13 @@
 	.max_range = "6500",
 	.resolution = "0.0625",
 	.sensor_power = "0.09",
-	.min_delay = 0,
+	.min_delay = (MIN_ALS_POLL_DELAY_NS / 1000),	/* us */
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = 200,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 static struct sensors_classdev sensors_proximity_cdev = {
@@ -207,6 +211,10 @@
 	.min_delay = 0,
 	.fifo_reserved_event_count = 0,
 	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = 200,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
 };
 
 struct data_filter {
@@ -219,6 +227,8 @@
 struct stk3x1x_data {
 	struct i2c_client *client;
 	struct stk3x1x_platform_data *pdata;
+	struct sensors_classdev als_cdev;
+	struct sensors_classdev ps_cdev;
 #if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
     int32_t irq;
     struct work_struct stk_work;
@@ -236,7 +246,7 @@
 	int32_t ps_distance_last;
 	bool ps_enabled;
 	struct wake_lock ps_wakelock;
-    struct work_struct stk_ps_work;
+	struct work_struct stk_ps_work;
 	struct workqueue_struct *stk_ps_wq;
 #ifdef STK_POLL_PS
 	struct wake_lock ps_nosuspend_wl;
@@ -903,6 +913,21 @@
     return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
 }
 
+static ssize_t stk_als_enable_set(struct sensors_classdev *sensors_cdev,
+						unsigned int enabled)
+{
+	struct stk3x1x_data *als_data = container_of(sensors_cdev,
+						struct stk3x1x_data, als_cdev);
+	int err;
+
+	mutex_lock(&als_data->io_lock);
+	err = stk3x1x_enable_als(als_data, enabled);
+	mutex_unlock(&als_data->io_lock);
+
+	if (err < 0)
+		return err;
+	return 0;
+}
 
 static ssize_t stk_als_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1008,7 +1033,8 @@
 static ssize_t stk_als_delay_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
-	return scnprintf(buf, PAGE_SIZE, "%lld\n", ktime_to_ns(ps_data->als_poll_delay));
+	return scnprintf(buf, PAGE_SIZE, "%u\n",
+			(u32)ktime_to_ms(ps_data->als_poll_delay));
 }
 
 static inline void stk_als_delay_store_fir(struct stk3x1x_data *ps_data)
@@ -1017,34 +1043,48 @@
 	ps_data->fir.idx = 0;
 	ps_data->fir.sum = 0;
 }
+
+static ssize_t stk_als_poll_delay_set(struct sensors_classdev *sensors_cdev,
+						unsigned int delay_msec)
+{
+	struct stk3x1x_data *als_data = container_of(sensors_cdev,
+						struct stk3x1x_data, als_cdev);
+	uint64_t value = 0;
+
+	value = delay_msec * 1000000;
+
+	if (value < MIN_ALS_POLL_DELAY_NS)
+		value = MIN_ALS_POLL_DELAY_NS;
+
+	mutex_lock(&als_data->io_lock);
+	if (value != ktime_to_ns(als_data->als_poll_delay))
+		als_data->als_poll_delay = ns_to_ktime(value);
+
+	if (als_data->use_fir)
+		stk_als_delay_store_fir(als_data);
+
+	mutex_unlock(&als_data->io_lock);
+
+	return 0;
+}
+
 static ssize_t stk_als_delay_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
 {
     uint64_t value = 0;
 	int ret;
-	struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
+	struct stk3x1x_data *als_data =  dev_get_drvdata(dev);
 	ret = kstrtoull(buf, 10, &value);
 	if(ret < 0)
 	{
-		printk(KERN_ERR "%s:kstrtoull failed, ret=0x%x\n",
-			__func__, ret);
+		dev_err(dev, "%s:kstrtoull failed, ret=0x%x\n",	__func__, ret);
 		return ret;
 	}
 #ifdef STK_DEBUG_PRINTF
-	printk(KERN_INFO "%s: set als poll delay=%lld\n", __func__, value);
+	dev_dbg(dev, "%s: set als poll delay=%lld\n", __func__, value);
 #endif
-	if(value < MIN_ALS_POLL_DELAY_NS)
-	{
-		printk(KERN_ERR "%s: delay is too small\n", __func__);
-		value = MIN_ALS_POLL_DELAY_NS;
-	}
-	mutex_lock(&ps_data->io_lock);
-	if(value != ktime_to_ns(ps_data->als_poll_delay))
-		ps_data->als_poll_delay = ns_to_ktime(value);
-
-	if (ps_data->use_fir)
-		stk_als_delay_store_fir(ps_data);
-
-	mutex_unlock(&ps_data->io_lock);
+	ret = stk_als_poll_delay_set(&als_data->als_cdev, value);
+	if (ret < 0)
+		return ret;
 	return size;
 }
 
@@ -1135,6 +1175,22 @@
     return scnprintf(buf, PAGE_SIZE, "%d\n", reading);
 }
 
+static ssize_t stk_ps_enable_set(struct sensors_classdev *sensors_cdev,
+						unsigned int enabled)
+{
+	struct stk3x1x_data *ps_data = container_of(sensors_cdev,
+						struct stk3x1x_data, ps_cdev);
+	int err;
+
+	mutex_lock(&ps_data->io_lock);
+	err = stk3x1x_enable_ps(ps_data, enabled);
+	mutex_unlock(&ps_data->io_lock);
+
+	if (err < 0)
+		return err;
+	return 0;
+}
+
 static ssize_t stk_ps_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
     int32_t enable, ret;
@@ -2389,10 +2445,16 @@
 	register_early_suspend(&ps_data->stk_early_suspend);
 #endif
 	/* make sure everything is ok before registering the class device */
-	err = sensors_classdev_register(&client->dev, &sensors_light_cdev);
+	ps_data->als_cdev = sensors_light_cdev;
+	ps_data->als_cdev.sensors_enable = stk_als_enable_set;
+	ps_data->als_cdev.sensors_poll_delay = stk_als_poll_delay_set;
+	err = sensors_classdev_register(&client->dev, &ps_data->als_cdev);
 	if (err)
 		goto err_power_on;
-	err = sensors_classdev_register(&client->dev, &sensors_proximity_cdev);
+
+	ps_data->ps_cdev = sensors_proximity_cdev;
+	ps_data->ps_cdev.sensors_enable = stk_ps_enable_set;
+	err = sensors_classdev_register(&client->dev, &ps_data->ps_cdev);
 	if (err)
 		goto err_class_sysfs;
 
@@ -2406,9 +2468,9 @@
 
 err_init_all_setting:
 	stk3x1x_power_ctl(ps_data, false);
-	sensors_classdev_unregister(&sensors_proximity_cdev);
+	sensors_classdev_unregister(&ps_data->ps_cdev);
 err_class_sysfs:
-	sensors_classdev_unregister(&sensors_light_cdev);
+	sensors_classdev_unregister(&ps_data->als_cdev);
 err_power_on:
 	stk3x1x_power_init(ps_data, false);
 err_power_init:
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 9b0c5c7..1e08169 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -110,6 +110,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called atmel_mxt_ts.
 
+config TOUCHSCREEN_ATMEL_MAXTOUCH_TS
+	tristate "Atmel Maxtouch Touchscreen Family"
+	depends on I2C
+	help
+	  Say Y here if you have Atmel MaXTouch Touchscreen
+	  using i2c connected to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel_maxtouch_ts.
+
 config TOUCHSCREEN_AUO_PIXCIR
 	tristate "AUO in-cell touchscreen using Pixcir ICs"
 	depends on I2C
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 3acc612..2b98145 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -14,6 +14,7 @@
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH)	+= atmel_maxtouch.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH_TS)	+= atmel_maxtouch_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 3731561..cd6989c 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
  * Author: Joonyoung Shim <jy0922.shim@samsung.com>
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, 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 as published by the
@@ -882,7 +882,7 @@
 		status = MXT_RELEASE;
 	}
 
-	if (status != MXT_RELEASE) {
+	if ((status != MXT_RELEASE) && status) {
 		input_report_abs(input_dev, ABS_X, finger[single_id].x);
 		input_report_abs(input_dev, ABS_Y, finger[single_id].y);
 		input_report_abs(input_dev,
@@ -2049,14 +2049,17 @@
 	return scnprintf(buf, PAGE_SIZE, "%u", val);
 }
 
-static DEVICE_ATTR(secure_touch_enable, 0666, mxt_secure_touch_enable_show,
-	mxt_secure_touch_enable_store);
-static DEVICE_ATTR(secure_touch, 0444, mxt_secure_touch_show, NULL);
+static DEVICE_ATTR(secure_touch_enable, S_IRUGO | S_IWUSR | S_IWGRP ,
+			 mxt_secure_touch_enable_show,
+			 mxt_secure_touch_enable_store);
+static DEVICE_ATTR(secure_touch, S_IRUGO, mxt_secure_touch_show, NULL);
 #endif
 
-static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
-static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
-static DEVICE_ATTR(force_cfg_update, 0664, NULL, mxt_force_cfg_update_store);
+static DEVICE_ATTR(object, S_IRUGO, mxt_object_show, NULL);
+static DEVICE_ATTR(update_fw, S_IWUSR | S_IWGRP , NULL, mxt_update_fw_store);
+static DEVICE_ATTR(force_cfg_update, S_IWUSR | S_IWGRP ,
+			 NULL,
+			 mxt_force_cfg_update_store);
 
 static struct attribute *mxt_attrs[] = {
 	&dev_attr_object.attr,
@@ -2547,6 +2550,15 @@
 	.resume		= mxt_resume,
 #endif
 };
+#else
+static int mxt_suspend(struct device *dev)
+{
+	return 0;
+};
+static int mxt_resume(struct device *dev)
+{
+	return 0;
+};
 #endif
 
 static int mxt_debugfs_object_show(struct seq_file *m, void *v)
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 9a4301e..4b8a3d4 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -1546,8 +1546,9 @@
 	data->family_id = pdata->family_id;
 
 	err = request_threaded_irq(client->irq, NULL,
-				   ft5x06_ts_interrupt, pdata->irqflags,
-				   client->dev.driver->name, data);
+				ft5x06_ts_interrupt,
+				pdata->irqflags | IRQF_ONESHOT,
+				client->dev.driver->name, data);
 	if (err) {
 		dev_err(&client->dev, "request irq failed\n");
 		goto free_reset_gpio;
diff --git a/drivers/input/touchscreen/gt9xx/goodix_tool.c b/drivers/input/touchscreen/gt9xx/goodix_tool.c
index aa8159f..521599a 100644
--- a/drivers/input/touchscreen/gt9xx/goodix_tool.c
+++ b/drivers/input/touchscreen/gt9xx/goodix_tool.c
@@ -23,16 +23,15 @@
 
 #include "gt9xx.h"
 #include <linux/mutex.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
 
 #define DATA_LENGTH_UINT    512
-#define CMD_HEAD_LENGTH     (sizeof(st_cmd_head) - sizeof(u8 *))
+#define CMD_HEAD_LENGTH     (sizeof(struct st_cmd_head) - sizeof(u8 *))
 static char procname[20] = {0};
 
-#define UPDATE_FUNCTIONS
-
-#pragma pack(1)
-struct {
-	u8  wr;		/* write read flag£¬0:R  1:W  2:PID 3: */
+struct st_cmd_head {
+	u8  wr;		/* write read flag 0:R 1:W 2:PID 3: */
 	u8  flag;	/* 0:no need flag/int 1: need flag  2:need int */
 	u8 flag_addr[2];/* flag address */
 	u8  flag_val;	/* flag val */
@@ -46,9 +45,9 @@
 	u8  addr[2];	/* address */
 	u8  res[3];	/* reserved */
 	u8  *data;	/* data pointer */
-} st_cmd_head;
-#pragma pack()
-st_cmd_head cmd_head;
+} __packed;
+
+static struct st_cmd_head cmd_head;
 
 static struct i2c_client *gt_client;
 
@@ -56,15 +55,11 @@
 
 static struct mutex lock;
 
-static s32 goodix_tool_write(struct file *filp, const char __user *buff,
-						unsigned long len, void *data);
-static s32 goodix_tool_read(char *page, char **start, off_t off, int count,
-							int *eof, void *data);
 static s32 (*tool_i2c_read)(u8 *, u16);
 static s32 (*tool_i2c_write)(u8 *, u16);
 
-s32 DATA_LENGTH;
-s8 IC_TYPE[16] = {0};
+s32 data_length;
+s8 ic_type[16] = {0};
 
 static void tool_set_proc_name(char *procname)
 {
@@ -75,7 +70,7 @@
 	int i = 0, n_month = 1, n_day = 0, n_year = 0;
 	snprintf(date, 20, "%s", __DATE__);
 
-	/* GTP_DEBUG("compile date: %s", date); */
+	/* pr_debug("compile date: %s", date); */
 
 	sscanf(date, "%s %d %d", month, &n_day, &n_year);
 
@@ -87,24 +82,27 @@
 	}
 
 	snprintf(procname, 20, "gmnode%04d%02d%02d", n_year, n_month, n_day);
-	/* GTP_DEBUG("procname = %s", procname); */
+	/* pr_debug("procname = %s", procname); */
 }
 
 static s32 tool_i2c_read_no_extra(u8 *buf, u16 len)
 {
 	s32 ret = -1;
-	s32 i = 0;
-	struct i2c_msg msgs[2];
-
-	msgs[0].flags = !I2C_M_RD;
-	msgs[0].addr  = gt_client->addr;
-	msgs[0].len   = cmd_head.addr_len;
-	msgs[0].buf   = &buf[0];
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr  = gt_client->addr;
-	msgs[1].len   = len;
-	msgs[1].buf   = &buf[GTP_ADDR_LENGTH];
+	u8 i = 0;
+	struct i2c_msg msgs[2] = {
+		{
+			.flags = !I2C_M_RD,
+			.addr  = gt_client->addr,
+			.len   = cmd_head.addr_len,
+			.buf   = &buf[0],
+		},
+		{
+			.flags = I2C_M_RD,
+			.addr  = gt_client->addr,
+			.len   = len,
+			.buf   = &buf[GTP_ADDR_LENGTH],
+		},
+	};
 
 	for (i = 0; i < cmd_head.retry; i++) {
 		ret = i2c_transfer(gt_client->adapter, msgs, 2);
@@ -112,25 +110,35 @@
 			break;
 	}
 
+	if (i == cmd_head.retry) {
+		dev_err(&gt_client->dev, "I2C read retry limit over.\n");
+		ret = -EIO;
+	}
+
 	return ret;
 }
 
 static s32 tool_i2c_write_no_extra(u8 *buf, u16 len)
 {
 	s32 ret = -1;
-	s32 i = 0;
-	struct i2c_msg msg;
-
-	msg.flags = !I2C_M_RD;
-	msg.addr  = gt_client->addr;
-	msg.len   = len;
-	msg.buf   = buf;
+	u8 i = 0;
+	struct i2c_msg msg = {
+		.flags = !I2C_M_RD,
+		.addr  = gt_client->addr,
+		.len   = len,
+		.buf   = buf,
+	};
 
 	for (i = 0; i < cmd_head.retry; i++) {
 		ret = i2c_transfer(gt_client->adapter, &msg, 1);
 		if (ret > 0)
 			break;
-		}
+	}
+
+	if (i == cmd_head.retry) {
+		dev_err(&gt_client->dev, "I2C write retry limit over.\n");
+		ret = -EIO;
+	}
 
 	return ret;
 }
@@ -163,22 +171,17 @@
 
 static void register_i2c_func(void)
 {
-	/* if (!strncmp(IC_TYPE, "GT818", 5) || !strncmp(IC_TYPE, "GT816", 5)
-	|| !strncmp(IC_TYPE, "GT811", 5) || !strncmp(IC_TYPE, "GT818F", 6)
-	|| !strncmp(IC_TYPE, "GT827", 5) || !strncmp(IC_TYPE,"GT828", 5)
-	|| !strncmp(IC_TYPE, "GT813", 5)) */
-
-	if (strncmp(IC_TYPE, "GT8110", 6) && strncmp(IC_TYPE, "GT8105", 6)
-	&& strncmp(IC_TYPE, "GT801", 5) && strncmp(IC_TYPE, "GT800", 5)
-	&& strncmp(IC_TYPE, "GT801PLUS", 9) && strncmp(IC_TYPE, "GT811", 5)
-	&& strncmp(IC_TYPE, "GTxxx", 5)) {
+	if (strcmp(ic_type, "GT8110") && strcmp(ic_type, "GT8105")
+	&& strcmp(ic_type, "GT801") && strcmp(ic_type, "GT800")
+	&& strcmp(ic_type, "GT801PLUS") && strcmp(ic_type, "GT811")
+	&& strcmp(ic_type, "GTxxx")) {
 		tool_i2c_read = tool_i2c_read_with_extra;
 		tool_i2c_write = tool_i2c_write_with_extra;
-		GTP_DEBUG("I2C function: with pre and end cmd!");
+		pr_debug("I2C function: with pre and end cmd!");
 	} else {
 		tool_i2c_read = tool_i2c_read_no_extra;
 		tool_i2c_write = tool_i2c_write_no_extra;
-		GTP_INFO("I2C function: without pre and end cmd!");
+		pr_info("I2C function: without pre and end cmd!");
 	}
 }
 
@@ -186,55 +189,11 @@
 {
 	tool_i2c_read = NULL;
 	tool_i2c_write = NULL;
-	GTP_INFO("I2C function: unregister i2c transfer function!");
-}
-
-s32 init_wr_node(struct i2c_client *client)
-{
-	u8 i;
-
-	gt_client = client;
-	memset(&cmd_head, 0, sizeof(cmd_head));
-	cmd_head.data = NULL;
-
-	i = 5;
-	while ((!cmd_head.data) && i) {
-		cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
-		if (NULL != cmd_head.data)
-			break;
-		i--;
-	}
-	if (i) {
-		DATA_LENGTH = i * DATA_LENGTH_UINT;
-		dev_dbg(&client->dev, "Applied memory size:%d.", DATA_LENGTH);
-	} else {
-		GTP_ERROR("Apply for memory failed.");
-		return FAIL;
-	}
-
-	cmd_head.addr_len = 2;
-	cmd_head.retry = 5;
-
-	register_i2c_func();
-
-	mutex_init(&lock);
-	tool_set_proc_name(procname);
-	goodix_proc_entry = create_proc_entry(procname, 0660, NULL);
-	if (goodix_proc_entry == NULL) {
-		GTP_ERROR("Couldn't create proc entry!");
-		return FAIL;
-	} else {
-		GTP_INFO("Create proc entry success!");
-		goodix_proc_entry->write_proc = goodix_tool_write;
-		dix_proc_entry->read_proc = goodix_tool_read;
-	}
-
-	return SUCCESS;
+	pr_info("I2C function: unregister i2c transfer function!");
 }
 
 void uninit_wr_node(void)
 {
-	kfree(cmd_head.data);
 	cmd_head.data = NULL;
 	unregister_i2c_func();
 	remove_proc_entry(procname, NULL);
@@ -252,7 +211,7 @@
 
 	case 1:
 		ret = (src == dst) ? true : false;
-		GTP_DEBUG("equal:src:0x%02x   dst:0x%02x  ret:%d.",
+		pr_debug("equal:src:0x%02x   dst:0x%02x  ret:%d.",
 					src, dst, (s32)ret);
 		break;
 
@@ -293,22 +252,18 @@
 	s32 i = 0;
 	u8 buf[32];
 
-/*    memcpy(&buf[GTP_ADDR_LENGTH - cmd_head.addr_len],
-			&cmd_head.flag_addr, cmd_head.addr_len);
-    memcpy(buf, &cmd_head.flag_addr, cmd_head.addr_len);
-		//Modified by Scott, 2012-02-17 */
 	memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
 
 	for (i = 0; i < cmd_head.times; i++) {
 		if (tool_i2c_read(buf, 1) <= 0) {
-			GTP_ERROR("Read flag data failed!");
+			dev_err(&gt_client->dev, "Read flag data failed!");
 			return FAIL;
 		}
 		if (true == relation(buf[GTP_ADDR_LENGTH], cmd_head.flag_val,
 						cmd_head.flag_relation)) {
-			GTP_DEBUG("value at flag addr:0x%02x.",
+			pr_debug("value at flag addr:0x%02x.",
 						buf[GTP_ADDR_LENGTH]);
-			GTP_DEBUG("flag value:0x%02x.", cmd_head.flag_val);
+			pr_debug("flag value:0x%02x.", cmd_head.flag_val);
 			break;
 		}
 
@@ -316,13 +271,34 @@
 	}
 
 	if (i >= cmd_head.times) {
-		GTP_ERROR("Didn't get the flag to continue!");
+		dev_err(&gt_client->dev, "Didn't get the flag to continue!");
 		return FAIL;
 	}
 
 	return SUCCESS;
 }
 
+#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
+static s32 fill_update_info(char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	u8 buf[4];
+
+	buf[0] = show_len >> 8;
+	buf[1] = show_len & 0xff;
+	buf[2] = total_len >> 8;
+	buf[3] = total_len & 0xff;
+	return simple_read_from_buffer(user_buf, count, ppos,
+			buf, sizeof(buf));
+}
+#else
+static s32 fill_update_info(char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	return -ENODEV;
+}
+#endif
+
 /********************************************************
 Function:
     Goodix tool write function.
@@ -331,117 +307,99 @@
 Output:
     Return write length.
 ********************************************************/
-static s32 goodix_tool_write(struct file *filp, const char __user *buff,
-						unsigned long len, void *data)
+static s32 goodix_tool_write(struct file *filp, const char __user *userbuf,
+						size_t count, loff_t *ppos)
 {
 	s32 ret = 0;
-	GTP_DEBUG_FUNC();
-	GTP_DEBUG_ARRAY((u8 *)buff, len);
 
 	mutex_lock(&lock);
-	ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+	ret = copy_from_user(&cmd_head, userbuf, CMD_HEAD_LENGTH);
 	if (ret) {
-		GTP_ERROR("copy_from_user failed.");
+		dev_err(&gt_client->dev, "copy_from_user failed.");
 		ret = -EACCES;
 		goto exit;
 	}
 
-	GTP_DEBUG("wr  :0x%02x.", cmd_head.wr);
-	GTP_DEBUG("flag:0x%02x.", cmd_head.flag);
-	GTP_DEBUG("flag addr:0x%02x%02x.", cmd_head.flag_addr[0],
-						cmd_head.flag_addr[1]);
-	GTP_DEBUG("flag val:0x%02x.", cmd_head.flag_val);
-	GTP_DEBUG("flag rel:0x%02x.", cmd_head.flag_relation);
-	GTP_DEBUG("circle  :%d.", (s32)cmd_head.circle);
-	GTP_DEBUG("times   :%d.", (s32)cmd_head.times);
-	GTP_DEBUG("retry   :%d.", (s32)cmd_head.retry);
-	GTP_DEBUG("delay   :%d.", (s32)cmd_head.delay);
-	GTP_DEBUG("data len:%d.", (s32)cmd_head.data_len);
-	GTP_DEBUG("addr len:%d.", (s32)cmd_head.addr_len);
-	GTP_DEBUG("addr:0x%02x%02x.", cmd_head.addr[0], cmd_head.addr[1]);
-	GTP_DEBUG("len:%d.", (s32)len);
-	GTP_DEBUG("buf[20]:0x%02x.", buff[CMD_HEAD_LENGTH]);
+	dev_dbg(&gt_client->dev, "wr:0x%02x, flag:0x%02x, flag addr:0x%02x%02x, flag val:0x%02x, flag rel:0x%02x, circle:%d, times:%d, retry:%d, delay:%d, data len:%d, addr len:%d, addr:0x%02x%02x, write len: %d.",
+		cmd_head.wr, cmd_head.flag, cmd_head.flag_addr[0],
+		cmd_head.flag_addr[1], cmd_head.flag_val,
+		cmd_head.flag_relation,	(s32)cmd_head.circle,
+		(s32)cmd_head.times, (s32)cmd_head.retry, (s32)cmd_head.delay,
+		(s32)cmd_head.data_len, (s32)cmd_head.addr_len,
+		cmd_head.addr[0], cmd_head.addr[1], (s32)count);
 
-	if (cmd_head.data_len > (DATA_LENGTH - GTP_ADDR_LENGTH)) {
-		pr_err("data len %d > data buff %d, rejected!\n",
-			cmd_head.data_len, (DATA_LENGTH - GTP_ADDR_LENGTH));
+	if (cmd_head.data_len > (data_length - GTP_ADDR_LENGTH)) {
+		dev_err(&gt_client->dev, "data len %d > data buff %d, rejected!\n",
+			cmd_head.data_len, (data_length - GTP_ADDR_LENGTH));
 		ret = -EINVAL;
 		goto exit;
 	}
 	if (cmd_head.addr_len > GTP_ADDR_LENGTH) {
-		pr_err(" addr len %d > data buff %d, rejected!\n",
+		dev_err(&gt_client->dev, "addr len %d > data buff %d, rejected!\n",
 			cmd_head.addr_len, GTP_ADDR_LENGTH);
 		ret = -EINVAL;
 		goto exit;
 	}
 
-	if (cmd_head.wr == 1) {
-		/*  copy_from_user(&cmd_head.data[cmd_head.addr_len],
-				&buff[CMD_HEAD_LENGTH], cmd_head.data_len); */
+	if (cmd_head.wr == GTP_RW_WRITE) {
 		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
-				&buff[CMD_HEAD_LENGTH], cmd_head.data_len);
-		if (ret)
-			GTP_ERROR("copy_from_user failed.");
+				&userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
+		if (ret) {
+			dev_err(&gt_client->dev, "copy_from_user failed.");
+			goto exit;
+		}
 
 		memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
 					cmd_head.addr, cmd_head.addr_len);
 
-		GTP_DEBUG_ARRAY(cmd_head.data,
-				cmd_head.data_len + cmd_head.addr_len);
-		GTP_DEBUG_ARRAY((u8 *)&buff[CMD_HEAD_LENGTH],
-							cmd_head.data_len);
-
-		if (cmd_head.flag == 1) {
-			if (FAIL == comfirm()) {
-				GTP_ERROR("[WRITE]Comfirm fail!");
+		if (cmd_head.flag == GTP_NEED_FLAG) {
+			if (comfirm() ==  FAIL) {
+				dev_err(&gt_client->dev, "Comfirm fail!");
 				ret = -EINVAL;
 				goto exit;
 			}
-		} else if (cmd_head.flag == 2) {
+		} else if (cmd_head.flag == GTP_NEED_INTERRUPT) {
 			/* Need interrupt! */
 		}
 		if (tool_i2c_write(
 		&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
 		cmd_head.data_len + cmd_head.addr_len) <= 0) {
-			GTP_ERROR("[WRITE]Write data failed!");
+			dev_err(&gt_client->dev, "Write data failed!");
 			ret = -EIO;
 			goto exit;
 		}
 
-		GTP_DEBUG_ARRAY(
-			&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
-			cmd_head.data_len + cmd_head.addr_len);
 		if (cmd_head.delay)
 			msleep(cmd_head.delay);
 
 		ret = cmd_head.data_len + CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 3) {  /* Write ic type */
-
-		ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH],
+	} else if (cmd_head.wr == GTP_RW_WRITE_IC_TYPE) {  /* Write ic type */
+		ret = copy_from_user(&cmd_head.data[0],
+				&userbuf[CMD_HEAD_LENGTH],
 				cmd_head.data_len);
-		if (ret)
-			GTP_ERROR("copy_from_user failed.");
+		if (ret) {
+			dev_err(&gt_client->dev, "copy_from_user failed.");
+			goto exit;
+		}
 
-		if (cmd_head.data_len > sizeof(IC_TYPE)) {
-			pr_err("<<-GTP->> data len %d > data buff %d, rejected!\n",
-			cmd_head.data_len, sizeof(IC_TYPE));
+		if (cmd_head.data_len > sizeof(ic_type)) {
+			dev_err(&gt_client->dev,
+				"data len %d > data buff %d, rejected!\n",
+				cmd_head.data_len, sizeof(ic_type));
 			ret = -EINVAL;
 			goto exit;
 		}
-		memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
+		memcpy(ic_type, cmd_head.data, cmd_head.data_len);
 
 		register_i2c_func();
 
 		ret = cmd_head.data_len + CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 5) {
-
-		/* memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len); */
-
+	} else if (cmd_head.wr == GTP_RW_NO_WRITE) {
 		ret = cmd_head.data_len + CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 7) { /* disable irq! */
+	} else if (cmd_head.wr == GTP_RW_DISABLE_IRQ) { /* disable irq! */
 		gtp_irq_disable(i2c_get_clientdata(gt_client));
 
 		#if GTP_ESD_PROTECT
@@ -449,7 +407,7 @@
 		#endif
 		ret = CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 9) { /* enable irq! */
+	} else if (cmd_head.wr == GTP_RW_ENABLE_IRQ) { /* enable irq! */
 		gtp_irq_enable(i2c_get_clientdata(gt_client));
 
 		#if GTP_ESD_PROTECT
@@ -457,49 +415,51 @@
 		#endif
 		ret = CMD_HEAD_LENGTH;
 		goto exit;
-	} else if (cmd_head.wr == 17) {
+	} else if (cmd_head.wr == GTP_RW_CHECK_RAWDIFF_MODE) {
 		struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
 		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
-				&buff[CMD_HEAD_LENGTH], cmd_head.data_len);
-		if (ret)
-			GTP_DEBUG("copy_from_user failed.");
+				&userbuf[CMD_HEAD_LENGTH], cmd_head.data_len);
+		if (ret) {
+			pr_debug("copy_from_user failed.");
+			goto exit;
+		}
 		if (cmd_head.data[GTP_ADDR_LENGTH]) {
-			GTP_DEBUG("gtp enter rawdiff.");
+			pr_debug("gtp enter rawdiff.");
 			ts->gtp_rawdiff_mode = true;
 		} else {
 			ts->gtp_rawdiff_mode = false;
-			GTP_DEBUG("gtp leave rawdiff.");
+			pr_debug("gtp leave rawdiff.");
 		}
 		ret = CMD_HEAD_LENGTH;
 		goto exit;
-	}
-#ifdef UPDATE_FUNCTIONS
-	else if (cmd_head.wr == 11) { /* Enter update mode! */
-		if (FAIL == gup_enter_update_mode(gt_client)) {
+	} else if (cmd_head.wr == GTP_RW_ENTER_UPDATE_MODE) {
+		/* Enter update mode! */
+		if (gup_enter_update_mode(gt_client) ==  FAIL) {
 			ret = -EBUSY;
 			goto exit;
 		}
-	} else if (cmd_head.wr == 13) { /* Leave update mode! */
-		gup_leave_update_mode();
-	} else if (cmd_head.wr == 15) { /* Update firmware! */
+	} else if (cmd_head.wr == GTP_RW_LEAVE_UPDATE_MODE) {
+		/* Leave update mode! */
+		gup_leave_update_mode(gt_client);
+	} else if (cmd_head.wr == GTP_RW_UPDATE_FW) {
+		/* Update firmware! */
 		show_len = 0;
 		total_len = 0;
-		if (cmd_head.data_len + 1 > DATA_LENGTH) {
-			pr_err("<<-GTP->> data len %d > data buff %d, rejected!\n",
-			cmd_head.data_len + 1, DATA_LENGTH);
+		if (cmd_head.data_len + 1 > data_length) {
+			dev_err(&gt_client->dev, "data len %d > data buff %d, rejected!\n",
+			cmd_head.data_len + 1, data_length);
 			ret = -EINVAL;
 			goto exit;
 		}
 		memset(cmd_head.data, 0, cmd_head.data_len + 1);
-		memcpy(cmd_head.data, &buff[CMD_HEAD_LENGTH],
+		memcpy(cmd_head.data, &userbuf[CMD_HEAD_LENGTH],
 					cmd_head.data_len);
 
-		if (FAIL == gup_update_proc((void *)cmd_head.data)) {
+		if (gup_update_proc((void *)cmd_head.data) == FAIL) {
 			ret = -EBUSY;
 			goto exit;
 		}
 	}
-#endif
 	ret = CMD_HEAD_LENGTH;
 
 exit:
@@ -511,95 +471,130 @@
 Function:
     Goodix tool read function.
 Input:
-  standard proc read function param.
+  standard seq file read function param.
 Output:
     Return read length.
 ********************************************************/
-static s32 goodix_tool_read(char *page, char **start, off_t off, int count,
-							int *eof, void *data)
+static s32 goodix_tool_read(struct file *file, char __user *user_buf,
+					size_t count, loff_t *ppos)
 {
+	u16 data_len = 0;
 	s32 ret;
-	GTP_DEBUG_FUNC();
+	u8 buf[32];
 
 	mutex_lock(&lock);
-	if (cmd_head.wr % 2) {
-		pr_err("<< [READ]command head wrong\n");
+	if (cmd_head.wr & 0x1) {
+		dev_err(&gt_client->dev, "command head wrong\n");
 		ret = -EINVAL;
 		goto exit;
-	} else if (!cmd_head.wr) {
-		u16 len = 0;
-		s16 data_len = 0;
-		u16 loc = 0;
+	}
 
-		if (cmd_head.flag == 1) {
-			if (FAIL == comfirm()) {
-				GTP_ERROR("[READ]Comfirm fail!");
+	switch (cmd_head.wr) {
+	case GTP_RW_READ:
+		if (cmd_head.flag == GTP_NEED_FLAG) {
+			if (comfirm() == FAIL) {
+				dev_err(&gt_client->dev, "Comfirm fail!");
 				ret = -EINVAL;
 				goto exit;
 			}
-		} else if (cmd_head.flag == 2) {
+		} else if (cmd_head.flag == GTP_NEED_INTERRUPT) {
 			/* Need interrupt! */
 		}
 
 		memcpy(cmd_head.data, cmd_head.addr, cmd_head.addr_len);
 
-		GTP_DEBUG("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0],
+		pr_debug("[CMD HEAD DATA] ADDR:0x%02x%02x.", cmd_head.data[0],
 							cmd_head.data[1]);
-		GTP_DEBUG("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0],
+		pr_debug("[CMD HEAD ADDR] ADDR:0x%02x%02x.", cmd_head.addr[0],
 							cmd_head.addr[1]);
 
 		if (cmd_head.delay)
 			msleep(cmd_head.delay);
 
 		data_len = cmd_head.data_len;
-		while (data_len > 0) {
-			if (data_len > DATA_LENGTH)
-				len = DATA_LENGTH;
-			else
-				len = data_len;
-
-			data_len -= len;
-
-			if (tool_i2c_read(cmd_head.data, len) <= 0) {
-				GTP_ERROR("[READ]Read data failed!");
-				ret = -EINVAL;
-				goto exit;
-			}
-			memcpy(&page[loc], &cmd_head.data[GTP_ADDR_LENGTH],
-									len);
-			loc += len;
-
-			GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH], len);
-			GTP_DEBUG_ARRAY(page, len);
+		if (data_len <= 0 || (data_len > data_length)) {
+			dev_err(&gt_client->dev, "Invalid data length %d\n",
+				data_len);
+			ret = -EINVAL;
+			goto exit;
 		}
-	} else if (cmd_head.wr == 2) {
-		/* memcpy(page, "gt8", cmd_head.data_len);
-		memcpy(page, "GT818", 5);
-		page[5] = 0; */
+		if (data_len > count)
+			data_len = count;
 
-		GTP_DEBUG("Return ic type:%s len:%d.", page,
-						(s32)cmd_head.data_len);
-		ret = cmd_head.data_len;
-		goto exit;
-		/* return sizeof(IC_TYPE_NAME); */
-	} else if (cmd_head.wr == 4) {
-		page[0] = show_len >> 8;
-		page[1] = show_len & 0xff;
-		page[2] = total_len >> 8;
-		page[3] = total_len & 0xff;
-	} else if (6 == cmd_head.wr) {
-		/* Read error code! */
-	} else if (8 == cmd_head.wr) { /*Read driver version */
-		/* memcpy(page, GTP_DRIVER_VERSION,
-				strlen(GTP_DRIVER_VERSION)); */
-		s32 tmp_len;
-		tmp_len = strlen(GTP_DRIVER_VERSION);
-		memcpy(page, GTP_DRIVER_VERSION, tmp_len);
-		page[tmp_len] = 0;
+		if (tool_i2c_read(cmd_head.data, data_len) <= 0) {
+			dev_err(&gt_client->dev, "Read data failed!\n");
+			ret = -EIO;
+			goto exit;
+		}
+		ret = simple_read_from_buffer(user_buf, count, ppos,
+			&cmd_head.data[GTP_ADDR_LENGTH], data_len);
+		break;
+	case GTP_RW_FILL_INFO:
+		ret = fill_update_info(user_buf, count, ppos);
+		break;
+	case GTP_RW_READ_VERSION:
+		/* Read driver version */
+		data_len = scnprintf(buf, sizeof(buf), "%s\n",
+			GTP_DRIVER_VERSION);
+		ret = simple_read_from_buffer(user_buf, count, ppos,
+			buf, data_len);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
 	}
-	ret = cmd_head.data_len;
 
 exit:
 	mutex_unlock(&lock);
 	return ret;
 }
+
+static const struct file_operations goodix_proc_fops = {
+	.write = goodix_tool_write,
+	.read = goodix_tool_read,
+	.open = simple_open,
+	.owner = THIS_MODULE,
+};
+
+s32 init_wr_node(struct i2c_client *client)
+{
+	u8 i;
+
+	gt_client = client;
+	memset(&cmd_head, 0, sizeof(cmd_head));
+	cmd_head.data = NULL;
+
+	i = GTP_I2C_RETRY_5;
+	while ((!cmd_head.data) && i) {
+		cmd_head.data = devm_kzalloc(&client->dev,
+				i * DATA_LENGTH_UINT, GFP_KERNEL);
+		if (cmd_head.data)
+			break;
+		i--;
+	}
+	if (i) {
+		data_length = i * DATA_LENGTH_UINT;
+		dev_dbg(&client->dev, "Applied memory size:%d.", data_length);
+	} else {
+		dev_err(&client->dev, "Apply for memory failed.");
+		return FAIL;
+	}
+
+	cmd_head.addr_len = 2;
+	cmd_head.retry = GTP_I2C_RETRY_5;
+
+	register_i2c_func();
+
+	mutex_init(&lock);
+	tool_set_proc_name(procname);
+	goodix_proc_entry = proc_create(procname,
+			S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+			goodix_proc_entry,
+			&goodix_proc_fops);
+	if (goodix_proc_entry == NULL) {
+		dev_err(&client->dev, "Couldn't create proc entry!");
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index b39cb0d..912d87c 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -1,6 +1,6 @@
 /* drivers/input/touchscreen/gt9xx.c
  *
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * Linux Foundation chooses to take subject only to the GPLv2 license
  * terms, and distributes only under these terms.
@@ -47,17 +47,16 @@
 #include "gt9xx.h"
 
 #include <linux/of_gpio.h>
-
+#include <linux/irq.h>
+#include <linux/module.h>
 #include <linux/input/mt.h>
+#include <linux/debugfs.h>
 
 #define GOODIX_DEV_NAME	"Goodix-CTP"
 #define CFG_MAX_TOUCH_POINTS	5
 #define GOODIX_COORDS_ARR_SIZE	4
 #define MAX_BUTTONS		4
 
-/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
-#define GTP_I2C_ADDRESS_HIGH	0x14
-#define GTP_I2C_ADDRESS_LOW	0x5D
 #define CFG_GROUP_LEN(p_cfg_grp)  (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
 
 #define GOODIX_VTG_MIN_UV	2600000
@@ -82,17 +81,8 @@
 static const u16 touch_key_array[] = {KEY_MENU, KEY_HOMEPAGE, KEY_BACK};
 #define GTP_MAX_KEY_NUM  (sizeof(touch_key_array)/sizeof(touch_key_array[0]))
 
-#if GTP_DEBUG_ON
-static const int  key_codes[] = {
-	KEY_HOME, KEY_BACK, KEY_MENU, KEY_SEARCH
-};
-static const char *const key_names[] = {
-	"Key_Home", "Key_Back", "Key_Menu", "Key_Search"
-};
-#endif
 #endif
 
-static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
 static void gtp_int_sync(struct goodix_ts_data *ts, int ms);
 static int gtp_i2c_test(struct i2c_client *client);
 static int goodix_power_off(struct goodix_ts_data *ts);
@@ -100,7 +90,9 @@
 
 #if defined(CONFIG_FB)
 static int fb_notifier_callback(struct notifier_block *self,
-				 unsigned long event, void *data);
+				unsigned long event, void *data);
+static int goodix_ts_suspend(struct device *dev);
+static int goodix_ts_resume(struct device *dev);
 #elif defined(CONFIG_HAS_EARLYSUSPEND)
 static void goodix_ts_early_suspend(struct early_suspend *h);
 static void goodix_ts_late_resume(struct early_suspend *h);
@@ -111,7 +103,6 @@
 static struct workqueue_struct *gtp_esd_check_workqueue;
 static void gtp_esd_check_func(struct work_struct *work);
 static int gtp_init_ext_watchdog(struct i2c_client *client);
-struct i2c_client  *i2c_connect_client;
 #endif
 
 #if GTP_SLIDE_WAKEUP
@@ -126,6 +117,12 @@
 bool init_done;
 static u8 chip_gt9xxs;  /* true if ic is gt9xxs, like gt915s */
 u8 grp_cfg_version;
+struct i2c_client  *i2c_connect_client;
+
+#define GTP_DEBUGFS_DIR			"ts_debug"
+#define GTP_DEBUGFS_FILE_SUSPEND	"suspend"
+#define GTP_DEBUGFS_FILE_DATA		"data"
+#define GTP_DEBUGFS_FILE_ADDR		"addr"
 
 /*******************************************************
 Function:
@@ -142,27 +139,30 @@
 int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
 {
 	struct goodix_ts_data *ts = i2c_get_clientdata(client);
-	struct i2c_msg msgs[2];
 	int ret = -EIO;
-	int retries = 0;
+	u8 retries;
+	struct i2c_msg msgs[2] = {
+		{
+			.flags	= !I2C_M_RD,
+			.addr	= client->addr,
+			.len	= GTP_ADDR_LENGTH,
+			.buf	= &buf[0],
+		},
+		{
+			.flags	= I2C_M_RD,
+			.addr	= client->addr,
+			.len	= len - GTP_ADDR_LENGTH,
+			.buf	= &buf[GTP_ADDR_LENGTH],
+		},
+	};
 
-	msgs[0].flags = !I2C_M_RD;
-	msgs[0].addr = client->addr;
-	msgs[0].len = GTP_ADDR_LENGTH;
-	msgs[0].buf = &buf[0];
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr = client->addr;
-	msgs[1].len = len - GTP_ADDR_LENGTH;
-	msgs[1].buf = &buf[GTP_ADDR_LENGTH];
-
-	while (retries < 5) {
+	for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) {
 		ret = i2c_transfer(client->adapter, msgs, 2);
 		if (ret == 2)
 			break;
-		retries++;
+		dev_err(&client->dev, "I2C retry: %d\n", retries + 1);
 	}
-	if (retries >= 5) {
+	if (retries == GTP_I2C_RETRY_5) {
 #if GTP_SLIDE_WAKEUP
 		/* reset chip would quit doze mode */
 		if (DOZE_ENABLED == doze_status)
@@ -172,7 +172,7 @@
 			gtp_reset_guitar(ts, 10);
 		else
 			dev_warn(&client->dev,
-				"<GTP> gtp_reset_guitar exit init_done=%d:\n",
+				"gtp_reset_guitar exit init_done=%d:\n",
 				init_done);
 	}
 	return ret;
@@ -193,22 +193,22 @@
 int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
 {
 	struct goodix_ts_data *ts = i2c_get_clientdata(client);
-	struct i2c_msg msg;
 	int ret = -EIO;
-	int retries = 0;
+	u8 retries;
+	struct i2c_msg msg = {
+		.flags = !I2C_M_RD,
+		.addr = client->addr,
+		.len = len,
+		.buf = buf,
+	};
 
-	msg.flags = !I2C_M_RD;
-	msg.addr = client->addr;
-	msg.len = len;
-	msg.buf = buf;
-
-	while (retries < 5) {
+	for (retries = 0; retries < GTP_I2C_RETRY_5; retries++) {
 		ret = i2c_transfer(client->adapter, &msg, 1);
 		if (ret == 1)
 			break;
-		retries++;
+		dev_err(&client->dev, "I2C retry: %d\n", retries + 1);
 	}
-	if ((retries >= 5)) {
+	if ((retries == GTP_I2C_RETRY_5)) {
 #if GTP_SLIDE_WAKEUP
 		if (DOZE_ENABLED == doze_status)
 			return ret;
@@ -217,11 +217,12 @@
 			gtp_reset_guitar(ts, 10);
 		else
 			dev_warn(&client->dev,
-				"<GTP> gtp_reset_guitar exit init_done=%d:\n",
+				"gtp_reset_guitar exit init_done=%d:\n",
 				init_done);
 	}
 	return ret;
 }
+
 /*******************************************************
 Function:
 	i2c read twice, compare the results
@@ -241,7 +242,7 @@
 	u8 confirm_buf[16] = {0};
 	u8 retry = 0;
 
-	while (retry++ < 3) {
+	while (retry++ < GTP_I2C_RETRY_3) {
 		memset(buf, 0xAA, 16);
 		buf[0] = (u8)(addr >> 8);
 		buf[1] = (u8)(addr & 0xFF);
@@ -255,7 +256,7 @@
 		if (!memcmp(buf, confirm_buf, len + 2))
 			break;
 	}
-	if (retry < 3) {
+	if (retry < GTP_I2C_RETRY_3) {
 		memcpy(rxbuf, confirm_buf + 2, len);
 		return SUCCESS;
 	} else {
@@ -275,7 +276,7 @@
 	result of i2c write operation.
 	> 0: succeed, otherwise: failed
 *********************************************************/
-static int gtp_send_cfg(struct goodix_ts_data *ts)
+int gtp_send_cfg(struct goodix_ts_data *ts)
 {
 	int ret;
 #if GTP_DRIVER_SEND_CFG
@@ -286,7 +287,7 @@
 			"Ic fixed config, no config sent!");
 		ret = 2;
 	} else {
-		for (retry = 0; retry < 5; retry++) {
+		for (retry = 0; retry < GTP_I2C_RETRY_5; retry++) {
 			ret = gtp_i2c_write(ts->client,
 				ts->config_data,
 				GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
@@ -498,31 +499,19 @@
 		memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
 	}
 
-#if GTP_HAVE_TOUCH_KEY
+
 	key_value = point_data[3 + 8 * touch_num];
 
 	if (key_value || pre_key) {
-		for (i = 0; i < GTP_MAX_KEY_NUM; i++) {
-
-#if GTP_DEBUG_ON
-			for (ret = 0; ret < 4; ++ret) {
-				if (key_codes[ret] == touch_key_array[i]) {
-					GTP_DEBUG("Key: %s %s",
-						key_names[ret],
-						(key_value & (0x01 << i))
-						? "Down" : "Up");
-					break;
-				}
-			}
-#endif
-
+		for (i = 0; i < ts->pdata->num_button; i++) {
 			input_report_key(ts->input_dev,
-				touch_key_array[i], key_value & (0x01<<i));
+				ts->pdata->button_map[i],
+				key_value & (0x01<<i));
 		}
 		touch_num = 0;
 		pre_touch = 0;
 	}
-#endif
+
 	pre_key = key_value;
 
 #if GTP_WITH_PEN
@@ -618,26 +607,6 @@
 
 /*******************************************************
 Function:
-	Timer interrupt service routine for polling mode.
-Input:
-	timer: timer struct pointer
-Output:
-	Timer work mode.
-	HRTIMER_NORESTART: no restart mode
-*********************************************************/
-static enum hrtimer_restart goodix_ts_timer_handler(struct hrtimer *timer)
-{
-	struct goodix_ts_data
-		*ts = container_of(timer, struct goodix_ts_data, timer);
-
-	queue_work(ts->goodix_wq, &ts->work);
-	hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
-			HRTIMER_MODE_REL);
-	return HRTIMER_NORESTART;
-}
-
-/*******************************************************
-Function:
 	External interrupt service routine for interrupt mode.
 Input:
 	irq:  interrupt number.
@@ -679,7 +648,7 @@
 Output:
 	None.
 *******************************************************/
-static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
+void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
 {
 	/* This reset sequence will selcet I2C slave address */
 	gpio_direction_output(ts->pdata->reset_gpio, 0);
@@ -726,7 +695,7 @@
 #endif
 	gtp_irq_disable(ts);
 
-	while (retry++ < 5) {
+	while (retry++ < GTP_I2C_RETRY_3) {
 		i2c_control_buf[0] = 0x80;
 		i2c_control_buf[1] = 0x46;
 		ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
@@ -753,16 +722,13 @@
 	return ret;
 }
 #else
-/*******************************************************
-Function:
-	Enter sleep mode.
-Input:
-	ts: private data.
-Output:
-	Executive outcomes.
-	>0: succeed, otherwise failed.
-*******************************************************/
-static s8 gtp_enter_sleep(struct goodix_ts_data  *ts)
+/**
+ * gtp_enter_sleep - Enter sleep mode
+ * @ts: driver private data
+ *
+ * Returns zero on success, else an error.
+ */
+static u8 gtp_enter_sleep(struct goodix_ts_data *ts)
 {
 	int ret = -1;
 	s8 retry = 0;
@@ -784,16 +750,16 @@
 		ret = goodix_power_off(ts);
 		if (ret) {
 			dev_err(&ts->client->dev, "GTP power off failed.\n");
-			return 0;
+			return ret;
 		}
-		return 1;
+		return 0;
 	} else {
 		usleep(5000);
-		while (retry++ < 5) {
+		while (retry++ < GTP_I2C_RETRY_5) {
 			ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
 			if (ret == 1) {
 				dev_dbg(&ts->client->dev, "GTP enter sleep!");
-				return ret;
+				return 0;
 			}
 			msleep(20);
 		}
@@ -1077,7 +1043,7 @@
 
 	ret = gtp_i2c_read(client, buf, sizeof(buf));
 	if (ret < 0) {
-		dev_err(&client->dev, "GTP read version failed.\n");
+		dev_err(&client->dev, "GTP read product_id failed.\n");
 		return -EIO;
 	}
 
@@ -1112,7 +1078,7 @@
 static int gtp_i2c_test(struct i2c_client *client)
 {
 	u8 buf[3] = { GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff };
-	int retry = 5;
+	int retry = GTP_I2C_RETRY_5;
 	int ret = -EIO;
 
 	while (retry--) {
@@ -1217,28 +1183,20 @@
 *******************************************************/
 static int gtp_request_irq(struct goodix_ts_data *ts)
 {
-	int ret;
+	int ret = 0;
 	const u8 irq_table[] = GTP_IRQ_TAB;
 
-	ret = request_irq(ts->client->irq, goodix_ts_irq_handler,
+	ret = request_threaded_irq(ts->client->irq, NULL,
+			goodix_ts_irq_handler,
 			irq_table[ts->int_trigger_type],
 			ts->client->name, ts);
 	if (ret) {
-		dev_err(&ts->client->dev, "Request IRQ failed!ERRNO:%d.\n",
-				ret);
-		gpio_direction_input(ts->pdata->irq_gpio);
-
-		hrtimer_init(&ts->timer, CLOCK_MONOTONIC,
-				HRTIMER_MODE_REL);
-		ts->timer.function = goodix_ts_timer_handler;
-		hrtimer_start(&ts->timer, ktime_set(1, 0),
-				HRTIMER_MODE_REL);
 		ts->use_irq = false;
 		return ret;
 	} else {
 		gtp_irq_disable(ts);
 		ts->use_irq = true;
-		return 0;
+		return ret;
 	}
 }
 
@@ -1272,12 +1230,12 @@
 	__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
 	input_mt_init_slots(ts->input_dev, 10);/* in case of "out of memory" */
 
-#if GTP_HAVE_TOUCH_KEY
-	for (index = 0; index < GTP_MAX_KEY_NUM; index++) {
+
+	for (index = 0; index < ts->pdata->num_button; index++) {
 		input_set_capability(ts->input_dev,
-				EV_KEY, touch_key_array[index]);
+				EV_KEY, ts->pdata->button_map[index]);
 	}
-#endif
+
 
 #if GTP_SLIDE_WAKEUP
 	input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
@@ -1572,12 +1530,62 @@
 	return size;
 }
 
+static ssize_t gtp_fw_upgrade_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct goodix_ts_data *ts = dev_get_drvdata(dev);
+	return snprintf(buf, 2, "%d\n", ts->fw_loading);
+}
+
+static ssize_t gtp_fw_upgrade_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct goodix_ts_data *ts = dev_get_drvdata(dev);
+	unsigned long val;
+	int ret;
+
+	if (size > 2)
+		return -EINVAL;
+
+	ret = kstrtoul(buf, 10, &val);
+	if (ret != 0)
+		return ret;
+
+	if (ts->gtp_is_suspend) {
+		dev_err(&ts->client->dev,
+			"Can't start fw upgrade. Device is in suspend state.");
+		return -EBUSY;
+	}
+
+	mutex_lock(&ts->input_dev->mutex);
+	if (!ts->fw_loading && val) {
+		disable_irq(ts->client->irq);
+		ts->fw_loading = true;
+		if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+			ret = gup_update_proc(NULL);
+			if (ret == FAIL)
+				dev_err(&ts->client->dev,
+						"Fail to update GTP firmware.\n");
+		}
+		ts->fw_loading = false;
+		enable_irq(ts->client->irq);
+	}
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return size;
+}
+
 static DEVICE_ATTR(fw_name, (S_IRUGO | S_IWUSR | S_IWGRP),
 			gtp_fw_name_show,
 			gtp_fw_name_store);
+static DEVICE_ATTR(fw_upgrade, (S_IRUGO | S_IWUSR | S_IWGRP),
+			gtp_fw_upgrade_show,
+			gtp_fw_upgrade_store);
 
 static struct attribute *gtp_attrs[] = {
 	&dev_attr_fw_name.attr,
+	&dev_attr_fw_upgrade.attr,
 	NULL
 };
 
@@ -1585,6 +1593,154 @@
 	.attrs = gtp_attrs,
 };
 
+static int gtp_debug_addr_is_valid(u16 addr)
+{
+	if (addr < GTP_VALID_ADDR_START || addr > GTP_VALID_ADDR_END) {
+		pr_err("GTP reg address is invalid: 0x%x\n", addr);
+		return false;
+	}
+
+	return true;
+}
+
+static int gtp_debug_data_set(void *_data, u64 val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	mutex_lock(&ts->input_dev->mutex);
+	if (gtp_debug_addr_is_valid(ts->addr))
+		dev_err(&ts->client->dev,
+			"Writing to GTP registers not supported.\n");
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+static int gtp_debug_data_get(void *_data, u64 *val)
+{
+	struct goodix_ts_data *ts = _data;
+	int ret;
+	u8 buf[3] = {0};
+
+	mutex_lock(&ts->input_dev->mutex);
+	buf[0] = ts->addr >> 8;
+	buf[1] = ts->addr & 0x00ff;
+
+	if (gtp_debug_addr_is_valid(ts->addr)) {
+		ret = gtp_i2c_read(ts->client, buf, 3);
+		if (ret < 0)
+			dev_err(&ts->client->dev,
+				"GTP read register 0x%x failed (%d)\n",
+				ts->addr, ret);
+		else
+			*val = buf[2];
+	}
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, gtp_debug_data_get,
+				gtp_debug_data_set, "%llx\n");
+
+static int gtp_debug_addr_set(void *_data, u64 val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	if (gtp_debug_addr_is_valid(val)) {
+		mutex_lock(&ts->input_dev->mutex);
+			ts->addr = val;
+		mutex_unlock(&ts->input_dev->mutex);
+	}
+
+	return 0;
+}
+
+static int gtp_debug_addr_get(void *_data, u64 *val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	mutex_lock(&ts->input_dev->mutex);
+	if (gtp_debug_addr_is_valid(ts->addr))
+		*val = ts->addr;
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, gtp_debug_addr_get,
+				gtp_debug_addr_set, "%llx\n");
+
+static int gtp_debug_suspend_set(void *_data, u64 val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	mutex_lock(&ts->input_dev->mutex);
+	if (val)
+		goodix_ts_suspend(&ts->client->dev);
+	else
+		goodix_ts_resume(&ts->client->dev);
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+static int gtp_debug_suspend_get(void *_data, u64 *val)
+{
+	struct goodix_ts_data *ts = _data;
+
+	mutex_lock(&ts->input_dev->mutex);
+	*val = ts->gtp_is_suspend;
+	mutex_unlock(&ts->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, gtp_debug_suspend_get,
+			gtp_debug_suspend_set, "%lld\n");
+
+static int gtp_debugfs_init(struct goodix_ts_data *data)
+{
+	data->debug_base = debugfs_create_dir(GTP_DEBUGFS_DIR, NULL);
+
+	if (IS_ERR_OR_NULL(data->debug_base)) {
+		dev_err(&data->client->dev, "Failed to create debugfs dir.\n");
+			return -EINVAL;
+	}
+
+	if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_SUSPEND,
+					S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+					data->debug_base,
+					data,
+					&debug_suspend_fops)))) {
+		dev_err(&data->client->dev, "Failed to create suspend file.\n");
+		debugfs_remove_recursive(data->debug_base);
+		return -EINVAL;
+	}
+
+	if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_DATA,
+					S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+					data->debug_base,
+					data,
+					&debug_data_fops)))) {
+		dev_err(&data->client->dev, "Failed to create data file.\n");
+		debugfs_remove_recursive(data->debug_base);
+		return -EINVAL;
+	}
+
+	if ((IS_ERR_OR_NULL(debugfs_create_file(GTP_DEBUGFS_FILE_ADDR,
+					S_IWUSR | S_IWGRP | S_IRUSR | S_IRGRP,
+					data->debug_base,
+					data,
+					&debug_addr_fops)))) {
+		dev_err(&data->client->dev, "Failed to create addr file.\n");
+		debugfs_remove_recursive(data->debug_base);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int goodix_ts_get_dt_coords(struct device *dev, char *name,
 				struct goodix_ts_platform_data *pdata)
 {
@@ -1689,6 +1845,9 @@
 			dev_err(dev, "Unable to read key codes\n");
 			return rc;
 		}
+		pdata->num_button = num_buttons;
+		memcpy(pdata->button_map, button_map,
+			pdata->num_button * sizeof(u32));
 	}
 
 	read_cfg_num = 0;
@@ -1762,16 +1921,14 @@
 		return -EINVAL;
 	}
 
-#if GTP_ESD_PROTECT
 	i2c_connect_client = client;
-#endif
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		dev_err(&client->dev, "GTP I2C not supported\n");
 		return -ENODEV;
 	}
 
-	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
 	if (!ts) {
 		dev_err(&client->dev, "GTP not enough memory for ts\n");
 		return -ENOMEM;
@@ -1818,15 +1975,14 @@
 		strlcpy(ts->fw_name, pdata->fw_name,
 						strlen(pdata->fw_name) + 1);
 
-#if GTP_AUTO_UPDATE
-	ret = gup_init_update_proc(ts);
-	if (ret < 0) {
-		dev_err(&client->dev,
-			"GTP Create firmware update thread error.\n");
-		goto exit_power_off;
+	if (config_enabled(CONFIG_GT9XX_TOUCHPANEL_UPDATE)) {
+		ret = gup_init_update_proc(ts);
+		if (ret < 0) {
+			dev_err(&client->dev,
+					"GTP Create firmware update thread error.\n");
+			goto exit_power_off;
+		}
 	}
-#endif
-
 	ret = gtp_init_panel(ts);
 	if (ret < 0) {
 		dev_err(&client->dev, "GTP init panel failed.\n");
@@ -1861,13 +2017,13 @@
 	INIT_WORK(&ts->work, goodix_ts_work_func);
 
 	ret = gtp_request_irq(ts);
-	if (ret < 0)
-		dev_info(&client->dev, "GTP works in polling mode.\n");
+	if (ret)
+		dev_info(&client->dev, "GTP request irq failed %d.\n", ret);
 	else
 		dev_info(&client->dev, "GTP works in interrupt mode.\n");
 
 	ret = gtp_read_fw_version(client, &version_info);
-	if (ret != 0)
+	if (ret != 2)
 		dev_err(&client->dev, "GTP firmware version read failed.\n");
 
 	ret = gtp_check_product_id(client);
@@ -1878,7 +2034,7 @@
 	if (ts->use_irq)
 		gtp_irq_enable(ts);
 
-#if GTP_CREATE_WR_NODE
+#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
 	init_wr_node(client);
 #endif
 
@@ -1891,6 +2047,13 @@
 		goto exit_free_irq;
 	}
 
+	ret = gtp_debugfs_init(ts);
+	if (ret != 0) {
+		dev_err(&client->dev, "Failed to create debugfs entries, %d\n",
+						ret);
+		goto exit_remove_sysfs;
+	}
+
 	init_done = true;
 	return 0;
 exit_free_irq:
@@ -1915,6 +2078,8 @@
 		input_free_device(ts->input_dev);
 		ts->input_dev = NULL;
 	}
+exit_remove_sysfs:
+	sysfs_remove_group(&ts->input_dev->dev.kobj, &gtp_attr_grp);
 exit_free_inputdev:
 	kfree(ts->config_data);
 exit_power_off:
@@ -1928,7 +2093,6 @@
 		gpio_free(pdata->irq_gpio);
 exit_free_client_data:
 	i2c_set_clientdata(client, NULL);
-	kfree(ts);
 	return ret;
 }
 
@@ -1955,7 +2119,7 @@
 #endif
 	mutex_destroy(&ts->lock);
 
-#if GTP_CREATE_WR_NODE
+#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
 	uninit_wr_node();
 #endif
 
@@ -1980,7 +2144,6 @@
 			input_free_device(ts->input_dev);
 			ts->input_dev = NULL;
 		}
-		kfree(ts->config_data);
 
 		if (gpio_is_valid(ts->pdata->reset_gpio))
 			gpio_free(ts->pdata->reset_gpio);
@@ -1990,8 +2153,8 @@
 		goodix_power_off(ts);
 		goodix_power_deinit(ts);
 		i2c_set_clientdata(client, NULL);
-		kfree(ts);
 	}
+	debugfs_remove_recursive(ts->debug_base);
 
 	return 0;
 }
@@ -2010,9 +2173,21 @@
 	struct goodix_ts_data *ts = dev_get_drvdata(dev);
 	int ret = 0, i;
 
+	if (ts->gtp_is_suspend) {
+		dev_dbg(&ts->client->dev, "Already in suspend state.\n");
+		return 0;
+	}
+
 	mutex_lock(&ts->lock);
+
+	if (ts->fw_loading) {
+		dev_info(&ts->client->dev,
+			"Fw upgrade in progress, can't go to suspend.");
+		mutex_unlock(&ts->lock);
+		return 0;
+	}
+
 #if GTP_ESD_PROTECT
-	ts->gtp_is_suspend = 1;
 	gtp_esd_switch(ts->client, SWITCH_OFF);
 #endif
 
@@ -2031,13 +2206,14 @@
 
 	ret = gtp_enter_sleep(ts);
 #endif
-	if (ret <= 0)
+	if (ret < 0)
 		dev_err(&ts->client->dev, "GTP early suspend failed.\n");
 	/* to avoid waking up while not sleeping,
 	 * delay 48 + 10ms to ensure reliability
 	 */
 	msleep(58);
 	mutex_unlock(&ts->lock);
+	ts->gtp_is_suspend = 1;
 
 	return ret;
 }
@@ -2055,6 +2231,11 @@
 	struct goodix_ts_data *ts = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (!ts->gtp_is_suspend) {
+		dev_dbg(&ts->client->dev, "Already in awake state.\n");
+		return 0;
+	}
+
 	mutex_lock(&ts->lock);
 	ret = gtp_wakeup_sleep(ts);
 
@@ -2072,10 +2253,10 @@
 			ktime_set(1, 0), HRTIMER_MODE_REL);
 
 #if GTP_ESD_PROTECT
-	ts->gtp_is_suspend = 0;
 	gtp_esd_switch(ts->client, SWITCH_ON);
 #endif
 	mutex_unlock(&ts->lock);
+	ts->gtp_is_suspend = 0;
 
 	return ret;
 }
@@ -2192,13 +2373,13 @@
 	msg.len   = 4;
 	msg.buf   = opr_buffer;
 
-	while (retries < 5) {
+	while (retries < GTP_I2C_RETRY_5) {
 		ret = i2c_transfer(client->adapter, &msg, 1);
 		if (ret == 1)
 			return 1;
 		retries++;
 	}
-	if (retries >= 5)
+	if (retries == GTP_I2C_RETRY_5)
 		dev_err(&client->dev, "init external watchdog failed!");
 	return 0;
 }
@@ -2214,7 +2395,7 @@
 *******************************************************/
 static void gtp_esd_check_func(struct work_struct *work)
 {
-	s32 i;
+	s32 retry;
 	s32 ret = -1;
 	struct goodix_ts_data *ts = NULL;
 	u8 test[4] = {0x80, 0x40};
@@ -2231,7 +2412,7 @@
 		return;
 #endif
 
-	for (i = 0; i < 3; i++) {
+	for (retry = 0; retry < GTP_I2C_RETRY_3; retry++) {
 		ret = gtp_i2c_read(ts->client, test, 4);
 
 		if ((ret < 0)) {
@@ -2240,7 +2421,7 @@
 		} else {
 			if ((test[2] == 0xAA) || (test[3] != 0xAA)) {
 				/* IC works abnormally..*/
-				i = 3;
+				retry = GTP_I2C_RETRY_3;
 				break;
 			} else {
 				/* IC works normally, Write 0x8040 0xAA*/
@@ -2250,7 +2431,7 @@
 			}
 		}
 	}
-	if (i >= 3) {
+	if (retry == GTP_I2C_RETRY_3) {
 		dev_err(&ts->client->dev,
 			"IC Working ABNORMALLY, Resetting Guitar...\n");
 		gtp_reset_guitar(ts, 50);
@@ -2268,8 +2449,15 @@
 }
 #endif
 
-static SIMPLE_DEV_PM_OPS(goodix_ts_dev_pm_ops, goodix_ts_suspend,
-					goodix_ts_resume);
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+static const struct dev_pm_ops goodix_ts_dev_pm_ops = {
+	.suspend = goodix_ts_suspend,
+	.resume = goodix_ts_resume,
+};
+#else
+static const struct dev_pm_ops goodix_ts_dev_pm_ops = {
+};
+#endif
 
 static const struct i2c_device_id goodix_ts_id[] = {
 	{ GTP_I2C_NAME, 0 },
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index 1d31f2a..7a1af23 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -1,6 +1,6 @@
 /* drivers/input/touchscreen/gt9xx.h
  *
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * Linux Foundation chooses to take subject only to the GPLv2 license
  * terms, and distributes only under these terms.
@@ -25,18 +25,9 @@
 
 #include <linux/kernel.h>
 #include <linux/i2c.h>
-#include <linux/irq.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
 #include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
-#include <linux/firmware.h>
-#include <linux/debugfs.h>
-#include <linux/mutex.h>
+#include <linux/uaccess.h>
 
 #if defined(CONFIG_FB)
 #include <linux/notifier.h>
@@ -46,6 +37,7 @@
 #define GOODIX_SUSPEND_LEVEL 1
 #endif
 
+#define MAX_BUTTONS 4
 #define GOODIX_MAX_CFG_GROUP	6
 #define GTP_FW_NAME_MAXSIZE	50
 
@@ -69,6 +61,8 @@
 	bool enable_power_off;
 	size_t config_data_len[GOODIX_MAX_CFG_GROUP];
 	u8 *config_data[GOODIX_MAX_CFG_GROUP];
+	u32 button_map[MAX_BUTTONS];
+	u8 num_button;
 };
 struct goodix_ts_data {
 	spinlock_t irq_lock;
@@ -79,10 +73,12 @@
 	struct workqueue_struct *goodix_wq;
 	struct work_struct	work;
 	char fw_name[GTP_FW_NAME_MAXSIZE];
+	struct delayed_work goodix_update_work;
 	s32 irq_is_disabled;
 	s32 use_irq;
 	u16 abs_x_max;
 	u16 abs_y_max;
+	u16 addr;
 	u8  max_touch_num;
 	u8  int_trigger_type;
 	u8  green_wake_mode;
@@ -97,6 +93,7 @@
 	u8  fw_error;
 	bool power_on;
 	struct mutex lock;
+	bool fw_loading;
 	struct regulator *avdd;
 	struct regulator *vdd;
 	struct regulator *vcc_i2c;
@@ -105,6 +102,7 @@
 #elif defined(CONFIG_HAS_EARLYSUSPEND)
 	struct early_suspend early_suspend;
 #endif
+	struct dentry *debug_base;
 };
 
 extern u16 show_len;
@@ -115,14 +113,6 @@
 #define GTP_CHANGE_X2Y			0
 #define GTP_DRIVER_SEND_CFG		1
 #define GTP_HAVE_TOUCH_KEY		1
-
-/* auto updated by .bin file as default */
-#define GTP_AUTO_UPDATE			0
-/* auto updated by head_fw_array in gt9xx_firmware.h,
- * function together with GTP_AUTO_UPDATE */
-#define GTP_HEADER_FW_UPDATE	0
-
-#define GTP_CREATE_WR_NODE		0
 #define GTP_ESD_PROTECT			0
 #define GTP_WITH_PEN			0
 
@@ -131,30 +121,14 @@
 /* double-click wakeup, function together with GTP_SLIDE_WAKEUP */
 #define GTP_DBL_CLK_WAKEUP		0
 
-#define GTP_DEBUG_ON			0
-#define GTP_DEBUG_ARRAY_ON		0
-#define GTP_DEBUG_FUNC_ON		0
-
-/*************************** PART2:TODO define *******************************/
-/* STEP_1(REQUIRED): Define Configuration Information Group(s) */
-/* Sensor_ID Map: */
-/* sensor_opt1 sensor_opt2 Sensor_ID
- *	GND			GND			0
- *	VDDIO		GND			1
- *	NC			GND			2
- *	GND			NC/300K		3
- *	VDDIO		NC/300K		4
- *	NC			NC/300K		5
-*/
-
-#define GTP_IRQ_TAB		{\
+#define GTP_IRQ_TAB            {\
 				IRQ_TYPE_EDGE_RISING,\
 				IRQ_TYPE_EDGE_FALLING,\
 				IRQ_TYPE_LEVEL_LOW,\
 				IRQ_TYPE_LEVEL_HIGH\
 				}
 
-/* STEP_3(optional): Specify your special config info if needed */
+
 #define GTP_IRQ_TAB_RISING	0
 #define GTP_IRQ_TAB_FALLING	1
 #if GTP_CUSTOM_CFG
@@ -193,53 +167,61 @@
 #define GTP_REG_FW_VERSION	0x8144
 #define GTP_REG_PRODUCT_ID	0x8140
 
+#define GTP_I2C_RETRY_3		3
+#define GTP_I2C_RETRY_5		5
+#define GTP_I2C_RETRY_10	10
+
 #define RESOLUTION_LOC		3
 #define TRIGGER_LOC		8
 
+/* HIGH: 0x28/0x29, LOW: 0xBA/0xBB */
+#define GTP_I2C_ADDRESS_HIGH	0x14
+#define GTP_I2C_ADDRESS_LOW	0x5D
+#define GTP_VALID_ADDR_START	0x8040
+#define GTP_VALID_ADDR_END	0x8177
+
 #define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
-/* Log define */
-#define GTP_DEBUG(fmt, arg...)	do {\
-		if (GTP_DEBUG_ON) {\
-			pr_debug("<<-GTP-DEBUG->> [%d]"fmt"\n",\
-				__LINE__, ##arg); } \
-		} while (0)
 
-#define GTP_DEBUG_ARRAY(array, num)    do {\
-		s32 i; \
-		u8 *a = array; \
-		if (GTP_DEBUG_ARRAY_ON) {\
-			pr_debug("<<-GTP-DEBUG-ARRAY->>\n");\
-			for (i = 0; i < (num); i++) { \
-				pr_debug("%02x   ", (a)[i]);\
-				if ((i + 1) % 10 == 0) { \
-					pr_debug("\n");\
-				} \
-			} \
-			pr_debug("\n");\
-		} \
-	} while (0)
+/* GTP CM_HEAD RW flags */
+#define GTP_RW_READ			0
+#define GTP_RW_WRITE			1
+#define GTP_RW_READ_IC_TYPE		2
+#define GTP_RW_WRITE_IC_TYPE		3
+#define GTP_RW_FILL_INFO		4
+#define GTP_RW_NO_WRITE			5
+#define GTP_RW_READ_ERROR		6
+#define GTP_RW_DISABLE_IRQ		7
+#define GTP_RW_READ_VERSION		8
+#define GTP_RW_ENABLE_IRQ		9
+#define GTP_RW_ENTER_UPDATE_MODE	11
+#define GTP_RW_LEAVE_UPDATE_MODE	13
+#define GTP_RW_UPDATE_FW		15
+#define GTP_RW_CHECK_RAWDIFF_MODE	17
 
-#define GTP_DEBUG_FUNC()	do {\
-	if (GTP_DEBUG_FUNC_ON)\
-		pr_debug("<<-GTP-FUNC->> Func:%s@Line:%d\n",\
-					__func__, __LINE__);\
-	} while (0)
+/* GTP need flag or interrupt */
+#define GTP_NO_NEED			0
+#define GTP_NEED_FLAG			1
+#define GTP_NEED_INTERRUPT		2
 
-#define GTP_SWAP(x, y)		do {\
-					typeof(x) z = x;\
-					x = y;\
-					y = z;\
-				} while (0)
 /*****************************End of Part III********************************/
 
 void gtp_esd_switch(struct i2c_client *client, int on);
 
-#if GTP_CREATE_WR_NODE
-extern s32 init_wr_node(struct i2c_client *client);
-extern void uninit_wr_node(void);
+int gtp_i2c_read_dbl_check(struct i2c_client *client, u16 addr,
+					u8 *rxbuf, int len);
+int gtp_send_cfg(struct goodix_ts_data *ts);
+void gtp_reset_guitar(struct goodix_ts_data *ts, int ms);
+void gtp_irq_disable(struct goodix_ts_data *ts);
+void gtp_irq_enable(struct goodix_ts_data *ts);
+
+#ifdef CONFIG_GT9XX_TOUCHPANEL_DEBUG
+s32 init_wr_node(struct i2c_client *client);
+void uninit_wr_node(void);
 #endif
 
-#if GTP_AUTO_UPDATE
-extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
-#endif
+u8 gup_init_update_proc(struct goodix_ts_data *ts);
+s32 gup_enter_update_mode(struct i2c_client *client);
+void gup_leave_update_mode(struct i2c_client *client);
+s32 gup_update_proc(void *dir);
+extern struct i2c_client  *i2c_connect_client;
 #endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx_update.c b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
index cf83154..71e8a55 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx_update.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx_update.c
@@ -31,25 +31,19 @@
  *          2. support firmware header array update.
  *                          By Meta, 2013/03/11
  */
-#include <linux/kthread.h>
 #include "gt9xx.h"
+#include <linux/firmware.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
 
-#if GTP_HEADER_FW_UPDATE
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include "gt9xx_firmware.h"
-#endif
+#define FIRMWARE_NAME_LEN_MAX		256
 
 #define GUP_REG_HW_INFO             0x4220
 #define GUP_REG_FW_MSG              0x41E4
 #define GUP_REG_PID_VID             0x8140
 
-#define GUP_SEARCH_FILE_TIMES       50
-#define UPDATE_FILE_PATH_2          "/data/_goodix_update_.bin"
-#define UPDATE_FILE_PATH_1          "/sdcard/_goodix_update_.bin"
-
-#define CONFIG_FILE_PATH_1          "/data/_goodix_config_.cfg"
-#define CONFIG_FILE_PATH_2          "/sdcard/_goodix_config_.cfg"
+#define GOODIX_FIRMWARE_FILE_NAME	"_goodix_update_.bin"
+#define GOODIX_CONFIG_FILE_NAME		"_goodix_config_.cfg"
 
 #define FW_HEAD_LENGTH               14
 #define FW_SECTION_LENGTH            0x2000
@@ -73,24 +67,22 @@
 #define FAIL    0
 #define SUCCESS 1
 
-#pragma pack(1)
-struct {
+struct st_fw_head {
 	u8  hw_info[4];		/* hardware info */
 	u8  pid[8];		/* product id   */
 	u16 vid;		/* version id   */
-} st_fw_head;
-#pragma pack()
+} __packed;
 
-struct {
+struct st_update_msg {
 	u8 force_update;
 	u8 fw_flag;
-	struct file *file;
-	struct file *cfg_file;
-	st_fw_head  ic_fw_msg;
-	mm_segment_t old_fs;
-} st_update_msg;
+	bool need_free;
+	u8 *fw_data;
+	u32 fw_len;
+	struct st_fw_head  ic_fw_msg;
+};
 
-st_update_msg update_msg;
+static struct st_update_msg update_msg;
 u16 show_len;
 u16 total_len;
 u8 got_file_flag;
@@ -107,25 +99,24 @@
     numbers of i2c_msgs to transfer:
       2: succeed, otherwise: failed
 *********************************************************/
-s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
+static s32 gup_i2c_read(struct i2c_client *client, u8 *buf, s32 len)
 {
-	struct i2c_msg msgs[2];
 	s32 ret = -1;
-	s32 retries = 0;
-
-	GTP_DEBUG_FUNC();
-
-	msgs[0].flags = !I2C_M_RD;
-	msgs[0].addr  = client->addr;
-	msgs[0].len   = GTP_ADDR_LENGTH;
-	msgs[0].buf   = &buf[0];
-	/* msgs[0].scl_rate = 300 * 1000;  (for Rockchip) */
-
-	msgs[1].flags = I2C_M_RD;
-	msgs[1].addr  = client->addr;
-	msgs[1].len   = len - GTP_ADDR_LENGTH;
-	msgs[1].buf   = &buf[GTP_ADDR_LENGTH];
-	/* msgs[1].scl_rate = 300 * 1000; */
+	u8 retries = 0;
+	struct i2c_msg msgs[2] = {
+		{
+			.flags = !I2C_M_RD,
+			.addr  = client->addr,
+			.len   = GTP_ADDR_LENGTH,
+			.buf   = &buf[0],
+		},
+		{
+			.flags = I2C_M_RD,
+			.addr  = client->addr,
+			.len   = len - GTP_ADDR_LENGTH,
+			.buf   = &buf[GTP_ADDR_LENGTH],
+		},
+	};
 
 	while (retries < 5) {
 		ret = i2c_transfer(client->adapter, msgs, 2);
@@ -134,6 +125,11 @@
 		retries++;
 	}
 
+	if (retries == 5) {
+		dev_err(&client->dev, "I2C read retry limit over.\n");
+		ret = -EIO;
+	}
+
 	return ret;
 }
 
@@ -151,17 +147,14 @@
 *********************************************************/
 s32 gup_i2c_write(struct i2c_client *client, u8 *buf, s32 len)
 {
-	struct i2c_msg msg;
 	s32 ret = -1;
-	s32 retries = 0;
-
-	GTP_DEBUG_FUNC();
-
-	msg.flags = !I2C_M_RD;
-	msg.addr  = client->addr;
-	msg.len   = len;
-	msg.buf   = buf;
-	/* msg.scl_rate = 300 * 1000;    (for Rockchip) */
+	u8 retries = 0;
+	struct i2c_msg msg = {
+		.flags = !I2C_M_RD,
+		.addr  = client->addr,
+		.len   = len,
+		.buf   = buf,
+	};
 
 	while (retries < 5) {
 		ret = i2c_transfer(client->adapter, &msg, 1);
@@ -170,123 +163,105 @@
 		retries++;
 	}
 
+	if (retries == 5) {
+		dev_err(&client->dev, "I2C write retry limit over.\n");
+		ret = -EIO;
+	}
+
 	return ret;
 }
 
 static s32 gup_init_panel(struct goodix_ts_data *ts)
 {
+	struct i2c_client *client = ts->client;
+	u8 *config_data;
 	s32 ret = 0;
 	s32 i = 0;
 	u8 check_sum = 0;
 	u8 opr_buf[16];
 	u8 sensor_id = 0;
 
-	u8 cfg_info_group1[] = CTP_CFG_GROUP1;
-	u8 cfg_info_group2[] = CTP_CFG_GROUP2;
-	u8 cfg_info_group3[] = CTP_CFG_GROUP3;
-	u8 cfg_info_group4[] = CTP_CFG_GROUP4;
-	u8 cfg_info_group5[] = CTP_CFG_GROUP5;
-	u8 cfg_info_group6[] = CTP_CFG_GROUP6;
-	u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2, cfg_info_group3,
-			cfg_info_group4, cfg_info_group5, cfg_info_group6};
-	u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group1),
-			CFG_GROUP_LEN(cfg_info_group2),
-			CFG_GROUP_LEN(cfg_info_group3),
-			CFG_GROUP_LEN(cfg_info_group4),
-			CFG_GROUP_LEN(cfg_info_group5),
-			CFG_GROUP_LEN(cfg_info_group6)};
+	for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
+		if (ts->pdata->config_data_len[i])
+			break;
 
-	if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
-	(!cfg_info_len[3]) && (!cfg_info_len[4]) &&
-	(!cfg_info_len[5])) {
+	if (i == GOODIX_MAX_CFG_GROUP) {
 		sensor_id = 0;
 	} else {
-		ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
+		ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID,
 							&sensor_id, 1);
 		if (SUCCESS == ret) {
-			if (sensor_id >= 0x06) {
-				GTP_ERROR("Invalid sensor_id(0x%02X), " \
-					"No Config Sent!", sensor_id);
+			if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
+				pr_err("Invalid sensor_id(0x%02X), No Config Sent!",
+					sensor_id);
 				return -EINVAL;
 			}
 		} else {
-			GTP_ERROR("Failed to get sensor_id, No config sent!");
+			pr_err("Failed to get sensor_id, No config sent!");
 			return -EINVAL;
 		}
 	}
 
-	GTP_DEBUG("Sensor_ID: %d", sensor_id);
+	pr_debug("Sensor ID selected: %d", sensor_id);
 
-	ts->gtp_cfg_len = cfg_info_len[sensor_id];
-
-	if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
-		GTP_ERROR("Sensor_ID(%d) matches with NULL or INVALID CONFIG" \
-			" GROUP! NO Config Sent! You need to check you header" \
-			"  file CFG_GROUP section!", sensor_id);
+	if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH ||
+		!ts->pdata->config_data_len[sensor_id]) {
+		pr_err("Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP!",
+				sensor_id);
 		return -EINVAL;
 	}
 
-	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
+	ret = gtp_i2c_read_dbl_check(client, GTP_REG_CONFIG_DATA,
 					&opr_buf[0], 1);
-
 	if (ret == SUCCESS) {
-		GTP_DEBUG("CFG_GROUP%d Config Version: %d, IC Config Version:" \
-		" %d", sensor_id+1, send_cfg_buf[sensor_id][0],	opr_buf[0]);
+		pr_debug("CFG_GROUP%d Config Version: %d, IC Config Version: %d",
+			sensor_id + 1,
+			ts->pdata->config_data[sensor_id][0],
+			opr_buf[0]);
 
-		send_cfg_buf[sensor_id][0] = opr_buf[0];
+		ts->pdata->config_data[sensor_id][0] = opr_buf[0];
 		ts->fixed_cfg = 0;
-		/*
-		if (opr_buf[0] < 90) {
-			grp_cfg_version = send_cfg_buf[sensor_id][0];
-				*** backup group config version ***
-			send_cfg_buf[sensor_id][0] = 0x00;
-			ts->fixed_cfg = 0;
-		} else { *** treated as fixed config, not send config ***
-			GTP_INFO("Ic fixed config with config version(%d)",
-							opr_buf[0]);
-			ts->fixed_cfg = 1;
-		}*/
 	} else {
-		GTP_ERROR("Failed to get ic config version!No config sent!");
+		pr_err("Failed to get ic config version!No config sent!");
 		return -EINVAL;
 	}
 
-	memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
-	memcpy(&config[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
-						ts->gtp_cfg_len);
+	config_data = ts->pdata->config_data[sensor_id];
+	ts->config_data = ts->pdata->config_data[sensor_id];
+	ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id];
 
-	GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
+	pr_debug("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
 	ts->abs_x_max, ts->abs_y_max, ts->int_trigger_type);
 
-	config[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;
-	config[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
-	config[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
-	config[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
+	config_data[RESOLUTION_LOC]     = (u8)GTP_MAX_WIDTH;
+	config_data[RESOLUTION_LOC + 1] = (u8)(GTP_MAX_WIDTH>>8);
+	config_data[RESOLUTION_LOC + 2] = (u8)GTP_MAX_HEIGHT;
+	config_data[RESOLUTION_LOC + 3] = (u8)(GTP_MAX_HEIGHT>>8);
 
 	if (GTP_INT_TRIGGER == 0)  /* RISING */
-		config[TRIGGER_LOC] &= 0xfe;
+		config_data[TRIGGER_LOC] &= 0xfe;
 	else if (GTP_INT_TRIGGER == 1)  /* FALLING */
-		config[TRIGGER_LOC] |= 0x01;
+		config_data[TRIGGER_LOC] |= 0x01;
 
 	check_sum = 0;
 	for (i = GTP_ADDR_LENGTH; i < ts->gtp_cfg_len; i++)
-		check_sum += config[i];
+		check_sum += config_data[i];
 
-	config[ts->gtp_cfg_len] = (~check_sum) + 1;
+	config_data[ts->gtp_cfg_len] = (~check_sum) + 1;
 
-	GTP_DEBUG_FUNC();
-	ret = gtp_send_cfg(ts->client);
+	ret = gtp_send_cfg(ts);
 	if (ret < 0)
-		GTP_ERROR("Send config error.");
+		pr_err("Send config error.");
 
+	ts->config_data = NULL;
+	ts->gtp_cfg_len = 0;
 	msleep(20);
 	return 0;
 }
 
-
 static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len)
 {
-	s32 i = 0;
+	u8 i = 0;
 
 	msg[0] = (addr >> 8) & 0xff;
 	msg[1] = addr & 0xff;
@@ -296,7 +271,7 @@
 			break;
 
 	if (i >= 5) {
-		GTP_ERROR("Read data from 0x%02x%02x failed!", msg[0], msg[1]);
+		pr_err("Read data from 0x%02x%02x failed!", msg[0], msg[1]);
 		return FAIL;
 	}
 
@@ -305,19 +280,19 @@
 
 static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val)
 {
-	s32 i = 0;
-	u8 msg[3];
-
-	msg[0] = (addr >> 8) & 0xff;
-	msg[1] = addr & 0xff;
-	msg[2] = val;
+	u8 i = 0;
+	u8 msg[3] = {
+		(addr >> 8) & 0xff,
+		addr & 0xff,
+		val,
+	};
 
 	for (i = 0; i < 5; i++)
 		if (gup_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0)
 			break;
 
 	if (i >= 5) {
-		GTP_ERROR("Set data to 0x%02x%02x failed!", msg[0], msg[1]);
+		pr_err("Set data to 0x%02x%02x failed!", msg[0], msg[1]);
 		return FAIL;
 	}
 
@@ -335,7 +310,7 @@
 	ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO,
 					&buf[GTP_ADDR_LENGTH], 4);
 	if (ret == FAIL) {
-		GTP_ERROR("[get_ic_fw_msg]get hw_info failed,exit");
+		pr_err("get hw_info failed,exit");
 		return FAIL;
 	}
 
@@ -344,7 +319,7 @@
 	for (i = 0; i < 4; i++)
 		update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i];
 
-	GTP_DEBUG("IC Hardware info:%02x%02x%02x%02x",
+	pr_debug("IC Hardware info:%02x%02x%02x%02x",
 		update_msg.ic_fw_msg.hw_info[0],
 		update_msg.ic_fw_msg.hw_info[1],
 		update_msg.ic_fw_msg.hw_info[2],
@@ -354,31 +329,31 @@
 	for (retry = 0; retry < 2; retry++) {
 		ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1);
 		if (ret == FAIL) {
-			GTP_ERROR("Read firmware message fail.");
+			pr_err("Read firmware message fail.");
 			return ret;
 		}
 
 		update_msg.force_update = buf[GTP_ADDR_LENGTH];
 		if ((0xBE != update_msg.force_update) && (!retry)) {
-			GTP_INFO("The check sum in ic is error.");
-			GTP_INFO("The IC will be updated by force.");
+			pr_info("The check sum in ic is error.");
+			pr_info("The IC will be updated by force.");
 			continue;
 		}
 		break;
 	}
-	GTP_DEBUG("IC force update flag:0x%x", update_msg.force_update);
+	pr_debug("IC force update flag:0x%x", update_msg.force_update);
 
 	/*  step3:get pid & vid */
 	ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID,
 						&buf[GTP_ADDR_LENGTH], 6);
-	if (FAIL == ret) {
-		GTP_ERROR("[get_ic_fw_msg]get pid & vid failed,exit");
+	if (ret == FAIL) {
+		pr_err("get pid & vid failed,exit");
 		return FAIL;
 	}
 
 	memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid));
 	memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4);
-	GTP_DEBUG("IC Product id:%s", update_msg.ic_fw_msg.pid);
+	pr_debug("IC Product id:%s", update_msg.ic_fw_msg.pid);
 
 	/* GT9XX PID MAPPING
 	|-----FLASH-----RAM-----|
@@ -392,7 +367,7 @@
 	|------9110P----9111----|*/
 	if (update_msg.ic_fw_msg.pid[0] != 0) {
 		if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) {
-			GTP_DEBUG("IC Mapping Product id:%s",
+			pr_debug("IC Mapping Product id:%s",
 					update_msg.ic_fw_msg.pid);
 			memcpy(update_msg.ic_fw_msg.pid, "9110P", 5);
 		}
@@ -400,7 +375,7 @@
 
 	update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] +
 				(buf[GTP_ADDR_LENGTH + 5] << 8);
-	GTP_DEBUG("IC version id:%04x", update_msg.ic_fw_msg.vid);
+	pr_debug("IC version id:%04x", update_msg.ic_fw_msg.vid);
 
 	return SUCCESS;
 }
@@ -408,19 +383,21 @@
 s32 gup_enter_update_mode(struct i2c_client *client)
 {
 	s32 ret = -1;
-	s32 retry = 0;
+	u8 retry = 0;
 	u8 rd_buf[3];
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
 
 	/* step1:RST output low last at least 2ms */
-	GTP_GPIO_OUTPUT(GTP_RST_PORT, 0);
-	msleep(20);
+	gpio_direction_output(ts->pdata->reset_gpio, 0);
+	usleep(20000);
 
 	/* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */
-	GTP_GPIO_OUTPUT(GTP_INT_PORT, (client->addr == 0x14));
+	gpio_direction_output(ts->pdata->irq_gpio,
+			(client->addr == GTP_I2C_ADDRESS_HIGH));
 	msleep(20);
 
 	/* step3:RST output high reset guitar */
-	GTP_GPIO_OUTPUT(GTP_RST_PORT, 1);
+	gpio_direction_output(ts->pdata->reset_gpio, 1);
 
 	/* 20121211 modify start */
 	msleep(20);
@@ -428,25 +405,25 @@
 		/* step4:Hold ss51 & dsp */
 		ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 		if (ret <= 0) {
-			GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);
+			pr_debug("Hold ss51 & dsp I2C error,retry:%d", retry);
 			continue;
 		}
 
 		/* step5:Confirm hold */
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_DEBUG("Hold ss51 & dsp I2C error,retry:%d", retry);
+			pr_debug("Hold ss51 & dsp I2C error,retry:%d", retry);
 			continue;
 		}
 		if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) {
-			GTP_DEBUG("Hold ss51 & dsp confirm SUCCESS");
+			pr_debug("Hold ss51 & dsp confirm SUCCESS");
 			break;
 		}
-		GTP_DEBUG("Hold ss51 & dsp confirm 0x4180 failed,value:%d",
+		pr_debug("Hold ss51 & dsp confirm 0x4180 failed,value:%d",
 					rd_buf[GTP_ADDR_LENGTH]);
 	}
 	if (retry >= 200) {
-		GTP_ERROR("Enter update Hold ss51 failed.");
+		pr_err("Enter update Hold ss51 failed.");
 		return FAIL;
 	}
 
@@ -457,12 +434,13 @@
 	return ret;
 }
 
-void gup_leave_update_mode(void)
+void gup_leave_update_mode(struct i2c_client *client)
 {
-	GTP_GPIO_AS_INT(GTP_INT_PORT);
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
 
-	GTP_DEBUG("[leave_update_mode]reset chip.");
-	gtp_reset_guitar(i2c_connect_client, 20);
+	gpio_direction_input(ts->pdata->irq_gpio);
+	pr_debug("reset chip.");
+	gtp_reset_guitar(ts, 20);
 }
 
 /*	Get the correct nvram data
@@ -483,7 +461,8 @@
 	3. IC PID == 91XX || File PID == 91XX
 */
 
-static u8 gup_enter_update_judge(st_fw_head *fw_head)
+static u8 gup_enter_update_judge(struct i2c_client *client,
+					struct st_fw_head *fw_head)
 {
 	u16 u16_tmp;
 	s32 i = 0;
@@ -491,38 +470,37 @@
 	u16_tmp = fw_head->vid;
 	fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8);
 
-	GTP_DEBUG("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0],
+	pr_debug("FILE HARDWARE INFO:%02x%02x%02x%02x", fw_head->hw_info[0],
 		fw_head->hw_info[1], fw_head->hw_info[2], fw_head->hw_info[3]);
-	TP_DEBUG("FILE PID:%s", fw_head->pid);
-	TP_DEBUG("FILE VID:%04x", fw_head->vid);
+	pr_debug("FILE PID:%s", fw_head->pid);
+	pr_debug("FILE VID:%04x", fw_head->vid);
 
-	TP_DEBUG("IC HARDWARE INFO:%02x%02x%02x%02x",
+	pr_debug("IC HARDWARE INFO:%02x%02x%02x%02x",
 		update_msg.ic_fw_msg.hw_info[0],
 		update_msg.ic_fw_msg.hw_info[1],
 		update_msg.ic_fw_msg.hw_info[2],
 		update_msg.ic_fw_msg.hw_info[3]);
-	TP_DEBUG("IC PID:%s", update_msg.ic_fw_msg.pid);
-	TP_DEBUG("IC VID:%04x", update_msg.ic_fw_msg.vid);
+	pr_debug("IC PID:%s", update_msg.ic_fw_msg.pid);
+	pr_debug("IC VID:%04x", update_msg.ic_fw_msg.vid);
 
 	/* First two conditions */
 	if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info,
 			sizeof(update_msg.ic_fw_msg.hw_info))) {
-		GTP_DEBUG("Get the same hardware info.");
+		pr_debug("Get the same hardware info.");
 		if (update_msg.force_update != 0xBE) {
-			GTP_INFO("FW chksum error,need enter update.");
+			pr_info("FW chksum error,need enter update.");
 			return SUCCESS;
 		}
 
 		/* 20130523 start */
 		if (strlen(update_msg.ic_fw_msg.pid) < 3) {
-			GTP_INFO("Illegal IC pid, need enter update");
+			pr_info("Illegal IC pid, need enter update");
 			return SUCCESS;
 		} else {
 			for (i = 0; i < 3; i++) {
 				if ((update_msg.ic_fw_msg.pid[i] < 0x30) ||
 					(update_msg.ic_fw_msg.pid[i] > 0x39)) {
-					GTP_INFO("Illegal IC pid, out of " \
-					"bound, need enter update");
+					pr_info("Illegal IC pid, out of bound, need enter update");
 					return SUCCESS;
 				}
 			}
@@ -534,398 +512,243 @@
 		(!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) ||
 		(!memcmp(fw_head->pid, "91XX", 4))) {
 			if (!memcmp(fw_head->pid, "91XX", 4))
-				GTP_DEBUG("Force none same pid update mode.");
+				pr_debug("Force none same pid update mode.");
 			else
-				GTP_DEBUG("Get the same pid.");
+				pr_debug("Get the same pid.");
 
 			/* The third condition */
 			if (fw_head->vid > update_msg.ic_fw_msg.vid) {
-				GTP_INFO("Need enter update.");
+				pr_info("Need enter update.");
 				return SUCCESS;
 			}
-			GTP_ERROR("Don't meet the third condition.");
-			GTP_ERROR("File VID <= Ic VID, update aborted!");
+			pr_err("Don't meet the third condition.");
+			pr_err("File VID <= Ic VID, update aborted!");
 		} else {
-			GTP_ERROR("File PID != Ic PID, update aborted!");
+			pr_err("File PID != Ic PID, update aborted!");
 		}
 	} else {
-		GTP_ERROR("Different Hardware, update aborted!");
+		pr_err("Different Hardware, update aborted!");
 	}
 
 	return FAIL;
 }
 
-static u8 ascii2hex(u8 a)
+static s8 gup_update_config(struct i2c_client *client,
+					const struct firmware *cfg)
 {
-	s8 value = 0;
-
-	if (a >= '0' && a <= '9')
-		value = a - '0';
-	else if (a >= 'A' && a <= 'F')
-		value = a - 'A' + 0x0A;
-	else if (a >= 'a' && a <= 'f')
-		value = a - 'a' + 0x0A;
-	else
-		value = 0xff;
-
-	return value;
-}
-
-static s8 gup_update_config(struct i2c_client *client)
-{
-	s32 file_len = 0;
 	s32 ret = 0;
 	s32 i = 0;
 	s32 file_cfg_len = 0;
-	s32 chip_cfg_len = 0;
+	u32 chip_cfg_len = 0;
 	s32 count = 0;
 	u8 *buf;
-	u8 *pre_buf;
 	u8 *file_config;
-	/* u8 checksum = 0; */
 	u8 pid[8];
+	u8 high, low;
 
-	if (update_msg.cfg_file == NULL) {
-		GTP_ERROR("[update_cfg]No need to upgrade config!");
+	if (!cfg || !cfg->data) {
+		pr_err("No need to upgrade config!");
 		return FAIL;
 	}
-	file_len = update_msg.cfg_file->f_op->llseek(update_msg.cfg_file,
-							0, SEEK_END);
 
 	ret = gup_get_ic_msg(client, GUP_REG_PID_VID, pid, 6);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_cfg]Read product id & version id fail.");
+		pr_err("Read product id & version id fail.");
 		return FAIL;
 	}
 	pid[5] = '\0';
-	GTP_DEBUG("update cfg get pid:%s", &pid[GTP_ADDR_LENGTH]);
+	pr_debug("update cfg get pid:%s", &pid[GTP_ADDR_LENGTH]);
 
 	chip_cfg_len = 186;
 	if (!memcmp(&pid[GTP_ADDR_LENGTH], "968", 3) ||
-	!memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) ||
-	!memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) {
+		!memcmp(&pid[GTP_ADDR_LENGTH], "910", 3) ||
+		!memcmp(&pid[GTP_ADDR_LENGTH], "960", 3)) {
 		chip_cfg_len = 228;
 	}
-	GTP_DEBUG("[update_cfg]config file len:%d", file_len);
-	GTP_DEBUG("[update_cfg]need config len:%d", chip_cfg_len);
-	if ((file_len+5) < chip_cfg_len*5) {
-		GTP_ERROR("Config length error");
+	pr_debug("config file ASCII len:%d", cfg->size);
+	pr_debug("need config binary len:%d", chip_cfg_len);
+	if ((cfg->size + 5) < chip_cfg_len * 5) {
+		pr_err("Config length error");
 		return -EINVAL;
 	}
 
-	buf = kzalloc(file_len, GFP_KERNEL);
-	pre_buf = kzalloc(file_len, GFP_KERNEL);
-	file_config = kzalloc(chip_cfg_len + GTP_ADDR_LENGTH, GFP_KERNEL);
-	update_msg.cfg_file->f_op->llseek(update_msg.cfg_file, 0, SEEK_SET);
-
-	GTP_DEBUG("[update_cfg]Read config from file.");
-	ret = update_msg.cfg_file->f_op->read(update_msg.cfg_file,
-			(char *)pre_buf, file_len, &update_msg.cfg_file->f_pos);
-	if (ret < 0) {
-		GTP_ERROR("[update_cfg]Read config file failed.");
-		goto update_cfg_file_failed;
+	buf = devm_kzalloc(&client->dev, cfg->size, GFP_KERNEL);
+	if (!buf) {
+		dev_err(&client->dev, "Memory allocation failed for buf.");
+		return -ENOMEM;
 	}
 
-	GTP_DEBUG("[update_cfg]Delete illgal charactor.");
-	for (i = 0, count = 0; i < file_len; i++) {
-		if (pre_buf[i] == ' ' || pre_buf[i] == '\r'
-					|| pre_buf[i] == '\n')
+	file_config = devm_kzalloc(&client->dev, chip_cfg_len + GTP_ADDR_LENGTH,
+								GFP_KERNEL);
+	if (!file_config) {
+		dev_err(&client->dev, "Memory allocation failed.");
+		return -ENOMEM;
+	}
+
+	pr_debug("Delete illgal charactor.");
+	for (i = 0, count = 0; i < cfg->size; i++) {
+		if (cfg->data[i] == ' ' || cfg->data[i] == '\r'
+					|| cfg->data[i] == '\n')
 			continue;
-		buf[count++] = pre_buf[i];
+		buf[count++] = cfg->data[i];
 	}
 
-	GTP_DEBUG("[update_cfg]Ascii to hex.");
+	pr_debug("Ascii to hex.");
 	file_config[0] = GTP_REG_CONFIG_DATA >> 8;
 	file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
-	for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i + = 5) {
-		if ((buf[i] == '0') && ((buf[i+1] == 'x') ||
-						(buf[i+1] == 'X'))) {
-			u8 high, low;
-			high = ascii2hex(buf[i+2]);
-			low = ascii2hex(buf[i+3]);
+	for (i = 0, file_cfg_len = GTP_ADDR_LENGTH; i < count; i = i + 5) {
+		if ((buf[i] == '0') && ((buf[i + 1] == 'x') ||
+						(buf[i + 1] == 'X'))) {
+			ret = hex2bin(&high, &buf[i + 2], 1);
+			if (ret) {
+				pr_err("Failed to convert high address from hex2bin");
+				return ret;
+			}
+			ret = hex2bin(&low, &buf[i + 3], 1);
+			if (ret) {
+				pr_err("Failed to convert low address from hex2bin");
+				return ret;
+			}
 
 			if ((high == 0xFF) || (low == 0xFF)) {
 				ret = 0;
-				GTP_ERROR("[update_cfg]Illegal config file.");
-				goto update_cfg_file_failed;
+				pr_err("Illegal config file.");
+				return ret;
 			}
 			file_config[file_cfg_len++] = (high<<4) + low;
 		} else {
 			ret = 0;
-			GTP_ERROR("[update_cfg]Illegal config file.");
-			goto update_cfg_file_failed;
+			pr_err("Illegal config file.");
+			return ret;
 		}
 	}
 
-	/* cal checksum */
-	/* for(i=GTP_ADDR_LENGTH; i<chip_cfg_len; i++)
-		checksum += file_config[i];
-	file_config[chip_cfg_len] = (~checksum) + 1;
-	file_config[chip_cfg_len+1] = 0x01; */
-
-	GTP_DEBUG("config:");
-	GTP_DEBUG_ARRAY(file_config+2, file_cfg_len);
-
 	i = 0;
 	while (i++ < 5) {
 		ret = gup_i2c_write(client, file_config, file_cfg_len);
 		if (ret > 0) {
-			GTP_INFO("[update_cfg]Send config SUCCESS.");
+			pr_info("Send config SUCCESS.");
 			break;
 		}
-		GTP_ERROR("[update_cfg]Send config i2c error.");
+		pr_err("Send config i2c error.");
 	}
 
-update_cfg_file_failed:
-	kfree(pre_buf);
-	kfree(buf);
-	kfree(file_config);
 	return ret;
 }
 
-#if GTP_HEADER_FW_UPDATE
-static u8 gup_check_fs_mounted(char *path_name)
+static s32 gup_get_firmware_file(struct i2c_client *client,
+		struct st_update_msg *msg, u8 *path)
 {
-	struct path root_path;
-	struct path path;
-	int err;
-	err = kern_path("/", LOOKUP_FOLLOW, &root_path);
+	s32 ret;
+	const struct firmware *fw = NULL;
 
-	if (err) {
-		GTP_DEBUG("\"/\" NOT Mounted: %d", err);
-		return FAIL;
-	}
-	err = kern_path(path_name, LOOKUP_FOLLOW, &path);
-
-	if (err) {
-		GTP_DEBUG("/data/ NOT Mounted: %d", err);
-		return FAIL;
+	ret = request_firmware(&fw, path, &client->dev);
+	if (ret < 0) {
+		dev_info(&client->dev, "Cannot get firmware - %s (%d)\n",
+					path, ret);
+		return -EEXIST;
 	}
 
-	return SUCCESS;
+	dev_dbg(&client->dev, "Config File: %s size=%d", path, fw->size);
+	msg->fw_data =
+		devm_kzalloc(&client->dev, fw->size, GFP_KERNEL);
+	if (!msg->fw_data) {
+		dev_err(&client->dev,
+			"Not enough memory for firmware data.");
+		release_firmware(fw);
+		return -ENOMEM;
+	}
 
-	/* if (path.mnt->mnt_sb == root_path.mnt->mnt_sb)
-		return FAIL;
-	else
-		return SUCCESS; */
+	memcpy(msg->fw_data, fw->data, fw->size);
+	msg->fw_len = fw->size;
+	msg->need_free = true;
+	release_firmware(fw);
+	return 0;
 }
-#endif
 
-static u8 gup_check_update_file(struct i2c_client *client, st_fw_head *fw_head,
-								u8 *path)
+static u8 gup_check_firmware_name(struct i2c_client *client,
+					u8 **path_p)
+{
+	u8 len;
+	u8 *fname;
+
+	if (!(*path_p)) {
+		*path_p = GOODIX_FIRMWARE_FILE_NAME;
+		return 0;
+	}
+
+	len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX);
+	if (len >= FIRMWARE_NAME_LEN_MAX) {
+		dev_err(&client->dev, "firmware name too long!");
+		return -EINVAL;
+	}
+
+	fname = strrchr(*path_p, '/');
+	if (fname) {
+		fname = fname + 1;
+		*path_p = fname;
+	}
+	return 0;
+}
+
+static u8 gup_check_update_file(struct i2c_client *client,
+			struct st_fw_head *fw_head, u8 *path)
 {
 	s32 ret = 0;
 	s32 i = 0;
 	s32 fw_checksum = 0;
-	u8 buf[FW_HEAD_LENGTH];
+	u16 temp;
+	const struct firmware *fw = NULL;
 
-	if (path) {
-		GTP_DEBUG("Update File path:%s, %d", path, strlen(path));
-		update_msg.file = file_open(path, O_RDONLY, 0);
-
-		if (IS_ERR(update_msg.file)) {
-			GTP_ERROR("Open update file(%s) error!", path);
-			return FAIL;
-		}
-	} else {
-#if GTP_HEADER_FW_UPDATE
-		for (i = 0; i < (GUP_SEARCH_FILE_TIMES); i++) {
-			GTP_DEBUG("Waiting for /data mounted [%d]", i);
-
-			if (gup_check_fs_mounted("/data") == SUCCESS) {
-				GTP_DEBUG("/data Mounted!");
-				break;
-			}
-			msleep(3000);
-		}
-		if (i >= (GUP_SEARCH_FILE_TIMES)) {
-			GTP_ERROR("Wait for /data mounted timeout!");
-			return FAIL;
-		}
-
-		/* update config */
-		update_msg.cfg_file = file_open(CONFIG_FILE_PATH_1,
-							O_RDONLY, 0);
-
-		if (IS_ERR(update_msg.cfg_file)) {
-			GTP_DEBUG("%s is unavailable", CONFIG_FILE_PATH_1);
-		} else {
-			GTP_INFO("Update Config File: %s", CONFIG_FILE_PATH_1);
-			ret = gup_update_config(client);
-			if (ret <= 0)
-				GTP_ERROR("Update config failed.");
-			filp_close(update_msg.cfg_file, NULL);
-		}
-
-		if (sizeof(header_fw_array) < (FW_HEAD_LENGTH+FW_SECTION_LENGTH
-		*4 + FW_DSP_ISP_LENGTH+FW_DSP_LENGTH + FW_BOOT_LENGTH)) {
-			GTP_ERROR("INVALID header_fw_array, check your " \
-				"gt9xx_firmware.h file!");
-			return FAIL;
-		}
-		update_msg.file = file_open(UPDATE_FILE_PATH_2, O_CREAT |
-								O_RDWR, 0666);
-		if ((IS_ERR(update_msg.file))) {
-			GTP_ERROR("Failed to Create file: %s for fw_header!",
-							UPDATE_FILE_PATH_2);
-			return FAIL;
-		}
-		update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET);
-		update_msg.file->f_op->write(update_msg.file,
-			(char *)header_fw_array, sizeof(header_fw_array),
-			&update_msg.file->f_pos);
-		file_close(update_msg.file, NULL);
-		update_msg.file = file_open(UPDATE_FILE_PATH_2, O_RDONLY, 0);
-#else
-		u8 fp_len = max(sizeof(UPDATE_FILE_PATH_1),
-						sizeof(UPDATE_FILE_PATH_2));
-		u8 cfp_len = max(sizeof(CONFIG_FILE_PATH_1),
-						sizeof(CONFIG_FILE_PATH_2));
-		u8 *search_update_path = kzalloc(fp_len, GFP_KERNEL);
-		u8 *search_cfg_path = kzalloc(cfp_len, GFP_KERNEL);
-		/* Begin to search update file,the config file & firmware
-			file must be in the same path,single or double. */
-		searching_file = 1;
-		for (i = 0; i < GUP_SEARCH_FILE_TIMES; i++) {
-			if (searching_file == 0) {
-				kfree(search_update_path);
-				kfree(search_cfg_path);
-				GTP_INFO(".bin/.cfg update file search " \
-						"forcely terminated!");
-				return FAIL;
-			}
-			if (i % 2) {
-				memcpy(search_update_path, UPDATE_FILE_PATH_1,
-						sizeof(UPDATE_FILE_PATH_1));
-				memcpy(search_cfg_path, CONFIG_FILE_PATH_1,
-						sizeof(CONFIG_FILE_PATH_1));
-			} else {
-				memcpy(search_update_path, UPDATE_FILE_PATH_2,
-						sizeof(UPDATE_FILE_PATH_2));
-				memcpy(search_cfg_path, CONFIG_FILE_PATH_2,
-						sizeof(CONFIG_FILE_PATH_2));
-			}
-
-			if (!(got_file_flag&0x0F)) {
-				update_msg.file = file_open(search_update_path,
-						O_RDONLY, 0);
-				if (!IS_ERR(update_msg.file)) {
-					GTP_DEBUG("Find the bin file");
-					got_file_flag |= 0x0F;
-				}
-			}
-			if (!(got_file_flag & 0xF0)) {
-				update_msg.cfg_file = file_open(search_cfg_path,
-						O_RDONLY, 0);
-				if (!IS_ERR(update_msg.cfg_file)) {
-					GTP_DEBUG("Find the cfg file");
-					got_file_flag |= 0xF0;
-				}
-			}
-
-			if (got_file_flag) {
-				if (got_file_flag == 0xFF)
-					break;
-				else
-					i += 4;
-			}
-			GTP_DEBUG("%3d:Searching %s %s file...", i,
-			(got_file_flag & 0x0F) ? "" : "bin",
-			(got_file_flag & 0xF0) ? "" : "cfg");
-
-			msleep(3000);
-		}
-
-		searching_file = 0;
-		kfree(search_update_path);
-		kfree(search_cfg_path);
-
-		if (!got_file_flag) {
-			GTP_ERROR("Can't find update file.");
-			goto load_failed;
-		}
-
-		if (got_file_flag & 0xF0) {
-			GTP_DEBUG("Got the update config file.");
-			ret = gup_update_config(client);
-			if (ret <= 0)
-				GTP_ERROR("Update config failed.");
-			filp_close(update_msg.cfg_file, NULL);
-			msleep(500); /* waiting config to be stored in FLASH. */
-		}
-		if (got_file_flag & 0x0F) {
-			GTP_DEBUG("Got the update firmware file.");
-		} else {
-			GTP_ERROR("No need to upgrade firmware.");
-			goto load_failed;
-		}
-#endif
-	}
-
-	update_msg.old_fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	update_msg.file->f_op->llseek(update_msg.file, 0, SEEK_SET);
-	/* update_msg.file->f_pos = 0; */
-
-	ret = update_msg.file->f_op->read(update_msg.file, (char *)buf,
-				FW_HEAD_LENGTH, &update_msg.file->f_pos);
+	ret = request_firmware(&fw, GOODIX_CONFIG_FILE_NAME, &client->dev);
 	if (ret < 0) {
-		GTP_ERROR("Read firmware head in update file error.");
-		goto load_failed;
+		dev_info(&client->dev, "Cannot get config file - %s (%d)\n",
+						GOODIX_CONFIG_FILE_NAME, ret);
+	} else {
+		dev_dbg(&client->dev,
+			"Update config File: %s", GOODIX_CONFIG_FILE_NAME);
+		ret = gup_update_config(client, fw);
+		if (ret <= 0)
+			dev_err(&client->dev, "Update config failed.");
+		release_firmware(fw);
 	}
-	memcpy(fw_head, buf, FW_HEAD_LENGTH);
+
+	update_msg.need_free = false;
+	update_msg.fw_len = 0;
+
+	if (gup_check_firmware_name(client, &path))
+		goto load_failed;
+
+	if (gup_get_firmware_file(client, &update_msg, path))
+		goto load_failed;
+
+	memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH);
 
 	/* check firmware legality */
 	fw_checksum = 0;
 	for (i = 0; i < FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH +
-			FW_DSP_LENGTH + FW_BOOT_LENGTH; i + = 2) {
-		u16 temp;
-		ret = update_msg.file->f_op->read(update_msg.file, (char *)buf,
-						2, &update_msg.file->f_pos);
-		if (ret < 0) {
-			GTP_ERROR("Read firmware file error.");
-			goto load_failed;
-		}
-		/* GTP_DEBUG("BUF[0]:%x", buf[0]); */
-		temp = (buf[0]<<8) + buf[1];
+			FW_DSP_LENGTH + FW_BOOT_LENGTH; i += 2) {
+		temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) +
+			update_msg.fw_data[FW_HEAD_LENGTH + i + 1];
 		fw_checksum += temp;
 	}
 
-	GTP_DEBUG("firmware checksum:%x", fw_checksum&0xFFFF);
+	pr_debug("firmware checksum:%x", fw_checksum & 0xFFFF);
 	if (fw_checksum & 0xFFFF) {
-		GTP_ERROR("Illegal firmware file.");
+		dev_err(&client->dev, "Illegal firmware file.");
 		goto load_failed;
 	}
 
 	return SUCCESS;
 
 load_failed:
-	set_fs(update_msg.old_fs);
+	if (update_msg.need_free) {
+		devm_kfree(&client->dev, update_msg.fw_data);
+		update_msg.need_free = false;
+	}
 	return FAIL;
 }
 
-#if 0
-static u8 gup_check_update_header(struct i2c_client *client,
-			st_fw_head *fw_head)
-{
-	const u8 *pos;
-	int i = 0;
-	u8 mask_num = 0;
-	s32 ret = 0;
-
-	pos = HEADER_UPDATE_DATA;
-
-	memcpy(fw_head, pos, FW_HEAD_LENGTH);
-	pos += FW_HEAD_LENGTH;
-
-	ret = gup_enter_update_judge(fw_head);
-	if (SUCCESS == ret)
-		return SUCCESS;
-	return FAIL;
-}
-#endif
-
 static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf, u16 start_addr,
 							u16 total_length)
 {
@@ -937,10 +760,10 @@
 	u8  rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
 	u8  retry = 0;
 
-	GTP_DEBUG("Begin burn %dk data to addr 0x%x", (total_length/1024),
+	pr_debug("Begin burn %dk data to addr 0x%x", (total_length / 1024),
 								start_addr);
 	while (burn_length < total_length) {
-		GTP_DEBUG("B/T:%04d/%04d", burn_length, total_length);
+		pr_debug("B/T:%04d/%04d", burn_length, total_length);
 		frame_length = ((total_length - burn_length) > PACK_SIZE)
 				? PACK_SIZE : (total_length - burn_length);
 		wr_buf[0] = (u8)(burn_addr>>8);
@@ -954,33 +777,26 @@
 			ret = gup_i2c_write(client, wr_buf,
 					GTP_ADDR_LENGTH + frame_length);
 			if (ret <= 0) {
-				GTP_ERROR("Write frame data i2c error.");
+				pr_err("Write frame data i2c error.");
 				continue;
 			}
 			ret = gup_i2c_read(client, rd_buf, GTP_ADDR_LENGTH +
 							frame_length);
 			if (ret <= 0) {
-				GTP_ERROR("Read back frame data i2c error.");
+				pr_err("Read back frame data i2c error.");
 				continue;
 			}
 
 			if (memcmp(&wr_buf[GTP_ADDR_LENGTH],
 				&rd_buf[GTP_ADDR_LENGTH], frame_length)) {
-				GTP_ERROR("Check frame data fail,not equal.");
-				GTP_DEBUG("write array:");
-				GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH],
-								frame_length);
-				GTP_DEBUG("read array:");
-				GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH],
-								frame_length);
+				pr_err("Check frame data fail,not equal.");
 				continue;
 			} else {
-				/* GTP_DEBUG("Check frame data success."); */
 				break;
 			}
 		}
 		if (retry >= MAX_FRAME_CHECK_TIME) {
-			GTP_ERROR("Burn frame data time out,exit.");
+			pr_err("Burn frame data time out,exit.");
 			return FAIL;
 		}
 		burn_length += frame_length;
@@ -991,20 +807,15 @@
 
 static u8 gup_load_section_file(u8 *buf, u16 offset, u16 length)
 {
-	s32 ret = 0;
-
-	if (update_msg.file == NULL) {
-		GTP_ERROR("cannot find update file,load section file fail.");
+	if (!update_msg.fw_data ||
+		update_msg.fw_len < FW_HEAD_LENGTH + offset + length) {
+		pr_err(
+			"<<-GTP->> cannot load section data. fw_len=%d read end=%d\n",
+			update_msg.fw_len ,
+			FW_HEAD_LENGTH + offset + length);
 		return FAIL;
 	}
-	update_msg.file->f_pos = FW_HEAD_LENGTH + offset;
-
-	ret = update_msg.file->f_op->read(update_msg.file, (char *)buf, length,
-						&update_msg.file->f_pos);
-	if (ret < 0) {
-		GTP_ERROR("Read update file fail.");
-		return FAIL;
-	}
+	memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset], length);
 
 	return SUCCESS;
 }
@@ -1023,30 +834,26 @@
 				? PACK_SIZE : (chk_length - recall_length);
 		ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length);
 		if (ret <= 0) {
-			GTP_ERROR("recall i2c error,exit");
+			pr_err("recall i2c error,exit");
 			return FAIL;
 		}
 
 		if (memcmp(&rd_buf[GTP_ADDR_LENGTH], &chk_src[recall_length],
 			frame_length)) {
-			GTP_ERROR("Recall frame data fail,not equal.");
-			GTP_DEBUG("chk_src array:");
-			GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length);
-			GTP_DEBUG("recall array:");
-			GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length);
+			pr_err("Recall frame data fail,not equal.");
 			return FAIL;
 		}
 
 		recall_length += frame_length;
 		recall_addr += frame_length;
 	}
-	GTP_DEBUG("Recall check %dk firmware success.", (chk_length/1024));
+	pr_debug("Recall check %dk firmware success.", (chk_length/1024));
 
 	return SUCCESS;
 }
 
 static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section,
-					u16 start_addr, u8 bank_cmdi)
+					u16 start_addr, u8 bank_cmd)
 {
 	s32 ret = 0;
 	u8  rd_buf[5];
@@ -1054,14 +861,14 @@
 	/* step1:hold ss51 & dsp */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]hold ss51 & dsp fail.");
+		pr_err("hold ss51 & dsp fail.");
 		return FAIL;
 	}
 
 	 /* step2:set scramble */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]set scramble fail.");
+		pr_err("set scramble fail.");
 		return FAIL;
 	}
 
@@ -1069,7 +876,7 @@
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
 						(bank_cmd >> 4)&0x0F);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]select bank %d fail.",
+		pr_err("select bank %d fail.",
 					(bank_cmd >> 4)&0x0F);
 		return FAIL;
 	}
@@ -1077,21 +884,21 @@
 	/* step4:enable accessing code */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]enable accessing code fail.");
+		pr_err("enable accessing code fail.");
 		return FAIL;
 	}
 
 	/* step5:burn 8k fw section */
 	ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH);
 	if (ret == FAIL)  {
-		GTP_ERROR("[burn_fw_section]burn fw_section fail.");
+		pr_err("burn fw_section fail.");
 		return FAIL;
 	}
 
 	/* step6:hold ss51 & release dsp */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]hold ss51 & release dsp fail.");
+		pr_err("hold ss51 & release dsp fail.");
 		return FAIL;
 	}
 	/* must delay */
@@ -1100,26 +907,24 @@
 	/* step7:send burn cmd to move data to flash from sram */
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]send burn cmd fail.");
+		pr_err("send burn cmd fail.");
 		return FAIL;
 	}
-	GTP_DEBUG("[burn_fw_section]Wait for the burn is complete......");
+	pr_debug("Wait for the burn is complete.");
 	do {
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_ERROR("[burn_fw_section]Get burn state fail");
+			pr_err("Get burn state fail");
 			return FAIL;
 		}
 		msleep(20);
-		/* GTP_DEBUG("[burn_fw_section]Get burn state:%d.",
-						rd_buf[GTP_ADDR_LENGTH]); */
 	} while (rd_buf[GTP_ADDR_LENGTH]);
 
 	/* step8:select bank */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
 							(bank_cmd >> 4)&0x0F);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]select bank %d fail.",
+		pr_err("select bank %d fail.",
 							(bank_cmd >> 4)&0x0F);
 		return FAIL;
 	}
@@ -1127,7 +932,7 @@
 	/* step9:enable accessing code */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]enable accessing code fail.");
+		pr_err("enable accessing code fail.");
 		return FAIL;
 	}
 
@@ -1135,14 +940,14 @@
 	ret = gup_recall_check(client, fw_section, start_addr,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_section]recall check 8k firmware fail.");
+		pr_err("recall check 8k firmware fail.");
 		return FAIL;
 	}
 
 	/* step11:disable accessing code */
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_section]disable accessing code fail.");
+		pr_err("disable accessing code fail.");
 		return FAIL;
 	}
 
@@ -1155,115 +960,105 @@
 	u8 *fw_dsp_isp = NULL;
 	u8  retry = 0;
 
-	GTP_DEBUG("[burn_dsp_isp]Begin burn dsp isp---->>");
+	pr_debug("Begin burn dsp isp.");
 
 	/* step1:alloc memory */
-	GTP_DEBUG("[burn_dsp_isp]step1:alloc memory");
+	pr_debug("step1:alloc memory");
 	while (retry++ < 5) {
-		fw_dsp_isp = kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL);
+		fw_dsp_isp = devm_kzalloc(&client->dev, FW_DSP_ISP_LENGTH,
+								GFP_KERNEL);
 		if (fw_dsp_isp == NULL) {
 			continue;
 		} else {
-			GTP_INFO("[burn_dsp_isp]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 					(FW_DSP_ISP_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_dsp_isp]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load dsp isp file data */
-	GTP_DEBUG("[burn_dsp_isp]step2:load dsp isp file data");
+	pr_debug("step2:load dsp isp file data");
 	ret = gup_load_section_file(fw_dsp_isp, (4 * FW_SECTION_LENGTH +
 		FW_DSP_LENGTH + FW_BOOT_LENGTH), FW_DSP_ISP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_dsp_isp]load firmware dsp_isp fail.");
-		goto exit_burn_dsp_isp;
+		pr_err("load firmware dsp_isp fail.");
+		return FAIL;
 	}
 
 	/* step3:disable wdt,clear cache enable */
-	GTP_DEBUG("[burn_dsp_isp]step3:disable wdt,clear cache enable");
+	pr_debug("step3:disable wdt,clear cache enable");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]disable wdt fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("disable wdt fail.");
+		return FAIL;
 	}
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]clear cache enable fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("clear cache enable fail.");
+		return FAIL;
 	}
 
 	/* step4:hold ss51 & dsp */
-	GTP_DEBUG("[burn_dsp_isp]step4:hold ss51 & dsp");
+	pr_debug("step4:hold ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]hold ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("hold ss51 & dsp fail.");
+		return FAIL;
 	}
 
 	/* step5:set boot from sram */
-	GTP_DEBUG("[burn_dsp_isp]step5:set boot from sram");
+	pr_debug("step5:set boot from sram");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]set boot from sram fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("set boot from sram fail.");
+		return FAIL;
 	}
 
 	/* step6:software reboot */
-	GTP_DEBUG("[burn_dsp_isp]step6:software reboot");
+	pr_debug("step6:software reboot");
 	ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]software reboot fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("software reboot fail.");
+		return FAIL;
 	}
 
 	/* step7:select bank2 */
-	GTP_DEBUG("[burn_dsp_isp]step7:select bank2");
+	pr_debug("step7:select bank2");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]select bank2 fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("select bank2 fail.");
+		return FAIL;
 	}
 
 	/* step8:enable accessing code */
-	GTP_DEBUG("[burn_dsp_isp]step8:enable accessing code");
+	pr_debug("step8:enable accessing code");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]enable accessing code fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("enable accessing code fail.");
+		return FAIL;
 	}
 
 	/* step9:burn 4k dsp_isp */
-	GTP_DEBUG("[burn_dsp_isp]step9:burn 4k dsp_isp");
+	pr_debug("step9:burn 4k dsp_isp");
 	ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_dsp_isp]burn dsp_isp fail.");
-		goto exit_burn_dsp_isp;
+		pr_err("burn dsp_isp fail.");
+		return FAIL;
 	}
 
 	/* step10:set scramble */
-	GTP_DEBUG("[burn_dsp_isp]step10:set scramble");
+	pr_debug("step10:set scramble");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_dsp_isp]set scramble fail.");
-		ret = FAIL;
-		goto exit_burn_dsp_isp;
+		pr_err("set scramble fail.");
+		return FAIL;
 	}
-	ret = SUCCESS;
 
-exit_burn_dsp_isp:
-	kfree(fw_dsp_isp);
-	return ret;
+	return SUCCESS;
 }
 
 static u8 gup_burn_fw_ss51(struct i2c_client *client)
@@ -1272,106 +1067,102 @@
 	u8  retry = 0;
 	s32 ret = 0;
 
-	GTP_DEBUG("[burn_fw_ss51]Begin burn ss51 firmware---->>");
+	pr_debug("Begin burn ss51 firmware.");
 
 	/* step1:alloc memory */
-	GTP_DEBUG("[burn_fw_ss51]step1:alloc memory");
+	pr_debug("step1:alloc memory");
 	while (retry++ < 5) {
-		fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+		fw_ss51 = devm_kzalloc(&client->dev, FW_SECTION_LENGTH,
+							GFP_KERNEL);
 		if (fw_ss51 == NULL) {
 			continue;
 		} else {
-			GTP_INFO("[burn_fw_ss51]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 						(FW_SECTION_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_fw_ss51]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load ss51 firmware section 1 file data */
-	GTP_DEBUG("[burn_fw_ss51]step2:load ss51 firmware section 1 file data");
+	pr_debug("step2:load ss51 firmware section 1 file data");
 	ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 1 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("load ss51 firmware section 1 fail.");
+		return FAIL;
 	}
 
 	/* step3:clear control flag */
-	GTP_DEBUG("[burn_fw_ss51]step3:clear control flag");
+	pr_debug("step3:clear control flag");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_ss51]clear control flag fail.");
-		ret = FAIL;
-		goto exit_burn_fw_ss51;
+		pr_err("clear control flag fail.");
+		return FAIL;
 	}
 
 	/* step4:burn ss51 firmware section 1 */
-	GTP_DEBUG("[burn_fw_ss51]step4:burn ss51 firmware section 1");
+	pr_debug("step4:burn ss51 firmware section 1");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 1 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 1 fail.");
+		return FAIL;
 	}
 
 	/* step5:load ss51 firmware section 2 file data */
-	GTP_DEBUG("[burn_fw_ss51]step5:load ss51 firmware section 2 file data");
+	pr_debug("step5:load ss51 firmware section 2 file data");
 	ret = gup_load_section_file(fw_ss51, FW_SECTION_LENGTH,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 2 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("[burn_fw_ss51]load ss51 firmware section 2 fail.");
+		return FAIL;
 	}
 
 	/* step6:burn ss51 firmware section 2 */
-	GTP_DEBUG("[burn_fw_ss51]step6:burn ss51 firmware section 2");
+	pr_debug("step6:burn ss51 firmware section 2");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 2 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 2 fail.");
+		return FAIL;
 	}
 
 	/* step7:load ss51 firmware section 3 file data */
-	GTP_DEBUG("[burn_fw_ss51]step7:load ss51 firmware section 3 file data");
+	pr_debug("step7:load ss51 firmware section 3 file data");
 	ret = gup_load_section_file(fw_ss51, 2*FW_SECTION_LENGTH,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 3 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("load ss51 firmware section 3 fail.");
+		return FAIL;
 	}
 
 	/* step8:burn ss51 firmware section 3 */
-	GTP_DEBUG("[burn_fw_ss51]step8:burn ss51 firmware section 3");
+	pr_debug("step8:burn ss51 firmware section 3");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 3 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 3 fail.");
+		return FAIL;
 	}
 
 	/* step9:load ss51 firmware section 4 file data */
-	GTP_DEBUG("[burn_fw_ss51]step9:load ss51 firmware section 4 file data");
+	pr_debug("step9:load ss51 firmware section 4 file data");
 	ret = gup_load_section_file(fw_ss51, 3*FW_SECTION_LENGTH,
 							FW_SECTION_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]load ss51 firmware section 4 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("load ss51 firmware section 4 fail.");
+		return FAIL;
 	}
 
 	/* step10:burn ss51 firmware section 4 */
-	GTP_DEBUG("[burn_fw_ss51]step10:burn ss51 firmware section 4");
+	pr_debug("step10:burn ss51 firmware section 4");
 	ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_ss51]burn ss51 firmware section 4 fail.");
-		goto exit_burn_fw_ss51;
+		pr_err("burn ss51 firmware section 4 fail.");
+		return FAIL;
 	}
 
-	ret = SUCCESS;
-
-exit_burn_fw_ss51:
-	kfree(fw_ss51);
-	return ret;
+	return SUCCESS;
 }
 
 static u8 gup_burn_fw_dsp(struct i2c_client *client)
@@ -1381,111 +1172,101 @@
 	u8  retry = 0;
 	u8  rd_buf[5];
 
-	GTP_DEBUG("[burn_fw_dsp]Begin burn dsp firmware---->>");
+	pr_debug("Begin burn dsp firmware.");
 	/* step1:alloc memory */
-	GTP_DEBUG("[burn_fw_dsp]step1:alloc memory");
+	pr_debug("step1:alloc memory");
 	while (retry++ < 5) {
-		fw_dsp = kzalloc(FW_DSP_LENGTH, GFP_KERNEL);
+		fw_dsp = devm_kzalloc(&client->dev, FW_DSP_LENGTH,
+							GFP_KERNEL);
 		if (fw_dsp == NULL) {
 			continue;
 		} else  {
-			GTP_INFO("[burn_fw_dsp]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 					(FW_SECTION_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_fw_dsp]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load firmware dsp */
-	GTP_DEBUG("[burn_fw_dsp]step2:load firmware dsp");
+	pr_debug("step2:load firmware dsp");
 	ret = gup_load_section_file(fw_dsp, 4*FW_SECTION_LENGTH, FW_DSP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_dsp]load firmware dsp fail.");
-		goto exit_burn_fw_dsp;
+		pr_err("load firmware dsp fail.");
+		return ret;
 	}
 
 	/* step3:select bank3 */
-	GTP_DEBUG("[burn_fw_dsp]step3:select bank3");
+	pr_debug("step3:select bank3");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]select bank3 fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("select bank3 fail.");
+		return FAIL;
 	}
 
 	/* Step4:hold ss51 & dsp */
-	GTP_DEBUG("[burn_fw_dsp]step4:hold ss51 & dsp");
+	pr_debug("step4:hold ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]hold ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("hold ss51 & dsp fail.");
+		return FAIL;
 	}
 
 	/* step5:set scramble */
-	GTP_DEBUG("[burn_fw_dsp]step5:set scramble");
+	pr_debug("step5:set scramble");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]set scramble fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("set scramble fail.");
+		return FAIL;
 	}
 
 	/* step6:release ss51 & dsp */
-	GTP_DEBUG("[burn_fw_dsp]step6:release ss51 & dsp");
+	pr_debug("step6:release ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]release ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_dsp;
+		pr_err("release ss51 & dsp fail.");
+		return FAIL;
 	}
 	/* must delay */
 	msleep(20);
 
 	/* step7:burn 4k dsp firmware */
-	GTP_DEBUG("[burn_fw_dsp]step7:burn 4k dsp firmware");
+	pr_debug("step7:burn 4k dsp firmware");
 	ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
-	if (FAIL == ret) {
-		GTP_ERROR("[burn_fw_dsp]burn fw_section fail.");
-		goto exit_burn_fw_dsp;
+	if (ret == FAIL) {
+		pr_err("[burn_fw_dsp]burn fw_section fail.");
+		return ret;
 	}
 
 	/* step8:send burn cmd to move data to flash from sram */
-	GTP_DEBUG("[burn_fw_dsp]step8:send burn cmd to move data to flash" \
-						"from sram");
+	pr_debug("step8:send burn cmd to move data to flash from sram");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_dsp]send burn cmd fail.");
-		goto exit_burn_fw_dsp;
+		pr_err("send burn cmd fail.");
+		return ret;
 	}
-	GTP_DEBUG("[burn_fw_dsp]Wait for the burn is complete......");
+	pr_debug("Wait for the burn is complete.");
 	do {
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_ERROR("[burn_fw_dsp]Get burn state fail");
-			goto exit_burn_fw_dsp;
+			pr_err("Get burn state fail");
+			return ret;
 		}
 		msleep(20);
-		/* GTP_DEBUG("[burn_fw_dsp]Get burn state:%d.",
-						rd_buf[GTP_ADDR_LENGTH]); */
 	} while (rd_buf[GTP_ADDR_LENGTH]);
 
 	/* step9:recall check 4k dsp firmware */
-	GTP_DEBUG("[burn_fw_dsp]step9:recall check 4k dsp firmware");
+	pr_debug("step9:recall check 4k dsp firmware");
 	ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_dsp]recall check 4k dsp firmware fail.");
-		goto exit_burn_fw_dsp;
+		pr_err("recall check 4k dsp firmware fail.");
+		return ret;
 	}
 
-	ret = SUCCESS;
-
-exit_burn_fw_dsp:
-	kfree(fw_dsp);
-	return ret;
+	return SUCCESS;
 }
 
 static u8 gup_burn_fw_boot(struct i2c_client *client)
@@ -1495,176 +1276,165 @@
 	u8  retry = 0;
 	u8  rd_buf[5];
 
-	GTP_DEBUG("[burn_fw_boot]Begin burn bootloader firmware---->>");
+	pr_debug("Begin burn bootloader firmware.");
 
 	/* step1:Alloc memory */
-	GTP_DEBUG("[burn_fw_boot]step1:Alloc memory");
+	pr_debug("step1:Alloc memory");
 	while (retry++ < 5) {
-		fw_boot = kzalloc(FW_BOOT_LENGTH, GFP_KERNEL);
+		fw_boot = devm_kzalloc(&client->dev, FW_BOOT_LENGTH,
+							GFP_KERNEL);
 		if (fw_boot == NULL) {
 			continue;
 		} else {
-			GTP_INFO("[burn_fw_boot]Alloc %dk byte memory success.",
+			pr_info("Alloc %dk byte memory success.",
 						(FW_BOOT_LENGTH/1024));
 			break;
 		}
 	}
-	if (retry >= 5) {
-		GTP_ERROR("[burn_fw_boot]Alloc memory fail,exit.");
+	if (retry == 5) {
+		pr_err("Alloc memory fail,exit.");
 		return FAIL;
 	}
 
 	/* step2:load firmware bootloader */
-	GTP_DEBUG("[burn_fw_boot]step2:load firmware bootloader");
+	pr_debug("step2:load firmware bootloader");
 	ret = gup_load_section_file(fw_boot, (4 * FW_SECTION_LENGTH +
 				FW_DSP_LENGTH), FW_BOOT_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_boot]load firmware dsp fail.");
-		goto exit_burn_fw_boot;
+		pr_err("load firmware dsp fail.");
+		return ret;
 	}
 
 	/* step3:hold ss51 & dsp */
-	GTP_DEBUG("[burn_fw_boot]step3:hold ss51 & dsp");
+	pr_debug("step3:hold ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]hold ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("hold ss51 & dsp fail.");
+		return FAIL;
 	}
 
 	/* step4:set scramble */
-	GTP_DEBUG("[burn_fw_boot]step4:set scramble");
+	pr_debug("step4:set scramble");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]set scramble fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("set scramble fail.");
+		return FAIL;
 	}
 
 	/* step5:release ss51 & dsp */
-	GTP_DEBUG("[burn_fw_boot]step5:release ss51 & dsp");
+	pr_debug("step5:release ss51 & dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]release ss51 & dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("release ss51 & dsp fail.");
+		return FAIL;
 	}
 	/* must delay */
 	msleep(20);
 
 	/* step6:select bank3 */
-	GTP_DEBUG("[burn_fw_boot]step6:select bank3");
+	pr_debug("step6:select bank3");
 	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]select bank3 fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("select bank3 fail.");
+		return FAIL;
 	}
 
 	/* step7:burn 2k bootloader firmware */
-	GTP_DEBUG("[burn_fw_boot]step7:burn 2k bootloader firmware");
+	pr_debug("step7:burn 2k bootloader firmware");
 	ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_boot]burn fw_section fail.");
-		goto exit_burn_fw_boot;
+		pr_err("burn fw_section fail.");
+		return ret;
 	}
 
 	/* step7:send burn cmd to move data to flash from sram */
-	GTP_DEBUG("[burn_fw_boot]step7:send burn cmd to move data to" \
-				"flash from sram");
+	pr_debug("step7:send burn cmd to flash data from sram");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]send burn cmd fail.");
-		goto exit_burn_fw_boot;
+		pr_err("send burn cmd fail.");
+		return ret;
 	}
-	GTP_DEBUG("[burn_fw_boot]Wait for the burn is complete......");
+	pr_debug("Wait for the burn is complete.");
 	do {
 		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
 		if (ret <= 0) {
-			GTP_ERROR("[burn_fw_boot]Get burn state fail");
-			goto exit_burn_fw_boot;
+			pr_err("Get burn state fail");
+			return ret;
 		}
 		msleep(20);
-		/* GTP_DEBUG("[burn_fw_boot]Get burn state:%d.",
-						rd_buf[GTP_ADDR_LENGTH]); */
 	} while (rd_buf[GTP_ADDR_LENGTH]);
 
 	/* step8:recall check 2k bootloader firmware */
-	GTP_DEBUG("[burn_fw_boot]step8:recall check 2k bootloader firmware");
+	pr_debug("step8:recall check 2k bootloader firmware");
 	ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
 	if (ret == FAIL) {
-		GTP_ERROR("[burn_fw_boot]recall check 4k dsp firmware fail.");
-		goto exit_burn_fw_boot;
+		pr_err("recall check 4k dsp firmware fail.");
+		return ret;
 	}
 
 	/* step9:enable download DSP code  */
-	GTP_DEBUG("[burn_fw_boot]step9:enable download DSP code ");
+	pr_debug("step9:enable download DSP code ");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]enable download DSP code fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("enable download DSP code fail.");
+		return FAIL;
 	}
 
 	/* step10:release ss51 & hold dsp */
-	GTP_DEBUG("[burn_fw_boot]step10:release ss51 & hold dsp");
+	pr_debug("step10:release ss51 & hold dsp");
 	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08);
 	if (ret <= 0) {
-		GTP_ERROR("[burn_fw_boot]release ss51 & hold dsp fail.");
-		ret = FAIL;
-		goto exit_burn_fw_boot;
+		pr_err("release ss51 & hold dsp fail.");
+		return FAIL;
 	}
 
-	ret = SUCCESS;
-
-exit_burn_fw_boot:
-	kfree(fw_boot);
-	return ret;
+	return SUCCESS;
 }
 
 s32 gup_update_proc(void *dir)
 {
 	s32 ret = 0;
-	u8  retry = 0;
-	st_fw_head fw_head;
+	u8 retry = 0;
+	struct st_fw_head fw_head;
 	struct goodix_ts_data *ts = NULL;
 
-	GTP_DEBUG("[update_proc]Begin update ......");
+	pr_debug("Begin update.");
+
+	if (!i2c_connect_client) {
+		pr_err("No i2c connect client for %s\n", __func__);
+		return -EIO;
+	}
 
 	show_len = 1;
 	total_len = 100;
-	if (dir == NULL)
-		/* wait main thread to be completed */
-	msleep(3000);
 
 	ts = i2c_get_clientdata(i2c_connect_client);
 
 	if (searching_file) {
 		/* exit .bin update file searching  */
 		searching_file = 0;
-		GTP_INFO("Exiting searching .bin update file...");
+		pr_info("Exiting searching .bin update file.");
 		/* wait for auto update quitted completely */
 		while ((show_len != 200) && (show_len != 100))
 			msleep(100);
 	}
 
-	update_msg.file = NULL;
 	ret = gup_check_update_file(i2c_connect_client, &fw_head, (u8 *)dir);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]check update file fail.");
+		pr_err("check update file fail.");
 		goto file_fail;
 	}
 
 	/* gtp_reset_guitar(i2c_connect_client, 20); */
 	ret = gup_get_ic_fw_msg(i2c_connect_client);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]get ic message fail.");
+		pr_err("get ic message fail.");
 		goto file_fail;
 	}
 
-	ret = gup_enter_update_judge(&fw_head);
+	ret = gup_enter_update_judge(ts->client, &fw_head);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]Check *.bin file fail.");
+		pr_err("Check *.bin file fail.");
 		goto file_fail;
 	}
 
@@ -1675,7 +1445,7 @@
 #endif
 	ret = gup_enter_update_mode(i2c_connect_client);
 	if (ret == FAIL) {
-		GTP_ERROR("[update_proc]enter update mode fail.");
+		pr_err("enter update mode fail.");
 		goto update_fail;
 	}
 
@@ -1684,52 +1454,46 @@
 		total_len = 100;
 		ret = gup_burn_dsp_isp(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn dsp isp fail.");
+			pr_err("burn dsp isp fail.");
 			continue;
 		}
 
 		show_len += 10;
 		ret = gup_burn_fw_ss51(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn ss51 firmware fail.");
+			pr_err("burn ss51 firmware fail.");
 			continue;
 		}
 
 		show_len += 40;
 		ret = gup_burn_fw_dsp(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn dsp firmware fail.");
+			pr_err("burn dsp firmware fail.");
 			continue;
 		}
 
 		show_len += 20;
 		ret = gup_burn_fw_boot(i2c_connect_client);
 		if (ret == FAIL) {
-			GTP_ERROR("[update_proc]burn bootloader fw fail.");
+			pr_err("burn bootloader fw fail.");
 			continue;
 		}
 		show_len += 10;
-		GTP_INFO("[update_proc]UPDATE SUCCESS.");
+		pr_info("UPDATE SUCCESS.");
 		break;
 	}
 	if (retry >= 5) {
-		GTP_ERROR("[update_proc]retry timeout,UPDATE FAIL.");
+		pr_err("retry timeout,UPDATE FAIL.");
 		goto update_fail;
 	}
 
-	GTP_DEBUG("[update_proc]leave update mode.");
-	gup_leave_update_mode();
+	pr_debug("leave update mode.");
+	gup_leave_update_mode(i2c_connect_client);
 
 	msleep(100);
 
-	/* GTP_DEBUG("[update_proc]send config.");
-	ret = gtp_send_cfg(i2c_connect_client);
-	if(ret < 0) {
-		GTP_ERROR("[update_proc]send config fail.");
-	} */
-
 	if (ts->fw_error) {
-		GTP_INFO("firmware error auto update, resent config!");
+		pr_info("firmware error auto update, resent config!");
 		gup_init_panel(ts);
 	}
 	show_len = 100;
@@ -1740,7 +1504,11 @@
 #if GTP_ESD_PROTECT
 	gtp_esd_switch(ts->client, SWITCH_ON);
 #endif
-	filp_close(update_msg.file, NULL);
+	if (update_msg.need_free) {
+		devm_kfree(&ts->client->dev, update_msg.fw_data);
+		update_msg.need_free = false;
+	}
+
 	return SUCCESS;
 
 update_fail:
@@ -1752,26 +1520,28 @@
 #endif
 
 file_fail:
-	if (update_msg.file && !IS_ERR(update_msg.file))
-		filp_close(update_msg.file, NULL);
-
 	show_len = 200;
 	total_len = 100;
+	if (update_msg.need_free) {
+		devm_kfree(&ts->client->dev, update_msg.fw_data);
+		update_msg.need_free = false;
+	}
 	return FAIL;
 }
 
-#if GTP_AUTO_UPDATE
+static void gup_update_work(struct work_struct *work)
+{
+	if (gup_update_proc(NULL) == FAIL)
+		pr_err("Goodix update work fail!\n");
+}
+
 u8 gup_init_update_proc(struct goodix_ts_data *ts)
 {
-	struct task_struct *thread = NULL;
+	dev_dbg(&ts->client->dev, "Ready to run update work.");
 
-	GTP_INFO("Ready to run update thread.");
-	thread = kthread_run(gup_update_proc, (void *)NULL, "guitar_update");
-	if (IS_ERR(thread)) {
-		GTP_ERROR("Failed to create update thread.\n");
-		return -EINVAL;
-	}
+	INIT_DELAYED_WORK(&ts->goodix_update_work, gup_update_work);
+	schedule_delayed_work(&ts->goodix_update_work,
+		msecs_to_jiffies(3000));
 
 	return 0;
 }
-#endif
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 7da0376..dce9dee 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -1559,7 +1559,7 @@
 		}
 
 		dev_dbg(&fwu->rmi4_data->i2c_client->dev,
-				"%s: Firmware image size = %d\n",
+				"%s: Firmware image size = %zu\n",
 				__func__, fw_entry->size);
 
 		fwu->data_buffer = fw_entry->data;
@@ -1670,7 +1670,7 @@
 
 	if (count < fwu->config_size) {
 		dev_err(&rmi4_data->i2c_client->dev,
-				"%s: Not enough space (%d bytes) in buffer\n",
+				"%s: Not enough space (%zu bytes) in buffer\n",
 				__func__, count);
 		return -EINVAL;
 	}
@@ -1905,12 +1905,20 @@
 		struct device_attribute *attr, const char *buf, size_t count)
 {
 	int retval;
-	unsigned long config_area;
+	unsigned short config_area;
+	struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
 
-	retval = kstrtoul(buf, 10, &config_area);
+	retval = kstrtou16(buf, 10, &config_area);
 	if (retval)
 		return retval;
 
+	if (config_area < 0x00 || config_area > 0x03) {
+		dev_err(&rmi4_data->i2c_client->dev,
+			"%s: Incorrect value of config_area\n",
+			 __func__);
+		return -EINVAL;
+	}
+
 	fwu->config_area = config_area;
 
 	return count;
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 7152ec8..ca47547 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -113,16 +113,15 @@
 
 static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data);
 
-static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data);
-
 static int synaptics_rmi4_check_configuration(struct synaptics_rmi4_data
 		*rmi4_data);
 
-#ifdef CONFIG_PM
+
 static int synaptics_rmi4_suspend(struct device *dev);
 
 static int synaptics_rmi4_resume(struct device *dev);
 
+#ifdef CONFIG_PM
 static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
 		struct device_attribute *attr, char *buf);
 
@@ -425,6 +424,31 @@
 static bool exp_fn_inited;
 static struct mutex exp_fn_list_mutex;
 static struct list_head exp_fn_list;
+
+static int synaptics_rmi4_debug_suspend_set(void *_data, u64 val)
+{
+	struct synaptics_rmi4_data *rmi4_data = _data;
+
+	if (val)
+		synaptics_rmi4_suspend(&rmi4_data->input_dev->dev);
+	else
+		synaptics_rmi4_resume(&rmi4_data->input_dev->dev);
+
+	return 0;
+}
+
+static int synaptics_rmi4_debug_suspend_get(void *_data, u64 *val)
+{
+	struct synaptics_rmi4_data *rmi4_data = _data;
+
+	*val = rmi4_data->suspended;
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, synaptics_rmi4_debug_suspend_get,
+			synaptics_rmi4_debug_suspend_set, "%lld\n");
+
 #ifdef CONFIG_PM
 static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -449,30 +473,6 @@
 	return count;
 }
 
-static int synaptics_rmi4_debug_suspend_set(void *_data, u64 val)
-{
-	struct synaptics_rmi4_data *rmi4_data = _data;
-
-	if (val)
-		synaptics_rmi4_suspend(&rmi4_data->input_dev->dev);
-	else
-		synaptics_rmi4_resume(&rmi4_data->input_dev->dev);
-
-	return 0;
-}
-
-static ssize_t synaptics_rmi4_debug_suspend_get(void *_data, u64 *val)
-{
-	struct synaptics_rmi4_data *rmi4_data = _data;
-
-	*val = rmi4_data->suspended;
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, synaptics_rmi4_debug_suspend_get,
-			synaptics_rmi4_debug_suspend_set, "%lld\n");
-
 #ifdef CONFIG_FB
 static void configure_sleep(struct synaptics_rmi4_data *rmi4_data)
 {
@@ -502,6 +502,11 @@
 	return;
 }
 #endif
+#else
+static void configure_sleep(struct synaptics_rmi4_data *rmi4_data)
+{
+	return;
+}
 #endif
 
 static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
@@ -3665,6 +3670,14 @@
 {
 	return 0;
 };
+static int synaptics_rmi4_suspend(struct device *dev);
+{
+	return 0;
+}
+static int synaptics_rmi4_resume(struct device *dev);
+{
+	return 0;
+}
 #endif
 
 static const struct i2c_device_id synaptics_rmi4_id_table[] = {
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index 7abd909..8478b24 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -461,7 +461,7 @@
 	return;
 }
 
-static char *rmi_char_devnode(struct device *dev, mode_t *mode)
+static char *rmi_char_devnode(struct device *dev, umode_t *mode)
 {
 	if (!mode)
 		return NULL;
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 5a1806e..38dd41b 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -43,6 +43,7 @@
 #define IOMMU_SECURE_CFG	2
 #define IOMMU_SECURE_PTBL_SIZE  3
 #define IOMMU_SECURE_PTBL_INIT  4
+#define IOMMU_SET_CP_POOL_SIZE	5
 #define IOMMU_SECURE_MAP	6
 #define IOMMU_SECURE_UNMAP      7
 #define IOMMU_SECURE_MAP2 0x0B
@@ -51,9 +52,21 @@
 
 /* commands for SCM_SVC_UTIL */
 #define IOMMU_DUMP_SMMU_FAULT_REGS 0X0C
+#define MAXIMUM_VIRT_SIZE	(300*SZ_1M)
+
+
+#define MAKE_CP_VERSION(major, minor, patch) \
+	(((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
+
 
 static struct iommu_access_ops *iommu_access_ops;
 
+static const struct of_device_id msm_smmu_list[] = {
+	{ .compatible = "qcom,msm-smmu-v1", },
+	{ .compatible = "qcom,msm-smmu-v2", },
+	{ }
+};
+
 struct msm_scm_paddr_list {
 	unsigned int list;
 	unsigned int list_size;
@@ -78,6 +91,11 @@
 	unsigned int flags;
 };
 
+struct msm_cp_pool_size {
+	uint32_t size;
+	uint32_t spare;
+};
+
 #define NUM_DUMP_REGS 14
 /*
  * some space to allow the number of registers returned by the secure
@@ -282,15 +300,37 @@
 	int psize[2] = {0, 0};
 	unsigned int spare;
 	int ret, ptbl_ret = 0;
+	int version;
 
-	for_each_compatible_node(np, NULL, "qcom,msm-smmu-v1")
-		if (of_find_property(np, "qcom,iommu-secure-id", NULL))
+	for_each_matching_node(np, msm_smmu_list)
+		if (of_find_property(np, "qcom,iommu-secure-id", NULL) &&
+				of_device_is_available(np))
 			break;
 
 	if (!np)
 		return 0;
 
 	of_node_put(np);
+
+	version = scm_get_feat_version(SCM_SVC_MP);
+
+	if (version >= MAKE_CP_VERSION(1, 1, 1)) {
+		struct msm_cp_pool_size psize;
+		int retval;
+
+		psize.size = MAXIMUM_VIRT_SIZE;
+		psize.spare = 0;
+
+		ret = scm_call(SCM_SVC_MP, IOMMU_SET_CP_POOL_SIZE, &psize,
+				sizeof(psize), &retval, sizeof(retval));
+
+		if (ret) {
+			pr_err("scm call IOMMU_SET_CP_POOL_SIZE failed\n");
+			goto fail;
+		}
+
+	}
+
 	ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_PTBL_SIZE, &spare,
 			sizeof(spare), psize, sizeof(psize));
 	if (ret) {
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index e776dbb..9208599 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -136,11 +136,11 @@
 #define	FLASH_SELFCHECK_ENABLE		0x80
 #define FLASH_RAMP_STEP_27US		0xBF
 
-#define FLASH_STROBE_SW			0xC0
-#define FLASH_STROBE_HW			0x04
+#define FLASH_HW_SW_STROBE_SEL_MASK	0x04
 #define FLASH_STROBE_MASK		0xC7
 #define FLASH_LED_0_OUTPUT		0x80
 #define FLASH_LED_1_OUTPUT		0x40
+#define FLASH_TORCH_OUTPUT		0xC0
 
 #define FLASH_CURRENT_PRGM_MIN		1
 #define FLASH_CURRENT_PRGM_SHIFT	1
@@ -255,7 +255,7 @@
 	WLED_OVP_35V,
 	WLED_OVP_32V,
 	WLED_OVP_29V,
-	WLED_OVP_37V,
+	WLED_OVP_27V,
 };
 
 enum flash_headroom {
@@ -1001,6 +1001,13 @@
 				goto error_reg_write;
 			}
 
+			if (!led->flash_cfg->strobe_type)
+				led->flash_cfg->trigger_flash &=
+						~FLASH_HW_SW_STROBE_SEL_MASK;
+			else
+				led->flash_cfg->trigger_flash |=
+						FLASH_HW_SW_STROBE_SEL_MASK;
+
 			rc = qpnp_led_masked_write(led,
 				FLASH_LED_STROBE_CTRL(led->base),
 				led->flash_cfg->trigger_flash,
@@ -1080,30 +1087,22 @@
 			 */
 			usleep(FLASH_RAMP_UP_DELAY_US);
 
-			if (!led->flash_cfg->strobe_type) {
-				rc = qpnp_led_masked_write(led,
-					FLASH_LED_STROBE_CTRL(led->base),
-					led->flash_cfg->trigger_flash,
-					led->flash_cfg->trigger_flash);
-				if (rc) {
-					dev_err(&led->spmi_dev->dev,
-					"LED %d strobe reg write failed(%d)\n",
-					led->id, rc);
-					goto error_flash_set;
-				}
-			} else {
-				rc = qpnp_led_masked_write(led,
-					FLASH_LED_STROBE_CTRL(led->base),
-					(led->flash_cfg->trigger_flash |
-					FLASH_STROBE_HW),
-					(led->flash_cfg->trigger_flash |
-					FLASH_STROBE_HW));
-				if (rc) {
-					dev_err(&led->spmi_dev->dev,
-					"LED %d strobe reg write failed(%d)\n",
-					led->id, rc);
-					goto error_flash_set;
-				}
+			if (!led->flash_cfg->strobe_type)
+				led->flash_cfg->trigger_flash &=
+						~FLASH_HW_SW_STROBE_SEL_MASK;
+			else
+				led->flash_cfg->trigger_flash |=
+						FLASH_HW_SW_STROBE_SEL_MASK;
+
+			rc = qpnp_led_masked_write(led,
+				FLASH_LED_STROBE_CTRL(led->base),
+				led->flash_cfg->trigger_flash,
+				led->flash_cfg->trigger_flash);
+			if (rc) {
+				dev_err(&led->spmi_dev->dev,
+				"LED %d strobe reg write failed(%d)\n",
+				led->id, rc);
+				goto error_flash_set;
 			}
 		}
 	} else {
@@ -1496,7 +1495,7 @@
 	num_wled_strings = led->wled_cfg->num_strings;
 
 	/* verify ranges */
-	if (led->wled_cfg->ovp_val > WLED_OVP_37V) {
+	if (led->wled_cfg->ovp_val > WLED_OVP_27V) {
 		dev_err(&led->spmi_dev->dev, "Invalid ovp value\n");
 		return -EINVAL;
 	}
@@ -1614,6 +1613,15 @@
 
 	}
 
+	/* Reset WLED enable register */
+	rc = qpnp_led_masked_write(led, WLED_MOD_CTRL_REG(led->base),
+		WLED_8_BIT_MASK, WLED_BOOST_OFF);
+	if (rc) {
+		dev_err(&led->spmi_dev->dev,
+			"WLED write ctrl reg failed(%d)\n", rc);
+		return rc;
+	}
+
 	/* dump wled registers */
 	qpnp_dump_regs(led, wled_debug_regs, ARRAY_SIZE(wled_debug_regs));
 
@@ -2733,7 +2741,7 @@
 			led->flash_cfg->enable_module = FLASH_ENABLE_MODULE;
 		} else
 			led->flash_cfg->enable_module = FLASH_ENABLE_ALL;
-		led->flash_cfg->trigger_flash = FLASH_STROBE_SW;
+		led->flash_cfg->trigger_flash = FLASH_TORCH_OUTPUT;
 	}
 
 	rc = of_property_read_u32(node, "qcom,current", &val);
@@ -3440,10 +3448,15 @@
 
 	return 0;
 }
+
+#ifdef CONFIG_OF
 static struct of_device_id spmi_match_table[] = {
-	{	.compatible = "qcom,leds-qpnp",
-	}
+	{ .compatible = "qcom,leds-qpnp",},
+	{ },
 };
+#else
+#define spmi_match_table NULL
+#endif
 
 static struct spmi_driver qpnp_leds_driver = {
 	.driver		= {
diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c
index eda6150..3f7ba6b 100644
--- a/drivers/media/platform/msm/camera_v2/camera/camera.c
+++ b/drivers/media/platform/msm/camera_v2/camera/camera.c
@@ -64,9 +64,13 @@
 	struct msm_v4l2_event_data *event_data =
 		(struct msm_v4l2_event_data *)&event->u.data[0];
 
-	if (event_data->status > MSM_CAMERA_ERR_EVT_BASE)
+	if (event_data->status > MSM_CAMERA_ERR_EVT_BASE) {
+		pr_err("%s : event_data status out of bounds\n",
+				__func__);
+		pr_err("%s : Line %d event_data->status 0X%x\n",
+				__func__, __LINE__, event_data->status);
 		return -EFAULT;
-
+	}
 	return 0;
 }
 
@@ -461,9 +465,11 @@
 	struct camera_v4l2_private *sp;
 
 	sp = kzalloc(sizeof(*sp), GFP_KERNEL);
-	if (!sp)
-		return -ENOMEM;
 
+	if (!sp) {
+		pr_err("%s : memory not available\n", __func__);
+		return -ENOMEM;
+	}
 	filep->private_data = &sp->fh;
 
 	/* stream_id = open id */
@@ -498,9 +504,10 @@
 	/* free up this buffer when stream is done */
 	q->drv_priv =
 		kzalloc(sizeof(struct msm_v4l2_format_data), GFP_KERNEL);
-	if (!q->drv_priv)
+	if (!q->drv_priv) {
+		pr_err("%s : memory not available\n", __func__);
 		return -ENOMEM;
-
+	}
 	q->mem_ops = msm_vb2_get_q_mem_ops();
 	q->ops = msm_vb2_get_q_ops();
 
@@ -530,38 +537,60 @@
 	BUG_ON(!pvdev);
 
 	rc = camera_v4l2_fh_open(filep);
-	if (rc < 0)
-		goto fh_open_fail;
 
+	if (rc < 0) {
+		pr_err("%s : camera_v4l2_fh_open failed Line %d rc %d\n",
+				__func__, __LINE__, rc);
+		goto fh_open_fail;
+	}
 	/* every stream has a vb2 queue */
 	rc = camera_v4l2_vb2_q_init(filep);
-	if (rc < 0)
-		goto vb2_q_fail;
 
+	if (rc < 0) {
+		pr_err("%s : vb2 queue init fails Line %d rc %d\n",
+				__func__, __LINE__, rc);
+		goto vb2_q_fail;
+	}
 	if (!atomic_read(&pvdev->opened)) {
 		pm_stay_awake(&pvdev->vdev->dev);
 
 		/* create a new session when first opened */
 		rc = msm_create_session(pvdev->vdev->num, pvdev->vdev);
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : session creation failed Line %d rc %d\n",
+					__func__, __LINE__, rc);
 			goto session_fail;
+		}
 		rc = msm_create_command_ack_q(pvdev->vdev->num, 0);
-		if (rc < 0)
-			goto command_ack_q_fail;
 
+		if (rc < 0) {
+			pr_err("%s : creation of command_ack queue failed\n",
+					__func__);
+			pr_err("%s : Line %d rc %d\n", __func__, __LINE__, rc);
+			goto command_ack_q_fail;
+		}
 		camera_pack_event(filep, MSM_CAMERA_NEW_SESSION, 0, -1, &event);
 		rc = msm_post_event(&event, MSM_POST_EVT_TIMEOUT);
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : posting of NEW_SESSION event failed\n",
+					__func__);
+			pr_err("%s : Line %d rc %d\n", __func__, __LINE__, rc);
 			goto post_fail;
-
+		}
 		rc = camera_check_event_status(&event);
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : checking event status fails Line %d rc %d\n",
+					__func__, __LINE__, rc);
 			goto post_fail;
+		}
 	} else {
 		rc = msm_create_command_ack_q(pvdev->vdev->num,
 			atomic_read(&pvdev->stream_cnt));
-		if (rc < 0)
+		if (rc < 0) {
+			pr_err("%s : creation of command_ack queue failed Line %d rc %d\n",
+					__func__, __LINE__, rc);
 			goto session_fail;
+		}
 	}
 
 	atomic_add(1, &pvdev->opened);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index 59b648d..a85f853 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -374,11 +374,14 @@
 		if (bufq->buf_type == ISP_SHARE_BUF) {
 			temp_buf_info = kzalloc(
 			   sizeof(struct msm_isp_buffer), GFP_ATOMIC);
-			temp_buf_info->buf_reuse_flag = 1;
-			temp_buf_info->buf_used[id] = 1;
-			temp_buf_info->buf_get_count = 1;
-			list_add_tail(&temp_buf_info->share_list,
-						  &bufq->share_head);
+			if (temp_buf_info) {
+				temp_buf_info->buf_reuse_flag = 1;
+				temp_buf_info->buf_used[id] = 1;
+				temp_buf_info->buf_get_count = 1;
+				list_add_tail(&temp_buf_info->share_list,
+							  &bufq->share_head);
+			} else
+				rc = -ENOMEM;
 		}
 	} else {
 		(*buf_info)->state = MSM_ISP_BUFFER_STATE_DEQUEUED;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 9dd0085..d33d34b 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -71,6 +71,12 @@
 	DISABLE_CAMIF_IMMEDIATELY
 };
 
+enum msm_isp_reset_type {
+	ISP_RST_HARD,
+	ISP_RST_SOFT,
+	ISP_RST_MAX
+};
+
 struct msm_isp_timestamp {
 	/*Monotonic clock for v4l2 buffer*/
 	struct timeval buf_time;
@@ -147,7 +153,8 @@
 
 struct msm_vfe_core_ops {
 	void (*reg_update) (struct vfe_device *vfe_dev);
-	long (*reset_hw) (struct vfe_device *vfe_dev);
+	long (*reset_hw) (struct vfe_device *vfe_dev,
+		enum msm_isp_reset_type reset_type);
 	int (*init_hw) (struct vfe_device *vfe_dev);
 	void (*init_hw_reg) (struct vfe_device *vfe_dev);
 	void (*release_hw) (struct vfe_device *vfe_dev);
@@ -397,6 +404,11 @@
 	uint32_t error_count;
 };
 
+struct msm_vfe_frame_ts {
+	struct timeval buf_time;
+	uint32_t frame_id;
+};
+
 struct vfe_device {
 	struct platform_device *pdev;
 	struct msm_sd_subdev subdev;
@@ -439,6 +451,7 @@
 	struct msm_vfe_axi_shared_data axi_data;
 	struct msm_vfe_stats_shared_data stats_data;
 	struct msm_vfe_error_info error_info;
+	struct msm_vfe_frame_ts frame_ts;
 	struct msm_isp_buf_mgr *buf_mgr;
 	int dump_reg;
 	int vfe_clk_idx;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 410fe8f..044f6f1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -152,6 +152,11 @@
 	msm_camera_io_w_mb(0x1CFFFFFF, vfe_dev->vfe_base + 0x20);
 	msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24);
 	msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28);
+	msm_camera_io_w(0x0, vfe_dev->vfe_base+0x6FC);
+	msm_camera_io_w( 0x10000000,vfe_dev->vfe_base + VFE32_RDI_BASE(1));
+	msm_camera_io_w( 0x10000000,vfe_dev->vfe_base + VFE32_RDI_BASE(2));
+	msm_camera_io_w(0x0, vfe_dev->vfe_base + VFE32_XBAR_BASE(0));
+	msm_camera_io_w(0x0, vfe_dev->vfe_base + VFE32_XBAR_BASE(4));
 
 }
 
@@ -322,7 +327,6 @@
 	uint32_t irq_status0, uint32_t irq_status1,
 	struct msm_isp_timestamp *ts)
 {
-	uint32_t rdi_status;
 	if (!(irq_status0 & 0x20) && !(irq_status1 & 0x1C000000))
 		return;
 
@@ -335,18 +339,6 @@
 	if (irq_status1 & BIT(28))
 		msm_isp_sof_notify(vfe_dev, VFE_RAW_2, ts);
 
-	if (vfe_dev->axi_data.stream_update) {
-		rdi_status = msm_camera_io_r(vfe_dev->vfe_base +
-						VFE32_XBAR_BASE(0));
-		rdi_status |= msm_camera_io_r(vfe_dev->vfe_base +
-						VFE32_XBAR_BASE(4));
-
-		if (((rdi_status & BIT(7)) || (rdi_status & BIT(7)) ||
-			(rdi_status & BIT(7)) || (rdi_status & BIT(7))) &&
-			(!(irq_status0 & 0x20)))
-			return;
-	}
-
 	if (vfe_dev->axi_data.stream_update)
 		msm_isp_axi_stream_update(vfe_dev);
 	if (atomic_read(&vfe_dev->stats_data.stats_update))
@@ -365,10 +357,24 @@
 	msm_camera_io_w_mb(0xF, vfe_dev->vfe_base + 0x260);
 }
 
-static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev)
+static uint32_t msm_vfe32_reset_values[ISP_RST_MAX] =
 {
+	0x3FF, /* ISP_RST_HARD reset everything */
+	0x3EF /* ISP_RST_SOFT same as HARD RESET */
+};
+
+static long msm_vfe32_reset_hardware(struct vfe_device *vfe_dev ,
+				enum msm_isp_reset_type reset_type)
+{
+
+	uint32_t rst_val;
+	if (reset_type >= ISP_RST_MAX) {
+		pr_err("%s: Error Invalid parameter\n", __func__);
+		reset_type = ISP_RST_HARD;
+	}
+	rst_val = msm_vfe32_reset_values[reset_type];
 	init_completion(&vfe_dev->reset_complete);
-	msm_camera_io_w_mb(0x3FF, vfe_dev->vfe_base + 0x4);
+	msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0x4);
 	return wait_for_completion_interruptible_timeout(
 	   &vfe_dev->reset_complete, msecs_to_jiffies(50));
 }
@@ -381,9 +387,8 @@
 		msm_camera_io_w_mb(reload_mask, vfe_dev->vfe_base + 0x38);
 	} else {
 		/*vfe32 B-family: 8610*/
-		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x24);
 		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x28);
-		msm_camera_io_w(0x0, vfe_dev->vfe_base + 0x20);
+		msm_camera_io_w(0x1C800000, vfe_dev->vfe_base + 0x20);
 		msm_camera_io_w_mb(0x1, vfe_dev->vfe_base + 0x18);
 		msm_camera_io_w(0x9AAAAAAA , vfe_dev->vfe_base + 0x600);
 		msm_camera_io_w(reload_mask, vfe_dev->vfe_base + 0x38);
@@ -632,9 +637,6 @@
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
 		msm_camera_io_w_mb(0x6, vfe_dev->vfe_base + 0x1E0);
-		vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	}
 }
@@ -708,6 +710,8 @@
 {
 	uint32_t val = 0;
 	uint32_t wm_base = VFE32_WM_BASE(stream_info->wm[plane_idx]);
+	/* FRAME BASED */
+	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base);
 	/*WR_IMAGE_SIZE*/
 	msm_camera_io_w(val, vfe_dev->vfe_base + wm_base + 0x10);
 	/*WR_BUFFER_CFG*/
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index ad4b75f..d53d7f6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -461,54 +461,62 @@
 {
 	uint32_t error_status1 = vfe_dev->error_info.error_mask1;
 	if (error_status1 & (1 << 0))
-		pr_err("%s: camif error status: 0x%x\n",
+		pr_err_ratelimited("%s: camif error status: 0x%x\n",
 			__func__, vfe_dev->error_info.camif_status);
 	if (error_status1 & (1 << 1))
-		pr_err("%s: stats bhist overwrite\n", __func__);
+		pr_err_ratelimited("%s: stats bhist overwrite\n", __func__);
 	if (error_status1 & (1 << 2))
-		pr_err("%s: stats cs overwrite\n", __func__);
+		pr_err_ratelimited("%s: stats cs overwrite\n", __func__);
 	if (error_status1 & (1 << 3))
-		pr_err("%s: stats ihist overwrite\n", __func__);
+		pr_err_ratelimited("%s: stats ihist overwrite\n", __func__);
 	if (error_status1 & (1 << 4))
-		pr_err("%s: realign buf y overflow\n", __func__);
+		pr_err_ratelimited("%s: realign buf y overflow\n", __func__);
 	if (error_status1 & (1 << 5))
-		pr_err("%s: realign buf cb overflow\n", __func__);
+		pr_err_ratelimited("%s: realign buf cb overflow\n", __func__);
 	if (error_status1 & (1 << 6))
-		pr_err("%s: realign buf cr overflow\n", __func__);
+		pr_err_ratelimited("%s: realign buf cr overflow\n", __func__);
 	if (error_status1 & (1 << 7)) {
-		pr_err("%s: violation\n", __func__);
+		pr_err_ratelimited("%s: violation\n", __func__);
 		msm_vfe40_process_violation_status(vfe_dev);
 	}
 	if (error_status1 & (1 << 9))
-		pr_err("%s: image master 0 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 0 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 10))
-		pr_err("%s: image master 1 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 1 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 11))
-		pr_err("%s: image master 2 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 2 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 12))
-		pr_err("%s: image master 3 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 3 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 13))
-		pr_err("%s: image master 4 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 4 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 14))
-		pr_err("%s: image master 5 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 5 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 15))
-		pr_err("%s: image master 6 bus overflow\n", __func__);
+		pr_err_ratelimited("%s: image master 6 bus overflow\n",
+			__func__);
 	if (error_status1 & (1 << 16))
-		pr_err("%s: status be bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status be bus overflow\n", __func__);
 	if (error_status1 & (1 << 17))
-		pr_err("%s: status bg bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status bg bus overflow\n", __func__);
 	if (error_status1 & (1 << 18))
-		pr_err("%s: status bf bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status bf bus overflow\n", __func__);
 	if (error_status1 & (1 << 19))
-		pr_err("%s: status awb bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status awb bus overflow\n", __func__);
 	if (error_status1 & (1 << 20))
-		pr_err("%s: status rs bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status rs bus overflow\n", __func__);
 	if (error_status1 & (1 << 21))
-		pr_err("%s: status cs bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status cs bus overflow\n", __func__);
 	if (error_status1 & (1 << 22))
-		pr_err("%s: status ihist bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status ihist bus overflow\n", __func__);
 	if (error_status1 & (1 << 23))
-		pr_err("%s: status skin bhist bus overflow\n", __func__);
+		pr_err_ratelimited("%s: status skin bhist bus overflow\n",
+			__func__);
 }
 
 static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
@@ -573,10 +581,24 @@
 	msm_camera_io_w_mb(0xF, vfe_dev->vfe_base + 0x378);
 }
 
-static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev)
+static uint32_t msm_vfe40_reset_values[ISP_RST_MAX] =
 {
+	0x1FF, /* ISP_RST_HARD reset everything */
+	0x1EF /* ISP_RST_SOFT all modules without registers */
+};
+
+
+static long msm_vfe40_reset_hardware(struct vfe_device *vfe_dev ,
+				enum msm_isp_reset_type reset_type)
+{
+	uint32_t rst_val;
+	if (reset_type >= ISP_RST_MAX) {
+		pr_err("%s: Error Invalid parameter\n", __func__);
+		reset_type = ISP_RST_HARD;
+	}
+	rst_val = msm_vfe40_reset_values[reset_type];
 	init_completion(&vfe_dev->reset_complete);
-	msm_camera_io_w_mb(0x1FF, vfe_dev->vfe_base + 0xC);
+	msm_camera_io_w_mb(rst_val, vfe_dev->vfe_base + 0xC);
 	return wait_for_completion_interruptible_timeout(
 		&vfe_dev->reset_complete, msecs_to_jiffies(50));
 }
@@ -878,9 +900,6 @@
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
 		msm_camera_io_w_mb(0x6, vfe_dev->vfe_base + 0x2F4);
-		vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
-		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
 		vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
 	}
 }
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 97b6347..0264d6d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -211,7 +211,7 @@
 				plane_cfg[plane_idx].output_width;
 		else
 			size = plane_cfg[plane_idx].output_height *
-				plane_cfg[plane_idx].output_width / 2;
+				plane_cfg[plane_idx].output_width;
 		break;
 	case V4L2_PIX_FMT_NV14:
 	case V4L2_PIX_FMT_NV41:
@@ -220,7 +220,7 @@
 				plane_cfg[plane_idx].output_width;
 		else
 			size = plane_cfg[plane_idx].output_height *
-				plane_cfg[plane_idx].output_width / 8;
+				plane_cfg[plane_idx].output_width;
 		break;
 	case V4L2_PIX_FMT_NV16:
 	case V4L2_PIX_FMT_NV61:
@@ -235,6 +235,21 @@
 	return size;
 }
 
+static void msm_isp_get_buffer_ts(struct vfe_device *vfe_dev,
+	struct msm_isp_timestamp *irq_ts, struct msm_isp_timestamp *ts)
+{
+	struct msm_vfe_frame_ts *frame_ts = &vfe_dev->frame_ts;
+	uint32_t frame_count = vfe_dev->error_info.info_dump_frame_count;
+
+	*ts = *irq_ts;
+	if (frame_count == frame_ts->frame_id) {
+		ts->buf_time = frame_ts->buf_time;
+	} else {
+		frame_ts->buf_time = irq_ts->buf_time;
+		frame_ts->frame_id = frame_count;
+	}
+}
+
 void msm_isp_axi_reserve_wm(struct msm_vfe_axi_shared_data *axi_data,
 	struct msm_vfe_axi_stream *stream_info)
 {
@@ -947,6 +962,68 @@
 	}
 }
 
+static void msm_isp_update_rdi_output_count(
+	  struct vfe_device *vfe_dev,
+	  struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd)
+{
+	int i;
+	struct msm_vfe_axi_stream *stream_info;
+	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+
+	if (stream_cfg_cmd->num_streams > MAX_NUM_STREAM) {
+		return;
+	}
+
+	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+		if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])
+		> MAX_NUM_STREAM) {
+			return;
+		}
+		stream_info =
+			&axi_data->stream_info[
+			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+		if (stream_info->stream_src < RDI_INTF_0)
+			continue;
+		if (stream_info->stream_src == RDI_INTF_0) {
+			if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_RAW_0].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_RAW_0].
+					raw_stream_count--;
+		} else if (stream_info->stream_src == RDI_INTF_1) {
+			if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_RAW_1].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_RAW_1].
+					raw_stream_count--;
+		} else if (stream_info->stream_src == RDI_INTF_2) {
+		       if (stream_cfg_cmd->cmd == START_STREAM)
+				vfe_dev->axi_data.src_info[VFE_RAW_2].
+					raw_stream_count++;
+			else
+				vfe_dev->axi_data.src_info[VFE_RAW_2].
+					raw_stream_count--;
+		}
+
+	}
+}
+
+static uint8_t msm_isp_get_curr_stream_cnt(
+	  struct vfe_device *vfe_dev)
+{
+         uint8_t curr_stream_cnt = 0;
+	  curr_stream_cnt = vfe_dev->axi_data.src_info[VFE_RAW_0].
+					raw_stream_count + vfe_dev->axi_data.src_info[VFE_RAW_1].
+					raw_stream_count + vfe_dev->axi_data.src_info[VFE_RAW_2].
+					raw_stream_count + vfe_dev->axi_data.src_info[VFE_PIX_0].
+					pix_stream_count  + vfe_dev->axi_data.src_info[VFE_PIX_0].
+					raw_stream_count;
+
+	  return curr_stream_cnt;
+}
+
 void msm_camera_io_dump_2(void __iomem *addr, int size)
 {
 	char line_str[128], *p_str;
@@ -1144,11 +1221,23 @@
 	vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
 
 	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+	msm_isp_update_rdi_output_count(vfe_dev, stream_cfg_cmd);
 	if (camif_update == ENABLE_CAMIF) {
 		vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id = 0;
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, camif_update);
 	}
+
+	if (vfe_dev->axi_data.src_info[VFE_RAW_0].raw_stream_count > 0) {
+		vfe_dev->axi_data.src_info[VFE_RAW_0].frame_id = 0;
+	}
+	else if (vfe_dev->axi_data.src_info[VFE_RAW_1].raw_stream_count > 0) {
+		vfe_dev->axi_data.src_info[VFE_RAW_1].frame_id = 0;
+	}
+	else if (vfe_dev->axi_data.src_info[VFE_RAW_2].raw_stream_count > 0) {
+		vfe_dev->axi_data.src_info[VFE_RAW_2].frame_id = 0;
+	}
+
 	if (wait_for_complete)
 		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
 
@@ -1160,7 +1249,7 @@
 			enum msm_isp_camif_update_state camif_update)
 {
 	int i, rc = 0;
-	uint8_t wait_for_complete = 0;
+	uint8_t wait_for_complete = 0, cur_stream_cnt = 0;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 
@@ -1216,6 +1305,15 @@
 		vfe_dev->hw_info->vfe_ops.core_ops.
 			update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY);
 	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
+	msm_isp_update_rdi_output_count(vfe_dev, stream_cfg_cmd);
+	cur_stream_cnt = msm_isp_get_curr_stream_cnt(vfe_dev);
+	if (cur_stream_cnt == 0) {
+		if (camif_update == DISABLE_CAMIF_IMMEDIATELY) {
+			vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+		}
+		vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_SOFT);
+		vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
+	}
 
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info = &axi_data->stream_info[
@@ -1365,6 +1463,7 @@
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_composite_info *comp_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+	struct msm_isp_timestamp buf_ts;
 
 	comp_mask = vfe_dev->hw_info->vfe_ops.axi_ops.
 		get_comp_mask(irq_status0, irq_status1);
@@ -1377,6 +1476,8 @@
 	pingpong_status =
 		vfe_dev->hw_info->vfe_ops.axi_ops.get_pingpong_status(vfe_dev);
 
+	msm_isp_get_buffer_ts(vfe_dev, ts, &buf_ts);
+
 	for (i = 0; i < axi_data->hw_info->num_comp_mask; i++) {
 		comp_info = &axi_data->composite_info[i];
 		if (comp_mask & (1 << i)) {
@@ -1409,7 +1510,7 @@
 				}
 				if (done_buf && !rc)
 					msm_isp_process_done_buf(vfe_dev,
-					stream_info, done_buf, ts);
+					stream_info, done_buf, &buf_ts);
 			}
 		}
 		wm_mask &= ~(comp_info->stream_composite_mask);
@@ -1441,7 +1542,7 @@
 			}
 			if (done_buf && !rc)
 				msm_isp_process_done_buf(vfe_dev,
-				stream_info, done_buf, ts);
+				stream_info, done_buf, &buf_ts);
 		}
 	}
 	return;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 3cb48d1..7347251 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -277,6 +277,43 @@
 	return rc;
 }
 
+static int msm_isp_get_max_clk_rate(struct vfe_device *vfe_dev, long *rate)
+{
+	int           clk_idx = 0;
+	unsigned long max_value = ~0;
+	long          round_rate = 0;
+
+	if (!vfe_dev || !rate) {
+		pr_err("%s:%d failed: vfe_dev %p rate %p\n", __func__, __LINE__,
+			vfe_dev, rate);
+		return -EINVAL;
+	}
+
+	*rate = 0;
+	if (!vfe_dev->hw_info) {
+		pr_err("%s:%d failed: vfe_dev->hw_info %p\n", __func__,
+			__LINE__, vfe_dev->hw_info);
+		return -EINVAL;
+	}
+
+	clk_idx = vfe_dev->hw_info->vfe_clk_idx;
+	if (clk_idx >= ARRAY_SIZE(vfe_dev->vfe_clk)) {
+		pr_err("%s:%d failed: clk_idx %d max array size %d\n",
+			__func__, __LINE__, clk_idx,
+			ARRAY_SIZE(vfe_dev->vfe_clk));
+		return -EINVAL;
+	}
+
+	round_rate = clk_round_rate(vfe_dev->vfe_clk[clk_idx], max_value);
+	if (round_rate < 0) {
+		pr_err("%s: Invalid vfe clock rate\n", __func__);
+		return -EINVAL;
+	}
+
+	*rate = round_rate;
+	return 0;
+}
+
 static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, long *rate)
 {
 	int rc = 0;
@@ -618,6 +655,23 @@
 	case GET_SOC_HW_VER:
 		*cfg_data = vfe_dev->soc_hw_version;
 		break;
+	case GET_MAX_CLK_RATE: {
+		int rc = 0;
+
+		if (cmd_len < sizeof(unsigned long)) {
+			pr_err("%s:%d failed: invalid cmd len %d exp %d\n",
+				__func__, __LINE__, cmd_len,
+				sizeof(unsigned long));
+			return -EINVAL;
+		}
+		rc = msm_isp_get_max_clk_rate(vfe_dev,
+			(unsigned long *)cfg_data);
+		if (rc < 0) {
+			pr_err("%s:%d failed: rc %d\n", __func__, __LINE__, rc);
+			return -EINVAL;
+		}
+		break;
+	}
 	}
 	return 0;
 }
@@ -1048,7 +1102,7 @@
 		return -EBUSY;
 	}
 
-	rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
+	rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev, ISP_RST_HARD);
 	if (rc <= 0) {
 		pr_err("%s: reset timeout\n", __func__);
 		mutex_unlock(&vfe_dev->core_mutex);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index de098c9..3f49f68 100755
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -200,7 +200,7 @@
 			ispif->base + ISPIF_VFE_m_INTF_CMD_0(i));
 		msm_camera_io_w(ISPIF_STOP_INTF_IMMEDIATELY,
 			ispif->base + ISPIF_VFE_m_INTF_CMD_1(i));
-		pr_debug("%s: base %x", __func__, (unsigned int)ispif->base);
+		pr_debug("%s: base %lx", __func__, (unsigned long)ispif->base);
 		msm_camera_io_w(0, ispif->base +
 			ISPIF_VFE_m_PIX_INTF_n_CID_MASK(i, 0));
 		msm_camera_io_w(0, ispif->base +
@@ -1045,7 +1045,8 @@
 	case MSM_SD_SHUTDOWN: {
 		struct ispif_device *ispif =
 			(struct ispif_device *)v4l2_get_subdevdata(sd);
-		msm_ispif_release(ispif);
+		if (ispif && ispif->base)
+			msm_ispif_release(ispif);
 		return 0;
 	}
 	default:
@@ -1197,6 +1198,7 @@
 
 static const struct of_device_id msm_ispif_dt_match[] = {
 	{.compatible = "qcom,ispif"},
+	{}
 };
 
 MODULE_DEVICE_TABLE(of, msm_ispif_dt_match);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index c8a4366..567a263 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -34,12 +34,20 @@
 #define ISPIF_VFE_m_INTF_CMD_0(m)                (0x0004 + ISPIF_VFE(m))
 #define ISPIF_VFE_m_INTF_CMD_1(m)                (0x0030 + ISPIF_VFE(m))
 #define ISPIF_VFE_m_PIX_INTF_n_CID_MASK(m, n)    (0x0010 + ISPIF_VFE(m) + 4*(n))
-#define ISPIF_VFE_m_RDI_INTF_n_CID_MASK(m, n)    (0x0014 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_INTF_n_CID_MASK(m, n)    (0x0014 + ISPIF_VFE(m) + \
+							((n > 0) ? (0x20) : 0) \
+							+ 8*(n))
 #define ISPIF_VFE_m_PIX_OUTPUT_n_MISR(m, n)      (0x0290 + ISPIF_VFE(m) + 4*(n))
-#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_0(m, n)    (0x0298 + ISPIF_VFE(m) + 8*(n))
-#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_1(m, n)    (0x029C + ISPIF_VFE(m) + 8*(n))
+#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_0(m, n)    (0x001C + ISPIF_VFE(m) + \
+							((n > 0) ? (0x24) : 0) \
+							+ 0xc*(n))
+#define ISPIF_VFE_m_RDI_OUTPUT_n_MISR_1(m, n)    (0x0020 + ISPIF_VFE(m) + \
+							((n > 0) ? (0x24) : 0) \
+							+ 0xc*(n))
 #define ISPIF_VFE_m_PIX_INTF_n_STATUS(m, n)      (0x0024 + ISPIF_VFE(m) + 4*(n))
-#define ISPIF_VFE_m_RDI_INTF_n_STATUS(m, n)      (0x0028 + ISPIF_VFE(m) + 4*(n))
+#define ISPIF_VFE_m_RDI_INTF_n_STATUS(m, n)      (0x0028 + ISPIF_VFE(m) + \
+							((n > 0) ? (0x34) : 0) \
+							+ 8*(n))
 
 /* Defines for compatibility with newer ISPIF versions */
 #define ISPIF_RST_CMD_1_ADDR                     (0x0000)
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
index 44a4014..cd35eb6 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -328,7 +328,7 @@
 int msm_jpeg_hw_exec_cmds(struct msm_jpeg_hw_cmd *hw_cmd_p, uint32_t m_cmds,
 	uint32_t max_size, void *base)
 {
-	int is_copy_to_user = -1;
+	int is_copy_to_user = 0;
 	uint32_t data;
 
 	while (m_cmds--) {
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index 5cc51ff..5c0dc22 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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,7 @@
 #include <linux/list.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/ratelimit.h>
 #include <media/msm_jpeg.h>
 #include "msm_jpeg_sync.h"
 #include "msm_jpeg_core.h"
@@ -721,6 +722,9 @@
 			kfree(hw_cmds_p);
 			return -EFAULT;
 		}
+	} else {
+		kfree(hw_cmds_p);
+		return is_copy_to_user;
 	}
 	kfree(hw_cmds_p);
 	return 0;
@@ -764,11 +768,12 @@
 	for (i = 0; i < 2; i++)
 		kfree(buf_out_free[i]);
 
+	pgmn_dev->state = MSM_JPEG_EXECUTING;
 	JPEG_DBG_HIGH("%s:%d] START\n", __func__, __LINE__);
 	wmb();
 	rc = msm_jpeg_ioctl_hw_cmds(pgmn_dev, arg);
 	wmb();
-	pgmn_dev->state = MSM_JPEG_EXECUTING;
+
 	JPEG_DBG("%s:%d]", __func__, __LINE__);
 	return rc;
 }
@@ -909,7 +914,7 @@
 		rc = msm_jpeg_ioctl_set_clk_rate(pgmn_dev, arg);
 		break;
 	default:
-		JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n",
+		pr_err_ratelimited("%s:%d] cmd = %d not supported\n",
 			__func__, __LINE__, _IOC_NR(cmd));
 		rc = -EINVAL;
 		break;
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 8a2c8e5..67f7c2b 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -341,17 +341,26 @@
 {
 	struct msm_session *session = NULL;
 
-	if (!msm_session_q)
+	if (!msm_session_q) {
+		pr_err("%s : session queue not available Line %d\n",
+				__func__, __LINE__);
 		return -ENODEV;
+	}
 
 	session = msm_queue_find(msm_session_q, struct msm_session,
 		list, __msm_queue_find_session, &session_id);
-	if (session)
+	if (session) {
+		pr_err("%s : Session not found Line %d\n",
+				__func__, __LINE__);
 		return -EINVAL;
+	}
 
 	session = kzalloc(sizeof(*session), GFP_KERNEL);
-	if (!session)
+	if (!session) {
+		pr_err("%s : Memory not available Line %d\n",
+				__func__, __LINE__);
 		return -ENOMEM;
+	}
 
 	session->session_id = session_id;
 	session->event_q.vdev = vdev;
@@ -367,17 +376,25 @@
 	struct msm_session *session;
 	struct msm_command_ack *cmd_ack;
 
-	if (!msm_session_q)
+	if (!msm_session_q) {
+		pr_err("%s : Session queue not available Line %d\n",
+				__func__, __LINE__);
 		return -ENODEV;
+	}
 
 	session = msm_queue_find(msm_session_q, struct msm_session,
 		list, __msm_queue_find_session, &session_id);
-	if (!session)
+	if (!session) {
+		pr_err("%s : Session not found Line %d\n",
+				__func__, __LINE__);
 		return -EINVAL;
+	}
 	mutex_lock(&session->lock);
 	cmd_ack = kzalloc(sizeof(*cmd_ack), GFP_KERNEL);
 	if (!cmd_ack) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : memory not available Line %d\n",
+				__func__, __LINE__);
 		return -ENOMEM;
 	}
 
@@ -652,6 +669,8 @@
 	spin_lock_irqsave(&msm_eventq_lock, flags);
 	if (!msm_eventq) {
 		spin_unlock_irqrestore(&msm_eventq_lock, flags);
+		pr_err("%s : msm event queue not available Line %d\n",
+				__func__, __LINE__);
 		return -ENODEV;
 	}
 	spin_unlock_irqrestore(&msm_eventq_lock, flags);
@@ -661,14 +680,19 @@
 	/* send to imaging server and wait for ACK */
 	session = msm_queue_find(msm_session_q, struct msm_session,
 		list, __msm_queue_find_session, &session_id);
-	if (WARN_ON(!session))
+	if (WARN_ON(!session)) {
+		pr_err("%s : session not found Line %d\n",
+				__func__, __LINE__);
 		return -EIO;
+	}
 	mutex_lock(&session->lock);
 	cmd_ack = msm_queue_find(&session->command_ack_q,
 		struct msm_command_ack, list,
 		__msm_queue_find_command_ack_q, &stream_id);
 	if (WARN_ON(!cmd_ack)) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : cmd_ack not found Line %d\n",
+				__func__, __LINE__);
 		return -EIO;
 	}
 
@@ -676,6 +700,8 @@
 
 	if (timeout < 0) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : timeout cannot be negative Line %d\n",
+				__func__, __LINE__);
 		return rc;
 	}
 
@@ -704,6 +730,8 @@
 		struct msm_command, list);
 	if (!cmd) {
 		mutex_unlock(&session->lock);
+		pr_err("%s : cmd dequeue failed Line %d\n",
+				__func__, __LINE__);
 		return -EINVAL;
 	}
 
@@ -711,9 +739,15 @@
 
 	/* compare cmd_ret and event */
 	if (WARN_ON(event->type != cmd->event.type) ||
-			WARN_ON(event->id != cmd->event.id))
+			WARN_ON(event->id != cmd->event.id)) {
+		pr_err("%s : Either event type or id didnot match Line %d\n",
+				__func__, __LINE__);
+		pr_err("%s : event->type %d event->id %d\n", __func__,
+				event->type, event->id);
+		pr_err("%s : cmd->event.type %d cmd->event.id %d\n", __func__,
+				cmd->event.type, cmd->event.id);
 		rc = -EINVAL;
-
+	}
 	*event = cmd->event;
 
 	kzfree(cmd);
@@ -1036,6 +1070,7 @@
 
 static const struct of_device_id msm_dt_match[] = {
 	{.compatible = "qcom,msm-cam"},
+	{}
 }
 
 MODULE_DEVICE_TABLE(of, msm_dt_match);
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 7520ce5..6994258 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -109,8 +109,9 @@
 	if (!list_empty(&buf_mngr_dev->buf_qhead)) {
 		list_for_each_entry_safe(bufs,
 			save, &buf_mngr_dev->buf_qhead, entry) {
-			pr_err("%s: Delete invalid bufs =%x\n", __func__,
-				(unsigned int)bufs);
+			pr_err("%s: Error delete invalid bufs =%x, ses_id=%d, str_id=%d, idx=%d\n",
+				__func__, (unsigned int)bufs, bufs->session_id,
+				bufs->stream_id, bufs->vb2_buf->v4l2_buf.index);
 			list_del_init(&bufs->entry);
 			kfree(bufs);
 		}
@@ -118,6 +119,36 @@
 	spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
 }
 
+static int msm_generic_buf_mngr_open(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	int rc = 0;
+	struct msm_buf_mngr_device *buf_mngr_dev = v4l2_get_subdevdata(sd);
+	if (!buf_mngr_dev) {
+		pr_err("%s buf manager device NULL\n", __func__);
+		rc = -ENODEV;
+		return rc;
+	}
+	buf_mngr_dev->msm_buf_mngr_open_cnt++;
+	return rc;
+}
+
+static int msm_generic_buf_mngr_close(struct v4l2_subdev *sd,
+	struct v4l2_subdev_fh *fh)
+{
+	int rc = 0;
+	struct msm_buf_mngr_device *buf_mngr_dev = v4l2_get_subdevdata(sd);
+	if (!buf_mngr_dev) {
+		pr_err("%s buf manager device NULL\n", __func__);
+		rc = -ENODEV;
+		return rc;
+	}
+	buf_mngr_dev->msm_buf_mngr_open_cnt--;
+	if (buf_mngr_dev->msm_buf_mngr_open_cnt == 0)
+		msm_buf_mngr_sd_shutdown(buf_mngr_dev);
+	return rc;
+}
+
 static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
 	unsigned int cmd, void *arg)
 {
@@ -141,6 +172,12 @@
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
 		rc = msm_buf_mngr_put_buf(buf_mngr_dev, argp);
 		break;
+	case VIDIOC_MSM_BUF_MNGR_INIT:
+		rc = msm_generic_buf_mngr_open(sd, NULL);
+		break;
+	case VIDIOC_MSM_BUF_MNGR_DEINIT:
+		rc = msm_generic_buf_mngr_close(sd, NULL);
+		break;
 	case MSM_SD_SHUTDOWN:
 		msm_buf_mngr_sd_shutdown(buf_mngr_dev);
 		break;
@@ -154,12 +191,19 @@
 	.ioctl = msm_buf_mngr_subdev_ioctl,
 };
 
+static const struct v4l2_subdev_internal_ops
+	msm_generic_buf_mngr_subdev_internal_ops = {
+	.open  = msm_generic_buf_mngr_open,
+	.close = msm_generic_buf_mngr_close,
+};
+
 static const struct v4l2_subdev_ops msm_buf_mngr_subdev_ops = {
 	.core = &msm_buf_mngr_subdev_core_ops,
 };
 
 static const struct of_device_id msm_buf_mngr_dt_match[] = {
 	{.compatible = "qcom,msm_buf_mngr"},
+	{}
 };
 
 static int __init msm_buf_mngr_init(void)
@@ -183,6 +227,8 @@
 	msm_buf_mngr_dev->subdev.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
 	msm_buf_mngr_dev->subdev.sd.entity.group_id =
 		MSM_CAMERA_SUBDEV_BUF_MNGR;
+	msm_buf_mngr_dev->subdev.sd.internal_ops =
+		&msm_generic_buf_mngr_subdev_internal_ops;
 	msm_buf_mngr_dev->subdev.close_seq = MSM_SD_CLOSE_4TH_CATEGORY;
 	rc = msm_sd_register(&msm_buf_mngr_dev->subdev);
 	if (rc != 0) {
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
index 56886cd..49fad22 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
@@ -36,5 +36,6 @@
 	spinlock_t buf_q_spinlock;
 	struct msm_sd_subdev subdev;
 	struct msm_sd_req_vb2_q vb2_ops;
+	uint32_t msm_buf_mngr_open_cnt;
 };
 #endif
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 532bebc..10a0085 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -67,6 +67,9 @@
 /* dump the frame command before writing to the hardware */
 #define  MSM_CPP_DUMP_FRM_CMD 0
 
+static int msm_cpp_buffer_ops(struct cpp_device *cpp_dev,
+	uint32_t buff_mgr_ops, struct msm_buf_mngr_info *buff_mgr_info);
+
 #if CONFIG_MSM_CPP_DBG
 #define CPP_DBG(fmt, args...) pr_err(fmt, ##args)
 #else
@@ -714,6 +717,14 @@
 			goto req_irq_fail;
 		}
 		cpp_dev->buf_mgr_subdev = msm_buf_mngr_get_subdev();
+
+		rc = msm_cpp_buffer_ops(cpp_dev,
+			VIDIOC_MSM_BUF_MNGR_INIT, NULL);
+		if (rc < 0) {
+			pr_err("buf mngr init failed\n");
+			free_irq(cpp_dev->irq->start, cpp_dev);
+			goto req_irq_fail;
+		}
 	}
 
 	cpp_dev->hw_info.cpp_hw_version =
@@ -757,7 +768,12 @@
 
 static void cpp_release_hardware(struct cpp_device *cpp_dev)
 {
+	int32_t rc;
 	if (cpp_dev->state != CPP_STATE_BOOT) {
+		rc = msm_cpp_buffer_ops(cpp_dev,
+			VIDIOC_MSM_BUF_MNGR_DEINIT, NULL);
+		if (rc < 0)
+			pr_err("error in buf mngr deinit rc=%d\n", rc);
 		free_irq(cpp_dev->irq->start, cpp_dev);
 		tasklet_kill(&cpp_dev->cpp_tasklet);
 		atomic_set(&cpp_dev->irq_cnt, 0);
@@ -807,7 +823,7 @@
 
 		/*Start firmware loading*/
 		msm_cpp_write(MSM_CPP_CMD_FW_LOAD, cpp_dev->base);
-		msm_cpp_write(MSM_CPP_END_ADDRESS, cpp_dev->base);
+		msm_cpp_write(fw->size, cpp_dev->base);
 		msm_cpp_write(MSM_CPP_START_ADDRESS, cpp_dev->base);
 
 		if (ptr_bin) {
@@ -1192,7 +1208,7 @@
 	uint32_t *cpp_frame_msg;
 	unsigned long in_phyaddr, out_phyaddr0, out_phyaddr1;
 	uint16_t num_stripes = 0;
-	struct msm_buf_mngr_info buff_mgr_info;
+	struct msm_buf_mngr_info buff_mgr_info, dup_buff_mgr_info;
 	struct msm_cpp_frame_info_t *u_frame_info =
 		(struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr;
 	int32_t status = 0;
@@ -1279,19 +1295,20 @@
 			new_frame->duplicate_identity);
 		memset(&new_frame->output_buffer_info[1], 0,
 			sizeof(struct msm_cpp_buffer_info_t));
-		memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
-		buff_mgr_info.session_id =
+		memset(&dup_buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
+		dup_buff_mgr_info.session_id =
 			((new_frame->duplicate_identity >> 16) & 0xFFFF);
-		buff_mgr_info.stream_id =
+		dup_buff_mgr_info.stream_id =
 			(new_frame->duplicate_identity & 0xFFFF);
 		rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
-			&buff_mgr_info);
+			&dup_buff_mgr_info);
 		if (rc < 0) {
 			rc = -EAGAIN;
 			pr_debug("error getting buffer rc:%d\n", rc);
-			goto ERROR2;
+			goto ERROR3;
 		}
-		new_frame->output_buffer_info[1].index = buff_mgr_info.index;
+		new_frame->output_buffer_info[1].index =
+			dup_buff_mgr_info.index;
 		out_phyaddr1 = msm_cpp_fetch_buffer_info(cpp_dev,
 			&new_frame->output_buffer_info[1],
 			((new_frame->duplicate_identity >> 16) & 0xFFFF),
@@ -1300,6 +1317,8 @@
 		if (!out_phyaddr1) {
 			pr_err("error gettting output physical address\n");
 			rc = -EINVAL;
+			msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+				&dup_buff_mgr_info);
 			goto ERROR3;
 		}
 		/* set duplicate enable bit */
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index bb2b074..ea16ebd 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -254,6 +254,9 @@
 	int32_t num_steps = move_params->num_steps;
 	struct msm_camera_i2c_reg_setting reg_setting;
 
+	curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos];
+	move_params->curr_lens_pos = curr_lens_pos;
+
 	if (copy_from_user(&ringing_params_kernel,
 		&(move_params->ringing_params[a_ctrl->curr_region_index]),
 		sizeof(struct damping_params_t))) {
@@ -267,7 +270,6 @@
 	if (dest_step_pos == a_ctrl->curr_step_pos)
 		return rc;
 
-	curr_lens_pos = a_ctrl->step_position_table[a_ctrl->curr_step_pos];
 	a_ctrl->i2c_tbl_index = 0;
 	CDBG("curr_step_pos =%d dest_step_pos =%d curr_lens_pos=%d\n",
 		a_ctrl->curr_step_pos, dest_step_pos, curr_lens_pos);
@@ -305,6 +307,7 @@
 		a_ctrl->curr_step_pos = target_step_pos;
 	}
 
+	move_params->curr_lens_pos = curr_lens_pos;
 	reg_setting.reg_setting = a_ctrl->i2c_reg_tbl;
 	reg_setting.data_type = a_ctrl->i2c_data_type;
 	reg_setting.size = a_ctrl->i2c_tbl_index;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 4e1f73e..e072e53 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
@@ -631,7 +631,11 @@
 static int msm_cci_subdev_g_chip_ident(struct v4l2_subdev *sd,
 			struct v4l2_dbg_chip_ident *chip)
 {
-	BUG_ON(!chip);
+	if (!chip) {
+		pr_err("%s:%d: NULL pointer supplied for chip ident\n",
+			 __func__, __LINE__);
+		return -EINVAL;
+	}
 	chip->ident = V4L2_IDENT_CCI;
 	chip->revision = 0;
 	return 0;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
old mode 100644
new mode 100755
index 03145c8..7e84e7b
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -967,6 +967,7 @@
 	struct msm_sensor_power_setting_array *power_setting_array = NULL;
 	struct msm_sensor_power_setting *power_setting = NULL;
 	struct msm_camera_sensor_board_info *data = s_ctrl->sensordata;
+	uint32_t retry = 0;
 	s_ctrl->stop_setting_valid = 0;
 
 	CDBG("%s:%d\n", __func__, __LINE__);
@@ -1068,13 +1069,22 @@
 		}
 	}
 
-	if (s_ctrl->func_tbl->sensor_match_id)
-		rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
-	else
-		rc = msm_sensor_match_id(s_ctrl);
-	if (rc < 0) {
-		pr_err("%s:%d match id failed rc %d\n", __func__, __LINE__, rc);
-		goto power_up_failed;
+	for (retry = 0; retry < 3; retry++)
+	{
+		if (s_ctrl->func_tbl->sensor_match_id)
+			rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+		else
+			rc = msm_sensor_match_id(s_ctrl);
+		if (rc < 0) {
+			if (retry < 2) {
+				continue;
+			} else {
+				pr_err("%s:%d match id failed rc %d\n", __func__, __LINE__, rc);
+				goto power_up_failed;
+			}
+		} else {
+			break;
+		}
 	}
 
 	CDBG("%s exit\n", __func__);
@@ -1864,11 +1874,11 @@
 	s_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_SENSOR;
 	s_ctrl->msm_sd.sd.entity.name =
 		s_ctrl->msm_sd.sd.name;
-	mount_pos = s_ctrl->sensordata->sensor_init_params->position;
-	mount_pos = mount_pos << 8;
-	mount_pos = mount_pos |
-	(s_ctrl->sensordata->sensor_init_params->sensor_mount_angle / 90);
-	s_ctrl->msm_sd.sd.entity.flags = mount_pos;
+
+	mount_pos = s_ctrl->sensordata->sensor_init_params->position << 16;
+	mount_pos = mount_pos | ((s_ctrl->sensordata->sensor_init_params->
+					sensor_mount_angle / 90) << 8);
+	s_ctrl->msm_sd.sd.entity.flags = mount_pos | MEDIA_ENT_FL_DEFAULT;
 
 	rc = camera_init_v4l2(&s_ctrl->pdev->dev, &session_id);
 	CDBG("%s rc %d session_id %d\n", __func__, rc, session_id);
@@ -1985,11 +1995,10 @@
 	s_ctrl->msm_sd.sd.entity.name =
 		s_ctrl->msm_sd.sd.name;
 
-	mount_pos = s_ctrl->sensordata->sensor_init_params->position;
-	mount_pos = mount_pos << 8;
-	mount_pos = mount_pos |
-	(s_ctrl->sensordata->sensor_init_params->sensor_mount_angle / 90);
-	s_ctrl->msm_sd.sd.entity.flags = mount_pos;
+	mount_pos = s_ctrl->sensordata->sensor_init_params->position << 16;
+	mount_pos = mount_pos | ((s_ctrl->sensordata->sensor_init_params->
+					sensor_mount_angle / 90) << 8);
+	s_ctrl->msm_sd.sd.entity.flags = mount_pos | MEDIA_ENT_FL_DEFAULT;
 
 	rc = camera_init_v4l2(&s_ctrl->sensor_i2c_client->client->dev,
 		&session_id);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 4da0f6f..4b7a3be 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -360,6 +360,18 @@
 	case HAL_EXTRADATA_MPEG2_SEQDISP:
 		ret = HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA;
 		break;
+	case HAL_EXTRADATA_FRAME_QP:
+		ret = HFI_PROPERTY_PARAM_VDEC_FRAME_QP_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_FRAME_BITS_INFO:
+		ret = HFI_PROPERTY_PARAM_VDEC_FRAME_BITS_INFO_EXTRADATA;
+		break;
+	case HAL_EXTRADATA_LTR_INFO:
+		ret = HFI_PROPERTY_PARAM_VENC_LTR_INFO;
+		break;
+	case HAL_EXTRADATA_METADATA_MBI:
+		ret = HFI_PROPERTY_PARAM_VENC_MBI_DUMPING;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
 		break;
@@ -389,6 +401,28 @@
 	return buf_mode;
 }
 
+static u32 get_hfi_ltr_mode(enum ltr_mode ltr_mode_type)
+{
+	u32 ltrmode;
+	switch (ltr_mode_type) {
+	case HAL_LTR_MODE_DISABLE:
+		ltrmode = HFI_LTR_MODE_DISABLE;
+		break;
+	case HAL_LTR_MODE_MANUAL:
+		ltrmode = HFI_LTR_MODE_MANUAL;
+		break;
+	case HAL_LTR_MODE_PERIODIC:
+		ltrmode = HFI_LTR_MODE_PERIODIC;
+		break;
+	default:
+		dprintk(VIDC_ERR, "Invalid ltr mode :0x%x\n",
+			ltr_mode_type);
+		ltrmode = HFI_LTR_MODE_DISABLE;
+		break;
+	}
+	return ltrmode;
+}
+
 int create_pkt_cmd_session_set_buffers(
 		struct hfi_cmd_session_set_buffers_packet *pkt,
 		u32 session_id,
@@ -1405,6 +1439,54 @@
 		pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
 		break;
 	}
+	case HAL_PARAM_VENC_LTRMODE:
+	{
+		struct hfi_ltrmode *hfi;
+		struct hal_ltrmode *hal = pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_LTRMODE;
+		hfi = (struct hfi_ltrmode *) &pkt->rg_property_data[1];
+		hfi->ltrmode = get_hfi_ltr_mode(hal->ltrmode);
+		hfi->ltrcount = hal->ltrcount;
+		hfi->trustmode = hal->trustmode;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_ltrmode);
+		pr_err("SET LTR\n");
+		break;
+	}
+	case HAL_CONFIG_VENC_USELTRFRAME:
+	{
+		struct hfi_ltruse *hfi;
+		struct hal_ltruse *hal = pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_USELTRFRAME;
+		hfi = (struct hfi_ltruse *) &pkt->rg_property_data[1];
+		hfi->frames = hal->frames;
+		hfi->refltr = hal->refltr;
+		hfi->useconstrnt = hal->useconstrnt;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_ltruse);
+		pr_err("USE LTR\n");
+		break;
+	}
+	case HAL_CONFIG_VENC_MARKLTRFRAME:
+	{
+		struct hfi_ltrmark *hfi;
+		struct hal_ltrmark *hal = pdata;
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_CONFIG_VENC_MARKLTRFRAME;
+		hfi = (struct hfi_ltrmark *) &pkt->rg_property_data[1];
+		hfi->markframe = hal->markframe;
+		pkt->size += sizeof(u32) + sizeof(struct hfi_ltrmark);
+		pr_err("MARK LTR\n");
+		break;
+	}
+	case HAL_PARAM_VENC_HIER_P_NUM_FRAMES:
+	{
+		pkt->rg_property_data[0] =
+			HFI_PROPERTY_PARAM_VENC_HIER_P_NUM_ENH_LAYER;
+		pkt->rg_property_data[1] = *(u32 *)pdata;
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
 	/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
 	case HAL_CONFIG_BUFFER_REQUIREMENTS:
 	case HAL_CONFIG_PRIORITY:
@@ -1432,7 +1514,7 @@
 	case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
 	case HAL_PARAM_VENC_LOW_LATENCY:
 	default:
-		dprintk(VIDC_ERR, "DEFAULT: Calling 0x%x", ptype);
+		dprintk(VIDC_ERR, "DEFAULT: Calling 0x%x\n", ptype);
 		rc = -ENOTSUPP;
 		break;
 	}
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 3fd5d3a..f4ad985 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -263,7 +263,9 @@
 		break;
 	case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
 		dprintk(VIDC_INFO, "HFI_EVENT_RELEASE_BUFFER_REFERENCE\n");
-		hfi_process_evt_release_buffer_ref(callback, device_id, pkt);
+		if (!validate_session_pkt(sessions, sess, session_lock))
+			hfi_process_evt_release_buffer_ref(callback,
+				device_id, pkt);
 		break;
 	default:
 		dprintk(VIDC_WARN, "hal_process_event_notify:unkown_event_id");
@@ -386,6 +388,10 @@
 		struct vidc_hal_session_init_done *sess_init_done)
 {
 	struct hal_capability_supported *out = NULL;
+	if (!in) {
+		dprintk(VIDC_ERR, "Invalid input for supported capabilties\n");
+		return;
+	}
 	switch (in->capability_type) {
 	case HFI_CAPABILITY_FRAME_WIDTH:
 		out = &sess_init_done->width;
@@ -418,9 +424,17 @@
 	case HFI_CAPABILITY_BITRATE:
 		out = &sess_init_done->bitrate;
 		break;
+
+	case HFI_CAPABILITY_ENC_LTR_COUNT:
+		out = &sess_init_done->ltr_count;
+		break;
+
+	case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS:
+		out = &sess_init_done->hier_p;
+		break;
 	}
 
-	if (in && out) {
+	if (out) {
 		out->capability_type =
 			(enum hal_capability)in->capability_type;
 		out->min = in->min;
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 468ba74..176c612 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -120,6 +120,13 @@
 	return msm_vidc_g_ctrl((void *)vidc_inst, a);
 }
 
+int msm_v4l2_s_ext_ctrl(struct file *file, void *fh,
+					struct v4l2_ext_controls *a)
+{
+	struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
+	return msm_vidc_s_ext_ctrl((void *)vidc_inst, a);
+}
+
 int msm_v4l2_reqbufs(struct file *file, void *fh,
 				struct v4l2_requestbuffers *b)
 {
@@ -242,6 +249,7 @@
 	.vidioc_streamoff = msm_v4l2_streamoff,
 	.vidioc_s_ctrl = msm_v4l2_s_ctrl,
 	.vidioc_g_ctrl = msm_v4l2_g_ctrl,
+	.vidioc_s_ext_ctrls = msm_v4l2_s_ext_ctrl,
 	.vidioc_subscribe_event = msm_v4l2_subscribe_event,
 	.vidioc_unsubscribe_event = msm_v4l2_unsubscribe_event,
 	.vidioc_decoder_cmd = msm_v4l2_decoder_cmd,
@@ -389,18 +397,22 @@
 	rc = msm_vidc_initialize_core(pdev, core);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to init core\n");
-		goto err_v4l2_register;
+		goto err_core_init;
 	}
 	rc = device_create_file(&pdev->dev, &dev_attr_pwr_collapse_delay);
 	if (rc) {
 		dprintk(VIDC_ERR,
 				"Failed to create pwr_collapse_delay sysfs node");
-		goto err_v4l2_register;
+		goto err_core_init;
 	}
 	if (core->hfi_type == VIDC_HFI_Q6) {
 		dprintk(VIDC_ERR, "Q6 hfi device probe called\n");
 		nr += MSM_VIDC_MAX_DEVICES;
+		core->id = MSM_VIDC_CORE_Q6;
+	} else {
+		core->id = MSM_VIDC_CORE_VENUS;
 	}
+
 	rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to register v4l2 device\n");
@@ -453,16 +465,20 @@
 				vidc_driver->num_cores);
 		goto err_cores_exceeded;
 	}
-	core->id = vidc_driver->num_cores++;
+	vidc_driver->num_cores++;
 	mutex_unlock(&vidc_driver->lock);
 
 	core->device = vidc_hfi_initialize(core->hfi_type, core->id,
 				&core->resources, &handle_cmd_response);
-	if (!core->device) {
-		dprintk(VIDC_ERR, "Failed to create HFI device\n");
+	if (IS_ERR_OR_NULL(core->device)) {
 		mutex_lock(&vidc_driver->lock);
 		vidc_driver->num_cores--;
 		mutex_unlock(&vidc_driver->lock);
+		rc = PTR_ERR(core->device);
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "Failed to create HFI device\n");
+		else
+			dprintk(VIDC_DBG, "msm_vidc: request probe defer\n");
 		goto err_cores_exceeded;
 	}
 
@@ -487,6 +503,8 @@
 err_dec_register:
 	v4l2_device_unregister(&core->v4l2_dev);
 err_v4l2_register:
+	device_remove_file(&pdev->dev, &dev_attr_pwr_collapse_delay);
+err_core_init:
 	kfree(core);
 err_no_mem:
 	return rc;
@@ -523,6 +541,7 @@
 }
 static const struct of_device_id msm_vidc_dt_match[] = {
 	{.compatible = "qcom,msm-vidc"},
+	{}
 };
 
 MODULE_DEVICE_TABLE(of, msm_vidc_dt_match);
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 9dd4e93..71ad080 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -22,15 +22,11 @@
 #define MSM_VDEC_DVC_NAME "msm_vdec_8974"
 #define MIN_NUM_OUTPUT_BUFFERS 4
 #define MAX_NUM_OUTPUT_BUFFERS 6
-#define DEFAULT_CONCEAL_COLOR 0x0
+#define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8080
 
-#define TZ_INFO_GET_FEATURE_VERSION_ID 0x3
 #define TZ_DYNAMIC_BUFFER_FEATURE_ID 12
 #define TZ_FEATURE_VERSION(major, minor, patch) \
 	(((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
-struct tz_get_feature_version {
-	u32 feature_id;
-};
 
 enum msm_vdec_ctrl_cluster {
 	MSM_VDEC_CTRL_CLUSTER_MAX = 1 << 0,
@@ -224,7 +220,7 @@
 		.name = "Extradata Type",
 		.type = V4L2_CTRL_TYPE_MENU,
 		.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
-		.maximum = V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP,
+		.maximum = V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO,
 		.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
 		.menu_skip_mask = ~(
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -245,7 +241,9 @@
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO) |
-			(1 << V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP)
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP) |
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP) |
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO)
 			),
 		.qmenu = mpeg_video_vidc_extradata,
 		.step = 0,
@@ -323,6 +321,16 @@
 		.qmenu = NULL,
 		.cluster = 0,
 	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR,
+		.name = "Picture concealed color",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0x0,
+		.maximum = 0xffffff,
+		.default_value = DEFAULT_VIDEO_CONCEAL_COLOR_BLACK,
+		.step = 1,
+		.cluster = 0,
+	},
 };
 
 #define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
@@ -568,15 +576,7 @@
 				core);
 		goto exit;
 	}
-	if (!inst->in_reconfig) {
-		rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
-		if (rc) {
-			dprintk(VIDC_ERR,
-				"Failed to move inst: %p to relase res done\n",
-				inst);
-			goto exit;
-		}
-	}
+
 	switch (b->type) {
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		break;
@@ -971,11 +971,17 @@
 			rc = -EINVAL;
 			goto err_invalid_fmt;
 		}
+		rc = msm_comm_try_state(inst, MSM_VIDC_CORE_INIT_DONE);
+		if (rc) {
+			dprintk(VIDC_ERR, "Failed to initialize instance\n");
+			goto err_invalid_fmt;
+		}
 		if (!(get_hal_codec_type(fmt->fourcc) &
 			inst->core->dec_codec_supported)) {
 			dprintk(VIDC_ERR,
-				"Codec(0x%x) not supported\n",
-				get_hal_codec_type(fmt->fourcc));
+				"Codec(0x%x) is not present in the supported codecs list(0x%x)\n",
+				get_hal_codec_type(fmt->fourcc),
+				inst->core->dec_codec_supported);
 			rc = -EINVAL;
 			goto err_invalid_fmt;
 		}
@@ -1319,7 +1325,6 @@
 {
 	struct msm_vidc_inst *inst;
 	int rc = 0;
-	int pdata = DEFAULT_CONCEAL_COLOR;
 	struct hfi_device *hdev;
 	if (!q || !q->drv_priv) {
 		dprintk(VIDC_ERR, "Invalid input, q = %p\n", q);
@@ -1337,10 +1342,6 @@
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
 		if (inst->bufq[CAPTURE_PORT].vb2_bufq.streaming)
 			rc = start_streaming(inst);
-		rc = call_hfi_op(hdev, session_set_property,
-			(void *) inst->session,
-			HAL_PARAM_VDEC_CONCEAL_COLOR,
-			(void *) &pdata);
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 		if (inst->bufq[OUTPUT_PORT].vb2_bufq.streaming)
@@ -1410,7 +1411,19 @@
 	}
 	switch (dec->cmd) {
 	case V4L2_DEC_QCOM_CMD_FLUSH:
+		if (core->state != VIDC_CORE_INVALID &&
+			inst->state ==  MSM_VIDC_CORE_INVALID) {
+			rc = msm_comm_recover_from_session_error(inst);
+			if (rc)
+				dprintk(VIDC_ERR,
+					"Failed to recover from session_error: %d\n",
+					rc);
+		}
 		rc = msm_comm_flush(inst, dec->flags);
+		if (rc) {
+			dprintk(VIDC_ERR,
+					"Failed to flush buffers: %d\n", rc);
+		}
 		break;
 	case V4L2_DEC_CMD_STOP:
 		if (core->state != VIDC_CORE_INVALID &&
@@ -1512,17 +1525,16 @@
 static int check_tz_dynamic_buffer_support(void)
 {
 	int rc = 0;
-	struct tz_get_feature_version tz_feature_id;
-	unsigned int resp = 0;
+	int version = scm_get_feat_version(TZ_DYNAMIC_BUFFER_FEATURE_ID);
 
-	tz_feature_id.feature_id = TZ_DYNAMIC_BUFFER_FEATURE_ID;
-	rc = scm_call(SCM_SVC_INFO,
-		  TZ_INFO_GET_FEATURE_VERSION_ID, &tz_feature_id,
-		  sizeof(tz_feature_id), &resp, sizeof(resp));
-	if ((rc) || (resp != TZ_FEATURE_VERSION(1, 1, 0))) {
+	/*
+	 * if the version is < 1.1.0 then dynamic buffer allocation is
+	 * not supported
+	 */
+	if (version < TZ_FEATURE_VERSION(1, 1, 0)) {
 		dprintk(VIDC_DBG,
-			"Dyamic buffer mode not supported, failed to get tz feature version id : %u, rc : %d, response : %u\n",
-			tz_feature_id.feature_id, rc, resp);
+			"Dynamic buffer mode not supported, tz version is : %u vs required : %u\n",
+			version, TZ_FEATURE_VERSION(1, 1, 0));
 		rc = -ENOTSUPP;
 	}
 	return rc;
@@ -1732,6 +1744,11 @@
 			break;
 		}
 		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR:
+		property_id = HAL_PARAM_VDEC_CONCEAL_COLOR;
+		property_val = ctrl->val;
+		pdata = &property_val;
+		break;
 	default:
 		break;
 	}
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index c0bf32c..b01a507 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -37,6 +37,8 @@
 #define B_FRAME_QP 30
 #define MAX_INTRA_REFRESH_MBS 300
 #define MAX_NUM_B_FRAMES 4
+#define MAX_LTR_FRAME_COUNT 10
+
 #define L_MODE V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY
 #define CODING V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY
 
@@ -114,6 +116,7 @@
 	"Extradata input crop",
 	"Extradata digital zoom",
 	"Extradata aspect ratio",
+	"Extradata macroblock metadata",
 };
 
 static const char *const perf_level[] = {
@@ -135,7 +138,8 @@
 	MSM_VENC_CTRL_CLUSTER_TIMING = 1 << 9,
 	MSM_VENC_CTRL_CLUSTER_VP8_PROFILE_LEVEL = 1 << 10,
 	MSM_VENC_CTRL_CLUSTER_DEINTERLACE = 1 << 11,
-	MSM_VENC_CTRL_CLUSTER_MAX = 1 << 12,
+	MSM_VENC_CTRL_CLUSTER_USE_LTRFRAME = 1 << 12,
+	MSM_VENC_CTRL_CLUSTER_MAX = 1 << 13,
 };
 
 static struct msm_vidc_ctrl msm_venc_ctrls[] = {
@@ -168,7 +172,7 @@
 		.name = "Intra Period for P frames",
 		.type = V4L2_CTRL_TYPE_INTEGER,
 		.minimum = 0,
-		.maximum = 10*DEFAULT_FRAME_RATE,
+		.maximum = INT_MAX,
 		.default_value = 2*DEFAULT_FRAME_RATE-1,
 		.step = 1,
 		.menu_skip_mask = 0,
@@ -651,7 +655,7 @@
 		.name = "Extradata Type",
 		.type = V4L2_CTRL_TYPE_MENU,
 		.minimum = V4L2_MPEG_VIDC_EXTRADATA_NONE,
-		.maximum = V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
+		.maximum = V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI,
 		.default_value = V4L2_MPEG_VIDC_EXTRADATA_NONE,
 		.menu_skip_mask = ~(
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_NONE) |
@@ -671,7 +675,9 @@
 			(1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_FILLER) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP) |
 			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM) |
-			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO)
+			(1 << V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO) |
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_LTR) |
+			(1 << V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI)
 			),
 		.qmenu = mpeg_video_vidc_extradata,
 		.step = 0,
@@ -729,6 +735,61 @@
 		.default_value = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED,
 		.step = 1,
 		.cluster = MSM_VENC_CTRL_CLUSTER_DEINTERLACE,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME,
+		.name = "H264 Use LTR",
+		.type = V4L2_CTRL_TYPE_BUTTON,
+		.minimum = 0,
+		.maximum = (MAX_LTR_FRAME_COUNT - 1),
+		.default_value = 0,
+		.step = 1,
+		.qmenu = NULL,
+		.cluster = 0,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT,
+		.name = "Ltr Count",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = MAX_LTR_FRAME_COUNT,
+		.default_value = 0,
+		.step = 1,
+		.qmenu = NULL,
+		.cluster = MSM_VENC_CTRL_CLUSTER_USE_LTRFRAME,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE,
+		.name = "Ltr Mode",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE,
+		.maximum = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_PERIODIC,
+		.default_value = V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE,
+		.step = 1,
+		.qmenu = NULL,
+		.cluster = MSM_VENC_CTRL_CLUSTER_USE_LTRFRAME,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME,
+		.name = "H264 Mark LTR",
+		.type = V4L2_CTRL_TYPE_BUTTON,
+		.minimum = 0,
+		.maximum = (MAX_LTR_FRAME_COUNT - 1),
+		.default_value = 0,
+		.step = 1,
+		.qmenu = NULL,
+		.cluster = 0,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS,
+		.name = "Set Hier P num layers",
+		.type = V4L2_CTRL_TYPE_INTEGER,
+		.minimum = 0,
+		.maximum = 3,
+		.default_value = 0,
+		.step = 1,
+		.qmenu = NULL,
+		.cluster = 0,
 	}
 };
 
@@ -836,28 +897,33 @@
 			*num_buffers = buff_req->buffer_count_actual =
 			max(*num_buffers, buff_req->buffer_count_actual);
 		}
-		if (*num_buffers < MIN_NUM_CAPTURE_BUFFERS)
-			*num_buffers = MIN_NUM_CAPTURE_BUFFERS;
 
-		if (*num_buffers > VIDEO_MAX_FRAME) {
-			dprintk(VIDC_ERR,
-				"Changing buffers requested, from %d to max"\
-				" supported (%d) best effort encoding\n",
-				*num_buffers, VIDEO_MAX_FRAME);
-			*num_buffers = VIDEO_MAX_FRAME;
+		if (*num_buffers < MIN_NUM_CAPTURE_BUFFERS ||
+				*num_buffers > VIDEO_MAX_FRAME) {
+			int temp = *num_buffers;
+
+			*num_buffers = clamp_val(*num_buffers,
+					MIN_NUM_CAPTURE_BUFFERS,
+					VIDEO_MAX_FRAME);
+			dprintk(VIDC_INFO,
+				"Changing buffer count on CAPTURE_MPLANE from %d to %d for best effort encoding\n",
+				temp, *num_buffers);
 		}
+
 		ctrl = v4l2_ctrl_find(&inst->ctrl_handler,
 				V4L2_CID_MPEG_VIDC_VIDEO_EXTRADATA);
 		if (ctrl)
 			extradata = v4l2_ctrl_g_ctrl(ctrl);
-		if (extradata)
+		if (extradata != V4L2_MPEG_VIDC_EXTRADATA_NONE)
 			*num_planes = *num_planes + 1;
 		inst->fmts[CAPTURE_PORT]->num_planes = *num_planes;
+
 		for (i = 0; i < *num_planes; i++) {
 			sizes[i] = inst->fmts[CAPTURE_PORT]->get_frame_size(
 					i, inst->prop.height[CAPTURE_PORT],
 					inst->prop.width[CAPTURE_PORT]);
 		}
+
 		property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
 		new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
 		new_buf_count.buffer_count_actual = *num_buffers;
@@ -1273,6 +1339,9 @@
 	struct v4l2_ctrl *temp_ctrl = NULL;
 	struct hfi_device *hdev;
 	struct hal_extradata_enable extra;
+	struct hal_ltruse useltr;
+	struct hal_ltrmark markltr;
+	u32 hier_p_layers;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1970,7 +2039,33 @@
 		pdata = &enable;
 		break;
 	}
+	case V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME:
+		property_id = HAL_CONFIG_VENC_USELTRFRAME;
+		useltr.refltr = ctrl->val;
+		useltr.useconstrnt = false;
+		useltr.frames = 0;
+		pdata = &useltr;
+		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME:
+		property_id = HAL_CONFIG_VENC_MARKLTRFRAME;
+		markltr.markframe = ctrl->val;
+		pdata = &markltr;
+		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS:
+		property_id = HAL_PARAM_VENC_HIER_P_NUM_FRAMES;
+		hier_p_layers = ctrl->val;
+		if (hier_p_layers > (inst->capability.hier_p.max - 1)) {
+			dprintk(VIDC_ERR,
+				"Error setting hier p num layers = %d max supported by f/w = %d\n",
+				hier_p_layers,
+				inst->capability.hier_p.max - 1);
+			rc = -ENOTSUPP;
+			break;
+		}
+		pdata = &hier_p_layers;
+		break;
 	default:
+		dprintk(VIDC_ERR, "Unsupported index: %x\n", ctrl->id);
 		rc = -ENOTSUPP;
 		break;
 	}
@@ -1987,6 +2082,89 @@
 	return rc;
 }
 
+static struct v4l2_ctrl *get_cluster_from_id(int id)
+{
+	int c;
+	for (c = 0; c < ARRAY_SIZE(msm_venc_ctrls); ++c)
+		if (msm_venc_ctrls[c].id == id)
+			return (struct v4l2_ctrl *)msm_venc_ctrls[c].priv;
+	return NULL;
+}
+
+static int try_set_ext_ctrl(struct msm_vidc_inst *inst,
+	struct v4l2_ext_controls *ctrl)
+{
+	int rc = 0, i;
+	struct v4l2_ext_control *control;
+	struct hfi_device *hdev;
+	struct hal_ltrmode ltrmode;
+	struct v4l2_ctrl *cluster;
+	u32 property_id = 0;
+	void *pdata = NULL;
+	struct msm_vidc_core_capability *cap = NULL;
+
+	if (!inst || !inst->core || !inst->core->device || !ctrl) {
+		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
+		return -EINVAL;
+	}
+
+	cluster = get_cluster_from_id(ctrl->controls[0].id);
+
+	if (!cluster) {
+		dprintk(VIDC_ERR, "Invalid Ctrl returned for id: %x\n",
+			ctrl->controls[0].id);
+		return -EINVAL;
+	}
+
+	hdev = inst->core->device;
+	cap = &inst->capability;
+
+	control = ctrl->controls;
+	for (i = 0; i < ctrl->count; i++) {
+		switch (control[i].id) {
+		case V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE:
+			ltrmode.ltrmode = control[i].value;
+			ltrmode.trustmode = 1;
+			property_id = HAL_PARAM_VENC_LTRMODE;
+			pdata = &ltrmode;
+			break;
+		case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
+			ltrmode.ltrcount =  control[i].value;
+			if (ltrmode.ltrcount > cap->ltr_count.max) {
+				dprintk(VIDC_ERR,
+						"Invalid LTR count %d. Supported max: %d\n",
+						ltrmode.ltrcount,
+						cap->ltr_count.max);
+				/*
+				 * FIXME: Return an error (-EINVALID)
+				 * here once VP8 supports LTR count
+				 * capability
+				 */
+				ltrmode.ltrcount = 1;
+			}
+			ltrmode.trustmode = 1;
+			property_id = HAL_PARAM_VENC_LTRMODE;
+			pdata = &ltrmode;
+			break;
+		default:
+			dprintk(VIDC_ERR, "Invalid id set: %d\n",
+					control[i].id);
+			rc = -ENOTSUPP;
+			break;
+		}
+		if (rc)
+			break;
+	}
+
+	if (!rc && property_id) {
+		dprintk(VIDC_DBG, "Control: HAL property=%x\n", property_id);
+		rc = call_hfi_op(hdev, session_set_property,
+				(void *)inst->session, property_id, pdata);
+	}
+	pr_err("Returning from %s\n", __func__);
+	return rc;
+}
+
 static int msm_venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 
@@ -2072,6 +2250,22 @@
 	return v4l2_g_ctrl(&inst->ctrl_handler, ctrl);
 }
 
+int msm_venc_s_ext_ctrl(struct msm_vidc_inst *inst,
+	struct v4l2_ext_controls *ctrl)
+{
+	int rc = 0;
+	if (ctrl->ctrl_class != V4L2_CTRL_CLASS_MPEG) {
+		dprintk(VIDC_ERR, "Invalid Class set for extended control\n");
+		return -EINVAL;
+	}
+	rc = try_set_ext_ctrl(inst, ctrl);
+	if (rc) {
+		dprintk(VIDC_ERR, "Error setting extended control\n");
+		return rc;
+	}
+	return rc;
+}
+
 int msm_venc_cmd(struct msm_vidc_inst *inst, struct v4l2_encoder_cmd *enc)
 {
 	int rc = 0;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.h b/drivers/media/platform/msm/vidc/msm_venc.h
index 9020167..5965d39 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.h
+++ b/drivers/media/platform/msm/vidc/msm_venc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,7 @@
 int msm_venc_g_fmt(void *instance, struct v4l2_format *f);
 int msm_venc_s_ctrl(void *instance, struct v4l2_control *a);
 int msm_venc_g_ctrl(void *instance, struct v4l2_control *a);
+int msm_venc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
 int msm_venc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
 int msm_venc_prepare_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
 int msm_venc_release_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 9da1220..59a1ec0 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -185,6 +185,15 @@
 		return msm_venc_g_ctrl(instance, control);
 	return -EINVAL;
 }
+int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *control)
+{
+	struct msm_vidc_inst *inst = instance;
+	if (!inst || !control)
+		return -EINVAL;
+	if (inst->session_type == MSM_VIDC_ENCODER)
+		return msm_venc_s_ext_ctrl(instance, control);
+	return -EINVAL;
+}
 int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b)
 {
 	struct msm_vidc_inst *inst = instance;
@@ -246,38 +255,38 @@
 	return ret;
 }
 
-struct buffer_info *get_same_fd_buffer(struct msm_vidc_inst *inst,
-			struct list_head *list, int fd, int *plane)
+struct msm_smem *get_same_fd_buffer(struct msm_vidc_inst *inst,
+			struct list_head *list, int fd)
 {
 	struct buffer_info *temp;
-	struct buffer_info *ret = NULL;
+	struct msm_smem *same_fd_handle = NULL;
+
 	int i;
 	if (fd == 0)
 		return NULL;
-	if (!list || fd < 0 || !plane) {
+	if (!list || fd < 0) {
 		dprintk(VIDC_ERR, "Invalid input\n");
 		goto err_invalid_input;
 	}
-	*plane = 0;
 	mutex_lock(&inst->lock);
 	list_for_each_entry(temp, list, list) {
 		for (i = 0; (i < temp->num_planes)
 			&& (i < VIDEO_MAX_PLANES); i++) {
-			if (temp && temp->fd[i] == fd)  {
+			if (temp && (temp->fd[i] == fd) &&
+				temp->handle[i] && temp->mapped[i])  {
 				temp->same_fd_ref[i]++;
 				dprintk(VIDC_INFO,
 				"Found same fd buffer\n");
-				ret = temp;
-				*plane = i;
+				same_fd_handle = temp->handle[i];
 				break;
 			}
 		}
-		if (ret)
+		if (same_fd_handle)
 			break;
 	}
 	mutex_unlock(&inst->lock);
 err_invalid_input:
-	return ret;
+	return same_fd_handle;
 }
 
 struct buffer_info *device_to_uvaddr(struct msm_vidc_inst *inst,
@@ -324,7 +333,6 @@
 	binfo->num_planes = b->length;
 	binfo->memory = b->memory;
 	binfo->v4l2_index = b->index;
-	binfo->dequeued = false;
 	binfo->timestamp.tv_sec = b->timestamp.tv_sec;
 	binfo->timestamp.tv_usec = b->timestamp.tv_usec;
 	dprintk(VIDC_DBG, "%s: fd[%d] = %d b->index = %d",
@@ -341,6 +349,7 @@
 	b->index = binfo->v4l2_index;
 	b->timestamp.tv_sec = binfo->timestamp.tv_sec;
 	b->timestamp.tv_usec = binfo->timestamp.tv_usec;
+	binfo->dequeued = false;
 	for (i = 0; i < binfo->num_planes; ++i) {
 		b->m.planes[i].reserved[0] = binfo->fd[i];
 		b->m.planes[i].reserved[1] = binfo->buff_off[i];
@@ -423,6 +432,7 @@
 	struct buffer_info *temp = NULL;
 	int plane = 0;
 	int i = 0, rc = 0;
+	struct msm_smem *same_fd_handle = NULL;
 
 	if (!b || !inst) {
 		dprintk(VIDC_ERR, "%s: invalid input\n", __func__);
@@ -480,16 +490,17 @@
 		if (rc < 0)
 			goto exit;
 
-		temp = get_same_fd_buffer(inst, &inst->registered_bufs,
-					b->m.planes[i].reserved[0], &plane);
+		same_fd_handle = get_same_fd_buffer(inst,
+					&inst->registered_bufs,
+					b->m.planes[i].reserved[0]);
 
 		populate_buf_info(binfo, b, i);
-		if (temp) {
+		if (same_fd_handle) {
 			binfo->device_addr[i] =
-			temp->handle[plane]->device_addr + binfo->buff_off[i];
+			same_fd_handle->device_addr + binfo->buff_off[i];
 			b->m.planes[i].m.userptr = binfo->device_addr[i];
 			binfo->mapped[i] = false;
-			binfo->handle[i] = temp->handle[i];
+			binfo->handle[i] = same_fd_handle;
 		} else {
 			if (inst->map_output_buffer) {
 				binfo->handle[i] =
@@ -716,7 +727,29 @@
 	if (!inst)
 		return -EINVAL;
 
+	if (!inst->in_reconfig) {
+		rc = msm_comm_try_state(inst, MSM_VIDC_RELEASE_RESOURCES_DONE);
+		if (rc) {
+			dprintk(VIDC_ERR,
+					"Failed to move inst: %p to release res done\n",
+					inst);
+		}
+	}
+
+	/*
+	* In dynamic buffer mode, driver needs to release resources,
+	* but not call release buffers on firmware, as the buffers
+	* were never registered with firmware.
+	*/
+	if ((buffer_type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+		(inst->buffer_mode_set[CAPTURE_PORT] ==
+				HAL_BUFFER_MODE_DYNAMIC)) {
+		goto free_and_unmap;
+	}
+
 	list_for_each_safe(ptr, next, &inst->registered_bufs) {
+		bool release_buf = false;
+		mutex_lock(&inst->lock);
 		bi = list_entry(ptr, struct buffer_info, list);
 		if (bi->type == buffer_type) {
 			buffer_info.type = bi->type;
@@ -734,19 +767,30 @@
 					buffer_info.m.planes[i].length);
 			}
 			buffer_info.length = bi->num_planes;
-			if (inst->session_type == MSM_VIDC_DECODER)
-				rc = msm_vdec_release_buf(instance,
-					&buffer_info);
-			if (inst->session_type == MSM_VIDC_ENCODER)
-				rc = msm_venc_release_buf(instance,
-					&buffer_info);
-			if (rc)
-				dprintk(VIDC_ERR,
-					"Failed Release buffer: %d, %d, %d\n",
-					buffer_info.m.planes[0].reserved[0],
-					buffer_info.m.planes[0].reserved[1],
-					buffer_info.m.planes[0].length);
+			release_buf = true;
+		}
+		mutex_unlock(&inst->lock);
+		if (!release_buf)
+			continue;
+		if (inst->session_type == MSM_VIDC_DECODER)
+			rc = msm_vdec_release_buf(instance,
+				&buffer_info);
+		if (inst->session_type == MSM_VIDC_ENCODER)
+			rc = msm_venc_release_buf(instance,
+				&buffer_info);
+		if (rc)
+			dprintk(VIDC_ERR,
+				"Failed Release buffer: %d, %d, %d\n",
+				buffer_info.m.planes[0].reserved[0],
+				buffer_info.m.planes[0].reserved[1],
+				buffer_info.m.planes[0].length);
+	}
 
+free_and_unmap:
+	mutex_lock(&inst->lock);
+	list_for_each_safe(ptr, next, &inst->registered_bufs) {
+		bi = list_entry(ptr, struct buffer_info, list);
+		if (bi->type == buffer_type) {
 			list_del(&bi->list);
 			for (i = 0; i < bi->num_planes; i++) {
 				if (bi->handle[i] && bi->mapped[i]) {
@@ -762,6 +806,7 @@
 			kfree(bi);
 		}
 	}
+	mutex_unlock(&inst->lock);
 	return rc;
 }
 
@@ -1076,8 +1121,6 @@
 {
 	int rc = 0;
 	struct msm_vidc_inst *vidc_inst = (struct msm_vidc_inst *)inst;
-	spin_lock_init(&pvdev->fh_lock);
-	INIT_LIST_HEAD(&pvdev->fh_list);
 
 	v4l2_fh_init(&vidc_inst->event_handler, pvdev);
 	v4l2_fh_add(&vidc_inst->event_handler);
@@ -1302,6 +1345,7 @@
 	if (!inst)
 		return -EINVAL;
 
+	v4l2_fh_del(&inst->event_handler);
 	list_for_each_safe(ptr, next, &inst->registered_bufs) {
 		bi = list_entry(ptr, struct buffer_info, list);
 		if (bi->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 7588994..95afa2a 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -463,6 +463,9 @@
 				session_init_done->frame_rate;
 			inst->capability.scale_x = session_init_done->scale_x;
 			inst->capability.scale_y = session_init_done->scale_y;
+			inst->capability.ltr_count =
+				session_init_done->ltr_count;
+			inst->capability.hier_p = session_init_done->hier_p;
 			inst->capability.pixelprocess_capabilities =
 				call_hfi_op(hdev, get_core_capabilities);
 			inst->capability.capability_set = true;
@@ -519,6 +522,14 @@
 					event_notify->packet_buffer,
 					event_notify->exra_data_buffer);
 
+				if (inst->state == MSM_VIDC_CORE_INVALID ||
+					inst->core->state ==
+						VIDC_CORE_INVALID) {
+					dprintk(VIDC_DBG,
+						"Event release buf ref received in invalid state - discard\n");
+					return;
+				}
+
 				/*
 				* Get the buffer_info entry for the
 				* device address.
@@ -1109,6 +1120,7 @@
 	struct vidc_hal_fbd *fill_buf_done;
 	enum hal_buffer buffer_type;
 	int64_t time_usec = 0;
+	int extra_idx = 0;
 
 	if (!response) {
 		dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -1155,6 +1167,15 @@
 				ns_to_timeval(time_usec * NSEC_PER_USEC);
 		}
 		vb->v4l2_buf.flags = 0;
+		extra_idx =
+			EXTRADATA_IDX(inst->fmts[CAPTURE_PORT]->num_planes);
+		if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+			vb->v4l2_planes[extra_idx].m.userptr =
+				(unsigned long)fill_buf_done->extra_data_buffer;
+			vb->v4l2_planes[extra_idx].bytesused =
+				vb->v4l2_planes[extra_idx].length;
+			vb->v4l2_planes[extra_idx].data_offset = 0;
+		}
 
 		handle_dynamic_buffer(inst, (u32)fill_buf_done->packet_buffer1,
 					fill_buf_done->flags1);
@@ -1209,6 +1230,13 @@
 		fill_buf_done->start_y_coord, fill_buf_done->frame_width,
 		fill_buf_done->frame_height, fill_buf_done->picture_type);
 
+		if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+			dprintk(VIDC_DBG,
+			"extradata: userptr = %p;  bytesused = %d; length = %d\n",
+			(u8 *)vb->v4l2_planes[extra_idx].m.userptr,
+			vb->v4l2_planes[extra_idx].bytesused,
+			vb->v4l2_planes[extra_idx].length);
+		}
 		mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
 		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 		mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
@@ -2952,9 +2980,6 @@
 				dprintk(VIDC_DBG,
 					"released buffer held in driver before issuing flush: 0x%x fd[0]: %d\n",
 					binfo->device_addr[0], binfo->fd[0]);
-				/*delete this buffer info from registered list*/
-				list_del(&binfo->list);
-				kfree(binfo);
 				/*send event to client*/
 				v4l2_event_queue_fh(&inst->event_handler,
 					&buf_event);
@@ -2999,6 +3024,9 @@
 		dprintk(VIDC_INFO, "Input only flush not supported\n");
 		return 0;
 	}
+	mutex_lock(&inst->sync_lock);
+	msm_comm_flush_dynamic_buffers(inst);
+	mutex_unlock(&inst->sync_lock);
 	if (inst->state == MSM_VIDC_CORE_INVALID ||
 			core->state == VIDC_CORE_INVALID) {
 		dprintk(VIDC_ERR,
@@ -3009,7 +3037,6 @@
 	}
 
 	mutex_lock(&inst->sync_lock);
-	msm_comm_flush_dynamic_buffers(inst);
 	if (inst->in_reconfig && !ip_flush && op_flush) {
 		if (!list_empty(&inst->pendingq)) {
 			/*Execution can never reach here since port reconfig
@@ -3114,6 +3141,18 @@
 	case V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP:
 		ret = HAL_EXTRADATA_MPEG2_SEQDISP;
 		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP:
+		ret = HAL_EXTRADATA_FRAME_QP;
+		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO:
+		ret = HAL_EXTRADATA_FRAME_BITS_INFO;
+		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_LTR:
+		ret = HAL_EXTRADATA_LTR_INFO;
+		break;
+	case V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI:
+		ret = HAL_EXTRADATA_METADATA_MBI;
+		break;
 	default:
 		dprintk(VIDC_WARN, "Extradata not found: %d\n", index);
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index e4f920f..06181dd 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -190,6 +190,8 @@
 	u32 pixelprocess_capabilities;
 	struct hal_capability_supported scale_x;
 	struct hal_capability_supported scale_y;
+	struct hal_capability_supported ltr_count;
+	struct hal_capability_supported hier_p;
 	u32 capability_set;
 	enum buffer_mode_type buffer_mode[MAX_PORT_NUM];
 };
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index 8e91f34..e70635d 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -210,8 +210,9 @@
 		iommu_map = &iommu_group_set->iommu_maps[i];
 		iommu_map->group = iommu_group_find(iommu_map->name);
 		if (!iommu_map->group) {
-			dprintk(VIDC_ERR, "Failed to find group :%s\n",
+			dprintk(VIDC_DBG, "Failed to find group :%s\n",
 					iommu_map->name);
+			rc = -EPROBE_DEFER;
 			goto fail_group;
 		}
 		domain = iommu_group_get_iommudata(iommu_map->group);
@@ -219,6 +220,7 @@
 			dprintk(VIDC_ERR,
 					"Failed to get domain data for group %p",
 					iommu_map->group);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 		iommu_map->domain = msm_find_domain_no(domain);
@@ -226,6 +228,7 @@
 			dprintk(VIDC_ERR,
 					"Failed to get domain index for domain %p",
 					domain);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 	}
@@ -239,7 +242,7 @@
 		iommu_map->group = NULL;
 		iommu_map->domain = -1;
 	}
-	return -EINVAL;
+	return rc;
 }
 
 static void q6_hfi_deregister_iommu_domains(struct q6_hfi_device *device)
@@ -275,8 +278,12 @@
 
 	device->res = res;
 	rc = q6_hfi_register_iommu_domains(device);
-	if (rc)
-		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
+	if (rc) {
+		if (rc != -EPROBE_DEFER) {
+			dprintk(VIDC_ERR,
+				"Failed to register iommu domains: %d\n", rc);
+		}
+	}
 
 	return rc;
 }
@@ -351,14 +358,15 @@
 
 	rc = q6_hfi_init_resources(device, res);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
 		goto err_fail_init_res;
 	}
 	return device;
 
 err_fail_init_res:
 	q6_hfi_delete_device(device);
-	return NULL;
+	return ERR_PTR(rc);
 }
 
 void q6_hfi_delete_device(void *device)
@@ -1379,6 +1387,12 @@
 	}
 	hdev->hfi_device_data = q6_hfi_get_device(device_id, res, callback);
 
+	if (IS_ERR_OR_NULL(hdev->hfi_device_data)) {
+		rc = PTR_ERR(hdev->hfi_device_data);
+		rc = !rc ? -EINVAL : rc;
+		goto err_hfi_init;
+	}
+
 	q6_init_hfi_callbacks(hdev);
 
 err_hfi_init:
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 2596a30..694335b 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -85,6 +85,9 @@
 
 static int venus_hfi_power_enable(void *dev);
 
+static unsigned long venus_hfi_get_clock_rate(struct venus_core_clock *clock,
+		int num_mbs_per_sec);
+
 static void venus_hfi_dump_packet(u8 *packet)
 {
 	u32 c = 0, packet_size = *(u32 *)packet;
@@ -853,6 +856,7 @@
 fail_clk_enable:
 	for (i--; i >= 0; i--) {
 		cl = &device->resources.clock[i];
+		usleep(100);
 		clk_disable(cl->clk);
 	}
 	return rc;
@@ -861,7 +865,7 @@
 /*Calling function is responsible to acquire device->clk_pwr_lock*/
 static inline void venus_hfi_clk_disable(struct venus_hfi_device *device)
 {
-	int i;
+	int i, rc = 0;
 	struct venus_core_clock *cl;
 
 	if (!device) {
@@ -873,8 +877,17 @@
 		return;
 	}
 
+	/* We get better power savings if we lower the venus core clock to the
+	 * lowest level before disabling it. */
+	rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
+			venus_hfi_get_clock_rate(
+			&device->resources.clock[VCODEC_CLK], 0));
+	if (rc)
+		dprintk(VIDC_WARN, "Failed to set clock rate to min: %d\n", rc);
+
 	for (i = 0; i <= device->clk_gating_level; i++) {
 		cl = &device->resources.clock[i];
+		usleep(100);
 		clk_disable(cl->clk);
 	}
 	device->clocks_enabled = 0;
@@ -1635,15 +1648,23 @@
 	return 0;
 }
 
-static int venus_hfi_is_cmd_pending(struct venus_hfi_device *dev)
+static int venus_hfi_get_q_size(struct venus_hfi_device *dev,
+	unsigned int q_index)
 {
 	struct hfi_queue_header *queue;
 	struct vidc_iface_q_info *q_info;
 	u32 write_ptr, read_ptr;
 	u32 rc = 0;
-	q_info = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
-	if (!q_info)
+	if (q_index >= VIDC_IFACEQ_NUMQ) {
+		dprintk(VIDC_ERR, "Invalid q index: %d\n", q_index);
+		return -ENOENT;
+	}
+
+	q_info = &dev->iface_queues[q_index];
+	if (!q_info) {
 		dprintk(VIDC_ERR, "cannot read shared Q's");
+		return -ENOENT;
+	}
 	queue = (struct hfi_queue_header *) q_info->q_hdr;
 	if (!queue) {
 		dprintk(VIDC_ERR, "queue not present");
@@ -1667,9 +1688,12 @@
 	}
 	/*SYS Idle should be last message so mask any further interrupts
 	 * until clocks are enabled again.*/
-	venus_hfi_write_register(device,
-			VIDC_WRAPPER_INTR_MASK,
-			VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK | VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK, 0);
+	if (!venus_hfi_get_q_size(device, VIDC_IFACEQ_MSGQ_IDX)) {
+		venus_hfi_write_register(device,
+				VIDC_WRAPPER_INTR_MASK,
+				VIDC_WRAPPER_INTR_MASK_A2HVCODEC_BMSK |
+				VIDC_WRAPPER_INTR_MASK_A2HCPU_BMSK, 0);
+	}
 	venus_hfi_clk_disable(device);
 	if (!queue_delayed_work(device->venus_pm_workq, &venus_hfi_pm_work,
 			msecs_to_jiffies(msm_vidc_pwr_collapse_delay)))
@@ -2512,7 +2536,7 @@
 	}
 	mutex_lock(&device->write_lock);
 	mutex_lock(&device->clk_pwr_lock);
-	rc = venus_hfi_is_cmd_pending(device);
+	rc = venus_hfi_get_q_size(device, VIDC_IFACEQ_CMDQ_IDX);
 	ctrl_status = venus_hfi_read_register(
 		device,
 		VIDC_CPU_CS_SCIACMDARG0);
@@ -2777,13 +2801,17 @@
 	mutex_lock(&device->clk_pwr_lock);
 	if (device->clocks_enabled) {
 		for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+			if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
+				continue;
 			cl = &device->resources.clock[i];
+			usleep(100);
 			clk_disable(cl->clk);
 		}
 	} else {
 		for (i = device->clk_gating_level + 1;
 			i < VCODEC_MAX_CLKS; i++) {
 			cl = &device->resources.clock[i];
+			usleep(100);
 			clk_disable(cl->clk);
 		}
 	}
@@ -2826,6 +2854,7 @@
 fail_clk_enable:
 	for (; i >= 0; i--) {
 		cl = &device->resources.clock[i];
+		usleep(100);
 		clk_disable_unprepare(cl->clk);
 	}
 	mutex_unlock(&device->clk_pwr_lock);
@@ -2848,8 +2877,9 @@
 		iommu_map = &iommu_group_set->iommu_maps[i];
 		iommu_map->group = iommu_group_find(iommu_map->name);
 		if (!iommu_map->group) {
-			dprintk(VIDC_ERR, "Failed to find group :%s\n",
+			dprintk(VIDC_DBG, "Failed to find group :%s\n",
 				iommu_map->name);
+			rc = -EPROBE_DEFER;
 			goto fail_group;
 		}
 		domain = iommu_group_get_iommudata(iommu_map->group);
@@ -2857,6 +2887,7 @@
 			dprintk(VIDC_ERR,
 				"Failed to get domain data for group %p",
 				iommu_map->group);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 		iommu_map->domain = msm_find_domain_no(domain);
@@ -2864,6 +2895,7 @@
 			dprintk(VIDC_ERR,
 				"Failed to get domain index for domain %p",
 				domain);
+			rc = -EINVAL;
 			goto fail_group;
 		}
 	}
@@ -2877,7 +2909,7 @@
 		iommu_map->group = NULL;
 		iommu_map->domain = -1;
 	}
-	return -EINVAL;
+	return rc;
 }
 
 static void venus_hfi_deregister_iommu_domains(struct venus_hfi_device *device)
@@ -3082,14 +3114,14 @@
 		return -EINVAL;
 	}
 	ocmem_buffer = device->resources.ocmem.buf;
-	if (!ocmem_buffer ||
-		ocmem_buffer->len < size) {
+	if (!ocmem_buffer || ocmem_buffer->len < size) {
 		ocmem_buffer = ocmem_allocate(OCMEM_VIDEO, size);
 		if (IS_ERR_OR_NULL(ocmem_buffer)) {
 			dprintk(VIDC_ERR,
 				"ocmem_allocate_nb failed: %d\n",
 				(u32) ocmem_buffer);
 			rc = -ENOMEM;
+			goto ocmem_set_failed;
 		}
 		device->resources.ocmem.buf = ocmem_buffer;
 		rc = venus_hfi_set_ocmem(device, ocmem_buffer);
@@ -3164,7 +3196,10 @@
 
 	rc = venus_hfi_register_iommu_domains(device, res);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to register iommu domains: %d\n", rc);
+		if (rc != -EPROBE_DEFER) {
+			dprintk(VIDC_ERR,
+				"Failed to register iommu domains: %d\n", rc);
+		}
 		goto err_register_iommu_domain;
 	}
 
@@ -3495,7 +3530,7 @@
 	struct venus_hfi_device *hdevice = NULL;
 	int rc = 0;
 
-	if (device_id || !res || !callback) {
+	if (!res || !callback) {
 		dprintk(VIDC_ERR, "Invalid Paramters");
 		return NULL;
 	}
@@ -3570,14 +3605,15 @@
 
 	rc = venus_hfi_init_resources(device, res);
 	if (rc) {
-		dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "Failed to init resources: %d\n", rc);
 		goto err_fail_init_res;
 	}
 	return device;
 
 err_fail_init_res:
 	venus_hfi_delete_device(device);
-	return NULL;
+	return ERR_PTR(rc);
 }
 
 void venus_hfi_delete_device(void *device)
@@ -3661,6 +3697,12 @@
 	}
 	hdev->hfi_device_data = venus_hfi_get_device(device_id, res, callback);
 
+	if (IS_ERR_OR_NULL(hdev->hfi_device_data)) {
+		rc = PTR_ERR(hdev->hfi_device_data);
+		rc = !rc ? -EINVAL : rc;
+		goto err_venus_hfi_init;
+	}
+
 	venus_init_hfi_callbacks(hdev);
 
 err_venus_hfi_init:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.c b/drivers/media/platform/msm/vidc/vidc_hfi.c
index 46293a6..ef0de37 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.c
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.c
@@ -44,7 +44,8 @@
 	}
 
 	if (rc) {
-		dprintk(VIDC_ERR, "%s device init failed rc = %d",
+		if (rc != -EPROBE_DEFER)
+			dprintk(VIDC_ERR, "%s device init failed rc = %d",
 				__func__, rc);
 		goto err_hfi_init;
 	}
@@ -53,7 +54,7 @@
 
 err_hfi_init:
 	kfree(hdev);
-	return NULL;
+	return ERR_PTR(rc);
 }
 
 void vidc_hfi_deinitialize(enum msm_vidc_hfi_type hfi_type,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 70b93ff0..75f583f 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -19,6 +19,7 @@
 
 #define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
 #define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
+#define HFI_EVENT_SESSION_LTRUSE_FAILED (HFI_OX_BASE + 0x5)
 #define HFI_EVENT_RELEASE_BUFFER_REFERENCE (HFI_OX_BASE + 0x6)
 
 #define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES	\
@@ -81,9 +82,12 @@
 #define HFI_EXTRADATA_CLOSED_CAPTION_UD		0x0000000A
 #define HFI_EXTRADATA_AFD_UD			0x0000000B
 #define HFI_EXTRADATA_MPEG2_SEQDISP		0x0000000D
+#define HFI_EXTRADATA_FRAME_QP			0x0000000F
+#define HFI_EXTRADATA_FRAME_BITS_INFO		0x00000010
 #define HFI_EXTRADATA_MULTISLICE_INFO		0x7F100000
 #define HFI_EXTRADATA_NUM_CONCEALED_MB		0x7F100001
 #define HFI_EXTRADATA_INDEX					0x7F100002
+#define HFI_EXTRADATA_METADATA_LTR			0x7F100004
 #define HFI_EXTRADATA_METADATA_FILLER		0x7FE00002
 
 #define HFI_INDEX_EXTRADATA_INPUT_CROP		0x0700000E
@@ -202,6 +206,10 @@
 	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x015)
 #define HFI_PROPERTY_PARAM_VDEC_MPEG2_SEQDISP_EXTRADATA \
 	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x016)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_QP_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x018)
+#define HFI_PROPERTY_PARAM_VDEC_FRAME_BITS_INFO_EXTRADATA \
+	(HFI_PROPERTY_PARAM_VDEC_OX_START + 0x019)
 
 #define HFI_PROPERTY_CONFIG_VDEC_OX_START				\
 	(HFI_DOMAIN_BASE_VDEC + HFI_ARCH_OX_OFFSET + 0x0000)
@@ -218,6 +226,10 @@
 	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x001)
 #define  HFI_PROPERTY_PARAM_VENC_H264_IDR_S3D_FRAME_PACKING_NAL \
 	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x002)
+#define  HFI_PROPERTY_PARAM_VENC_LTR_INFO			\
+	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x003)
+#define  HFI_PROPERTY_PARAM_VENC_MBI_DUMPING				\
+	(HFI_PROPERTY_PARAM_VENC_OX_START + 0x005)
 
 #define HFI_PROPERTY_CONFIG_VENC_OX_START				\
 	(HFI_DOMAIN_BASE_VENC + HFI_ARCH_OX_OFFSET + 0x6000)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 846171e..c764758 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -97,7 +97,11 @@
 	HAL_EXTRADATA_NUM_CONCEALED_MB,
 	HAL_EXTRADATA_METADATA_FILLER,
 	HAL_EXTRADATA_ASPECT_RATIO,
-	HAL_EXTRADATA_MPEG2_SEQDISP
+	HAL_EXTRADATA_MPEG2_SEQDISP,
+	HAL_EXTRADATA_FRAME_QP,
+	HAL_EXTRADATA_FRAME_BITS_INFO,
+	HAL_EXTRADATA_LTR_INFO,
+	HAL_EXTRADATA_METADATA_MBI,
 };
 
 enum hal_property {
@@ -177,6 +181,11 @@
 	HAL_PARAM_BUFFER_ALLOC_MODE,
 	HAL_PARAM_VDEC_FRAME_ASSEMBLY,
 	HAL_PARAM_VDEC_CONCEAL_COLOR,
+	HAL_PARAM_VENC_LTRMODE,
+	HAL_CONFIG_VENC_MARKLTRFRAME,
+	HAL_CONFIG_VENC_USELTRFRAME,
+	HAL_CONFIG_VENC_LTRPERIOD,
+	HAL_PARAM_VENC_HIER_P_NUM_FRAMES,
 };
 
 enum hal_domain {
@@ -896,6 +905,27 @@
 	enum buffer_mode_type buffer_mode;
 };
 
+enum ltr_mode {
+	HAL_LTR_MODE_DISABLE,
+	HAL_LTR_MODE_MANUAL,
+	HAL_LTR_MODE_PERIODIC,
+};
+
+struct hal_ltrmode {
+	enum ltr_mode ltrmode;
+	u32 ltrcount;
+	u32 trustmode;
+};
+
+struct hal_ltruse {
+	u32 refltr;
+	u32 useconstrnt;
+	u32 frames;
+};
+
+struct hal_ltrmark {
+	u32 markframe;
+};
 /* HAL Response */
 
 enum command_response {
@@ -1032,6 +1062,8 @@
 	struct hal_capability_supported scale_x;
 	struct hal_capability_supported scale_y;
 	struct hal_capability_supported bitrate;
+	struct hal_capability_supported ltr_count;
+	struct hal_capability_supported hier_p;
 	struct hal_uncompressed_format_supported uncomp_format;
 	struct hal_interlace_format_supported HAL_format;
 	struct hal_nal_stream_format_supported nal_stream_format;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 1916e9f..5117266 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -309,7 +309,7 @@
 	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01A)
 #define HFI_PROPERTY_PARAM_VENC_H264_NAL_SVC_EXT		\
 	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01B)
-#define HFI_PROPERTY_PARAM_VENC_H264_LTRMODE		\
+#define HFI_PROPERTY_PARAM_VENC_LTRMODE		\
 	 (HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01C)
 #define HFI_PROPERTY_PARAM_VENC_VIDEO_FULL_RANGE	\
 	(HFI_PROPERTY_PARAM_VENC_COMMON_START + 0x01D)
@@ -338,7 +338,12 @@
 	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_COMMON_OFFSET + 0x7000)
 #define  HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER	\
 	(HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x008)
-
+#define  HFI_PROPERTY_CONFIG_VENC_MARKLTRFRAME			\
+	(HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x009)
+#define  HFI_PROPERTY_CONFIG_VENC_USELTRFRAME			\
+	(HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x00A)
+#define  HFI_PROPERTY_CONFIG_VENC_LTRPERIOD			\
+	(HFI_PROPERTY_CONFIG_VENC_COMMON_START + 0x00C)
 #define HFI_PROPERTY_CONFIG_VPE_COMMON_START				\
 	(HFI_DOMAIN_BASE_VPE + HFI_ARCH_COMMON_OFFSET + 0x8000)
 #define HFI_PROPERTY_CONFIG_VPE_DEINTERLACE				\
@@ -361,6 +366,7 @@
 #define HFI_CAPABILITY_BITRATE				(HFI_COMMON_BASE + 0x8)
 #define  HFI_CAPABILITY_BFRAME				(HFI_COMMON_BASE + 0x9)
 #define  HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS   (HFI_COMMON_BASE + 0x10)
+#define  HFI_CAPABILITY_ENC_LTR_COUNT      (HFI_COMMON_BASE + 0x11)
 
 struct hfi_capability_supported {
 	u32 capability_type;
@@ -531,6 +537,26 @@
 	u32 layer_id;
 };
 
+#define HFI_LTR_MODE_DISABLE	0x0
+#define HFI_LTR_MODE_MANUAL		0x1
+#define HFI_LTR_MODE_PERIODIC	0x2
+
+struct hfi_ltrmode {
+	u32 ltrmode;
+	u32 ltrcount;
+	u32 trustmode;
+};
+
+struct hfi_ltruse {
+	u32 refltr;
+	u32 useconstrnt;
+	u32 frames;
+};
+
+struct hfi_ltrmark {
+	u32 markframe;
+};
+
 struct hfi_frame_size {
 	u32 buffer_type;
 	u32 width;
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 9cd199b..40d1b2c 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -14,6 +14,7 @@
 #include <linux/bitmap.h>
 #include <linux/completion.h>
 #include <linux/ion.h>
+#include <linux/jiffies.h>
 #include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
@@ -28,6 +29,7 @@
 
 #define BUF_TYPE_OUTPUT V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
 #define BUF_TYPE_INPUT V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
+#define TIMEOUT msecs_to_jiffies(100)
 
 static struct ion_client *venc_ion_client;
 static long venc_secure(struct v4l2_subdev *sd);
@@ -377,7 +379,8 @@
 		goto vidc_wq_create_fail;
 	}
 
-	inst->vidc_context = msm_vidc_open(MSM_VIDC_CORE_0, MSM_VIDC_ENCODER);
+	inst->vidc_context = msm_vidc_open(MSM_VIDC_CORE_VENUS,
+				MSM_VIDC_ENCODER);
 	if (!inst->vidc_context) {
 		WFD_MSG_ERR("Failed to create vidc context\n");
 		rc = -ENXIO;
@@ -1026,10 +1029,18 @@
 		index = next_free_index(&inst->free_output_indices);
 		mutex_unlock(&inst->lock);
 
-		if (index < 0)
-			wait_for_completion(&inst->dq_complete);
-		else
+		if (index < 0) {
+			rc = wait_for_completion_timeout(&inst->dq_complete,
+					TIMEOUT);
+			if (!rc) {
+				WFD_MSG_ERR(
+					"Timed out waiting for an output buffer\n");
+				rc = -ETIMEDOUT;
+				goto err_fill_buf;
+			}
+		} else {
 			break;
+		}
 	}
 
 	buffer = (struct v4l2_buffer) {
@@ -1049,6 +1060,7 @@
 		mutex_unlock(&inst->lock);
 	}
 
+err_fill_buf:
 	return rc;
 }
 
@@ -1152,10 +1164,18 @@
 		index = next_free_index(&inst->free_input_indices);
 		mutex_unlock(&inst->lock);
 
-		if (index < 0)
-			wait_for_completion(&inst->dq_complete);
-		else
+		if (index < 0) {
+			rc = wait_for_completion_timeout(&inst->dq_complete,
+					TIMEOUT);
+			if (!rc) {
+				WFD_MSG_ERR(
+					"Timed out waiting for an input buffer\n");
+				rc = -ETIMEDOUT;
+				goto err_encode_frame;
+			}
+		} else {
 			break;
+		}
 	}
 
 	buffer = (struct v4l2_buffer) {
@@ -1175,6 +1195,7 @@
 		mark_index_busy(&inst->free_input_indices, index);
 		mutex_unlock(&inst->lock);
 	}
+err_encode_frame:
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index c20250e..433468e 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -23,12 +23,8 @@
 #define DEFAULT_MAX_FRAME_INTERVAL (1*NSEC_PER_SEC)
 #define DEFAULT_MODE ((enum vsg_modes)VSG_MODE_CFR)
 #define MAX_BUFS_BUSY_WITH_ENC 5
+#define TICKS_PER_TIMEOUT 2
 
-static void vsg_reset_timer(struct hrtimer *timer, ktime_t time)
-{
-	hrtimer_forward_now(timer, time);
-	hrtimer_restart(timer);
-}
 
 static int vsg_release_input_buffer(struct vsg_context *context,
 		struct vsg_buf_info *buf)
@@ -120,9 +116,10 @@
 	INIT_LIST_HEAD(&buf_info->node);
 
 	ktime_get_ts(&buf_info->time);
-	vsg_reset_timer(&context->threshold_timer, ns_to_ktime(
-				context->max_frame_interval));
-
+	if (work->work_delayed) {
+		buf_info->time = timespec_sub(buf_info->time,
+					context->delayed_frame_interval);
+	}
 	temp = NULL;
 	list_for_each_entry(temp, &context->busy_queue.node, node) {
 		if (mdp_buf_info_equals(&temp->mdp_buf_info,
@@ -233,6 +230,7 @@
 
 		INIT_WORK(&new_work->work, vsg_work_func);
 		new_work->context = context;
+		new_work->work_delayed = work->work_delayed;
 		queue_work(context->work_queue, &new_work->work);
 	}
 
@@ -245,25 +243,43 @@
 {
 	struct vsg_context *context = NULL;
 	struct vsg_work *task = NULL;
-
-	task = kzalloc(sizeof(*task), GFP_ATOMIC);
+	int64_t max_frame_interval = 0;
 	context = container_of(timer, struct vsg_context,
 			threshold_timer);
+
+	if (!context) {
+		WFD_MSG_ERR("Context not proper in %s", __func__);
+		goto threshold_err_no_context;
+	}
+	max_frame_interval = context->max_frame_interval;
+	if (list_empty(&context->free_queue.node) && !context->vsync_wait) {
+		context->vsync_wait = true;
+		max_frame_interval = context->max_frame_interval /
+					TICKS_PER_TIMEOUT;
+		goto restart_timer;
+	} else if (context->vsync_wait) {
+			max_frame_interval = context->max_frame_interval /
+						TICKS_PER_TIMEOUT;
+		context->vsync_wait = false;
+	}
+
+	task = kzalloc(sizeof(*task), GFP_ATOMIC);
 	if (!task) {
 		WFD_MSG_ERR("Out of memory in %s", __func__);
 		goto threshold_err_bad_param;
-	} else if (!context) {
-		WFD_MSG_ERR("Context not proper in %s", __func__);
-		goto threshold_err_no_context;
 	}
 
 	INIT_WORK(&task->work, vsg_timer_helper_func);
 	task->context = context;
+	task->work_delayed = false;
+	if (max_frame_interval < context->max_frame_interval)
+		task->work_delayed = true;
 
 	queue_work(context->work_queue, &task->work);
+restart_timer:
 threshold_err_bad_param:
 	hrtimer_forward_now(&context->threshold_timer, ns_to_ktime(
-				context->max_frame_interval));
+				max_frame_interval));
 	return HRTIMER_RESTART;
 threshold_err_no_context:
 	return HRTIMER_NORESTART;
@@ -298,6 +314,7 @@
 	context->last_buffer = NULL;
 	context->mode = DEFAULT_MODE;
 	context->state = VSG_STATE_NONE;
+	context->vsync_wait = false;
 	mutex_init(&context->mutex);
 
 	sd->dev_priv = context;
@@ -444,7 +461,7 @@
 			 * otherwise, diff between two consecutive frames might
 			 * be less than max_frame_interval (for just one sample)
 			 */
-			vsg_reset_timer(&context->threshold_timer,
+			hrtimer_forward_now(&context->threshold_timer,
 				ns_to_ktime(context->max_frame_interval));
 		}
 	}
@@ -568,7 +585,8 @@
 				context->max_frame_interval, interval);
 		context->max_frame_interval = interval;
 	}
-
+	context->delayed_frame_interval =
+		ns_to_timespec(context->frame_interval / TICKS_PER_TIMEOUT);
 	mutex_unlock(&context->mutex);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.h b/drivers/media/platform/msm/wfd/vsg-subdev.h
index 3347e5b..bbaced1 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.h
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -56,7 +56,7 @@
 };
 
 struct vsg_context {
-	struct vsg_buf_info	free_queue, busy_queue;
+	struct vsg_buf_info free_queue, busy_queue;
 	struct vsg_msg_ops vmops;
 	/* All time related values below in nanosecs */
 	int64_t frame_interval, max_frame_interval, frame_interval_variance;
@@ -66,11 +66,14 @@
 	struct vsg_buf_info *last_buffer;
 	int mode;
 	int state;
+	bool vsync_wait;
+	struct timespec delayed_frame_interval;
 };
 
 struct vsg_work {
 	struct vsg_context *context;
 	struct work_struct work;
+	bool work_delayed;
 };
 
 struct vsg_encode_work {
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 5dde469..9f18508 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -499,7 +499,7 @@
 	struct kfifo *data_b;
 	unsigned char evt = event;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
@@ -511,9 +511,14 @@
 
 static int hci_send_frame(struct sk_buff *skb)
 {
-	struct radio_hci_dev *hdev = (struct radio_hci_dev *) skb->dev;
+	struct radio_hci_dev *hdev;
 
-	if (!hdev) {
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return -EINVAL;
+	}
+	hdev = (struct radio_hci_dev *) skb->dev;
+	if (unlikely(!hdev)) {
 		kfree_skb(skb);
 		return -ENODEV;
 	}
@@ -528,6 +533,11 @@
 {
 	struct radio_hci_dev *hdev = (struct radio_hci_dev *) arg;
 	struct sk_buff *skb;
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, HCI Device is null\n", __func__);
+		return;
+	}
 	if (!(atomic_read(&hdev->cmd_cnt))
 		&& time_after(jiffies, hdev->cmd_last_tx + HZ)) {
 		FMDERR("%s command tx timeout", hdev->name);
@@ -555,6 +565,10 @@
 	struct radio_hci_dev *hdev = (struct radio_hci_dev *) arg;
 	struct sk_buff *skb;
 
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, HCI Device is null\n", __func__);
+		return;
+	}
 	read_lock(&hci_task_lock);
 
 	skb = skb_dequeue(&hdev->rx_q);
@@ -618,8 +632,14 @@
 
 int radio_hci_recv_frame(struct sk_buff *skb)
 {
-	struct radio_hci_dev *hdev = (struct radio_hci_dev *) skb->dev;
-	if (!hdev) {
+	struct radio_hci_dev *hdev;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return -EINVAL;
+	}
+	hdev = (struct radio_hci_dev *) skb->dev;
+	if (unlikely(!hdev)) {
 		FMDERR("%s hdev is null while receiving frame", hdev->name);
 		kfree_skb(skb);
 		return -ENXIO;
@@ -641,6 +661,10 @@
 	struct sk_buff *skb;
 	int ret = 0;
 
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci device is null\n", __func__);
+		return -EINVAL;
+	}
 	skb = alloc_skb(len, GFP_ATOMIC);
 	if (!skb) {
 		FMDERR("%s no memory for command", hdev->name);
@@ -679,7 +703,7 @@
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 	__u16 opcode = 0;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -746,6 +770,10 @@
 	struct hci_fm_recv_conf_req *recv_conf_req =
 		(struct hci_fm_recv_conf_req *) param;
 
+	if (recv_conf_req == NULL) {
+		FMDERR("%s, recv conf is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_RECV_CONF_REQ);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*recv_conf_req)),
@@ -760,6 +788,11 @@
 	struct hci_fm_trans_conf_req_struct *trans_conf_req =
 		(struct hci_fm_trans_conf_req_struct *) param;
 
+	if (trans_conf_req == NULL) {
+		FMDERR("%s, tx conf is null\n", __func__);
+		return -EINVAL;
+	}
+
 	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_TRANS_CONF_REQ);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*trans_conf_req)),
@@ -783,6 +816,10 @@
 	struct hci_fm_mute_mode_req *mute_mode_req =
 		(struct hci_fm_mute_mode_req *) param;
 
+	if (mute_mode_req == NULL) {
+		FMDERR("%s, mute mode is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_MUTE_MODE_REQ);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*mute_mode_req)),
@@ -797,6 +834,10 @@
 	struct hci_fm_tx_ps *tx_ps_req =
 		(struct hci_fm_tx_ps *) param;
 
+	if (tx_ps_req == NULL) {
+		FMDERR("%s, tx ps req is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
 		HCI_OCF_FM_RDS_PS_REQ);
 
@@ -811,6 +852,10 @@
 	struct hci_fm_tx_rt *tx_rt_req =
 		(struct hci_fm_tx_rt *) param;
 
+	if (tx_rt_req == NULL) {
+		FMDERR("%s, tx rt req is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
 		HCI_OCF_FM_RDS_RT_REQ);
 
@@ -824,6 +869,11 @@
 	__u16 opcode = 0;
 	struct hci_fm_stereo_mode_req *stereo_mode_req =
 		(struct hci_fm_stereo_mode_req *) param;
+
+	if (stereo_mode_req == NULL) {
+		FMDERR("%s, stere mode req is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_STEREO_MODE_REQ);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*stereo_mode_req)),
@@ -913,6 +963,10 @@
 	struct hci_fm_search_station_req *srch_stations =
 		(struct hci_fm_search_station_req *) param;
 
+	if (srch_stations == NULL) {
+		FMDERR("%s, search station param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SEARCH_STATIONS);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*srch_stations)),
@@ -926,6 +980,10 @@
 	struct hci_fm_search_rds_station_req *srch_stations =
 		(struct hci_fm_search_rds_station_req *) param;
 
+	if (srch_stations == NULL) {
+		FMDERR("%s, rds stations param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SEARCH_RDS_STATIONS);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*srch_stations)),
@@ -939,6 +997,10 @@
 	struct hci_fm_search_station_list_req *srch_list =
 		(struct hci_fm_search_station_list_req *) param;
 
+	if (srch_list == NULL) {
+		FMDERR("%s, search list param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SEARCH_STATIONS_LIST);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*srch_list)),
@@ -963,6 +1025,10 @@
 	struct hci_fm_rds_grp_req *fm_grp_mask =
 		(struct hci_fm_rds_grp_req *)param;
 
+	if (fm_grp_mask == NULL) {
+		FMDERR("%s, grp mask param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_RDS_GRP);
 	return radio_hci_send_cmd(hdev, opcode, sizeof(*fm_grp_mask),
@@ -1001,6 +1067,10 @@
 	struct hci_fm_def_data_rd_req *def_data_rd =
 		(struct hci_fm_def_data_rd_req *) param;
 
+	if (def_data_rd == NULL) {
+		FMDERR("%s, def data read param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
 		HCI_OCF_FM_DEFAULT_DATA_READ);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*def_data_rd)),
@@ -1014,6 +1084,10 @@
 	struct hci_fm_def_data_wr_req *def_data_wr =
 		(struct hci_fm_def_data_wr_req *) param;
 
+	if (def_data_wr == NULL) {
+		FMDERR("%s, def data write param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
 		HCI_OCF_FM_DEFAULT_DATA_WRITE);
 
@@ -1083,6 +1157,10 @@
 	__u16 opcode = 0;
 	struct hci_fm_riva_data *peek_data = (struct hci_fm_riva_data *)param;
 
+	if (peek_data == NULL) {
+		FMDERR("%s, peek data param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
 		HCI_OCF_FM_PEEK_DATA);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*peek_data)),
@@ -1094,6 +1172,10 @@
 	__u16 opcode = 0;
 	struct hci_fm_riva_poke *poke_data = (struct hci_fm_riva_poke *) param;
 
+	if (poke_data == NULL) {
+		FMDERR("%s, poke data param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
 		HCI_OCF_FM_POKE_DATA);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*poke_data)),
@@ -1106,6 +1188,10 @@
 	__u16 opcode = 0;
 	struct hci_fm_ssbi_peek *ssbi_peek = (struct hci_fm_ssbi_peek *) param;
 
+	if (ssbi_peek == NULL) {
+		FMDERR("%s, ssbi peek param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
 		HCI_OCF_FM_SSBI_PEEK_REG);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*ssbi_peek)),
@@ -1118,6 +1204,10 @@
 	__u16 opcode = 0;
 	struct hci_fm_ssbi_req *ssbi_poke = (struct hci_fm_ssbi_req *) param;
 
+	if (ssbi_poke == NULL) {
+		FMDERR("%s, ssbi poke param is null\n", __func__);
+		return -EINVAL;
+	}
 	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
 		HCI_OCF_FM_SSBI_POKE_REG);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*ssbi_poke)),
@@ -1139,7 +1229,13 @@
 {
 	struct hci_fm_ch_det_threshold *ch_det_th =
 			 (struct hci_fm_ch_det_threshold *) param;
-	u16 opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+	u16 opcode;
+
+	if (ch_det_th == NULL) {
+		FMDERR("%s, channel det thrshld is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_CH_DET_THRESHOLD);
 	return radio_hci_send_cmd(hdev, opcode, sizeof((*ch_det_th)),
 		ch_det_th);
@@ -1183,9 +1279,13 @@
 			unsigned long param, __u32 timeout)
 {
 	int err = 0;
-
 	DECLARE_WAITQUEUE(wait, current);
 
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci dev is null\n", __func__);
+		return -EINVAL;
+	}
+
 	mutex_lock(&iris_fm);
 	hdev->req_status = HCI_REQ_PEND;
 
@@ -1208,11 +1308,6 @@
 	case HCI_REQ_STATUS:
 		err = radio_hci_err(hdev->req_result);
 		break;
-
-	case HCI_REQ_CANCELED:
-		err = -hdev->req_result;
-		break;
-
 	default:
 		err = -ETIMEDOUT;
 		break;
@@ -1239,7 +1334,13 @@
 static inline int hci_conf_event_mask(__u8 *arg,
 		struct radio_hci_dev *hdev)
 {
-	u8 event_mask = *arg;
+	u8 event_mask;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	event_mask = *arg;
 	return  radio_hci_request(hdev, hci_fm_set_event_mask,
 				event_mask, RADIO_HCI_TIMEOUT);
 }
@@ -1270,8 +1371,13 @@
 static int hci_fm_tune_station(__u32 *arg, struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u32 tune_freq = *arg;
+	__u32 tune_freq;
 
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	tune_freq = *arg;
 	ret = radio_hci_request(hdev, hci_fm_tune_station_req, tune_freq,
 		RADIO_HCI_TIMEOUT);
 
@@ -1305,8 +1411,13 @@
 static int hci_fm_set_antenna(__u8 *arg, struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u8 antenna = *arg;
+	__u8 antenna;
 
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	antenna = *arg;
 	ret = radio_hci_request(hdev, hci_fm_set_antenna_req, antenna,
 		RADIO_HCI_TIMEOUT);
 
@@ -1317,8 +1428,13 @@
 	struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u8 sig_threshold = *arg;
+	__u8 sig_threshold;
 
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	sig_threshold = *arg;
 	ret = radio_hci_request(hdev, hci_fm_set_sig_threshold_req,
 		sig_threshold, RADIO_HCI_TIMEOUT);
 
@@ -1377,8 +1493,13 @@
 static int hci_fm_rds_grps_process(__u32 *arg, struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u32 fm_grps_process = *arg;
+	__u32 fm_grps_process;
 
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	fm_grps_process = *arg;
 	ret = radio_hci_request(hdev, hci_fm_rds_grp_process_req,
 		fm_grps_process, RADIO_HCI_TIMEOUT);
 
@@ -1410,8 +1531,13 @@
 int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u8 mode = *arg;
+	__u8 mode;
 
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	mode = *arg;
 	ret = radio_hci_request(hdev, hci_fm_do_calibration_req, mode,
 		RADIO_HCI_TIMEOUT);
 
@@ -1421,7 +1547,13 @@
 static int hci_read_grp_counters(__u8 *arg, struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u8 reset_counters = *arg;
+	__u8 reset_counters;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	reset_counters = *arg;
 	ret = radio_hci_request(hdev, hci_read_grp_counters_req,
 		reset_counters, RADIO_HCI_TIMEOUT);
 
@@ -1431,7 +1563,14 @@
 static int hci_set_notch_filter(__u8 *arg, struct radio_hci_dev *hdev)
 {
 	int ret = 0;
-	__u8 notch_filter = *arg;
+	__u8 notch_filter;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+
+	notch_filter = *arg;
 	ret = radio_hci_request(hdev, hci_set_notch_filter_req,
 		notch_filter, RADIO_HCI_TIMEOUT);
 
@@ -1505,8 +1644,8 @@
 
 	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
 		HCI_OCF_FM_SET_CALIBRATION);
-	return radio_hci_send_cmd(hdev, opcode, sizeof(*cal_req),
-		cal_req);
+	return radio_hci_send_cmd(hdev, opcode,
+		sizeof(hci_fm_set_cal_req_proc), cal_req);
 }
 
 static int hci_fm_do_cal_req(struct radio_hci_dev *hdev,
@@ -1623,6 +1762,11 @@
 
 static void radio_hci_req_complete(struct radio_hci_dev *hdev, int result)
 {
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci device is null\n", __func__);
+		return;
+	}
 	hdev->req_result = result;
 	hdev->req_status = HCI_REQ_DONE;
 	wake_up_interruptible(&hdev->req_wait_q);
@@ -1630,6 +1774,10 @@
 
 static void radio_hci_status_complete(struct radio_hci_dev *hdev, int result)
 {
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci device is null\n", __func__);
+		return;
+	}
 	hdev->req_result = result;
 	hdev->req_status = HCI_REQ_STATUS;
 	wake_up_interruptible(&hdev->req_wait_q);
@@ -1637,10 +1785,13 @@
 
 static void hci_cc_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	__u8 status;
 
-	if (status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
+	}
+	status = *((__u8 *) skb->data);
 
 	radio_hci_req_complete(hdev, status);
 }
@@ -1648,14 +1799,20 @@
 static void hci_cc_fm_disable_rsp(struct radio_hci_dev *hdev,
 	struct sk_buff *skb)
 {
-	__u8 status = *((__u8 *) skb->data);
+	__u8 status;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
-                FMDERR(":radio is null");
-                return;
-        }
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
+		return;
+	}
 
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	status = *((__u8 *) skb->data);
 	if ((radio->mode == FM_TURNING_OFF) && (status == 0)) {
 		iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
 		radio_hci_req_complete(hdev, status);
@@ -1665,54 +1822,71 @@
 	} else if ((radio->mode == FM_RECV) || (radio->mode == FM_TRANS)) {
 		iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
 		radio->mode = FM_OFF;
+	} else if ((radio->mode == FM_TURNING_OFF) && (status != 0)) {
+		radio_hci_req_complete(hdev, status);
 	}
 }
 
 static void hci_cc_conf_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_fm_conf_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_conf_rsp  *rsp;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
-
-	radio->recv_conf = rsp->recv_conf_rsp;
+	}
+	rsp = (struct hci_fm_conf_rsp *)skb->data;
+	if (!rsp->status)
+		radio->recv_conf = rsp->recv_conf_rsp;
 	radio_hci_req_complete(hdev, rsp->status);
 }
 
 static void hci_cc_fm_trans_get_conf_rsp(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
 {
-	struct hci_fm_get_trans_conf_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_get_trans_conf_rsp  *rsp;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
-
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
-	memcpy((void *)&radio->trans_conf,  (void*)&rsp->trans_conf_rsp,
+	}
+
+	rsp = (struct hci_fm_get_trans_conf_rsp *)skb->data;
+	if (!rsp->status)
+		memcpy((void *)&radio->trans_conf,
+			(void *)&rsp->trans_conf_rsp,
 			sizeof(rsp->trans_conf_rsp));
+
 	radio_hci_req_complete(hdev, rsp->status);
 }
 
 static void hci_cc_fm_enable_rsp(struct radio_hci_dev *hdev,
 	struct sk_buff *skb)
 {
-	struct hci_fm_conf_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_conf_rsp  *rsp;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
 
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_conf_rsp *)skb->data;
 	if (rsp->status) {
 		radio_hci_req_complete(hdev, rsp->status);
 		return;
@@ -1732,18 +1906,21 @@
 static void hci_cc_fm_trans_set_conf_rsp(struct radio_hci_dev *hdev,
 	struct sk_buff *skb)
 {
-	struct hci_fm_conf_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_conf_rsp  *rsp;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
 
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
-
-	iris_q_event(radio, HCI_EV_CMD_COMPLETE);
+	}
+	rsp = (struct hci_fm_conf_rsp  *)skb->data;
+	if (!rsp->status)
+		iris_q_event(radio, HCI_EV_CMD_COMPLETE);
 
 	radio_hci_req_complete(hdev, rsp->status);
 }
@@ -1752,31 +1929,41 @@
 static void hci_cc_sig_threshold_rsp(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
 {
-	struct hci_fm_sig_threshold_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_sig_threshold_rsp  *rsp;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
-
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
+	}
 
-	memcpy(&radio->sig_th, rsp, sizeof(struct hci_fm_sig_threshold_rsp));
+	rsp = (struct hci_fm_sig_threshold_rsp  *)skb->data;
+	if (!rsp->status)
+		memcpy(&radio->sig_th, rsp,
+			sizeof(struct hci_fm_sig_threshold_rsp));
+
 	radio_hci_req_complete(hdev, rsp->status);
 }
 
 static void hci_cc_station_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	struct hci_fm_station_rsp *rsp = (void *)skb->data;
+	struct hci_fm_station_rsp *rsp;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
 
+	rsp = (struct hci_fm_station_rsp *)skb->data;
 	radio->fm_st_rsp = *(rsp);
 
 	/* Tune is always succesful */
@@ -1785,31 +1972,41 @@
 
 static void hci_cc_prg_srv_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_fm_prgm_srv_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_prgm_srv_rsp  *rsp;
 
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
+	}
+
+	rsp = (struct hci_fm_prgm_srv_rsp  *)skb->data;
 
 	radio_hci_req_complete(hdev, rsp->status);
 }
 
 static void hci_cc_rd_txt_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_fm_radio_txt_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_radio_txt_rsp  *rsp;
 
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
+	}
 
+	rsp = (struct hci_fm_radio_txt_rsp  *)skb->data;
 	radio_hci_req_complete(hdev, rsp->status);
 }
 
 static void hci_cc_af_list_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
 {
-	struct hci_fm_af_list_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_af_list_rsp  *rsp;
 
-	if (rsp->status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
+	}
 
+	rsp = (struct hci_fm_af_list_rsp  *)skb->data;
 	radio_hci_req_complete(hdev, rsp->status);
 }
 
@@ -1817,20 +2014,25 @@
 	struct sk_buff *skb)
 {
 	struct v4l2_capability *v4l_cap;
-	struct hci_fm_feature_list_rsp  *rsp = (void *)skb->data;
+	struct hci_fm_feature_list_rsp  *rsp;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
 
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_feature_list_rsp  *)skb->data;
 	v4l_cap = &radio->g_cap;
 
-	if (rsp->status)
-		return;
-	v4l_cap->capabilities = (rsp->feature_mask & 0x000002) |
-		(rsp->feature_mask & 0x000001);
+	if (!rsp->status)
+		v4l_cap->capabilities = (rsp->feature_mask & 0x000002) |
+						(rsp->feature_mask & 0x000001);
 
 	radio_hci_req_complete(hdev, rsp->status);
 }
@@ -1839,17 +2041,20 @@
 	struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	struct hci_fm_dbg_param_rsp *rsp = (void *)skb->data;
+	struct hci_fm_dbg_param_rsp *rsp;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
 
-	radio->st_dbg_param = *(rsp);
-	if (radio->st_dbg_param.status)
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
+	}
 
+	rsp = (struct hci_fm_dbg_param_rsp *)skb->data;
+	radio->st_dbg_param = *(rsp);
 	radio_hci_req_complete(hdev, radio->st_dbg_param.status);
 }
 
@@ -1858,7 +2063,7 @@
 {
 	struct kfifo *data_b;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
@@ -1871,46 +2076,55 @@
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	__u8 status = *((__u8 *) skb->data);
+	__u8 status;
 	int len;
 	char *data;
 
-	if (status)
-		return;
-	len = skb->data[RIVA_PEEK_LEN_OFSET] + RIVA_PEEK_PARAM;
-	data = kmalloc(len, GFP_ATOMIC);
-
-	if (!data) {
-		FMDERR("Memory allocation failed");
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
 	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		len = skb->data[RIVA_PEEK_LEN_OFSET] + RIVA_PEEK_PARAM;
+		data = kmalloc(len, GFP_ATOMIC);
 
-	memcpy(data, &skb->data[PEEK_DATA_OFSET], len);
-	iris_q_evt_data(radio, data, len, IRIS_BUF_PEEK);
+		if (data != NULL) {
+			memcpy(data, &skb->data[PEEK_DATA_OFSET], len);
+			iris_q_evt_data(radio, data, len, IRIS_BUF_PEEK);
+			kfree(data);
+		} else {
+			FMDERR("Memory allocation failed");
+		}
+	}
+
 	radio_hci_req_complete(hdev, status);
-	kfree(data);
-
 }
 
 static void hci_cc_riva_read_default_rsp(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	__u8 status = *((__u8 *) skb->data);
+	__u8 status;
 	__u8 len;
 
-        if (radio == NULL) {
-                FMDERR(":radio is null");
-                return;
-        }
-
-	if (status)
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
 		return;
-	len = skb->data[1];
-
-	memset(&radio->default_data, 0 , sizeof(struct hci_fm_data_rd_rsp));
-	memcpy(&radio->default_data, &skb->data[0], len+2);
-	iris_q_evt_data(radio, &skb->data[0], len+2, IRIS_BUF_RD_DEFAULT);
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		len = skb->data[1];
+		memset(&radio->default_data, 0,
+			sizeof(struct hci_fm_data_rd_rsp));
+		memcpy(&radio->default_data, &skb->data[0], len+2);
+		iris_q_evt_data(radio, &skb->data[0], len+2,
+				IRIS_BUF_RD_DEFAULT);
+	}
 	radio_hci_req_complete(hdev, status);
 }
 
@@ -1918,41 +2132,53 @@
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	__u8 status = *((__u8 *) skb->data);
+	__u8 status;
 	char *data;
 
-	if (status)
-		return;
-	data = kmalloc(SSBI_PEEK_LEN, GFP_ATOMIC);
-	if (!data) {
-		FMDERR("Memory allocation failed");
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
 	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		data = kmalloc(SSBI_PEEK_LEN, GFP_ATOMIC);
+		if (data != NULL) {
+			data[0] = skb->data[PEEK_DATA_OFSET];
+			iris_q_evt_data(radio, data, SSBI_PEEK_LEN,
+					IRIS_BUF_SSBI_PEEK);
+			kfree(data);
+		} else {
+			FMDERR("Memory allocation failed");
+		}
+	}
 
-	data[0] = skb->data[PEEK_DATA_OFSET];
-	iris_q_evt_data(radio, data, SSBI_PEEK_LEN, IRIS_BUF_SSBI_PEEK);
 	radio_hci_req_complete(hdev, status);
-	kfree(data);
 }
 
 static void hci_cc_rds_grp_cntrs_rsp(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	__u8 status = *((__u8 *) skb->data);
+	__u8 status;
 	char *data;
-	if (status)
-		return;
-	data = kmalloc(RDS_GRP_CNTR_LEN, GFP_ATOMIC);
-	if (!data) {
-		FMDERR("memory allocation failed");
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
 	}
-	memcpy(data, &skb->data[1], RDS_GRP_CNTR_LEN);
-	iris_q_evt_data(radio, data, RDS_GRP_CNTR_LEN, IRIS_BUF_RDS_CNTRS);
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		data = kmalloc(RDS_GRP_CNTR_LEN, GFP_ATOMIC);
+		if (data != NULL) {
+			memcpy(data, &skb->data[1], RDS_GRP_CNTR_LEN);
+			iris_q_evt_data(radio, data, RDS_GRP_CNTR_LEN,
+						IRIS_BUF_RDS_CNTRS);
+			kfree(data);
+		} else {
+			FMDERR("memory allocation failed");
+		}
+	}
 	radio_hci_req_complete(hdev, status);
-	kfree(data);
-
 }
 
 static void hci_cc_do_calibration_rsp(struct radio_hci_dev *hdev,
@@ -1960,22 +2186,23 @@
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 	static struct hci_cc_do_calibration_rsp rsp ;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
 	rsp.status = skb->data[0];
 	rsp.mode = skb->data[CALIB_MODE_OFSET];
 
-	if (rsp.status) {
-		FMDERR("status = %d", rsp.status);
-		return;
-	}
-	if (rsp.mode == PROCS_CALIB_MODE) {
-		memcpy(&rsp.data[0], &skb->data[CALIB_DATA_OFSET],
+	if (!rsp.status) {
+		if (rsp.mode == PROCS_CALIB_MODE) {
+			memcpy(&rsp.data[0], &skb->data[CALIB_DATA_OFSET],
 				PROCS_CALIB_SIZE);
-	iris_q_evt_data(radio, rsp.data, PROCS_CALIB_SIZE,
+			iris_q_evt_data(radio, rsp.data, PROCS_CALIB_SIZE,
 					IRIS_BUF_CAL_DATA);
-	} else {
-		return;
+		}
 	}
-
 	radio_hci_req_complete(hdev, rsp.status);
 }
 
@@ -1983,27 +2210,37 @@
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	u8  status = skb->data[0];
+	u8  status;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
-	if (status) {
-		FMDERR("status = %d", status);
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
 		return;
 	}
-	memcpy(&radio->ch_det_threshold, &skb->data[1],
-		sizeof(struct hci_fm_ch_det_threshold));
+	status = skb->data[0];
+	if (!status)
+		memcpy(&radio->ch_det_threshold, &skb->data[1],
+			sizeof(struct hci_fm_ch_det_threshold));
+
 	radio_hci_req_complete(hdev, status);
 }
 
 static inline void hci_cmd_complete_event(struct radio_hci_dev *hdev,
 		struct sk_buff *skb)
 {
-	struct hci_ev_cmd_complete *cmd_compl_ev = (void *) skb->data;
+	struct hci_ev_cmd_complete *cmd_compl_ev;
 	__u16 opcode;
 
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	cmd_compl_ev = (struct hci_ev_cmd_complete *)skb->data;
 	skb_pull(skb, sizeof(*cmd_compl_ev));
 
 	opcode = __le16_to_cpu(cmd_compl_ev->cmd_opcode);
@@ -2122,7 +2359,7 @@
 	int i;
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
@@ -2154,6 +2391,7 @@
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	radio->search_on = 0;
 	iris_q_event(radio, IRIS_EVT_SEEK_COMPLETE);
 }
 
@@ -2168,10 +2406,15 @@
 	int abs_freq;
 	int len;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
 	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
 	if (!ev) {
 		FMDERR("Memory allocation failed");
@@ -2210,7 +2453,13 @@
 		struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	__u8 st_status = *((__u8 *) skb->data);
+	__u8 st_status;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	st_status = *((__u8 *) skb->data);
 	if (st_status)
 		iris_q_event(radio, IRIS_EVT_STEREO);
 	else
@@ -2230,10 +2479,16 @@
 	radio = video_get_drvdata(video_get_dev());
 	index = RDSGRP_DATA_OFFSET;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return;
 	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
 	for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
 		temp.rdsBlk[blocknum].rdsLsb =
 			(skb->data[index]);
@@ -2304,6 +2559,10 @@
 	unsigned short int info_byte = 0;
 	unsigned short int byte_pair_index;
 
+	if (rds_buf == NULL) {
+		FMDERR("%s, rds buffer is null\n", __func__);
+		return;
+	}
 	byte_pair_index = AGT(rds_buf->rdsBlk[1].rdsLsb);
 	if (byte_pair_index == 0) {
 		c_byt_pair_index = 0;
@@ -2486,6 +2745,10 @@
 	int len = 0;
 	char *data;
 
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
 	iris_q_event(radio, IRIS_EVT_NEW_RT_RDS);
 
 	while ((skb->data[len+RDS_OFFSET] != 0x0d) && (len < MAX_RT_LENGTH))
@@ -2516,6 +2779,10 @@
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
 	struct hci_ev_af_list ev;
 
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
 	ev.tune_freq = *((int *) &skb->data[0]);
 	ev.pi_code = *((__le16 *) &skb->data[PI_CODE_OFFSET]);
 	ev.af_size = skb->data[AF_SIZE_OFFSET];
@@ -2534,7 +2801,14 @@
 	struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	__u8 rds_status = skb->data[0];
+	__u8 rds_status;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rds_status = skb->data[0];
 
 	if (rds_status)
 		iris_q_event(radio, IRIS_EVT_RDS_AVAIL);
@@ -2546,7 +2820,13 @@
 	struct sk_buff *skb)
 {
 	struct iris_device *radio = video_get_drvdata(video_get_dev());
-	u8 serv_avble = skb->data[0];
+	u8 serv_avble;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	serv_avble = skb->data[0];
 	if (serv_avble)
 		iris_q_event(radio, IRIS_EVT_ABOVE_TH);
 	else
@@ -2641,13 +2921,15 @@
 {
 	int retval = 0;
 	enum search_t srch;
+	int saved_val;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
 
 	srch = radio->g_search_mode & SRCH_MODE;
+	saved_val = radio->search_on;
 	radio->search_on = on;
 	if (on) {
 		switch (srch) {
@@ -2682,6 +2964,8 @@
 		retval = hci_cmd(HCI_FM_CANCEL_SEARCH_CMD, radio->fm_hdev);
 	}
 
+	if (retval < 0)
+		radio->search_on = saved_val;
 	return retval;
 }
 
@@ -2691,7 +2975,7 @@
 	int rds_grps_proc = 0x00;
 	int retval = 0;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -2734,18 +3018,22 @@
 static int iris_recv_set_region(struct iris_device *radio, int req_region)
 {
 	int retval;
+	int saved_val;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
-
+	saved_val = radio->region;
 	radio->region = req_region;
 
 	retval = hci_set_fm_recv_conf(
 			&radio->recv_conf,
 			radio->fm_hdev);
 
+	if (retval < 0)
+		radio->region = saved_val;
+
 	return retval;
 }
 
@@ -2753,16 +3041,22 @@
 static int iris_trans_set_region(struct iris_device *radio, int req_region)
 {
 	int retval;
+	int saved_val;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
+
+	saved_val = radio->region;
 	radio->region = req_region;
 
 	retval = hci_set_fm_trans_conf(
 			&radio->trans_conf,
 				radio->fm_hdev);
+
+	if (retval < 0)
+		radio->region = saved_val;
 	return retval;
 }
 
@@ -2772,7 +3066,7 @@
 
 	int retval;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -2789,6 +3083,10 @@
 	unsigned char i;
 	int retval = -EINVAL;
 
+	if (unlikely(qc == NULL)) {
+		FMDERR("%s, query ctrl is null\n", __func__);
+		return retval;
+	}
 	for (i = 0; i < ARRAY_SIZE(iris_v4l2_queryctrl); i++) {
 		if (qc->id && qc->id == iris_v4l2_queryctrl[i].id) {
 			memcpy(qc, &(iris_v4l2_queryctrl[i]), sizeof(*qc));
@@ -2805,7 +3103,7 @@
 	char cal_mode = 0x00;
 	int retval = 0x00;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -2844,28 +3142,46 @@
 	struct hci_fm_def_data_rd_req rd;
 	int lsb, msb;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
-		return -EINVAL;
+		retval = -EINVAL;
+		goto END;
 	}
 
+	if (unlikely(ctrl == NULL)) {
+		FMDERR("%s, v4l2 ctrl is null\n", __func__);
+		retval = -EINVAL;
+		goto END;
+	}
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_VOLUME:
 		break;
 	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = radio->mute_mode.hard_mute;
+		if (is_valid_hard_mute(radio->mute_mode.hard_mute))
+			ctrl->value = radio->mute_mode.hard_mute;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCHMODE:
-		ctrl->value = radio->g_search_mode;
+		if (is_valid_srch_mode(radio->g_search_mode))
+			ctrl->value = radio->g_search_mode;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SCANDWELL:
-		ctrl->value = radio->g_scan_time;
+		if (is_valid_scan_dwell_prd(radio->g_scan_time))
+			ctrl->value = radio->g_scan_time;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCHON:
 		ctrl->value = radio->search_on;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_STATE:
-		ctrl->value = radio->mode;
+		if (is_valid_fm_state(radio->mode))
+			ctrl->value = radio->mode;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_IOVERC:
 		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
@@ -2875,68 +3191,115 @@
 		break;
 	case V4L2_CID_PRIVATE_IRIS_INTDET:
 		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
-		if (retval < 0)
-			return retval;
-		ctrl->value = radio->st_dbg_param.in_det_out;
+		if (retval == 0)
+			ctrl->value = radio->st_dbg_param.in_det_out;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_REGION:
 		ctrl->value = radio->region;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
 		retval = hci_cmd(HCI_FM_GET_SIGNAL_TH_CMD, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Error in get signal threshold %d\n", retval);
-			return retval;
-		}
-		ctrl->value = radio->sig_th.sig_threshold;
+		if ((retval == 0) &&
+			is_valid_sig_th(radio->sig_th.sig_threshold))
+			ctrl->value = radio->sig_th.sig_threshold;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
-		ctrl->value = radio->srch_rds.srch_pty;
+		if (is_valid_pty(radio->srch_rds.srch_pty))
+			ctrl->value = radio->srch_rds.srch_pty;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCH_PI:
-		ctrl->value = radio->srch_rds.srch_pi;
+		if (is_valid_pi(radio->srch_rds.srch_pi))
+			ctrl->value = radio->srch_rds.srch_pi;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
-		ctrl->value = radio->srch_st_result.num_stations_found;
+		if (is_valid_srch_station_cnt(
+			radio->srch_st_result.num_stations_found))
+			ctrl->value = radio->srch_st_result.num_stations_found;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
 		if (radio->mode == FM_RECV) {
-			ctrl->value = radio->recv_conf.emphasis;
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_emphasis(radio->recv_conf.emphasis))
+				ctrl->value = radio->recv_conf.emphasis;
+			else
+				retval = -EINVAL;
 		} else if (radio->mode == FM_TRANS) {
-			ctrl->value = radio->trans_conf.emphasis;
+			retval =  hci_cmd(HCI_FM_GET_TX_CONFIG,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_emphasis(radio->trans_conf.emphasis))
+				ctrl->value = radio->trans_conf.emphasis;
+			else
+				retval = -EINVAL;
 		} else {
-			FMDERR("Error in radio mode"
-				" %d\n", retval);
-			return -EINVAL;
+			retval = -EINVAL;
+			FMDERR("Error in radio mode"" %d\n", retval);
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDS_STD:
 		if (radio->mode == FM_RECV) {
-			ctrl->value = radio->recv_conf.rds_std;
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_rds_std(radio->recv_conf.rds_std))
+				ctrl->value = radio->recv_conf.rds_std;
+			else
+				retval = -EINVAL;
 		} else if (radio->mode == FM_TRANS) {
-			ctrl->value = radio->trans_conf.rds_std;
+			retval =  hci_cmd(HCI_FM_GET_TX_CONFIG,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_rds_std(radio->trans_conf.rds_std))
+				ctrl->value = radio->trans_conf.rds_std;
+			else
+				retval = -EINVAL;
 		} else {
+			retval = -EINVAL;
 			FMDERR("Error in radio mode"
 				" %d\n", retval);
-			return -EINVAL;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SPACING:
 		if (radio->mode == FM_RECV) {
-			ctrl->value = radio->recv_conf.ch_spacing;
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_chan_spacing(
+						radio->recv_conf.ch_spacing))
+				ctrl->value = radio->recv_conf.ch_spacing;
+			else
+				retval = -EINVAL;
 		} else {
+			retval = -EINVAL;
 			FMDERR("Error in radio mode"
 				" %d\n", retval);
-			return -EINVAL;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSON:
 		if (radio->mode == FM_RECV) {
-			ctrl->value = radio->recv_conf.rds_std;
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_rds_std(radio->recv_conf.rds_std))
+				ctrl->value = radio->recv_conf.rds_std;
+			else
+				retval = -EINVAL;
 		} else {
+			retval = -EINVAL;
 			FMDERR("Error in radio mode"
 				" %d\n", retval);
-			return -EINVAL;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
@@ -2956,7 +3319,12 @@
 		ctrl->value = radio->g_antenna;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
-		ctrl->value = radio->mute_mode.soft_mute;
+		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
+		if ((retval == 0) &&
+			is_valid_soft_mute(radio->mute_mode.soft_mute))
+			ctrl->value = radio->mute_mode.soft_mute;
+		else
+			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION:
 		retval = iris_do_calibration(radio);
@@ -2965,47 +3333,30 @@
 		if (radio->mode == FM_RECV) {
 			retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD,
 						 radio->fm_hdev);
-			if (retval < 0) {
-				FMDERR("Get SINR Failed");
-				return retval;
-			}
-			ctrl->value = radio->fm_st_rsp.station_rsp.sinr;
-
+			if (retval == 0)
+				ctrl->value = radio->fm_st_rsp.station_rsp.sinr;
 		} else
 			retval = -EINVAL;
 		break;
 	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Get High det threshold failed %x", retval);
-			return retval;
-		}
-		ctrl->value = radio->ch_det_threshold.high_th;
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.high_th;
 		break;
 	case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Get Low det threshold failed %x", retval);
-			return retval;
-		}
-		ctrl->value = radio->ch_det_threshold.low_th;
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.low_th;
 		break;
 	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Get SINR threshold failed %x", retval);
-			return retval;
-		}
-		ctrl->value = radio->ch_det_threshold.sinr;
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.sinr;
 		break;
 	case V4L2_CID_PRIVATE_SINR_SAMPLES:
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Get SINR samples failed %x", retval);
-			return retval;
-		}
-
-		ctrl->value = radio->ch_det_threshold.sinr_samples;
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.sinr_samples;
 		break;
 	case V4L2_CID_PRIVATE_VALID_CHANNEL:
 		ctrl->value = radio->is_station_valid;
@@ -3017,13 +3368,11 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Get AF Jump Threshold failed %x", retval);
-			return retval;
+		if (retval == 0) {
+			lsb = radio->default_data.data[AF_RMSSI_TH_LSB_OFFSET];
+			msb = radio->default_data.data[AF_RMSSI_TH_MSB_OFFSET];
+			ctrl->value = ((msb << 8) | lsb);
 		}
-		lsb = radio->default_data.data[AF_RMSSI_TH_LSB_OFFSET];
-		msb = radio->default_data.data[AF_RMSSI_TH_MSB_OFFSET];
-		ctrl->value = ((msb << 8) | lsb);
 		break;
 	case V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES:
 		rd.mode = FM_RDS_CNFG_MODE;
@@ -3032,11 +3381,9 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("Get AF jump rmssi samples failed %x", retval);
-			return retval;
-		}
-		ctrl->value = radio->default_data.data[AF_RMSSI_SAMPLES_OFFSET];
+		if (retval == 0)
+			ctrl->value =
+			radio->default_data.data[AF_RMSSI_SAMPLES_OFFSET];
 		break;
 	case V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH:
 		rd.mode = FM_RX_CONFG_MODE;
@@ -3045,13 +3392,12 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("get good channel rmssi th failed %x", retval);
-			return retval;
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[GD_CH_RMSSI_TH_OFFSET];
+			if (ctrl->value > MAX_GD_CH_RMSSI_TH)
+				ctrl->value -= 256;
 		}
-		ctrl->value = radio->default_data.data[GD_CH_RMSSI_TH_OFFSET];
-		if (ctrl->value > MAX_GD_CH_RMSSI_TH)
-			ctrl->value -= 256;
 		break;
 	case V4L2_CID_PRIVATE_SRCHALGOTYPE:
 		rd.mode = FM_RX_CONFG_MODE;
@@ -3060,11 +3406,9 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("get search algo type failed %x", retval);
-			return retval;
-		}
-		ctrl->value = radio->default_data.data[SRCH_ALGO_TYPE_OFFSET];
+		if (retval == 0)
+			ctrl->value =
+			radio->default_data.data[SRCH_ALGO_TYPE_OFFSET];
 		break;
 	case V4L2_CID_PRIVATE_SINRFIRSTSTAGE:
 		rd.mode = FM_RX_CONFG_MODE;
@@ -3073,13 +3417,12 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("default data read failed %x", retval);
-			return retval;
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[SINRFIRSTSTAGE_OFFSET];
+			if (ctrl->value > MAX_SINR_FIRSTSTAGE)
+				ctrl->value -= 256;
 		}
-		ctrl->value = radio->default_data.data[SINRFIRSTSTAGE_OFFSET];
-		if (ctrl->value > MAX_SINR_FIRSTSTAGE)
-			ctrl->value -= 256;
 		break;
 	case V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE:
 		rd.mode = FM_RX_CONFG_MODE;
@@ -3088,13 +3431,12 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("default data read failed %x", retval);
-			return retval;
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[RMSSIFIRSTSTAGE_OFFSET];
+			if (ctrl->value > MAX_RMSSI_FIRSTSTAGE)
+				ctrl->value -= 256;
 		}
-		ctrl->value = radio->default_data.data[RMSSIFIRSTSTAGE_OFFSET];
-		if (ctrl->value > MAX_RMSSI_FIRSTSTAGE)
-			ctrl->value -= 256;
 		break;
 	case V4L2_CID_PRIVATE_CF0TH12:
 		rd.mode = FM_RX_CONFG_MODE;
@@ -3103,26 +3445,31 @@
 		rd.param = 0;
 
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
-		if (retval < 0) {
-			FMDERR("default data read failed %x", retval);
-			return retval;
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[CF0TH12_BYTE1_OFFSET];
+			cf0 = radio->default_data.data[CF0TH12_BYTE2_OFFSET];
+			ctrl->value |= (cf0 << 8);
+			cf0 = radio->default_data.data[CF0TH12_BYTE3_OFFSET];
+			ctrl->value |= (cf0 << 16);
+			cf0 = radio->default_data.data[CF0TH12_BYTE4_OFFSET];
+			if (cf0 > 127)
+				cf0 -= 256;
+			ctrl->value |= (cf0 << 24);
 		}
-		ctrl->value = radio->default_data.data[CF0TH12_BYTE1_OFFSET];
-		cf0 = radio->default_data.data[CF0TH12_BYTE2_OFFSET];
-		ctrl->value |= (cf0 << 8);
-		cf0 = radio->default_data.data[CF0TH12_BYTE3_OFFSET];
-		ctrl->value |= (cf0 << 16);
-		cf0 = radio->default_data.data[CF0TH12_BYTE4_OFFSET];
-		if (cf0 > 127)
-			cf0 -= 256;
-		ctrl->value |= (cf0 << 24);
 		break;
 	default:
 		retval = -EINVAL;
+		break;
 	}
+
+END:
+	if (retval > 0)
+		retval = -EINVAL;
 	if (retval < 0)
 		FMDERR("get control failed with %d, id: %d\n",
 			retval, ctrl->id);
+
 	return retval;
 }
 
@@ -3134,24 +3481,38 @@
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	struct hci_fm_def_data_rd_req default_data_rd;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
-		return -EINVAL;
+		retval = -EINVAL;
+		goto END;
 	}
 
+	if (unlikely((ctrl == NULL)) || unlikely((ctrl->count == 0))
+		|| unlikely((ctrl->controls == NULL))) {
+		FMDERR("%s, invalid v4l2 ctrl\n", __func__);
+		retval = -EINVAL;
+		goto END;
+	}
 	switch ((ctrl->controls[0]).id) {
 	case V4L2_CID_PRIVATE_IRIS_READ_DEFAULT:
 		data = (ctrl->controls[0]).string;
 		memset(&default_data_rd, 0, sizeof(default_data_rd));
 		if (copy_from_user(&default_data_rd.mode, data,
-					sizeof(default_data_rd)))
-			return -EFAULT;
+					sizeof(default_data_rd))) {
+			retval = -EFAULT;
+			goto END;
+		}
 		retval = hci_def_data_read(&default_data_rd, radio->fm_hdev);
 		break;
 	default:
 		retval = -EINVAL;
+		break;
 	}
 
+END:
+	if (retval > 0)
+		retval = -EINVAL;
+
 	return retval;
 }
 
@@ -3168,10 +3529,17 @@
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	char *data = NULL;
 
-	if ((ctrl == NULL) || (ctrl->controls == NULL)
-		|| (ctrl->count == 0)) {
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
 		retval = -EINVAL;
-		return retval;
+		goto END;
+	}
+
+	if (unlikely((ctrl == NULL)) || unlikely((ctrl->count == 0))
+		|| unlikely((ctrl->controls == NULL))) {
+		FMDERR("%s, invalid v4l2 ctrl\n", __func__);
+		retval = -EINVAL;
+		goto END;
 	}
 
 	switch ((ctrl->controls[0]).id) {
@@ -3185,16 +3553,23 @@
 		data = (ctrl->controls[0]).string;
 
 		if (copy_from_user(tx_ps.ps_data,
-				data, bytes_to_copy))
-				return -EFAULT;
-		tx_ps.ps_control =  0x01;
-		tx_ps.pi = radio->pi;
-		tx_ps.pty = radio->pty;
-		tx_ps.ps_repeatcount = radio->ps_repeatcount;
-		tx_ps.ps_num = (bytes_to_copy / PS_STRING_LEN);
+				data, bytes_to_copy)) {
+			FMDERR("%s: copy from user for tx ps name failed\n",
+				__func__);
+			retval = -EFAULT;
+			goto END;
+		} else {
+			tx_ps.ps_control =  0x01;
+			tx_ps.pi = radio->pi;
+			tx_ps.pty = radio->pty;
+			tx_ps.ps_repeatcount = radio->ps_repeatcount;
+			tx_ps.ps_num = (bytes_to_copy / PS_STRING_LEN);
 
-		retval = radio_hci_request(radio->fm_hdev, hci_trans_ps_req,
-				(unsigned long)&tx_ps, RADIO_HCI_TIMEOUT);
+			retval = radio_hci_request(radio->fm_hdev,
+							hci_trans_ps_req,
+							(unsigned long)&tx_ps,
+							RADIO_HCI_TIMEOUT);
+		}
 		break;
 	case V4L2_CID_RDS_TX_RADIO_TEXT:
 		bytes_to_copy =
@@ -3204,16 +3579,22 @@
 		memset(tx_rt.rt_data, 0, MAX_RT_LENGTH);
 
 		if (copy_from_user(tx_rt.rt_data,
-				data, bytes_to_copy))
-				return -EFAULT;
+				data, bytes_to_copy)) {
+			FMDERR("%s: copy from user for tx rt failed\n",
+				 __func__);
+			retval = -EFAULT;
+			goto END;
+		} else {
+			tx_rt.rt_control = 0x01;
+			tx_rt.pi = radio->pi;
+			tx_rt.pty = radio->pty;
+			tx_rt.rt_len = bytes_to_copy;
 
-		tx_rt.rt_control =  0x01;
-		tx_rt.pi = radio->pi;
-		tx_rt.pty = radio->pty;
-		tx_rt.rt_len = bytes_to_copy;
-
-		retval = radio_hci_request(radio->fm_hdev, hci_trans_rt_req,
-				(unsigned long)&tx_rt, RADIO_HCI_TIMEOUT);
+			retval = radio_hci_request(radio->fm_hdev,
+							hci_trans_rt_req,
+							(unsigned long)&tx_rt,
+							RADIO_HCI_TIMEOUT);
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT:
 		data = (ctrl->controls[0]).string;
@@ -3228,7 +3609,8 @@
 		 */
 		if (ctrl->controls[0].size > (DEFAULT_DATA_SIZE + 2)) {
 			pr_err("%s: Default data buffer overflow!\n", __func__);
-			return -EINVAL;
+			retval = -EINVAL;
+			goto END;
 		}
 
 		/* copy only 'size' bytes of data as requested by user */
@@ -3237,7 +3619,8 @@
 		if (retval > 0) {
 			pr_err("%s: Failed to copy %d bytes of default data"
 				" passed by user\n", __func__, retval);
-			return -EFAULT;
+			retval = -EFAULT;
+			goto END;
 		}
 		FMDBG("%s: XFR Mode\t: 0x%x\n", __func__, default_data.mode);
 		FMDBG("%s: XFR Data Length\t: %d\n", __func__,
@@ -3252,7 +3635,8 @@
 		if (default_data.length != (ctrl->controls[0].size - 2)) {
 			pr_err("%s: Invalid 'length' parameter passed for "
 				"actual xfr data\n", __func__);
-			return -EINVAL;
+			retval = -EINVAL;
+			goto END;
 		}
 		retval = hci_def_data_write(&default_data, radio->fm_hdev);
 		break;
@@ -3261,24 +3645,32 @@
 		bytes_to_copy = (ctrl->controls[0]).size;
 		if (bytes_to_copy < PROCS_CALIB_SIZE) {
 			FMDERR("data is less than required size");
-			return -EFAULT;
+			retval = -EFAULT;
+			goto END;
 		}
 		memset(proc_cal_req.data, 0, PROCS_CALIB_SIZE);
 		proc_cal_req.mode = PROCS_CALIB_MODE;
 		if (copy_from_user(&proc_cal_req.data[0],
-				data, sizeof(proc_cal_req.data)))
-				return -EFAULT;
+				data, sizeof(proc_cal_req.data))) {
+			retval = -EFAULT;
+			goto END;
+		}
 		retval = radio_hci_request(radio->fm_hdev,
 				hci_fm_set_cal_req_proc,
 				(unsigned long)&proc_cal_req,
 				 RADIO_HCI_TIMEOUT);
-		if (retval < 0)
-			FMDERR("Set Process calibration failed %d", retval);
 		break;
 	default:
 		FMDBG("Shouldn't reach here\n");
 		retval = -1;
+		goto END;
+		break;
 	}
+
+END:
+	if (retval > 0)
+		retval = -EINVAL;
+
 	return retval;
 }
 
@@ -3289,6 +3681,7 @@
 	int retval = 0;
 	unsigned int rds_grps_proc = 0;
 	__u8 temp_val = 0;
+	int saved_val;
 	unsigned long arg = 0;
 	struct hci_fm_tx_ps tx_ps = {0};
 	struct hci_fm_tx_rt tx_rt = {0};
@@ -3297,37 +3690,71 @@
 	char sinr_th, sinr;
 	__u8 intf_det_low_th, intf_det_high_th, intf_det_out;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
-		return -EINVAL;
+		retval = -EINVAL;
+		goto END;
 	}
 
+	if (unlikely(ctrl == NULL)) {
+		FMDERR("%s, v4l2 ctrl is null\n", __func__);
+		retval = -EINVAL;
+		goto END;
+	}
 	switch (ctrl->id) {
 	case V4L2_CID_PRIVATE_IRIS_TX_TONE:
+		if (!is_valid_tone(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: tone value is not valid\n", __func__);
+			goto END;
+		}
+		saved_val = radio->tone_freq;
 		radio->tone_freq = ctrl->value;
 		retval = radio_hci_request(radio->fm_hdev,
 				hci_fm_tone_generator, arg,
 				msecs_to_jiffies(RADIO_HCI_TIMEOUT));
-		if (retval < 0)
+		if (retval < 0) {
 			FMDERR("Error while setting the tone %d", retval);
+			radio->tone_freq = saved_val;
+		}
 		break;
 	case V4L2_CID_AUDIO_VOLUME:
 		break;
 	case V4L2_CID_AUDIO_MUTE:
+		if (!is_valid_hard_mute(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: hard mute value is not valid\n", __func__);
+			goto END;
+		}
+		saved_val = radio->mute_mode.hard_mute;
 		radio->mute_mode.hard_mute = ctrl->value;
 		radio->mute_mode.soft_mute = IOC_SFT_MUTE;
 		retval = hci_set_fm_mute_mode(
 				&radio->mute_mode,
 				radio->fm_hdev);
-		if (retval < 0)
+		if (retval < 0) {
 			FMDERR("Error while set FM hard mute"" %d\n",
-			retval);
+				retval);
+			radio->mute_mode.hard_mute = saved_val;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCHMODE:
-		radio->g_search_mode = ctrl->value;
+		if (is_valid_srch_mode(ctrl->value)) {
+			radio->g_search_mode = ctrl->value;
+		} else {
+			FMDERR("%s: srch mode is not valid\n", __func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SCANDWELL:
-		radio->g_scan_time = ctrl->value;
+		if (is_valid_scan_dwell_prd(ctrl->value)) {
+			radio->g_scan_time = ctrl->value;
+		} else {
+			FMDERR("%s: scandwell period is not valid\n", __func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCHON:
 		iris_search(radio, ctrl->value, SRCH_DIR_UP);
@@ -3335,8 +3762,12 @@
 	case V4L2_CID_PRIVATE_IRIS_STATE:
 		switch (ctrl->value) {
 		case FM_RECV:
-			if (is_enable_rx_possible(radio) != 0)
-				return -EINVAL;
+			if (is_enable_rx_possible(radio) != 0) {
+				FMDERR("%s: fm is not in proper state\n",
+					 __func__);
+				retval = -EINVAL;
+				goto END;
+			}
 			radio->mode = FM_RECV_TURNING_ON;
 			retval = hci_cmd(HCI_FM_ENABLE_RECV_CMD,
 							 radio->fm_hdev);
@@ -3344,14 +3775,16 @@
 				FMDERR("Error while enabling RECV FM"
 							" %d\n", retval);
 				radio->mode = FM_OFF;
-				return retval;
+				goto END;
 			} else {
 				initialise_recv(radio);
 			}
 			break;
 		case FM_TRANS:
-			if (is_enable_tx_possible(radio) != 0)
-				return -EINVAL;
+			if (is_enable_tx_possible(radio) != 0) {
+				retval = -EINVAL;
+				goto END;
+			}
 			radio->mode = FM_TRANS_TURNING_ON;
 			retval = hci_cmd(HCI_FM_ENABLE_TRANS_CMD,
 							 radio->fm_hdev);
@@ -3359,7 +3792,7 @@
 				FMDERR("Error while enabling TRANS FM"
 							" %d\n", retval);
 				radio->mode = FM_OFF;
-				return retval;
+				goto END;
 			} else {
 				initialise_trans(radio);
 			}
@@ -3375,7 +3808,7 @@
 					FMDERR("Err on disable recv FM"
 						   " %d\n", retval);
 					radio->mode = FM_RECV;
-					return retval;
+					goto END;
 				}
 				break;
 			case FM_TRANS:
@@ -3387,7 +3820,7 @@
 					FMDERR("Err disabling trans FM"
 						" %d\n", retval);
 					radio->mode = FM_TRANS;
-					return retval;
+					goto END;
 				}
 				break;
 			default:
@@ -3402,136 +3835,236 @@
 		if (radio->mode == FM_RECV) {
 			retval = iris_recv_set_region(radio, ctrl->value);
 		} else {
-			if (radio->mode == FM_TRANS)
+			if (radio->mode == FM_TRANS) {
 				retval = iris_trans_set_region(radio,
 						ctrl->value);
-			else
+			} else {
+				FMDERR("%s: fm is not in proper state\n",
+					__func__);
 				retval = -EINVAL;
+				goto END;
+			}
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
+		if (!is_valid_sig_th(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: sig threshold is not valid\n", __func__);
+			goto END;
+		}
 		temp_val = ctrl->value;
 		retval = hci_fm_set_signal_threshold(
 				&temp_val,
 				radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Error while setting signal threshold\n");
-			break;
+			goto END;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
-		radio->srch_rds.srch_pty = ctrl->value;
-		radio->srch_st_list.srch_pty = ctrl->value;
+		if (is_valid_pty(ctrl->value)) {
+			radio->srch_rds.srch_pty = ctrl->value;
+			radio->srch_st_list.srch_pty = ctrl->value;
+		} else {
+			FMDERR("%s: pty is not valid\n", __func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCH_PI:
-		radio->srch_rds.srch_pi = ctrl->value;
+		if (is_valid_pi(ctrl->value)) {
+			radio->srch_rds.srch_pi = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: Pi is not valid\n", __func__);
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
-		radio->srch_st_list.srch_list_max = ctrl->value;
+		if (is_valid_srch_station_cnt(ctrl->value)) {
+			radio->srch_st_list.srch_list_max = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: srch station count is not valid\n",
+				__func__);
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SPACING:
+		if (!is_valid_chan_spacing(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: channel spacing is not valid\n", __func__);
+			goto END;
+		}
 		if (radio->mode == FM_RECV) {
+			saved_val = radio->recv_conf.ch_spacing;
 			radio->recv_conf.ch_spacing = ctrl->value;
 			retval = hci_set_fm_recv_conf(
 					&radio->recv_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in setting channel spacing");
+				radio->recv_conf.ch_spacing = saved_val;
+				goto END;
+			}
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
+		if (!is_valid_emphasis(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s, emphasis is not valid\n", __func__);
+			goto END;
+		}
 		switch (radio->mode) {
 		case FM_RECV:
+			saved_val = radio->recv_conf.emphasis;
 			radio->recv_conf.emphasis = ctrl->value;
 			retval = hci_set_fm_recv_conf(
 					&radio->recv_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in setting emphasis");
+				radio->recv_conf.emphasis = saved_val;
+				goto END;
+			}
 			break;
 		case FM_TRANS:
+			saved_val = radio->trans_conf.emphasis;
 			radio->trans_conf.emphasis = ctrl->value;
 			retval = hci_set_fm_trans_conf(
 					&radio->trans_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in setting emphasis");
+				radio->trans_conf.emphasis = saved_val;
+				goto END;
+			}
 			break;
 		default:
 			retval = -EINVAL;
+			FMDERR("%s, FM is not in proper state\n", __func__);
+			goto END;
+			break;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDS_STD:
+		if (!is_valid_rds_std(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: rds std is not valid\n", __func__);
+			goto END;
+		}
 		switch (radio->mode) {
 		case FM_RECV:
+			saved_val = radio->recv_conf.rds_std;
 			radio->recv_conf.rds_std = ctrl->value;
 			retval = hci_set_fm_recv_conf(
 					&radio->recv_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in rds_std");
+				radio->recv_conf.rds_std = saved_val;
+				goto END;
+			}
 			break;
 		case FM_TRANS:
+			saved_val = radio->trans_conf.rds_std;
 			radio->trans_conf.rds_std = ctrl->value;
 			retval = hci_set_fm_trans_conf(
 					&radio->trans_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in rds_Std");
+				radio->trans_conf.rds_std = saved_val;
+				goto END;
+			}
 			break;
 		default:
 			retval = -EINVAL;
+			FMDERR("%s: fm is not in proper state\n", __func__);
+			goto END;
+			break;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSON:
+		if (!is_valid_rds_std(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: rds std is not valid\n", __func__);
+			goto END;
+		}
 		switch (radio->mode) {
 		case FM_RECV:
+			saved_val = radio->recv_conf.rds_std;
 			radio->recv_conf.rds_std = ctrl->value;
 			retval = hci_set_fm_recv_conf(
 					&radio->recv_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in rds_std");
+				radio->recv_conf.rds_std = saved_val;
+				goto END;
+			}
 			break;
 		case FM_TRANS:
+			saved_val = radio->trans_conf.rds_std;
 			radio->trans_conf.rds_std = ctrl->value;
 			retval = hci_set_fm_trans_conf(
 					&radio->trans_conf,
 						radio->fm_hdev);
-			if (retval < 0)
+			if (retval < 0) {
 				FMDERR("Error in rds_Std");
+				radio->trans_conf.rds_std = saved_val;
+				goto END;
+			}
 			break;
 		default:
 			retval = -EINVAL;
+			FMDERR("%s: fm is not in proper state\n", __func__);
+			goto END;
+			break;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
+		saved_val = radio->rds_grp.rds_grp_enable_mask;
 		grp_mask = (grp_mask | oda_agt | ctrl->value);
 		radio->rds_grp.rds_grp_enable_mask = grp_mask;
 		radio->rds_grp.rds_buf_size = 1;
 		radio->rds_grp.en_rds_change_filter = 0;
 		retval = hci_fm_rds_grp(&radio->rds_grp, radio->fm_hdev);
-		if (retval < 0)
+		if (retval < 0) {
 			FMDERR("error in setting group mask\n");
+			radio->rds_grp.rds_grp_enable_mask = saved_val;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
+		saved_val = radio->g_rds_grp_proc_ps;
 		rds_grps_proc = radio->g_rds_grp_proc_ps | ctrl->value;
 		radio->g_rds_grp_proc_ps = (rds_grps_proc >> RDS_CONFIG_OFFSET);
 		retval = hci_fm_rds_grps_process(
 				&radio->g_rds_grp_proc_ps,
 				radio->fm_hdev);
+		if (retval < 0) {
+			radio->g_rds_grp_proc_ps = saved_val;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDSD_BUF:
 		radio->rds_grp.rds_buf_size = ctrl->value;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_PSALL:
+		saved_val = radio->g_rds_grp_proc_ps;
 		rds_grps_proc = (ctrl->value << RDS_CONFIG_OFFSET);
 		radio->g_rds_grp_proc_ps |= rds_grps_proc;
 		retval = hci_fm_rds_grps_process(
 				&radio->g_rds_grp_proc_ps,
 				radio->fm_hdev);
+		if (retval < 0) {
+			radio->g_rds_grp_proc_ps = saved_val;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_AF_JUMP:
+		saved_val = radio->g_rds_grp_proc_ps;
 		/*Clear the current AF jump settings*/
 		radio->g_rds_grp_proc_ps &= ~(1 << RDS_AF_JUMP_OFFSET);
 		radio->af_jump_bit = ctrl->value;
@@ -3541,24 +4074,45 @@
 		retval = hci_fm_rds_grps_process(
 				&radio->g_rds_grp_proc_ps,
 				radio->fm_hdev);
+		if (retval < 0) {
+			radio->g_rds_grp_proc_ps = saved_val;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_LP_MODE:
 		set_low_power_mode(radio, ctrl->value);
 		break;
 	case V4L2_CID_PRIVATE_IRIS_ANTENNA:
+		if (!is_valid_antenna(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: antenna type is not valid\n", __func__);
+			goto END;
+		}
 		temp_val = ctrl->value;
 		retval = hci_fm_set_antenna(&temp_val, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Set Antenna failed retval = %x", retval);
-			return retval;
+			goto END;
 		}
 		radio->g_antenna =  ctrl->value;
 		break;
 	case V4L2_CID_RDS_TX_PTY:
-		radio->pty = ctrl->value;
+		if (is_valid_pty(ctrl->value)) {
+			radio->pty = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: pty is not valid\n", __func__);
+			goto END;
+		}
 		break;
 	case V4L2_CID_RDS_TX_PI:
-		radio->pi = ctrl->value;
+		if (is_valid_pi(ctrl->value)) {
+			radio->pi = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: pi is not valid\n", __func__);
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME:
 		tx_ps.ps_control =  0x00;
@@ -3571,7 +4125,13 @@
 				(unsigned long)&tx_rt, RADIO_HCI_TIMEOUT);
 		break;
 	case V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT:
-		radio->ps_repeatcount = ctrl->value;
+		if (is_valid_ps_repeat_cnt(ctrl->value)) {
+			radio->ps_repeatcount = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: ps repeat count is not valid\n", __func__);
+			goto END;
+		}
 		break;
 	case V4L2_CID_TUNE_POWER_LEVEL:
 		if (ctrl->value > FM_TX_PWR_LVL_MAX)
@@ -3586,8 +4146,8 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Default data read failed for PHY_CFG %d\n",
-			retval);
-			break;
+				retval);
+			goto END;
 		}
 		memset(&wrd, 0, sizeof(wrd));
 		wrd.mode = FM_TX_PHY_CFG_MODE;
@@ -3599,40 +4159,58 @@
 		retval = hci_def_data_write(&wrd, radio->fm_hdev);
 		if (retval < 0)
 			FMDERR("Default write failed for PHY_TXGAIN %d\n",
-			retval);
+				retval);
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
+		if (!is_valid_soft_mute(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: soft mute is not valid\n", __func__);
+			goto END;
+		}
+		saved_val = radio->mute_mode.soft_mute;
 		radio->mute_mode.soft_mute = ctrl->value;
 		retval = hci_set_fm_mute_mode(
 				&radio->mute_mode,
 				radio->fm_hdev);
-		if (retval < 0)
+		if (retval < 0) {
 			FMDERR("Error while setting FM soft mute"" %d\n",
-			retval);
+				retval);
+			radio->mute_mode.soft_mute = saved_val;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR:
 		radio->riva_data_req.cmd_params.start_addr = ctrl->value;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN:
-		if ((ctrl->value > 0) &&
-			(ctrl->value <= MAX_RIVA_PEEK_RSP_SIZE)) {
+		if (is_valid_peek_len(ctrl->value)) {
 			radio->riva_data_req.cmd_params.length = ctrl->value;
 		} else {
-			FMDERR("Length %d is more than the buffer size %d\n",
-			ctrl->value, MAX_RIVA_PEEK_RSP_SIZE);
 			retval = -EINVAL;
+			FMDERR("%s: riva access len is not valid\n", __func__);
+			goto END;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RIVA_POKE:
-		if (radio->riva_data_req.cmd_params.length <= MAX_RIVA_PEEK_RSP_SIZE) {
-			memcpy(radio->riva_data_req.data, (void *)ctrl->value,
-						radio->riva_data_req.cmd_params.length);
-			radio->riva_data_req.cmd_params.subopcode = RIVA_POKE_OPCODE;
-			retval = hci_poke_data(&radio->riva_data_req , radio->fm_hdev);
+		if (radio->riva_data_req.cmd_params.length <=
+		    MAX_RIVA_PEEK_RSP_SIZE) {
+			retval = copy_from_user(
+					radio->riva_data_req.data,
+					(void *)ctrl->value,
+					radio->riva_data_req.cmd_params.length);
+			if (retval != 0) {
+				retval = -retval;
+				goto END;
+			}
+			radio->riva_data_req.cmd_params.subopcode =
+						RIVA_POKE_OPCODE;
+			retval = hci_poke_data(
+					&radio->riva_data_req,
+					radio->fm_hdev);
 		} else {
-			FMDERR("Can not copy into driver's buffer. Length %d is more than"
-			 "the buffer size %d\n", ctrl->value, MAX_RIVA_PEEK_RSP_SIZE);
+			FMDERR("Can not copy into driver's buffer.\n");
 			retval = -EINVAL;
+			goto END;
 		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR:
@@ -3653,80 +4231,133 @@
 		hci_ssbi_peek_reg(&radio->ssbi_peek_reg, radio->fm_hdev);
 		break;
 	case V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS:
-		temp_val = ctrl->value;
-		hci_read_grp_counters(&temp_val, radio->fm_hdev);
+		if (is_valid_reset_cntr(ctrl->value)) {
+			temp_val = ctrl->value;
+			hci_read_grp_counters(&temp_val, radio->fm_hdev);
+		} else {
+			FMDERR("%s: reset counter value is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_IRIS_HLSI:
+		if (!is_valid_hlsi(ctrl->value)) {
+			FMDERR("%s: hlsi value is not valid\n", __func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
 						radio->fm_hdev);
 		if (retval)
-			break;
+			goto END;
+		saved_val = radio->recv_conf.hlsi;
 		radio->recv_conf.hlsi = ctrl->value;
 		retval = hci_set_fm_recv_conf(
 					&radio->recv_conf,
 						radio->fm_hdev);
+		if (retval < 0)
+			radio->recv_conf.hlsi = saved_val;
 		break;
 	case V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER:
-		temp_val = ctrl->value;
-		retval = hci_set_notch_filter(&temp_val, radio->fm_hdev);
+		if (is_valid_notch_filter(ctrl->value)) {
+			temp_val = ctrl->value;
+			retval = hci_set_notch_filter(&temp_val,
+							radio->fm_hdev);
+		} else {
+			FMDERR("%s: notch filter is not valid\n", __func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		break;
 	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
+		if (!is_valid_intf_det_hgh_th(ctrl->value)) {
+			FMDERR("%s: intf high threshold is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to get chnl det thresholds  %d", retval);
-			return retval;
+			goto END;
 		}
+		saved_val = radio->ch_det_threshold.high_th;
 		radio->ch_det_threshold.high_th = ctrl->value;
 		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
 							 radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to set High det threshold %d ", retval);
-			return retval;
+			radio->ch_det_threshold.high_th = saved_val;
+			goto END;
 		}
 		break;
 
 	case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
+		if (!is_valid_intf_det_low_th(ctrl->value)) {
+			FMDERR("%s: intf det low threshold is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to get chnl det thresholds  %d", retval);
-			return retval;
+			goto END;
 		}
+		saved_val = radio->ch_det_threshold.low_th;
 		radio->ch_det_threshold.low_th = ctrl->value;
 		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
 							 radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to Set Low det threshold %d", retval);
-			return retval;
+			radio->ch_det_threshold.low_th = saved_val;
+			goto END;
 		}
 		break;
 
 	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
+		if (!is_valid_sinr_th(ctrl->value)) {
+			FMDERR("%s: sinr threshold is not valid\n", __func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to get chnl det thresholds  %d", retval);
-			return retval;
+			goto END;
 		}
+		saved_val = radio->ch_det_threshold.sinr;
 		radio->ch_det_threshold.sinr = ctrl->value;
 		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
 							 radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to set SINR threshold %d", retval);
-			return retval;
+			radio->ch_det_threshold.sinr = saved_val;
+			goto END;
 		}
 		break;
 
 	case V4L2_CID_PRIVATE_SINR_SAMPLES:
+		if (!is_valid_sinr_samples(ctrl->value)) {
+			FMDERR("%s: sinr samples count is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto END;
+		}
 		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("Failed to get chnl det thresholds  %d", retval);
-			return retval;
+			goto END;
 		}
+		saved_val = radio->ch_det_threshold.sinr_samples;
 		radio->ch_det_threshold.sinr_samples = ctrl->value;
 		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
 							 radio->fm_hdev);
 	       if (retval < 0) {
 			FMDERR("Failed to set SINR samples  %d", retval);
-			return retval;
+			radio->ch_det_threshold.sinr_samples = saved_val;
+			goto END;
 		}
 		break;
 
@@ -3773,18 +4404,23 @@
 		if (retval < 0) {
 			FMDERR("%s: Failed to determine channel's validity\n",
 				__func__);
-			return retval;
+			goto END;
 		} else {
 			sinr_th = radio->ch_det_threshold.sinr;
 			intf_det_low_th = radio->ch_det_threshold.low_th;
 			intf_det_high_th = radio->ch_det_threshold.high_th;
 		}
-
+		if (!is_valid_sinr_th(sinr_th) ||
+			!is_valid_intf_det_low_th(intf_det_low_th) ||
+			!is_valid_intf_det_hgh_th(intf_det_high_th)) {
+			retval = -EINVAL;
+			goto END;
+		}
 		retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("%s: Failed to determine channel's validity\n",
 				__func__);
-			return retval;
+			goto END;
 		} else
 			sinr = radio->fm_st_rsp.station_rsp.sinr;
 
@@ -3792,7 +4428,7 @@
 		if (retval < 0) {
 			FMDERR("%s: Failed to determine channel's validity\n",
 				 __func__);
-			return retval;
+			goto END;
 		} else
 			intf_det_out = radio->st_dbg_param.in_det_out;
 
@@ -3811,7 +4447,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RDS_CNFG_MODE;
 		wrd.length = FM_RDS_CNFG_LEN;
@@ -3832,7 +4468,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RDS_CNFG_MODE;
 		wrd.length = FM_RDS_CNFG_LEN;
@@ -3852,7 +4488,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RX_CONFG_MODE;
 		wrd.length = FM_RX_CNFG_LEN;
@@ -3872,7 +4508,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RX_CONFG_MODE;
 		wrd.length = FM_RX_CNFG_LEN;
@@ -3892,7 +4528,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RX_CONFG_MODE;
 		wrd.length = FM_RX_CNFG_LEN;
@@ -3912,7 +4548,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RX_CONFG_MODE;
 		wrd.length = FM_RX_CNFG_LEN;
@@ -3932,7 +4568,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = FM_RX_CONFG_MODE;
 		wrd.length = FM_RX_CNFG_LEN;
@@ -3955,7 +4591,7 @@
 		retval = hci_def_data_read(&rd, radio->fm_hdev);
 		if (retval < 0) {
 			FMDERR("default data read failed for PS0 %x", retval);
-			return retval;
+			goto END;
 		}
 		wrd.mode = RDS_PS0_XFR_MODE;
 		wrd.length = RDS_PS0_LEN;
@@ -3969,7 +4605,13 @@
 		break;
 	default:
 		retval = -EINVAL;
+		break;
 	}
+
+END:
+	if (retval > 0)
+		retval = -EINVAL;
+
 	return retval;
 }
 
@@ -3984,7 +4626,7 @@
 	/* Pass the mode of SPUR_CLK */
 	default_data.mode = CKK_SPUR;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -4058,10 +4700,14 @@
 	int retval;
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
+	if (unlikely(tuner == NULL)) {
+		FMDERR("%s, tuner is null\n", __func__);
+		return -EINVAL;
+	}
 	if (tuner->index > 0) {
 		FMDERR("Invalid Tuner Index");
 		return -EINVAL;
@@ -4106,11 +4752,16 @@
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	int retval = 0;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
 
+	if (unlikely(tuner == NULL)) {
+		FMDERR("%s, tuner is null\n", __func__);
+		return -EINVAL;
+	}
+
 	if (tuner->index > 0)
 		return -EINVAL;
 
@@ -4160,9 +4811,15 @@
 {
 	struct iris_device  *radio = video_get_drvdata(video_devdata(file));
 	int retval = -1;
-	freq->frequency = freq->frequency / TUNE_PARAM;
+	u32 f;
 
-	if (radio == NULL) {
+	if (unlikely(freq == NULL)) {
+		FMDERR("%s, v4l2 freq is null\n", __func__);
+		return -EINVAL;
+	}
+	f = (freq->frequency / TUNE_PARAM);
+
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -4182,7 +4839,7 @@
 				radio->fm_hdev);
 	}
 
-	retval = iris_set_freq(radio, freq->frequency);
+	retval = iris_set_freq(radio, f);
 
 	if (radio->mode == FM_TRANS
 		 && radio->trans_conf.rds_std == 2
@@ -4281,6 +4938,11 @@
 {
 	struct iris_device *radio = video_get_drvdata(video_devdata(file));
 	int dir;
+
+	if (unlikely(seek == NULL)) {
+		FMDERR("%s, v4l2_hw_freq_seek is null\n", __func__);
+		return -EINVAL;
+	}
 	if (seek->seek_upward)
 		dir = SRCH_DIR_UP;
 	else
@@ -4294,10 +4956,14 @@
 	struct iris_device *radio;
 	radio = video_get_drvdata(video_devdata(file));
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
+	if (unlikely(capability == NULL)) {
+		FMDERR("%s, capability struct is null\n", __func__);
+		return -EINVAL;
+	}
 	strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
 	strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
 
@@ -4313,7 +4979,7 @@
 {
 	int retval;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -4357,7 +5023,7 @@
 
 	int retval;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
@@ -4373,7 +5039,7 @@
 {
 	int retval = 1;
 
-	if (radio == NULL) {
+	if (unlikely(radio == NULL)) {
 		FMDERR(":radio is null");
 		return -EINVAL;
 	}
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 5b2ec1f..ca28003 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -2348,6 +2348,7 @@
 	int ret = 0;
 
 	switch (cmd) {
+	case VIDIOC_PREPARE_BUF:
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF: {
diff --git a/drivers/mfd/wcd9xxx-core-resource.c b/drivers/mfd/wcd9xxx-core-resource.c
index 1791d72..1d0f894 100644
--- a/drivers/mfd/wcd9xxx-core-resource.c
+++ b/drivers/mfd/wcd9xxx-core-resource.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -55,6 +55,8 @@
 	int (*codec_read)(struct wcd9xxx_core_resource*, unsigned short),
 	int (*codec_write)(struct wcd9xxx_core_resource*, unsigned short, u8),
 	int (*codec_bulk_read) (struct wcd9xxx_core_resource*, unsigned short,
+							int, u8*),
+	int (*codec_bulk_write) (struct wcd9xxx_core_resource*, unsigned short,
 							int, u8*))
 {
 	mutex_init(&wcd9xxx_core_res->pm_lock);
@@ -68,6 +70,7 @@
 	wcd9xxx_core_res->codec_reg_read = codec_read;
 	wcd9xxx_core_res->codec_reg_write = codec_write;
 	wcd9xxx_core_res->codec_bulk_read = codec_bulk_read;
+	wcd9xxx_core_res->codec_bulk_write = codec_bulk_write;
 	wcd9xxx_core_res->num_irqs = num_irqs;
 	wcd9xxx_core_res->num_irq_regs = num_irq_regs;
 
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 907ce7c..1c42431 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -605,7 +605,7 @@
 				wcd9xxx->codec_type->num_irqs,
 				wcd9xxx_num_irq_regs(wcd9xxx),
 				wcd9xxx_reg_read, wcd9xxx_reg_write,
-				wcd9xxx_bulk_read);
+				wcd9xxx_bulk_read, wcd9xxx_bulk_write);
 
 	if (wcd9xxx_core_irq_init(&wcd9xxx->core_res))
 		goto err;
@@ -1673,10 +1673,8 @@
 		wcd9xxx->slim_device_bootup = false;
 		return 0;
 	}
-	ret = wcd9xxx_reset(wcd9xxx);
-	if (ret)
-		pr_err("%s: Resetting Codec failed\n", __func__);
 
+	dev_info(wcd9xxx->dev, "%s: codec bring up\n", __func__);
 	wcd9xxx_bring_up(wcd9xxx);
 	ret = wcd9xxx_irq_init(wcd9xxx_res);
 	if (ret) {
@@ -1688,6 +1686,25 @@
 	return ret;
 }
 
+static int wcd9xxx_slim_device_reset(struct slim_device *sldev)
+{
+	int ret;
+	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+	if (!wcd9xxx) {
+		pr_err("%s: wcd9xxx is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	dev_info(wcd9xxx->dev, "%s: device reset\n", __func__);
+	if (wcd9xxx->slim_device_bootup)
+		return 0;
+	ret = wcd9xxx_reset(wcd9xxx);
+	if (ret)
+		dev_err(wcd9xxx->dev, "%s: Resetting Codec failed\n", __func__);
+
+	return ret;
+}
+
 static int wcd9xxx_slim_device_up(struct slim_device *sldev)
 {
 	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
@@ -1695,7 +1712,7 @@
 		pr_err("%s: wcd9xxx is NULL\n", __func__);
 		return -EINVAL;
 	}
-	dev_dbg(wcd9xxx->dev, "%s: device up\n", __func__);
+	dev_info(wcd9xxx->dev, "%s: slim device up\n", __func__);
 	return wcd9xxx_device_up(wcd9xxx);
 }
 
@@ -1703,6 +1720,7 @@
 {
 	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
 
+	dev_info(wcd9xxx->dev, "%s: device down\n", __func__);
 	if (!wcd9xxx) {
 		pr_err("%s: wcd9xxx is NULL\n", __func__);
 		return -EINVAL;
@@ -1826,6 +1844,7 @@
 	.resume = wcd9xxx_slim_resume,
 	.suspend = wcd9xxx_slim_suspend,
 	.device_up = wcd9xxx_slim_device_up,
+	.reset_device = wcd9xxx_slim_device_reset,
 	.device_down = wcd9xxx_slim_device_down,
 };
 
@@ -1845,6 +1864,7 @@
 	.resume = wcd9xxx_slim_resume,
 	.suspend = wcd9xxx_slim_suspend,
 	.device_up = wcd9xxx_slim_device_up,
+	.reset_device = wcd9xxx_slim_device_reset,
 	.device_down = wcd9xxx_slim_device_down,
 };
 
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 9209f0b..7644984 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -316,10 +316,12 @@
 		}
 
 		memset(status, 0xff, num_irq_regs);
-		wcd9xxx_bulk_write(wcd9xxx_res, WCD9XXX_A_INTR_CLEAR0,
-				   num_irq_regs, status);
+
+		ret = wcd9xxx_res->codec_bulk_write(wcd9xxx_res,
+				WCD9XXX_A_INTR_CLEAR0,
+				num_irq_regs, status);
 		if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
-			wcd9xxx_reg_write(wcd9xxx_res,
+			wcd9xxx_res->codec_reg_write(wcd9xxx_res,
 					WCD9XXX_A_INTR_MODE, 0x02);
 	}
 	wcd9xxx_unlock_sleep(wcd9xxx_res);
diff --git a/drivers/misc/isa1200.c b/drivers/misc/isa1200.c
index 8090b95..d7fa87b 100644
--- a/drivers/misc/isa1200.c
+++ b/drivers/misc/isa1200.c
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2009 Samsung Electronics
  *  Kyungmin Park <kyungmin.park@samsung.com>
- *  Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2010-2014, 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 as
@@ -318,7 +318,7 @@
 
 	value |= (haptic->pdata->mode_ctrl << 3) |
 		(haptic->pdata->overdrive_high << 5) |
-		(haptic->pdata->overdrive_en << 5) |
+		(haptic->pdata->overdrive_en << 6) |
 		(haptic->pdata->chip_en << 7);
 
 	rc = isa1200_write_reg(client, ISA1200_HCTRL0, value);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 0bc18fb..aad7fb3 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -71,6 +71,9 @@
 
 #define RPMB_SERVICE			0x2000
 
+#define QSEECOM_SEND_CMD_CRYPTO_TIMEOUT	2000
+#define QSEECOM_LOAD_APP_CRYPTO_TIMEOUT	2000
+
 enum qseecom_clk_definitions {
 	CLK_DFAB = 0,
 	CLK_SFPB,
@@ -99,7 +102,7 @@
 struct qseecom_registered_listener_list {
 	struct list_head                 list;
 	struct qseecom_register_listener_req svc;
-	u8  *sb_reg_req;
+	uint32_t user_virt_sb_base;
 	u8 *sb_virt;
 	s32 sb_phys;
 	size_t sb_length;
@@ -162,6 +165,12 @@
 	struct qseecom_clk qsee;
 	struct qseecom_clk ce_drv;
 	struct cdev cdev;
+
+	bool support_bus_scaling;
+	uint32_t  cumulative_mode;
+	enum qseecom_bandwidth_request_mode  current_mode;
+	struct timer_list bw_scale_down_timer;
+	struct work_struct bw_inactive_req_ws;
 };
 
 struct qseecom_client_handle {
@@ -191,6 +200,7 @@
 	atomic_t          ioctl_count;
 	bool  perf_enabled;
 	bool  fast_load_enabled;
+	enum qseecom_bandwidth_request_mode mode;
 };
 
 enum qseecom_set_clear_key_flag {
@@ -212,6 +222,10 @@
 	uint32_t len;
 };
 
+uint8_t *key_id_array[QSEECOM_KEY_ID_SIZE] = {
+	"Disk Encryption"
+};
+
 /* Function proto types */
 static int qsee_vote_for_clock(struct qseecom_dev_handle *, int32_t);
 static void qsee_disable_clock_vote(struct qseecom_dev_handle *, int32_t);
@@ -319,7 +333,12 @@
 		pr_err("copy_from_user failed\n");
 		return ret;
 	}
+	if (!access_ok(VERIFY_WRITE, (void __user *)rcvd_lstnr.virt_sb_base,
+			rcvd_lstnr.sb_size))
+		return -EFAULT;
+
 	data->listener.id = 0;
+	data->type = QSEECOM_LISTENER_SERVICE;
 	if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
 		pr_err("Service is not unique and is already registered\n");
 		data->released = true;
@@ -336,6 +355,7 @@
 
 	new_entry->svc.listener_id = rcvd_lstnr.listener_id;
 	new_entry->sb_length = rcvd_lstnr.sb_size;
+	new_entry->user_virt_sb_base = rcvd_lstnr.virt_sb_base;
 	if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) {
 		pr_err("qseecom_set_sb_memoryfailed\n");
 		kzfree(new_entry);
@@ -428,6 +448,157 @@
 	return ret;
 }
 
+static int __qseecom_set_msm_bus_request(uint32_t mode)
+{
+	int ret = 0;
+	struct qseecom_clk *qclk;
+
+	qclk = &qseecom.qsee;
+	if (qclk->ce_core_src_clk != NULL) {
+		if (mode == INACTIVE) {
+			__qseecom_disable_clk(CLK_QSEE);
+		} else {
+			ret = __qseecom_enable_clk(CLK_QSEE);
+			if (ret)
+				pr_err("CLK enabling failed (%d) MODE (%d)\n",
+							ret, mode);
+		}
+	}
+
+	if ((!ret) && (qseecom.current_mode != mode)) {
+		ret = msm_bus_scale_client_update_request(
+					qseecom.qsee_perf_client, mode);
+		if (ret) {
+			pr_err("Bandwidth req failed(%d) MODE (%d)\n",
+							ret, mode);
+			if (qclk->ce_core_src_clk != NULL) {
+				if (mode == INACTIVE)
+					__qseecom_enable_clk(CLK_QSEE);
+				else
+					__qseecom_disable_clk(CLK_QSEE);
+			}
+		}
+		qseecom.current_mode = mode;
+	}
+	return ret;
+}
+
+static void qseecom_bw_inactive_req_work(struct work_struct *work)
+{
+	mutex_lock(&app_access_lock);
+	mutex_lock(&qsee_bw_mutex);
+	__qseecom_set_msm_bus_request(INACTIVE);
+	pr_debug("current_mode = %d, cumulative_mode = %d\n",
+				qseecom.current_mode, qseecom.cumulative_mode);
+	mutex_unlock(&qsee_bw_mutex);
+	mutex_unlock(&app_access_lock);
+	return;
+}
+
+static void qseecom_scale_bus_bandwidth_timer_callback(unsigned long data)
+{
+	schedule_work(&qseecom.bw_inactive_req_ws);
+	return;
+}
+
+static int qseecom_scale_bus_bandwidth_timer(uint32_t mode, uint32_t duration)
+{
+	int32_t ret = 0;
+	int32_t request_mode = INACTIVE;
+
+	mutex_lock(&qsee_bw_mutex);
+	if (mode == 0) {
+		if (qseecom.cumulative_mode > MEDIUM)
+			request_mode = HIGH;
+		else
+			request_mode = qseecom.cumulative_mode;
+	} else {
+		request_mode = mode;
+	}
+	__qseecom_set_msm_bus_request(request_mode);
+
+	del_timer_sync(&(qseecom.bw_scale_down_timer));
+	qseecom.bw_scale_down_timer.expires = jiffies +
+				msecs_to_jiffies(duration);
+	add_timer(&(qseecom.bw_scale_down_timer));
+
+	mutex_unlock(&qsee_bw_mutex);
+	return ret;
+}
+
+
+static int qseecom_unregister_bus_bandwidth_needs(
+					struct qseecom_dev_handle *data)
+{
+	int32_t ret = 0;
+
+	qseecom.cumulative_mode -= data->mode;
+	data->mode = INACTIVE;
+
+	return ret;
+}
+
+static int __qseecom_register_bus_bandwidth_needs(
+			struct qseecom_dev_handle *data, uint32_t request_mode)
+{
+	int32_t ret = 0;
+
+	if (data->mode == INACTIVE) {
+		qseecom.cumulative_mode += request_mode;
+		data->mode = request_mode;
+	} else {
+		if (data->mode != request_mode) {
+			qseecom.cumulative_mode -= data->mode;
+			qseecom.cumulative_mode += request_mode;
+			data->mode = request_mode;
+		}
+	}
+	return ret;
+}
+
+static int qseecom_scale_bus_bandwidth(struct qseecom_dev_handle *data,
+						void __user *argp)
+{
+	int32_t ret = 0;
+	int32_t req_mode;
+
+	ret = copy_from_user(&req_mode, argp, sizeof(req_mode));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+	if (req_mode > HIGH) {
+		pr_err("Invalid bandwidth mode (%d)\n", req_mode);
+		return ret;
+	}
+	mutex_lock(&qsee_bw_mutex);
+	ret = __qseecom_register_bus_bandwidth_needs(data, req_mode);
+	mutex_unlock(&qsee_bw_mutex);
+
+	return ret;
+}
+
+static void __qseecom_disable_clk_scale_down(struct qseecom_dev_handle *data)
+{
+	if (!qseecom.support_bus_scaling)
+		qsee_disable_clock_vote(data, CLK_SFPB);
+	return;
+}
+
+static int __qseecom_enable_clk_scale_up(struct qseecom_dev_handle *data)
+{
+	int ret = 0;
+	if (qseecom.support_bus_scaling) {
+		qseecom_scale_bus_bandwidth_timer(
+			MEDIUM, QSEECOM_LOAD_APP_CRYPTO_TIMEOUT);
+	} else {
+		ret = qsee_vote_for_clock(data, CLK_SFPB);
+		if (ret)
+			pr_err("Fail vote for clk SFPB ret %d\n", ret);
+	}
+	return ret;
+}
+
 static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data,
 						void __user *argp)
 {
@@ -446,6 +617,10 @@
 			req.ifd_data_fd, req.sb_len, req.virt_sb_base);
 		return -EFAULT;
 	}
+	if (!access_ok(VERIFY_WRITE, (void __user *)req.virt_sb_base,
+			req.sb_len))
+		return -EFAULT;
+
 	/* Get the handle of the shared fd */
 	data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt,
 						req.ifd_data_fd);
@@ -613,7 +788,7 @@
 	u32 app_id = 0;
 	struct ion_handle *ihandle;	/* Ion handle */
 	struct qseecom_load_img_req load_img_req;
-	int32_t ret;
+	int32_t ret = 0;
 	ion_phys_addr_t pa = 0;
 	uint32_t len;
 	struct qseecom_command_scm_resp resp;
@@ -628,16 +803,16 @@
 		return -EFAULT;
 	}
 	/* Vote for the SFPB clock */
-	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	ret = __qseecom_enable_clk_scale_up(data);
 	if (ret)
-		pr_warning("Unable to vote for SFPB clock");
+		return ret;
 	req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
 	load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0';
 	memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
 
 	ret = __qseecom_check_app_exists(req);
 	if (ret < 0) {
-		qsee_disable_clock_vote(data, CLK_SFPB);
+		__qseecom_disable_clk_scale_down(data);
 		return ret;
 	}
 
@@ -663,7 +838,7 @@
 					load_img_req.ifd_data_fd);
 		if (IS_ERR_OR_NULL(ihandle)) {
 			pr_err("Ion client could not retrieve the handle\n");
-			qsee_disable_clock_vote(data, CLK_SFPB);
+			__qseecom_disable_clk_scale_down(data);
 			return -ENOMEM;
 		}
 
@@ -688,7 +863,7 @@
 			pr_err("scm_call to load app failed\n");
 			if (!IS_ERR_OR_NULL(ihandle))
 				ion_free(qseecom.ion_clnt, ihandle);
-			qsee_disable_clock_vote(data, CLK_SFPB);
+			__qseecom_disable_clk_scale_down(data);
 			return -EINVAL;
 		}
 
@@ -696,7 +871,7 @@
 			pr_err("scm_call rsp.result is QSEOS_RESULT_FAILURE\n");
 			if (!IS_ERR_OR_NULL(ihandle))
 				ion_free(qseecom.ion_clnt, ihandle);
-			qsee_disable_clock_vote(data, CLK_SFPB);
+			__qseecom_disable_clk_scale_down(data);
 			return -EFAULT;
 		}
 
@@ -707,7 +882,7 @@
 					ret);
 				if (!IS_ERR_OR_NULL(ihandle))
 					ion_free(qseecom.ion_clnt, ihandle);
-				qsee_disable_clock_vote(data, CLK_SFPB);
+				__qseecom_disable_clk_scale_down(data);
 				return ret;
 			}
 		}
@@ -717,7 +892,7 @@
 				resp.result);
 			if (!IS_ERR_OR_NULL(ihandle))
 				ion_free(qseecom.ion_clnt, ihandle);
-			qsee_disable_clock_vote(data, CLK_SFPB);
+			__qseecom_disable_clk_scale_down(data);
 			return -EFAULT;
 		}
 
@@ -726,7 +901,7 @@
 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 		if (!entry) {
 			pr_err("kmalloc failed\n");
-			qsee_disable_clock_vote(data, CLK_SFPB);
+			__qseecom_disable_clk_scale_down(data);
 			return -ENOMEM;
 		}
 		entry->app_id = app_id;
@@ -749,10 +924,10 @@
 	if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
 		pr_err("copy_to_user failed\n");
 		kzfree(entry);
-		qsee_disable_clock_vote(data, CLK_SFPB);
+		__qseecom_disable_clk_scale_down(data);
 		return -EFAULT;
 	}
-	qsee_disable_clock_vote(data, CLK_SFPB);
+	__qseecom_disable_clk_scale_down(data);
 	return 0;
 }
 
@@ -861,6 +1036,13 @@
 	return data->client.sb_phys + (virt - data->client.user_virt_sb_base);
 }
 
+static uint32_t __qseecom_uvirt_to_kvirt(struct qseecom_dev_handle *data,
+						uint32_t virt)
+{
+	return (uint32_t)data->client.sb_virt +
+				(virt - data->client.user_virt_sb_base);
+}
+
 int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr,
 		struct qseecom_send_svc_cmd_req *req_ptr,
 		struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
@@ -933,6 +1115,8 @@
 		return -EINVAL;
 	}
 
+	data->type = QSEECOM_SECURE_SERVICE;
+
 	switch (req.cmd_id) {
 	case QSEOS_RPMB_PROVISION_KEY_COMMAND:
 	case QSEOS_RPMB_ERASE_COMMAND:
@@ -945,15 +1129,25 @@
 		return -EINVAL;
 	}
 
-	ret = qsee_vote_for_clock(data, CLK_DFAB);
-	if (ret) {
-		pr_err("Failed to vote for DFAB clock%d\n", ret);
-		return ret;
-	}
-	ret = qsee_vote_for_clock(data, CLK_SFPB);
-	if (ret) {
-		pr_err("Failed to vote for SFPB clock%d\n", ret);
-		goto exit_reset_dfab_freq;
+	if (qseecom.support_bus_scaling) {
+		qseecom_scale_bus_bandwidth_timer(HIGH,
+					QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
+		if (ret) {
+			pr_err("Fail to set bw HIGH%d\n", ret);
+			return ret;
+		}
+	} else {
+		ret = qsee_vote_for_clock(data, CLK_DFAB);
+		if (ret) {
+			pr_err("Failed to vote for DFAB clock%d\n", ret);
+			return ret;
+		}
+		ret = qsee_vote_for_clock(data, CLK_SFPB);
+		if (ret) {
+			qsee_disable_clock_vote(data, CLK_DFAB);
+			pr_err("Failed to vote for SFPB clock%d\n", ret);
+			goto exit;
+		}
 	}
 
 	msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
@@ -967,7 +1161,11 @@
 				ION_IOC_INV_CACHES);
 	if (ret) {
 		pr_err("qseecom_scm_call failed with err: %d\n", ret);
-		goto exit_reset_sdfab_freq;
+		if (!qseecom.support_bus_scaling) {
+			qsee_disable_clock_vote(data, CLK_DFAB);
+			qsee_disable_clock_vote(data, CLK_SFPB);
+		}
+		goto exit;
 	}
 
 	switch (resp.result) {
@@ -990,10 +1188,7 @@
 		ret = -EINVAL;
 		break;
 	}
-exit_reset_sdfab_freq:
-	qsee_disable_clock_vote(data, CLK_SFPB);
-exit_reset_dfab_freq:
-	qsee_disable_clock_vote(data, CLK_DFAB);
+exit:
 	return ret;
 }
 
@@ -1105,26 +1300,6 @@
 	return ret;
 }
 
-static int qseecom_unprotect_buffer(void __user *argp)
-{
-	int ret = 0;
-	struct ion_handle *ihandle;
-	int32_t ion_fd;
-
-	ret = copy_from_user(&ion_fd, argp, sizeof(ion_fd));
-	if (ret) {
-		pr_err("copy_from_user failed");
-		return ret;
-	}
-
-	ihandle = ion_import_dma_buf(qseecom.ion_clnt, ion_fd);
-
-	ret = msm_ion_unsecure_buffer(qseecom.ion_clnt, ihandle);
-	if (ret)
-		return -EINVAL;
-	return 0;
-}
-
 static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
 					struct qseecom_dev_handle *data,
 					bool listener_svc)
@@ -1173,21 +1348,6 @@
 				pr_err("Ion client can't retrieve the handle\n");
 				return -ENOMEM;
 			}
-			switch (lstnr_resp->protection_mode) {
-			case QSEOS_PROTECT_BUFFER:
-				 ret = msm_ion_secure_buffer(qseecom.ion_clnt,
-								ihandle,
-								VIDEO_PIXEL,
-								0);
-				break;
-			case QSEOS_UNPROTECT_PROTECTED_BUFFER:
-				ret = msm_ion_unsecure_buffer(qseecom.ion_clnt,
-								ihandle);
-				break;
-			case QSEOS_UNPROTECTED_BUFFER:
-			default:
-				break;
-			}
 			field = lstnr_resp->resp_buf_ptr +
 				lstnr_resp->ifd_data[i].cmd_buf_offset;
 		} else {
@@ -1269,6 +1429,24 @@
 		pr_err("copy_from_user failed\n");
 		return ret;
 	}
+
+	if (req.cmd_req_buf == NULL || req.resp_buf == NULL) {
+		pr_err("cmd buffer or response buffer is null\n");
+		return -EINVAL;
+	}
+	if (((uint32_t)req.cmd_req_buf < data->client.user_virt_sb_base) ||
+		((uint32_t)req.cmd_req_buf >= (data->client.user_virt_sb_base +
+					data->client.sb_length))) {
+		pr_err("cmd buffer address not within shared bufffer\n");
+		return -EINVAL;
+	}
+
+	if (((uint32_t)req.resp_buf < data->client.user_virt_sb_base)  ||
+		((uint32_t)req.resp_buf >= (data->client.user_virt_sb_base +
+					data->client.sb_length))){
+		pr_err("response buffer address not within shared bufffer\n");
+		return -EINVAL;
+	}
 	send_cmd_req.cmd_req_buf = req.cmd_req_buf;
 	send_cmd_req.cmd_req_len = req.cmd_req_len;
 	send_cmd_req.resp_buf = req.resp_buf;
@@ -1282,6 +1460,11 @@
 			return -EINVAL;
 		}
 	}
+	req.cmd_req_buf = (void *)__qseecom_uvirt_to_kvirt(data,
+						(uint32_t)req.cmd_req_buf);
+	req.resp_buf = (void *)__qseecom_uvirt_to_kvirt(data,
+						(uint32_t)req.resp_buf);
+
 	ret = __qseecom_update_cmd_buf(&req, false, data, false);
 	if (ret)
 		return ret;
@@ -1476,10 +1659,9 @@
 	/* Populate the remaining parameters */
 	load_req.qsee_cmd_id = QSEOS_APP_START_COMMAND;
 	memcpy(load_req.app_name, appname, MAX_APP_NAME_SIZE);
-	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	ret = __qseecom_enable_clk_scale_up(data);
 	if (ret) {
 		kzfree(img_data);
-		pr_warning("Unable to vote for SFPB clock");
 		return -EIO;
 	}
 
@@ -1491,7 +1673,7 @@
 	kzfree(img_data);
 	if (ret) {
 		pr_err("scm_call to load failed : ret %d\n", ret);
-		qsee_disable_clock_vote(data, CLK_SFPB);
+		__qseecom_disable_clk_scale_down(data);
 		return -EIO;
 	}
 
@@ -1514,7 +1696,7 @@
 		ret = -EINVAL;
 		break;
 	}
-	qsee_disable_clock_vote(data, CLK_SFPB);
+	__qseecom_disable_clk_scale_down(data);
 
 	return ret;
 }
@@ -1543,9 +1725,8 @@
 	/* Populate the remaining parameters */
 	load_req.qsee_cmd_id = QSEOS_LOAD_SERV_IMAGE_COMMAND;
 	/* Vote for the SFPB clock */
-	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	ret = __qseecom_enable_clk_scale_up(data);
 	if (ret) {
-		pr_err("Unable to vote for SFPB clock: ret = %d", ret);
 		kzfree(img_data);
 		return -EIO;
 	}
@@ -1581,7 +1762,7 @@
 		}
 	}
 	kzfree(img_data);
-	qsee_disable_clock_vote(data, CLK_SFPB);
+	__qseecom_disable_clk_scale_down(data);
 	return ret;
 }
 
@@ -1791,10 +1972,24 @@
 		pr_err("Unable to find the handle, exiting\n");
 	else
 		ret = qseecom_unload_app(data);
-	if (data->fast_load_enabled == true)
-		qsee_disable_clock_vote(data, CLK_SFPB);
-	if (data->perf_enabled == true)
-		qsee_disable_clock_vote(data, CLK_DFAB);
+
+	if (qseecom.support_bus_scaling) {
+		mutex_lock(&qsee_bw_mutex);
+		if (data->mode != INACTIVE) {
+			qseecom_unregister_bus_bandwidth_needs(data);
+			if (qseecom.cumulative_mode == INACTIVE) {
+				ret = __qseecom_set_msm_bus_request(INACTIVE);
+				if (ret)
+					pr_err("Fail to scale down bus\n");
+			}
+		}
+		mutex_unlock(&qsee_bw_mutex);
+	} else {
+		if (data->fast_load_enabled == true)
+			qsee_disable_clock_vote(data, CLK_SFPB);
+		if (data->perf_enabled == true)
+			qsee_disable_clock_vote(data, CLK_DFAB);
+	}
 	if (ret == 0) {
 		kzfree(data);
 		kzfree(*handle);
@@ -1825,7 +2020,9 @@
 
 	mutex_lock(&app_access_lock);
 	atomic_inc(&data->ioctl_count);
-
+	if (qseecom.support_bus_scaling)
+		qseecom_scale_bus_bandwidth_timer(INACTIVE,
+					QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
 	ret = __qseecom_send_cmd(data, &req);
 
 	atomic_dec(&data->ioctl_count);
@@ -1848,17 +2045,30 @@
 		return -EINVAL;
 	}
 	if (high) {
-		ret = qsee_vote_for_clock(handle->dev, CLK_DFAB);
-		if (ret)
-			pr_err("Failed to vote for DFAB clock%d\n", ret);
-		ret = qsee_vote_for_clock(handle->dev, CLK_SFPB);
-		if (ret) {
-			pr_err("Failed to vote for SFPB clock%d\n", ret);
-			qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+		if (qseecom.support_bus_scaling) {
+			mutex_lock(&qsee_bw_mutex);
+			__qseecom_register_bus_bandwidth_needs(handle->dev,
+									HIGH);
+			mutex_unlock(&qsee_bw_mutex);
+			if (ret)
+				pr_err("Failed to scale bus (med) %d\n", ret);
+		} else {
+			ret = qsee_vote_for_clock(handle->dev, CLK_DFAB);
+			if (ret)
+				pr_err("Failed to vote for DFAB clock%d\n",
+									ret);
+			ret = qsee_vote_for_clock(handle->dev, CLK_SFPB);
+			if (ret) {
+				pr_err("Failed to vote for SFPB clock%d\n",
+									ret);
+				qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+			}
 		}
 	} else {
-		qsee_disable_clock_vote(handle->dev, CLK_DFAB);
-		qsee_disable_clock_vote(handle->dev, CLK_SFPB);
+		if (!qseecom.support_bus_scaling) {
+			qsee_disable_clock_vote(handle->dev, CLK_DFAB);
+			qsee_disable_clock_vote(handle->dev, CLK_SFPB);
+		}
 	}
 	return ret;
 }
@@ -1877,11 +2087,20 @@
 {
 	struct qseecom_send_modfd_listener_resp resp;
 	int i;
+	struct qseecom_registered_listener_list *this_lstnr = NULL;
 
 	if (copy_from_user(&resp, argp, sizeof(resp))) {
 		pr_err("copy_from_user failed");
 		return -EINVAL;
 	}
+	this_lstnr = __qseecom_find_svc(data->listener.id);
+	if (this_lstnr == NULL)
+		return -EINVAL;
+
+	if (resp.resp_buf_ptr == NULL) {
+		pr_err("Invalid resp_buf_ptr\n");
+		return -EINVAL;
+	}
 	/* validate offsets */
 	for (i = 0; i < MAX_ION_FD; i++) {
 		if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) {
@@ -1890,6 +2109,17 @@
 			return -EINVAL;
 		}
 	}
+
+	if (((uint32_t)resp.resp_buf_ptr <
+			this_lstnr->user_virt_sb_base)
+			|| ((uint32_t)resp.resp_buf_ptr >=
+			(this_lstnr->user_virt_sb_base +
+			this_lstnr->sb_length))) {
+		pr_err("resp_buf_ptr address not within shared buffer\n");
+		return -EINVAL;
+	}
+	resp.resp_buf_ptr = (uint32_t)this_lstnr->sb_virt +
+		(resp.resp_buf_ptr - this_lstnr->user_virt_sb_base);
 	__qseecom_update_cmd_buf(&resp, false, data, true);
 	qseecom.send_resp_flag = 1;
 	wake_up_interruptible(&qseecom.send_resp_wq);
@@ -2203,9 +2433,8 @@
 	}
 
 	/* Vote for the SFPB clock */
-	ret = qsee_vote_for_clock(data, CLK_SFPB);
+	ret = __qseecom_enable_clk_scale_up(data);
 	if (ret) {
-		pr_err("Unable to vote for SFPB clock: ret = %d", ret);
 		ret = -EIO;
 		goto exit_cpu_restore;
 	}
@@ -2243,7 +2472,7 @@
 	}
 
 exit_disable_clock:
-	qsee_disable_clock_vote(data, CLK_SFPB);
+	__qseecom_disable_clk_scale_down(data);
 exit_cpu_restore:
 	/* Restore the CPU mask */
 	mask = CPU_MASK_ALL;
@@ -2400,25 +2629,20 @@
 
 static int __qseecom_generate_and_save_key(struct qseecom_dev_handle *data,
 			enum qseecom_key_management_usage_type usage,
-			uint8_t *key_id, uint32_t flags)
+			struct qseecom_key_generate_ireq *ireq)
 {
-	struct qseecom_key_generate_ireq ireq;
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
-	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		usage >= QSEOS_KM_USAGE_MAX) {
 		pr_err("Error:: unsupported usage %d\n", usage);
 		return -EFAULT;
 	}
-
-	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_TZSCHEDULER, 1,
-				&ireq, sizeof(struct qseecom_key_generate_ireq),
+				ireq, sizeof(struct qseecom_key_generate_ireq),
 				&resp, sizeof(resp));
 	if (ret) {
 		pr_err("scm call to generate key failed : %d\n", ret);
@@ -2456,9 +2680,8 @@
 
 static int __qseecom_delete_saved_key(struct qseecom_dev_handle *data,
 			enum qseecom_key_management_usage_type usage,
-			uint8_t *key_id, uint32_t flags)
+			struct qseecom_key_delete_ireq *ireq)
 {
-	struct qseecom_key_delete_ireq ireq;
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
@@ -2467,14 +2690,10 @@
 		return -EFAULT;
 	}
 
-	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_TZSCHEDULER, 1,
-				&ireq, sizeof(struct qseecom_key_delete_ireq),
+				ireq, sizeof(struct qseecom_key_delete_ireq),
 				&resp, sizeof(struct qseecom_command_scm_resp));
 	if (ret) {
 		pr_err("scm call to delete key failed : %d\n", ret);
@@ -2504,13 +2723,13 @@
 
 static int __qseecom_set_clear_ce_key(struct qseecom_dev_handle *data,
 			enum qseecom_key_management_usage_type usage,
-			struct qseecom_set_key_parameter *set_key_para)
+			struct qseecom_key_select_ireq *ireq)
 {
-	struct qseecom_key_select_ireq ireq;
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
-	if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		usage >= QSEOS_KM_USAGE_MAX) {
 			pr_err("Error:: unsupported usage %d\n", usage);
 			return -EFAULT;
 	}
@@ -2519,24 +2738,8 @@
 	if (qseecom.qsee.instance != qseecom.ce_drv.instance)
 		__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 both PIPE_ENC and PIPE_ENC_XTS*/
-	ireq.pipe_type = QSEOS_PIPE_ENC|QSEOS_PIPE_ENC_XTS;
-
-	if (set_key_para->set_clear_key_flag ==
-			QSEECOM_SET_CE_KEY_CMD)
-		memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
-				QSEECOM_HASH_SIZE);
-	else
-		memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
-
 	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
-				&ireq, sizeof(struct qseecom_key_select_ireq),
+				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 key failed : %d\n", ret);
@@ -2569,16 +2772,63 @@
 	return ret;
 }
 
+static int __qseecom_update_current_key_user_info(
+			struct qseecom_dev_handle *data,
+			enum qseecom_key_management_usage_type usage,
+			struct qseecom_key_userinfo_update_ireq *ireq)
+{
+	struct qseecom_command_scm_resp resp;
+	int ret;
+
+	if (usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		usage >= QSEOS_KM_USAGE_MAX) {
+			pr_err("Error:: unsupported usage %d\n", usage);
+			return -EFAULT;
+	}
+
+	__qseecom_enable_clk(CLK_QSEE);
+
+	ret = scm_call(SCM_SVC_TZSCHEDULER, 1,
+		ireq, sizeof(struct qseecom_key_userinfo_update_ireq),
+		&resp, sizeof(struct qseecom_command_scm_resp));
+	if (ret) {
+		pr_err("scm call to update key userinfo failed : %d\n", ret);
+		__qseecom_disable_clk(CLK_QSEE);
+		if (qseecom.qsee.instance != qseecom.ce_drv.instance)
+			__qseecom_disable_clk(CLK_CE_DRV);
+		return ret;
+	}
+
+	switch (resp.result) {
+	case QSEOS_RESULT_SUCCESS:
+		break;
+	case QSEOS_RESULT_INCOMPLETE:
+		ret = __qseecom_process_incomplete_cmd(data, &resp);
+		if (ret)
+			pr_err("process_incomplete_cmd FAILED, resp.result %d\n",
+					resp.result);
+		break;
+	case QSEOS_RESULT_FAILURE:
+	default:
+		pr_err("Set key scm call failed resp.result %d\n", resp.result);
+		ret = -EINVAL;
+		break;
+	}
+
+	__qseecom_disable_clk(CLK_QSEE);
+	return ret;
+}
+
 static int qseecom_create_key(struct qseecom_dev_handle *data,
 			void __user *argp)
 {
 	uint32_t ce_hw = 0;
 	uint32_t pipe = 0;
-	uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
 	int ret = 0;
 	uint32_t flags = 0;
-	struct qseecom_set_key_parameter set_key_para;
 	struct qseecom_create_key_req create_key_req;
+	struct qseecom_key_generate_ireq generate_key_ireq;
+	struct qseecom_key_select_ireq set_key_ireq;
 
 	ret = copy_from_user(&create_key_req, argp, sizeof(create_key_req));
 	if (ret) {
@@ -2586,7 +2836,8 @@
 		return ret;
 	}
 
-	if (create_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (create_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		create_key_req.usage >= QSEOS_KM_USAGE_MAX) {
 		pr_err("Error:: unsupported usage %d\n", create_key_req.usage);
 		return -EFAULT;
 	}
@@ -2597,23 +2848,40 @@
 		return -EINVAL;
 	}
 
+	generate_key_ireq.flags = flags;
+	generate_key_ireq.qsee_command_id = QSEOS_GENERATE_KEY;
+	memset((void *)generate_key_ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memset((void *)generate_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+	memcpy((void *)generate_key_ireq.key_id,
+			(void *)key_id_array[create_key_req.usage - 1],
+			QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)generate_key_ireq.hash32,
+			(void *)create_key_req.hash32, QSEECOM_HASH_SIZE);
+
 	ret = __qseecom_generate_and_save_key(data, create_key_req.usage,
-								key_id, flags);
+					&generate_key_ireq);
 	if (ret) {
 		pr_err("Failed to generate key on storage: %d\n", ret);
 		return -EFAULT;
 	}
 
-	set_key_para.ce_hw = ce_hw;
-	set_key_para.pipe = pipe;
-	memcpy(set_key_para.key_id, key_id, QSEECOM_KEY_ID_SIZE);
-	set_key_para.flags = flags;
-	set_key_para.set_clear_key_flag = QSEECOM_SET_CE_KEY_CMD;
-	memcpy((void *)set_key_para.hash32, (void *)create_key_req.hash32,
+	set_key_ireq.qsee_command_id = QSEOS_SET_KEY;
+	set_key_ireq.ce = ce_hw;
+	set_key_ireq.pipe = pipe;
+	set_key_ireq.flags = flags;
+
+	/* set both PIPE_ENC and PIPE_ENC_XTS*/
+	set_key_ireq.pipe_type = QSEOS_PIPE_ENC|QSEOS_PIPE_ENC_XTS;
+	memset((void *)set_key_ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memset((void *)set_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+	memcpy((void *)set_key_ireq.key_id,
+			(void *)key_id_array[create_key_req.usage - 1],
+				QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)set_key_ireq.hash32, (void *)create_key_req.hash32,
 				QSEECOM_HASH_SIZE);
 
 	ret = __qseecom_set_clear_ce_key(data, create_key_req.usage,
-								&set_key_para);
+								&set_key_ireq);
 	if (ret) {
 		pr_err("Failed to create key: pipe %d, ce %d: %d\n",
 			pipe, ce_hw, ret);
@@ -2628,12 +2896,12 @@
 {
 	uint32_t ce_hw = 0;
 	uint32_t pipe = 0;
-	uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
 	int ret = 0;
 	uint32_t flags = 0;
 	int i;
 	struct qseecom_wipe_key_req wipe_key_req;
-	struct qseecom_set_key_parameter clear_key_para;
+	struct qseecom_key_delete_ireq delete_key_ireq;
+	struct qseecom_key_select_ireq clear_key_ireq;
 
 	ret = copy_from_user(&wipe_key_req, argp, sizeof(wipe_key_req));
 	if (ret) {
@@ -2641,7 +2909,8 @@
 		return ret;
 	}
 
-	if (wipe_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+	if (wipe_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		wipe_key_req.usage >= QSEOS_KM_USAGE_MAX) {
 		pr_err("Error:: unsupported usage %d\n", wipe_key_req.usage);
 		return -EFAULT;
 	}
@@ -2652,22 +2921,32 @@
 		return -EINVAL;
 	}
 
-	ret = __qseecom_delete_saved_key(data, wipe_key_req.usage, key_id,
-									flags);
+	delete_key_ireq.flags = flags;
+	delete_key_ireq.qsee_command_id = QSEOS_DELETE_KEY;
+	memset((void *)delete_key_ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)delete_key_ireq.key_id,
+			(void *)key_id_array[wipe_key_req.usage - 1],
+			QSEECOM_KEY_ID_SIZE);
+	memset((void *)delete_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+
+	ret = __qseecom_delete_saved_key(data, wipe_key_req.usage,
+					&delete_key_ireq);
 	if (ret) {
 		pr_err("Failed to delete key from ssd storage: %d\n", ret);
 		return -EFAULT;
 	}
 
-	/* an invalid key_id 0xff is used to indicate clear key*/
+	clear_key_ireq.qsee_command_id = QSEOS_SET_KEY;
+	clear_key_ireq.ce = ce_hw;
+	clear_key_ireq.pipe = pipe;
+	clear_key_ireq.flags = flags;
+	clear_key_ireq.pipe_type = QSEOS_PIPE_ENC|QSEOS_PIPE_ENC_XTS;
 	for (i = 0; i < QSEECOM_KEY_ID_SIZE; i++)
-		clear_key_para.key_id[i] = 0xff;
-	clear_key_para.ce_hw = ce_hw;
-	clear_key_para.pipe = pipe;
-	clear_key_para.flags = flags;
-	clear_key_para.set_clear_key_flag = QSEECOM_CLEAR_CE_KEY_CMD;
+			clear_key_ireq.key_id[i] = 0xff;
+	memset((void *)clear_key_ireq.hash32, 0, QSEECOM_HASH_SIZE);
+
 	ret = __qseecom_set_clear_ce_key(data, wipe_key_req.usage,
-							&clear_key_para);
+							&clear_key_ireq);
 	if (ret) {
 		pr_err("Failed to wipe key: pipe %d, ce %d: %d\n",
 			pipe, ce_hw, ret);
@@ -2677,6 +2956,48 @@
 	return ret;
 }
 
+static int qseecom_update_key_user_info(struct qseecom_dev_handle *data,
+			void __user *argp)
+{
+	int ret = 0;
+	uint32_t flags = 0;
+	struct qseecom_update_key_userinfo_req update_key_req;
+	struct qseecom_key_userinfo_update_ireq ireq;
+
+	ret = copy_from_user(&update_key_req, argp, sizeof(update_key_req));
+	if (ret) {
+		pr_err("copy_from_user failed\n");
+		return ret;
+	}
+
+	if (update_key_req.usage < QSEOS_KM_USAGE_DISK_ENCRYPTION ||
+		update_key_req.usage >= QSEOS_KM_USAGE_MAX) {
+		pr_err("Error:: unsupported usage %d\n", update_key_req.usage);
+		return -EFAULT;
+	}
+
+	ireq.qsee_command_id = QSEOS_UPDATE_KEY_USERINFO;
+	ireq.flags = flags;
+	memset(ireq.key_id, 0, QSEECOM_KEY_ID_SIZE);
+	memset((void *)ireq.current_hash32, 0, QSEECOM_HASH_SIZE);
+	memset((void *)ireq.new_hash32, 0, QSEECOM_HASH_SIZE);
+	memcpy(ireq.key_id, key_id_array[update_key_req.usage - 1],
+						QSEECOM_KEY_ID_SIZE);
+	memcpy((void *)ireq.current_hash32,
+		(void *)update_key_req.current_hash32, QSEECOM_HASH_SIZE);
+	memcpy((void *)ireq.new_hash32,
+		(void *)update_key_req.new_hash32, QSEECOM_HASH_SIZE);
+
+	ret = __qseecom_update_current_key_user_info(data, update_key_req.usage,
+						&ireq);
+	if (ret) {
+		pr_err("Failed to update key info: %d\n", ret);
+		return -EFAULT;
+	}
+	return ret;
+
+}
+
 static int qseecom_is_es_activated(void __user *argp)
 {
 	struct qseecom_is_es_activated_req req;
@@ -2794,6 +3115,7 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_CMD_REQ: {
+		pr_debug("qseecom.current_mode %d\n", qseecom.current_mode);
 		if ((data->client.app_id == 0) ||
 			(data->type != QSEECOM_CLIENT_APP)) {
 			pr_err("send cmd req: invalid handle (%d) app_id(%d)\n",
@@ -2803,6 +3125,9 @@
 		}
 		/* Only one client allowed here at a time */
 		mutex_lock(&app_access_lock);
+		if (qseecom.support_bus_scaling)
+			qseecom_scale_bus_bandwidth_timer(INACTIVE,
+					QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_send_cmd(data, argp);
 		atomic_dec(&data->ioctl_count);
@@ -2813,6 +3138,7 @@
 		break;
 	}
 	case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: {
+		pr_debug("qseecom.current_mode %d\n", qseecom.current_mode);
 		if ((data->client.app_id == 0) ||
 			(data->type != QSEECOM_CLIENT_APP)) {
 			pr_err("send mdfd cmd: invalid handle (%d) appid(%d)\n",
@@ -2822,6 +3148,9 @@
 		}
 		/* Only one client allowed here at a time */
 		mutex_lock(&app_access_lock);
+		if (qseecom.support_bus_scaling)
+			qseecom_scale_bus_bandwidth_timer(INACTIVE,
+					QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_send_modfd_cmd(data, argp);
 		atomic_dec(&data->ioctl_count);
@@ -2948,12 +3277,18 @@
 			break;
 		}
 		atomic_inc(&data->ioctl_count);
-		ret = qsee_vote_for_clock(data, CLK_DFAB);
-		if (ret)
-			pr_err("Failed to vote for DFAB clock%d\n", ret);
-		ret = qsee_vote_for_clock(data, CLK_SFPB);
-		if (ret)
-			pr_err("Failed to vote for SFPB clock%d\n", ret);
+		if (qseecom.support_bus_scaling) {
+			mutex_lock(&qsee_bw_mutex);
+			__qseecom_register_bus_bandwidth_needs(data, HIGH);
+			mutex_unlock(&qsee_bw_mutex);
+		} else {
+			ret = qsee_vote_for_clock(data, CLK_DFAB);
+			if (ret)
+				pr_err("Fail to vote for DFAB clock%d\n", ret);
+			ret = qsee_vote_for_clock(data, CLK_SFPB);
+			if (ret)
+				pr_err("Fail to vote for SFPB clock%d\n", ret);
+		}
 		atomic_dec(&data->ioctl_count);
 		break;
 	}
@@ -2973,8 +3308,24 @@
 			break;
 		}
 		atomic_inc(&data->ioctl_count);
+		if (!qseecom.support_bus_scaling) {
 			qsee_disable_clock_vote(data, CLK_DFAB);
 			qsee_disable_clock_vote(data, CLK_SFPB);
+		}
+		atomic_dec(&data->ioctl_count);
+		break;
+	}
+
+	case QSEECOM_IOCTL_SET_BUS_SCALING_REQ: {
+		if ((data->client.app_id == 0) ||
+			(data->type != QSEECOM_CLIENT_APP)) {
+			pr_err("set bus scale: invalid handle (%d) appid(%d)\n",
+					data->type, data->client.app_id);
+			ret = -EINVAL;
+			break;
+		}
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_scale_bus_bandwidth(data, argp);
 		atomic_dec(&data->ioctl_count);
 		break;
 	}
@@ -3056,14 +3407,12 @@
 			return -EINVAL;
 		}
 		data->released = true;
-		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_create_key(data, argp);
 		if (ret)
 			pr_err("failed to create encryption key: %d\n", ret);
 
 		atomic_dec(&data->ioctl_count);
-		mutex_unlock(&app_access_lock);
 		break;
 	}
 	case QSEECOM_IOCTL_WIPE_KEY_REQ: {
@@ -3079,13 +3428,31 @@
 			return -EINVAL;
 		}
 		data->released = true;
-		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_wipe_key(data, argp);
 		if (ret)
 			pr_err("failed to wipe encryption key: %d\n", ret);
 		atomic_dec(&data->ioctl_count);
-		mutex_unlock(&app_access_lock);
+		break;
+	}
+	case QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ: {
+		if (data->type != QSEECOM_GENERIC) {
+			pr_err("update key req: invalid handle (%d)\n",
+								data->type);
+			ret = -EINVAL;
+			break;
+		}
+		if (qseecom.qsee_version < QSEE_VERSION_05) {
+			pr_err("Update Key feature unsupported in qsee ver %u\n",
+				qseecom.qsee_version);
+			return -EINVAL;
+		}
+		data->released = true;
+		atomic_inc(&data->ioctl_count);
+		ret = qseecom_update_key_user_info(data, argp);
+		if (ret)
+			pr_err("failed to update key user info: %d\n", ret);
+		atomic_dec(&data->ioctl_count);
 		break;
 	}
 	case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: {
@@ -3135,23 +3502,6 @@
 			pr_err("failed qseecom_send_mod_resp: %d\n", ret);
 		break;
 	}
-	case QSEECOM_IOCTL_UNPROTECT_BUF: {
-		if ((data->listener.id == 0) ||
-			(data->type != QSEECOM_LISTENER_SERVICE)) {
-			pr_err("receive req: invalid handle (%d), lid(%d)\n",
-						data->type, data->listener.id);
-			ret = -EINVAL;
-			break;
-		}
-		/* Only one client allowed here at a time */
-		atomic_inc(&data->ioctl_count);
-		ret = qseecom_unprotect_buffer(argp);
-		atomic_dec(&data->ioctl_count);
-		wake_up_all(&data->abort_wq);
-		if (ret)
-			pr_err("failed qseecom_unprotect: %d\n", ret);
-		break;
-	}
 	default:
 		pr_err("Invalid IOCTL: %d\n", cmd);
 		return -EINVAL;
@@ -3173,6 +3523,7 @@
 	data->abort = 0;
 	data->type = QSEECOM_GENERIC;
 	data->released = false;
+	data->mode = INACTIVE;
 	init_waitqueue_head(&data->abort_wq);
 	atomic_set(&data->ioctl_count, 0);
 
@@ -3185,8 +3536,8 @@
 	int ret = 0;
 
 	if (data->released == false) {
-		pr_warn("data: released = false, type = %d, data = 0x%x\n",
-			data->type, (u32)data);
+		pr_warn("data: released=false, type=%d, mode=%d, data=0x%x\n",
+			data->type, data->mode, (u32)data);
 		switch (data->type) {
 		case QSEECOM_LISTENER_SERVICE:
 			ret = qseecom_unregister_listener(data);
@@ -3209,11 +3560,23 @@
 		}
 	}
 
-	if (data->fast_load_enabled == true)
-		qsee_disable_clock_vote(data, CLK_SFPB);
-	if (data->perf_enabled == true)
-		qsee_disable_clock_vote(data, CLK_DFAB);
-
+	if (qseecom.support_bus_scaling) {
+		mutex_lock(&qsee_bw_mutex);
+		if (data->mode != INACTIVE) {
+			qseecom_unregister_bus_bandwidth_needs(data);
+			if (qseecom.cumulative_mode == INACTIVE) {
+				ret = __qseecom_set_msm_bus_request(INACTIVE);
+				if (ret)
+					pr_err("Fail to scale down bus\n");
+			}
+		}
+		mutex_unlock(&qsee_bw_mutex);
+	} else {
+		if (data->fast_load_enabled == true)
+			qsee_disable_clock_vote(data, CLK_SFPB);
+		if (data->perf_enabled == true)
+			qsee_disable_clock_vote(data, CLK_DFAB);
+	}
 	kfree(data);
 
 	return ret;
@@ -3356,6 +3719,10 @@
 	qseecom.qsee.ce_core_src_clk = NULL;
 	qseecom.qsee.ce_bus_clk = NULL;
 
+	qseecom.cumulative_mode = 0;
+	qseecom.current_mode = INACTIVE;
+	qseecom.support_bus_scaling = false;
+
 	qseecom.ce_drv.ce_core_clk = NULL;
 	qseecom.ce_drv.ce_clk = NULL;
 	qseecom.ce_drv.ce_core_src_clk = NULL;
@@ -3435,7 +3802,11 @@
 
 	/* register client for bus scaling */
 	if (pdev->dev.of_node) {
-
+		qseecom.support_bus_scaling =
+				of_property_read_bool((&pdev->dev)->of_node,
+						"qcom,support-bus-scaling");
+		pr_warn("support_bus_scaling=0x%x",
+				qseecom.support_bus_scaling);
 		if (of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,disk-encrypt-pipe-pair",
 				&qseecom.ce_info.disk_encrypt_pipe)) {
@@ -3528,7 +3899,13 @@
 		qseecom_platform_support = (struct msm_bus_scale_pdata *)
 						pdev->dev.platform_data;
 	}
-
+	if (qseecom.support_bus_scaling) {
+		init_timer(&(qseecom.bw_scale_down_timer));
+		INIT_WORK(&qseecom.bw_inactive_req_ws,
+					qseecom_bw_inactive_req_work);
+		qseecom.bw_scale_down_timer.function =
+				qseecom_scale_bus_bandwidth_timer_callback;
+	}
 	qseecom.qsee_perf_client = msm_bus_scale_register_client(
 					qseecom_platform_support);
 
@@ -3594,6 +3971,11 @@
 	if (pdev->dev.platform_data != NULL)
 		msm_bus_scale_unregister_client(qseecom.qsee_perf_client);
 
+	if (qseecom.support_bus_scaling) {
+		cancel_work_sync(&qseecom.bw_inactive_req_ws);
+		del_timer_sync(&qseecom.bw_scale_down_timer);
+	}
+
 	/* register client for bus scaling */
 	if (pdev->dev.of_node) {
 		__qseecom_deinit_clk(CLK_QSEE);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 743668b..3eedc32 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2670,7 +2670,8 @@
 	 */
 	if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) ||
 			((mq->flags & MMC_QUEUE_URGENT_REQUEST) &&
-				!(mq->mqrq_cur->req->cmd_flags & REQ_URGENT))) {
+			 !(mq->mqrq_cur->req->cmd_flags &
+				MMC_REQ_NOREINSERT_MASK))) {
 		if (mmc_card_need_bkops(card))
 			mmc_start_bkops(card, false);
 		/* release host only when there are no more requests */
@@ -3073,6 +3074,8 @@
 		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
 	MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
 		  MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+	MMC_FIXUP(CID_NAME_ANY, CID_MANFID_HYNIX, CID_OEMID_ANY, add_quirk_mmc,
+		  MMC_QUIRK_BROKEN_DATA_TIMEOUT),
 
 	END_FIXUP
 };
@@ -3158,6 +3161,9 @@
 	/* send power off notification */
 	if (mmc_card_mmc(card)) {
 		mmc_rpm_hold(card->host, &card->dev);
+		mmc_claim_host(card->host);
+		mmc_stop_bkops(card);
+		mmc_release_host(card->host);
 		mmc_send_long_pon(card);
 		mmc_rpm_release(card->host, &card->dev);
 	}
@@ -3265,4 +3271,3 @@
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver");
-
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 39296ef..5cc2806 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -2285,6 +2285,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -2383,6 +2386,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -2491,6 +2497,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -2605,6 +2614,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -2730,6 +2742,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -2818,6 +2833,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -2978,6 +2996,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
@@ -3051,6 +3072,9 @@
 			       size_t count,
 			       loff_t *offset)
 {
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return count;
+
 	memset((void *)buffer, 0, count);
 
 	snprintf(buffer, count,
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 8986829..fa3dcdc 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -79,7 +79,8 @@
 				continue; /* fetch again */
 			} else if ((mq->flags & MMC_QUEUE_URGENT_REQUEST) &&
 				   (mq->mqrq_cur->req &&
-				!(mq->mqrq_cur->req->cmd_flags & REQ_URGENT))) {
+				!(mq->mqrq_cur->req->cmd_flags &
+				       MMC_REQ_NOREINSERT_MASK))) {
 				/*
 				 * clean current request when urgent request
 				 * processing in progress and current request is
@@ -348,22 +349,43 @@
 #endif
 
 	if (!mqrq_cur->bounce_buf && !mqrq_prev->bounce_buf) {
+		unsigned int max_segs = host->max_segs;
+
 		blk_queue_bounce_limit(mq->queue, limit);
 		blk_queue_max_hw_sectors(mq->queue,
 			min(host->max_blk_count, host->max_req_size / 512));
-		blk_queue_max_segments(mq->queue, host->max_segs);
 		blk_queue_max_segment_size(mq->queue, host->max_seg_size);
+retry:
+		blk_queue_max_segments(mq->queue, host->max_segs);
 
 		mqrq_cur->sg = mmc_alloc_sg(host->max_segs, &ret);
-		if (ret)
+		if (ret == -ENOMEM)
+			goto cur_sg_alloc_failed;
+		else if (ret)
 			goto cleanup_queue;
 
-
 		mqrq_prev->sg = mmc_alloc_sg(host->max_segs, &ret);
-		if (ret)
+		if (ret == -ENOMEM)
+			goto prev_sg_alloc_failed;
+		else if (ret)
 			goto cleanup_queue;
+
+		goto success;
+
+prev_sg_alloc_failed:
+		kfree(mqrq_cur->sg);
+		mqrq_cur->sg = NULL;
+cur_sg_alloc_failed:
+		host->max_segs /= 2;
+		if (host->max_segs) {
+			goto retry;
+		} else {
+			host->max_segs = max_segs;
+			goto cleanup_queue;
+		}
 	}
 
+success:
 	sema_init(&mq->thread_sem, 1);
 
 	mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a296e48..cd94960 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -895,7 +895,8 @@
 			mmc_post_req(host, host->areq->mrq, 0);
 			host->areq = NULL;
 			if (areq) {
-				if (!(areq->cmd_flags & REQ_URGENT)) {
+				if (!(areq->cmd_flags &
+						MMC_REQ_NOREINSERT_MASK)) {
 					areq->reinsert_req(areq);
 					mmc_post_req(host, areq->mrq, 0);
 				} else {
@@ -1307,6 +1308,11 @@
 		data->timeout_ns = 4000000000u; /* 4s */
 		data->timeout_clks = 0;
 	}
+	/* Some emmc cards require a longer read/write time */
+	if (card->quirks & MMC_QUIRK_BROKEN_DATA_TIMEOUT) {
+		if (data->timeout_ns <  4000000000u)
+			data->timeout_ns = 4000000000u;	/* 4s */
+	}
 }
 EXPORT_SYMBOL(mmc_set_data_timeout);
 
@@ -3141,6 +3147,7 @@
 		return;
 
 	mmc_bus_get(host);
+	mmc_rpm_hold(host, &host->class_dev);
 
 	/*
 	 * if there is a _removable_ card registered, check whether it is
@@ -3173,10 +3180,13 @@
 
 	/* if there still is a card present, stop here */
 	if (host->bus_ops != NULL) {
+		mmc_rpm_release(host, &host->class_dev);
 		mmc_bus_put(host);
 		goto out;
 	}
 
+	mmc_rpm_release(host, &host->class_dev);
+
 	/*
 	 * Only we can add a new handler, so it's safe to
 	 * release the lock here.
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 903decf..4ec8941 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/fault-inject.h>
+#include <linux/uaccess.h>
 
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
@@ -392,6 +393,9 @@
 	if (!card)
 		return cnt;
 
+	if (!access_ok(VERIFY_WRITE, ubuf, cnt))
+		return cnt;
+
 	if (!card->wr_pack_stats.print_in_read)
 		return 0;
 
@@ -532,6 +536,9 @@
 	if (!card)
 		return cnt;
 
+	if (!access_ok(VERIFY_READ, ubuf, cnt))
+		return cnt;
+
 	sscanf(ubuf, "%d", &value);
 	if (value) {
 		mmc_blk_init_packed_statistics(card);
@@ -571,6 +578,9 @@
 	if (!card)
 		return cnt;
 
+	if (!access_ok(VERIFY_WRITE, ubuf, cnt))
+		return cnt;
+
 	bkops_stats = &card->bkops_info.bkops_stats;
 
 	if (!bkops_stats->print_stats)
@@ -637,6 +647,9 @@
 	if (!card)
 		return cnt;
 
+	if (!access_ok(VERIFY_READ, ubuf, cnt))
+		return cnt;
+
 	bkops_stats = &card->bkops_info.bkops_stats;
 
 	sscanf(ubuf, "%d", &value);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 4d3a560..739a237 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2,7 +2,7 @@
  * drivers/mmc/host/sdhci-msm.c - Qualcomm MSM SDHCI Platform
  * driver source file
  *
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -2355,6 +2355,12 @@
 	bool curr_pwrsave;
 
 	if (!clock) {
+		/*
+		 * disable pwrsave to ensure clock is not auto-gated until
+		 * the rate is >400KHz (initialization complete).
+		 */
+		writel_relaxed(readl_relaxed(host->ioaddr + CORE_VENDOR_SPEC) &
+			~CORE_CLK_PWRSAVE, host->ioaddr + CORE_VENDOR_SPEC);
 		sdhci_msm_prepare_clocks(host, false);
 		host->clock = clock;
 		return;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 830223d..32f5220 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -746,12 +746,6 @@
 	if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL)
 		return 0xE;
 
-	/* During initialization, don't use max timeout as the clock is slow */
-	if ((host->quirks2 & SDHCI_QUIRK2_USE_RESERVED_MAX_TIMEOUT) &&
-		(host->clock > 400000)) {
-		return 0xF;
-	}
-
 	/* Unspecified timeout, assume max */
 	if (!data && !cmd->cmd_timeout_ms)
 		return 0xE;
@@ -1498,6 +1492,7 @@
 	struct sdhci_host *host;
 	bool present;
 	unsigned long flags;
+	u32 tuning_opcode;
 
 	host = mmc_priv(mmc);
 
@@ -1552,14 +1547,25 @@
 		 * is no on-going data transfer. If so, we need to execute
 		 * tuning procedure before sending command.
 		 */
-		if ((host->flags & SDHCI_NEEDS_RETUNING) &&
+		if ((mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK) &&
+		    (mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK_HS400) &&
+		    (mrq->cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) &&
+		    (host->flags & SDHCI_NEEDS_RETUNING) &&
 		    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
-			spin_unlock_irqrestore(&host->lock, flags);
-			sdhci_execute_tuning(mmc, mrq->cmd->opcode);
-			spin_lock_irqsave(&host->lock, flags);
+			if (mmc->card) {
+				/* eMMC uses cmd21 but sd and sdio use cmd19 */
+				tuning_opcode =
+					mmc->card->type == MMC_TYPE_MMC ?
+					MMC_SEND_TUNING_BLOCK_HS200 :
+					MMC_SEND_TUNING_BLOCK;
+				host->mrq = NULL;
+				spin_unlock_irqrestore(&host->lock, flags);
+				sdhci_execute_tuning(mmc, tuning_opcode);
+				spin_lock_irqsave(&host->lock, flags);
 
-			/* Restore original mmc_request structure */
-			host->mrq = mrq;
+				/* Restore original mmc_request structure */
+				host->mrq = mrq;
+			}
 		}
 
 		if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
@@ -2527,6 +2533,8 @@
 	}
 
 	if (host->cmd->error) {
+		if (host->cmd->error == -EILSEQ)
+			host->flags |= SDHCI_NEEDS_RETUNING;
 		tasklet_schedule(&host->finish_tasklet);
 		return;
 	}
@@ -2655,8 +2663,11 @@
 							    SDHCI_COMMAND));
 			if ((command != MMC_SEND_TUNING_BLOCK_HS400) &&
 			    (command != MMC_SEND_TUNING_BLOCK_HS200) &&
-			    (command != MMC_SEND_TUNING_BLOCK))
+			    (command != MMC_SEND_TUNING_BLOCK)) {
 				pr_msg = true;
+				if (intmask & SDHCI_INT_DATA_CRC)
+					host->flags |= SDHCI_NEEDS_RETUNING;
+			}
 		} else {
 			pr_msg = true;
 		}
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index 7f02187..2e06b42 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -1919,7 +1919,7 @@
 	buf = (uint8_t *)dma_buffer + sizeof(*dma_buffer);
 
 	cmd = dma_buffer->cmd;
-	memset(&data, 0, sizeof(struct msm_nand_erase_reg_data));
+	memset(&data, 0, sizeof(struct msm_nand_blk_isbad_data));
 	data.cfg.cmd = MSM_NAND_CMD_PAGE_READ_ALL;
 	data.cfg.cfg0 = chip->cfg0_raw & ~(7U << CW_PER_PAGE);
 	data.cfg.cfg1 = chip->cfg1_raw;
diff --git a/drivers/net/ethernet/msm/ecm_ipa.c b/drivers/net/ethernet/msm/ecm_ipa.c
index 644a751..cc2ade4 100644
--- a/drivers/net/ethernet/msm/ecm_ipa.c
+++ b/drivers/net/ethernet/msm/ecm_ipa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -294,6 +294,7 @@
 	params->ecm_ipa_rx_dp_notify = ecm_ipa_packet_receive_notify;
 	params->ecm_ipa_tx_dp_notify = ecm_ipa_tx_complete_notify;
 	params->private = (void *)ecm_ipa_ctx;
+	params->skip_ep_cfg = false;
 	ecm_ipa_ctx->state = ECM_IPA_INITIALIZED;
 	ECM_IPA_STATE_DEBUG(ecm_ipa_ctx);
 
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index 9f06258..7ec317a 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -341,6 +341,8 @@
 	if (bam_ret != 0 && bam_ret != -EAGAIN && bam_ret != -EFAULT) {
 		pr_err("[%s] %s: write returned error %d",
 			dev->name, __func__, bam_ret);
+		if (RMNET_IS_MODE_QOS(opmode))
+			skb_pull(skb, sizeof(struct QMI_QOS_HDR_S));
 		return -EPERM;
 	}
 
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index d1f3748..9682b48 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -38,10 +38,6 @@
 #define ACM_CTRL_RI		BIT(2)
 #define ACM_CTRL_CD		BIT(3)
 
-/* polling interval for Interrupt ep */
-#define HS_INTERVAL		7
-#define FS_LS_INTERVAL		3
-
 /*echo modem_wait > /sys/class/hsicctl/hsicctlx/modem_wait*/
 static ssize_t modem_wait_store(struct device *d, struct device_attribute *attr,
 		const char *buf, size_t n)
@@ -941,9 +937,7 @@
 		dev->intf->cur_altsetting->desc.bInterfaceNumber;
 	dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
 
-	interval = max((int)int_in->desc.bInterval,
-			(udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL
-							: FS_LS_INTERVAL);
+	interval = int_in->desc.bInterval;
 
 	usb_fill_int_urb(dev->inturb, udev,
 			 dev->int_pipe,
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index f9bb5c8..b0db01e 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -362,13 +362,10 @@
 	return skb;
 }
 
-static __be16 rmnet_ip_type_trans(struct sk_buff *skb,
-	struct net_device *dev)
+static __be16 rmnet_ip_type_trans(struct sk_buff *skb)
 {
 	__be16	protocol = 0;
 
-	skb->dev = dev;
-
 	switch (skb->data[0] & 0xf0) {
 	case 0x40:
 		protocol = htons(ETH_P_IP);
@@ -404,7 +401,6 @@
 			/*map urb to actual network iface based on mux id*/
 			unet_id = unet_offset + mux_id;
 			skb->dev = unet_list[unet_id]->net;
-			entry->dev = unet_list[unet_id];
 		}
 	}
 
@@ -414,7 +410,7 @@
 static int rmnet_usb_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	if (test_bit(RMNET_MODE_LLP_IP, &dev->data[0]))
-		skb->protocol = rmnet_ip_type_trans(skb, dev->net);
+		skb->protocol = rmnet_ip_type_trans(skb);
 	else /*set zero for eth mode*/
 		skb->protocol = 0;
 
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 12c5704..38c70a3 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -45,6 +45,7 @@
 #endif
 
 #define DEVICE "wcnss_wlan"
+#define CTRL_DEVICE "wcnss_ctrl"
 #define VERSION "1.01"
 #define WCNSS_PIL_DEVICE "wcnss"
 
@@ -147,6 +148,9 @@
 #define MSM_PRONTO_TXP_PHY_ABORT        0xfb080488
 #define MSM_PRONTO_BRDG_ERR_SRC         0xfb080fb0
 
+#define MSM_PRONTO_ALARMS_TXCTL         0xfb0120a8
+#define MSM_PRONTO_ALARMS_TACTL         0xfb012448
+
 #define WCNSS_DEF_WLAN_RX_BUFF_COUNT		1024
 #define WCNSS_VBATT_THRESHOLD		3500000
 #define WCNSS_VBATT_GUARD		200
@@ -157,6 +161,16 @@
 #define WCNSS_MAX_FRAME_SIZE		(4*1024)
 #define WCNSS_VERSION_LEN			30
 #define WCNSS_MAX_BUILD_VER_LEN		256
+#define WCNSS_MAX_CMD_LEN		(128)
+#define WCNSS_MIN_CMD_LEN		(3)
+#define WCNSS_MIN_SERIAL_LEN		(6)
+
+/* control messages from userspace */
+#define WCNSS_USR_CTRL_MSG_START  0x00000000
+#define WCNSS_USR_SERIAL_NUM      (WCNSS_USR_CTRL_MSG_START + 1)
+#define WCNSS_USR_HAS_CAL_DATA    (WCNSS_USR_CTRL_MSG_START + 2)
+
+#define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x"
 
 /* message types */
 #define WCNSS_CTRL_MSG_START	0x01000000
@@ -172,6 +186,8 @@
 #define	WCNSS_BUILD_VER_REQ           (WCNSS_CTRL_MSG_START + 9)
 #define	WCNSS_BUILD_VER_RSP           (WCNSS_CTRL_MSG_START + 10)
 
+/* max 20mhz channel count */
+#define WCNSS_MAX_CH_NUM			45
 
 #define VALID_VERSION(version) \
 	((strncmp(version, "INVALID", WCNSS_VERSION_LEN)) ? 1 : 0)
@@ -347,6 +363,8 @@
 	void __iomem *wlan_tx_status;
 	void __iomem *wlan_tx_phy_aborts;
 	void __iomem *wlan_brdg_err_source;
+	void __iomem *alarms_txctl;
+	void __iomem *alarms_tactl;
 	void __iomem *fiq_reg;
 	int	nv_downloaded;
 	unsigned char *fw_cal_data;
@@ -361,13 +379,62 @@
 	int	device_opened;
 	int	iris_xo_mode_set;
 	int	fw_vbatt_state;
+	int	ctrl_device_opened;
+	char	wlan_nv_macAddr[WLAN_MAC_ADDR_SIZE];
 	struct mutex dev_lock;
+	struct mutex ctrl_lock;
 	wait_queue_head_t read_wait;
 	struct qpnp_adc_tm_btm_param vbat_monitor_params;
 	struct qpnp_adc_tm_chip *adc_tm_dev;
 	struct mutex vbat_monitor_mutex;
+	u16 unsafe_ch_count;
+	u16 unsafe_ch_list[WCNSS_MAX_CH_NUM];
 } *penv = NULL;
 
+static ssize_t wcnss_wlan_macaddr_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	char macAddr[WLAN_MAC_ADDR_SIZE];
+
+	if (!penv)
+		return -ENODEV;
+
+	pr_debug("%s: Receive MAC Addr From user space: %s\n", __func__, buf);
+
+	if (WLAN_MAC_ADDR_SIZE != sscanf(buf, MAC_ADDRESS_STR,
+		 (int *)&macAddr[0], (int *)&macAddr[1],
+		 (int *)&macAddr[2], (int *)&macAddr[3],
+		 (int *)&macAddr[4], (int *)&macAddr[5])) {
+
+		pr_err("%s: Failed to Copy MAC\n", __func__);
+		return -EINVAL;
+	}
+
+	memcpy(penv->wlan_nv_macAddr, macAddr, sizeof(penv->wlan_nv_macAddr));
+
+	pr_info("%s: Write MAC Addr:" MAC_ADDRESS_STR "\n", __func__,
+		penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
+		penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
+		penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
+
+	return count;
+}
+
+static ssize_t wcnss_wlan_macaddr_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	if (!penv)
+		return -ENODEV;
+
+	return scnprintf(buf, PAGE_SIZE, MAC_ADDRESS_STR,
+		penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
+		penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
+		penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
+}
+
+static DEVICE_ATTR(wcnss_mac_addr, S_IRUSR | S_IWUSR,
+	wcnss_wlan_macaddr_show, wcnss_wlan_macaddr_store);
+
 static ssize_t wcnss_serial_number_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
@@ -671,14 +738,41 @@
 
 	reg = readl_relaxed(penv->wlan_tx_status);
 	pr_info_ratelimited("%s: WLAN_TX_STATUS %08x\n", __func__, reg);
+
+	reg = readl_relaxed(penv->alarms_txctl);
+	pr_err("ALARMS_TXCTL %08x\n", reg);
+
+	reg = readl_relaxed(penv->alarms_tactl);
+	pr_err("ALARMS_TACTL %08x\n", reg);
 }
 EXPORT_SYMBOL(wcnss_pronto_log_debug_regs);
 
 #ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE
 void wcnss_log_debug_regs_on_bite(void)
 {
-	if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
-		wcnss_pronto_log_debug_regs();
+	struct platform_device *pdev = wcnss_get_platform_device();
+	struct clk *measure;
+	struct clk *wcnss_debug_mux;
+	unsigned long clk_rate;
+
+	if (wcnss_hardware_type() != WCNSS_PRONTO_HW)
+		return;
+
+	measure = clk_get(&pdev->dev, "measure");
+	wcnss_debug_mux = clk_get(&pdev->dev, "wcnss_debug");
+
+	if (!IS_ERR(measure) && !IS_ERR(wcnss_debug_mux)) {
+		if (clk_set_parent(measure, wcnss_debug_mux))
+			return;
+
+		clk_rate = clk_get_rate(measure);
+		pr_debug("wcnss: clock frequency is: %luHz\n", clk_rate);
+
+		if (clk_rate)
+			wcnss_pronto_log_debug_regs();
+		else
+			pr_err("clock frequency is zero, cannot access PMU or other registers\n");
+	}
 }
 #endif
 
@@ -716,8 +810,14 @@
 	if (ret)
 		goto remove_thermal;
 
+	ret = device_create_file(dev, &dev_attr_wcnss_mac_addr);
+	if (ret)
+		goto remove_version;
+
 	return 0;
 
+remove_version:
+	device_remove_file(dev, &dev_attr_wcnss_version);
 remove_thermal:
 	device_remove_file(dev, &dev_attr_thermal_mitigation);
 remove_serial:
@@ -732,6 +832,7 @@
 		device_remove_file(dev, &dev_attr_serial_number);
 		device_remove_file(dev, &dev_attr_thermal_mitigation);
 		device_remove_file(dev, &dev_attr_wcnss_version);
+		device_remove_file(dev, &dev_attr_wcnss_mac_addr);
 	}
 }
 static void wcnss_smd_notify_event(void *data, unsigned int event)
@@ -1029,6 +1130,20 @@
 }
 EXPORT_SYMBOL(wcnss_get_serial_number);
 
+int wcnss_get_wlan_mac_address(char mac_addr[WLAN_MAC_ADDR_SIZE])
+{
+	if (!penv)
+		return -ENODEV;
+
+	memcpy(mac_addr, penv->wlan_nv_macAddr, WLAN_MAC_ADDR_SIZE);
+	pr_debug("%s: Get MAC Addr:" MAC_ADDRESS_STR "\n", __func__,
+		penv->wlan_nv_macAddr[0], penv->wlan_nv_macAddr[1],
+		penv->wlan_nv_macAddr[2], penv->wlan_nv_macAddr[3],
+		penv->wlan_nv_macAddr[4], penv->wlan_nv_macAddr[5]);
+	return 0;
+}
+EXPORT_SYMBOL(wcnss_get_wlan_mac_address);
+
 static int enable_wcnss_suspend_notify;
 
 static int enable_wcnss_suspend_notify_set(const char *val,
@@ -1166,6 +1281,35 @@
 }
 EXPORT_SYMBOL(wcnss_get_wlan_rx_buff_count);
 
+int wcnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count)
+{
+	if (penv && unsafe_ch_list &&
+		(ch_count <= WCNSS_MAX_CH_NUM)) {
+		memcpy((char *)penv->unsafe_ch_list,
+			(char *)unsafe_ch_list, ch_count * sizeof(u16));
+		penv->unsafe_ch_count = ch_count;
+		return 0;
+	} else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(wcnss_set_wlan_unsafe_channel);
+
+int wcnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 buffer_size,
+					u16 *ch_count)
+{
+	if (penv) {
+		if (buffer_size < penv->unsafe_ch_count * sizeof(u16))
+			return -ENODEV;
+		memcpy((char *)unsafe_ch_list,
+			(char *)penv->unsafe_ch_list,
+			penv->unsafe_ch_count * sizeof(u16));
+		*ch_count = penv->unsafe_ch_count;
+		return 0;
+	} else
+		return -ENODEV;
+}
+EXPORT_SYMBOL(wcnss_get_wlan_unsafe_channel);
+
 static int wcnss_smd_tx(void *data, int len)
 {
 	int ret = 0;
@@ -1823,6 +1967,80 @@
 	.notifier_call = wcnss_pm_notify,
 };
 
+static int wcnss_ctrl_open(struct inode *inode, struct file *file)
+{
+	int rc = 0;
+
+	if (!penv || penv->ctrl_device_opened)
+		return -EFAULT;
+
+	penv->ctrl_device_opened = 1;
+
+	return rc;
+}
+
+
+void process_usr_ctrl_cmd(u8 *buf, size_t len)
+{
+	u16 cmd = buf[0] << 8 | buf[1];
+
+	switch (cmd) {
+
+	case WCNSS_USR_SERIAL_NUM:
+		if (WCNSS_MIN_SERIAL_LEN > len) {
+			pr_err("%s: Invalid serial number\n", __func__);
+			return;
+		}
+		penv->serial_number = buf[2] << 24 | buf[3] << 16
+			| buf[4] << 8 | buf[5];
+		break;
+
+	case WCNSS_USR_HAS_CAL_DATA:
+		if (1 < buf[2])
+			pr_err("%s: Invalid data for cal %d\n", __func__,
+				buf[2]);
+		has_calibrated_data = buf[2];
+		break;
+
+	default:
+		pr_err("%s: Invalid command %d\n", __func__, cmd);
+		break;
+	}
+}
+
+static ssize_t wcnss_ctrl_write(struct file *fp, const char __user
+			*user_buffer, size_t count, loff_t *position)
+{
+	int rc = 0;
+	u8 buf[WCNSS_MAX_CMD_LEN];
+
+	if (!penv || !penv->ctrl_device_opened || WCNSS_MAX_CMD_LEN < count
+			|| WCNSS_MIN_CMD_LEN > count)
+		return -EFAULT;
+
+	mutex_lock(&penv->ctrl_lock);
+	rc = copy_from_user(buf, user_buffer, count);
+	if (0 == rc)
+		process_usr_ctrl_cmd(buf, count);
+
+	mutex_unlock(&penv->ctrl_lock);
+
+	return rc;
+}
+
+
+static const struct file_operations wcnss_ctrl_fops = {
+	.owner = THIS_MODULE,
+	.open = wcnss_ctrl_open,
+	.write = wcnss_ctrl_write,
+};
+
+static struct miscdevice wcnss_usr_ctrl = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = CTRL_DEVICE,
+	.fops = &wcnss_ctrl_fops,
+};
+
 static int
 wcnss_trigger_config(struct platform_device *pdev)
 {
@@ -2000,6 +2218,18 @@
 			pr_err("%s: ioremap wlan TX STATUS failed\n", __func__);
 			goto fail_ioremap9;
 		}
+		penv->alarms_txctl = ioremap(MSM_PRONTO_ALARMS_TXCTL, SZ_8);
+		if (!penv->alarms_txctl) {
+			ret = -ENOMEM;
+			pr_err("%s: ioremap alarms TXCTL failed\n", __func__);
+			goto fail_ioremap10;
+		}
+		penv->alarms_tactl = ioremap(MSM_PRONTO_ALARMS_TACTL, SZ_8);
+		if (!penv->alarms_tactl) {
+			ret = -ENOMEM;
+			pr_err("%s: ioremap alarms TACTL failed\n", __func__);
+			goto fail_ioremap11;
+		}
 	}
 	penv->adc_tm_dev = qpnp_get_adc_tm(&penv->pdev->dev, "wcnss");
 	if (IS_ERR(penv->adc_tm_dev)) {
@@ -2025,6 +2255,12 @@
 fail_pil:
 	if (penv->riva_ccu_base)
 		iounmap(penv->riva_ccu_base);
+	if (penv->alarms_tactl)
+		iounmap(penv->alarms_tactl);
+fail_ioremap11:
+	if (penv->alarms_txctl)
+		iounmap(penv->alarms_txctl);
+fail_ioremap10:
 	if (penv->wlan_tx_status)
 		iounmap(penv->wlan_tx_status);
 fail_ioremap9:
@@ -2225,6 +2461,7 @@
 	}
 
 	mutex_init(&penv->dev_lock);
+	mutex_init(&penv->ctrl_lock);
 	mutex_init(&penv->vbat_monitor_mutex);
 	init_waitqueue_head(&penv->read_wait);
 
@@ -2237,6 +2474,9 @@
 	 * place
 	 */
 	pr_info(DEVICE " probed in built-in mode\n");
+
+	misc_register(&wcnss_usr_ctrl);
+
 	return misc_register(&wcnss_misc);
 
 }
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index 99e17a6..c6192ed 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -30,10 +30,12 @@
 
 struct qca199x_platform_data {
 	unsigned int irq_gpio;
+	unsigned int	irq_gpio_clk_req;
+	unsigned int	clk_req_irq_num;
 	unsigned int dis_gpio;
-	unsigned int ven_gpio;
+	unsigned int clkreq_gpio;
 	unsigned int reg;
-	const char *clk_src;
+	const char *clk_src_name;
 	unsigned int clk_src_gpio;
 };
 
@@ -44,30 +46,62 @@
 
 MODULE_DEVICE_TABLE(of, msm_match_table);
 
-#define MAX_BUFFER_SIZE		(780)
+#define MAX_BUFFER_SIZE			(780)
+#define PACKET_MAX_LENGTH			(258)
 /* Read data */
 #define PACKET_HEADER_SIZE_NCI	(4)
-#define PACKET_TYPE_NCI		(16)
-#define MAX_PACKET_SIZE		(PACKET_HEADER_SIZE_NCI + 255)
-#define MAX_QCA_REG		(116)
+#define PACKET_TYPE_NCI			(16)
+#define MAX_PACKET_SIZE			(PACKET_HEADER_SIZE_NCI + 255)
+#define MAX_QCA_REG				(116)
+/* will timeout in approx. 100ms as 10us steps */
+#define NFC_RF_CLK_FREQ			(19200000)
+#define NTF_TIMEOUT				(10000)
+#define	CORE_RESET_RSP_GID		(0x60)
+#define	CORE_RESET_OID			(0x00)
+#define CORE_RST_NTF_LENGTH			(0x02)
 
-static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
-static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
+static void clk_req_update(struct work_struct *work);
 
 struct qca199x_dev {
 	wait_queue_head_t read_wq;
-	struct mutex read_mutex;
-	struct i2c_client *client;
-	struct miscdevice qca199x_device;
-	unsigned int irq_gpio;
-	unsigned int dis_gpio;
-	unsigned int ven_gpio;
-	bool irq_enabled;
-	spinlock_t irq_enabled_lock;
-	unsigned int count_irq;
+	struct	mutex		read_mutex;
+	struct	i2c_client	*client;
+	struct	miscdevice	qca199x_device;
+	/* NFC_IRQ new NCI data available */
+	unsigned int		irq_gpio;
+	/* CLK_REQ IRQ to signal the state has changed */
+	unsigned int		irq_gpio_clk_req;
+	/* Actual IRQ no. assigned to CLK_REQ */
+	unsigned int		clk_req_irq_num;
+	unsigned int		dis_gpio;
+	unsigned int		clkreq_gpio;
+	/* NFC_IRQ state */
+	bool			irq_enabled;
+	bool			sent_first_nci_write;
+	spinlock_t		irq_enabled_lock;
+	unsigned int		count_irq;
+	/* CLK_REQ IRQ state */
+	bool			irq_enabled_clk_req;
+	spinlock_t		irq_enabled_lock_clk_req;
+	unsigned int		count_irq_clk_req;
 	enum	nfcc_state	state;
+	/* CLK control */
+	unsigned int		clk_src_gpio;
+	const	char		*clk_src_name;
+	struct	clk		*s_clk;
+	bool			clk_run;
+	struct work_struct	msm_clock_controll_work;
+	struct workqueue_struct *my_wq;
 };
 
+static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
+static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr);
+static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
+static int qca199x_clock_select(struct qca199x_dev *qca199x_dev);
+static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev);
+
+
+
 /*
  * To allow filtering of nfc logging from user. This is set via
  * IOCTL NFC_KERNEL_LOGGING_MODE.
@@ -76,9 +110,10 @@
 /*
  * FTM-RAW-I2C RD/WR MODE
  */
-static struct	devicemode	device_mode;
-static int	ftm_raw_write_mode;
-static int	ftm_werr_code;
+static struct devicemode	device_mode;
+static int					ftm_raw_write_mode;
+static int					ftm_werr_code;
+
 
 static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
 {
@@ -140,6 +175,95 @@
 	return mask;
 }
 
+/* Handlers for CLK_REQ */
+static void qca199x_disable_irq_clk_req(struct qca199x_dev *qca199x_dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
+	if (qca199x_dev->irq_enabled_clk_req) {
+		disable_irq_nosync(qca199x_dev->clk_req_irq_num);
+		qca199x_dev->irq_enabled_clk_req = false;
+	}
+	spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
+}
+
+
+static void qca199x_enable_irq_clk_req(struct qca199x_dev *qca199x_dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
+	if (!qca199x_dev->irq_enabled_clk_req) {
+		qca199x_dev->irq_enabled_clk_req = true;
+		enable_irq(qca199x_dev->clk_req_irq_num);
+	}
+	spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
+}
+
+
+static irqreturn_t qca199x_dev_irq_handler_clk_req(int irq, void *dev_id)
+{
+	struct qca199x_dev *qca199x_dev = dev_id;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
+	qca199x_dev->count_irq_clk_req++;
+	spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
+
+	queue_work(qca199x_dev->my_wq, &qca199x_dev->msm_clock_controll_work);
+
+	return IRQ_HANDLED;
+}
+
+
+static struct gpiomux_setting nfc_clk_on = {
+	.func = GPIOMUX_FUNC_2,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+static struct gpiomux_setting nfc_clk_on_suspend = {
+	.func = GPIOMUX_FUNC_2,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+static struct gpiomux_setting nfc_clk_off = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv  = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static void clk_req_update(struct work_struct *work)
+{
+	struct	i2c_client *client;
+	struct	qca199x_dev *qca199x_dev;
+	int		gpio_clk_req_level = 0;
+
+	qca199x_dev =	container_of(work, struct qca199x_dev,
+			msm_clock_controll_work);
+	client =	qca199x_dev->client;
+
+	/* Read status level of CLK_REQ from NFC Controller, QCA199_x */
+	gpio_clk_req_level = gpio_get_value(qca199x_dev->irq_gpio_clk_req);
+	if (gpio_clk_req_level == 1) {
+		if (qca199x_dev->clk_run == false) {
+			msm_gpiomux_write(qca199x_dev->clk_src_gpio,
+				GPIOMUX_ACTIVE, &nfc_clk_on, NULL);
+			msm_gpiomux_write(qca199x_dev->clk_src_gpio,
+				GPIOMUX_SUSPENDED, &nfc_clk_on_suspend, NULL);
+			qca199x_dev->clk_run = true;
+			}
+	} else{
+		if (qca199x_dev->clk_run == true) {
+			msm_gpiomux_write(qca199x_dev->clk_src_gpio,
+				GPIOMUX_ACTIVE, &nfc_clk_off, NULL);
+			msm_gpiomux_write(qca199x_dev->clk_src_gpio,
+				GPIOMUX_SUSPENDED, &nfc_clk_off, NULL);
+			qca199x_dev->clk_run = false;
+		}
+	}
+}
+
 /*
  * ONLY for FTM-RAW-I2C Mode
  * Required to instigate a read, which comes from DT layer. This means we need
@@ -205,23 +329,33 @@
 	/* NORMAL NCI Behaviour */
 	/* Read the header */
 	ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
+	/*
+		We ignore all packets of length PAYLOAD_HEADER_LENGTH
+		or less (i.e <=3). In this case return a total length
+		of ZERO. So ALL PACKETS MUST HAVE A PAYLOAD.
+		If ret < 0 then this is an error code.
+	*/
 	if (ret != PAYLOAD_HEADER_LENGTH) {
-		total = 0;
+		if (ret < 0)
+			total = ret;
+		else
+			total = 0;
 		goto err;
 	}
 	length = len[PAYLOAD_HEADER_LENGTH - 1];
-	if (length == 0)
-		total = 0;
+	if (length == 0) {
+		ret = 0;
+		total = ret;
+		goto err;
+	}
 	/** make sure full packet fits in the buffer **/
 	if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= count)) {
 		/* Read the packet */
 		ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
 			PAYLOAD_HEADER_LENGTH));
-		if (ret < 0) {
-			total = 0;
+		total = ret;
+		if (ret < 0)
 			goto err;
-		}
-		total = (length + PAYLOAD_HEADER_LENGTH);
 	}
 
 	if (total > 0) {
@@ -232,14 +366,57 @@
 			total = -EFAULT;
 		}
 	}
-	mutex_unlock(&qca199x_dev->read_mutex);
 err:
-	if (ret < 0)
 		mutex_unlock(&qca199x_dev->read_mutex);
 done:
 	return total;
 }
 
+/*
+	Local routine to read from nfcc buffer. This is called to clear any
+	pending receive messages in the nfcc's read buffer, which may be there
+	following a POR. In this way, the upper layers (Device Transport) will
+	associate the next rsp/ntf nci message with the next nci command to the
+	nfcc. Otherwise, the DT may interpret a ntf from the nfcc as being from
+	the nci core reset command when in fact it was already present in the
+	nfcc read buffer following a POR.
+*/
+
+int nfcc_read_buff_svc(struct qca199x_dev *qca199x_dev)
+{
+	unsigned char tmp[PACKET_MAX_LENGTH];
+	unsigned char len[PAYLOAD_HEADER_LENGTH];
+	int total, length, ret;
+	total = 0;
+	length = 0;
+	mutex_lock(&qca199x_dev->read_mutex);
+	memset(tmp, 0, sizeof(tmp));
+	memset(len, 0, sizeof(len));
+
+	/* Read the header */
+	ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
+	if (ret < PAYLOAD_HEADER_LENGTH) {
+		total = ret;
+		goto leave;
+	}
+	length = len[PAYLOAD_HEADER_LENGTH - 1];
+	if (length == 0) {
+		ret = PAYLOAD_HEADER_LENGTH;
+		total = ret;
+		goto leave;
+	}
+	/** make sure full packet fits in the buffer **/
+	if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= PACKET_MAX_LENGTH)) {
+		/* Read the packet */
+		ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
+			PAYLOAD_HEADER_LENGTH));
+		total = ret;
+	}
+leave:
+	mutex_unlock(&qca199x_dev->read_mutex);
+	return total;
+}
+
 static ssize_t nfc_write(struct file *filp, const char __user *buf,
 				size_t count, loff_t *offset)
 {
@@ -247,6 +424,7 @@
 	char tmp[MAX_BUFFER_SIZE];
 	int ret = 0;
 	enum ehandler_mode dmode;
+	int nfcc_buffer = 0;
 
 	if (count > MAX_BUFFER_SIZE) {
 		dev_err(&qca199x_dev->client->dev, "out of memory\n");
@@ -257,10 +435,28 @@
 			"nfc-nci write: failed to copy from user space\n");
 		return -EFAULT;
 	}
+	/*
+		A catch for when the DT is sending the initial NCI write
+		following a hardware POR. In this case we should clear any
+		pending messages in nfcc buffer and open the interrupt gate
+		for new messages coming from the nfcc.
+	*/
+	if ((qca199x_dev->sent_first_nci_write == false) &&
+		 (qca199x_dev->irq_enabled == false)) {
+		/* check rsp/ntf from nfcc read-side buffer */
+		nfcc_buffer = nfcc_read_buff_svc(qca199x_dev);
+		/* There has been an error while reading from nfcc */
+		if (nfcc_buffer < 0) {
+			dev_err(&qca199x_dev->client->dev,
+				"nfc-nci write: error while servicing nfcc read buffer\n");
+		}
+		qca199x_dev->sent_first_nci_write = true;
+		qca199x_enable_irq(qca199x_dev);
+	}
 	mutex_lock(&qca199x_dev->read_mutex);
 	dmode = device_mode.handle_flavour;
 	/* FTM-DIRECT-I2C RD/WR MODE */
-	/* This is a special FTM-i2c mode case,where tester is not using NCI */
+	/* This is a special FTM-i2c mode case, where tester is not using NCI */
 	if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
 		(dmode == SOLICITED_FTM_RAW_MODE)) {
 		/* Read From Register */
@@ -308,7 +504,14 @@
 
 	filp->private_data = qca199x_dev;
 	qca199x_init_stat(qca199x_dev);
+	/* Enable interrupts from NFCC NFC_INT new NCI data available */
 	qca199x_enable_irq(qca199x_dev);
+
+	if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
+		(!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
+		/* Enable interrupts from NFCC CLK_REQ */
+		qca199x_enable_irq_clk_req(qca199x_dev);
+	}
 	dev_dbg(&qca199x_dev->client->dev,
 			"%d,%d\n", imajor(inode), iminor(inode));
 	return ret;
@@ -378,6 +581,9 @@
 	struct qca199x_dev *qca199x_dev = filp->private_data;
 
 	if (arg == 0) {
+		r = qca199x_clock_select(qca199x_dev);
+		if (r < 0)
+			goto err_req;
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
 		r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
 		if (r) {
@@ -389,6 +595,23 @@
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
 		msleep(20);
 	} else if (arg == 1) {
+		/*
+			We are attempting a hardware reset so let us disable
+			interrupts to avoid spurious notifications to upper
+			layers.
+		*/
+		qca199x_disable_irq(qca199x_dev);
+		/* Deselection of clock */
+		r = qca199x_clock_deselect(qca199x_dev);
+		if (r < 0)
+			goto err_req;
+		/*
+			Also, set flag for initial NCI write following resetas
+			may wish to do some house keeping. Ensure no pending
+			messages in NFCC buffers which may be wrongly
+			construed as response to initial message
+		*/
+		qca199x_dev->sent_first_nci_write = false;
 		gpio_set_value(qca199x_dev->dis_gpio, 0);
 		r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
 		if (r) {
@@ -402,10 +625,12 @@
 	} else if (arg == 2) {
 		mutex_lock(&qca199x_dev->read_mutex);
 		r = nfcc_initialise(qca199x_dev->client, 0xE);
+		/* Also reset first NCI write */
+		qca199x_dev->sent_first_nci_write = false;
 		mutex_unlock(&qca199x_dev->read_mutex);
 		if (r) {
 			dev_err(&qca199x_dev->client->dev,
-					"nfc-nci probe: request nfcc initialise failed\n");
+				"nfc_ioctl_power_states: request nfcc initialise failed\n");
 			goto err_req;
 		}
 	} else if (arg == 3) {
@@ -536,8 +761,6 @@
 	return raw_chip_version;
 }
 
-
-
 /*
  * Inside nfc_ioctl_kernel_logging
  *
@@ -651,6 +874,33 @@
 	return r;
 }
 
+/* Check for availability of qca199x_ NFC controller hardware */
+static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr)
+{
+	int r = 0;
+	unsigned char buf = 0;
+
+	client->addr = curr_addr;
+	/* Set-up Addr 0. No data written */
+	r = i2c_master_send(client, &buf, 1);
+	if (r < 0)
+		goto err_presence_check;
+	buf = 0;
+	/* Read back from Addr 0 */
+	r = i2c_master_recv(client, &buf, 1);
+	if (r < 0)
+		goto err_presence_check;
+
+	r = 0;
+	return r;
+
+err_presence_check:
+	r = -ENXIO;
+	dev_err(&client->dev,
+		"nfc-nci nfcc_presence check - no NFCC available\n");
+	return r;
+}
+/* Initialise qca199x_ NFC controller hardware */
 static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
 {
 	int r = 0;
@@ -664,72 +914,219 @@
 	unsigned char raw_1P8_PAD_CFG_CLK_REQ[]	= {0xA5, 0x1};
 	unsigned char raw_1P8_PAD_CFG_PWR_REQ[]	= {0xA7, 0x1};
 	unsigned char buf = 0;
+	bool core_reset_completed = false;
+	unsigned char rsp[6];
+	int time_taken = 0;
+	int ret = 0;
 
 	client->addr = curr_addr;
 	r = i2c_master_send(client, &buf, 1);
+	if (r < 0)
+		goto err_init;
+
 	buf = 0;
 	r = i2c_master_recv(client, &buf, 1);
+	if (r < 0)
+		goto err_init;
+
 	if (0x10 != (0x10 & buf)) {
 		RAW(s73, 0x02);
 
 		r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 		RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
 
 		r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
 						sizeof(raw_1p8_CONTROL_011));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 		RAW(1P8_CONTROL_010, (0x8));
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
 
 		usleep(10000);  /* 10ms wait */
 		RAW(1P8_CONTROL_010, (0xC));
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 					sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
+
 		usleep(100);  /* 100uS wait */
 		RAW(1P8_X0_0B0, (FREQ_SEL_19));
 		r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
 						sizeof(raw_1P8_X0_0B0));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		/* PWR_EN = 1 */
 		RAW(1P8_CONTROL_010, (0xd));
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
+
+
 		usleep(20000);  /* 20ms wait */
 		/* LS_EN = 1 */
 		RAW(1P8_CONTROL_010, 0xF);
 		r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
 						sizeof(raw_1P8_CONTROL_010));
+		if (r < 0)
+			goto err_init;
+
 		usleep(20000);  /* 20ms wait */
 
 		/* Enable the PMIC clock */
 		RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
 		r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
 					  sizeof(raw_1P8_PAD_CFG_CLK_REQ));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
 		r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
 					  sizeof(raw_1P8_PAD_CFG_PWR_REQ));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		RAW(slave2, 0x10);
 		r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		RAW(slave1, NCI_I2C_SLAVE);
 		r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
+		if (r < 0)
+			goto err_init;
+
 		usleep(1000);
 
 		/* QCA199x NFCC CPU should now boot... */
 		r = i2c_master_recv(client, &raw_slave1_rd, 1);
 		/* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
 		client->addr = NCI_I2C_SLAVE;
+
+		/*
+			Start with small delay and then we will poll until we
+			get a core reset notification - This is time for chip
+			& NFCC controller to come-up.
+		*/
+		usleep(1000); /* 1 ms */
+
+		do {
+			ret = i2c_master_recv(client, rsp, 5);
+			/* Found core reset notification */
+			if (((rsp[0] == CORE_RESET_RSP_GID) &&
+				(rsp[1] == CORE_RESET_OID) &&
+				(rsp[2] == CORE_RST_NTF_LENGTH))
+					|| time_taken == NTF_TIMEOUT) {
+				core_reset_completed = true;
+			}
+			usleep(10);  /* 10us sleep before retry */
+			time_taken++;
+		} while (!core_reset_completed);
 		r = 0;
 	} else {
-		r = 1;
+		goto err_init;
+	}
+	return r;
+err_init:
+	r = 1;
+	dev_err(&client->dev,
+		"nfc-nci nfcc_initialise: failed. Check Hardware\n");
+	return r;
+}
+/*
+	Routine to Select clocks
+*/
+static int qca199x_clock_select(struct qca199x_dev *qca199x_dev)
+{
+	int r = 0;
+
+	if (!strcmp(qca199x_dev->clk_src_name, "BBCLK2")) {
+		qca199x_dev->s_clk  =
+			clk_get(&qca199x_dev->client->dev, "ref_clk");
+		if (qca199x_dev->s_clk == NULL)
+			goto err_invalid_dis_gpio;
+	} else if (!strcmp(qca199x_dev->clk_src_name, "RFCLK3")) {
+		qca199x_dev->s_clk  =
+			clk_get(&qca199x_dev->client->dev, "ref_clk_rf");
+		if (qca199x_dev->s_clk == NULL)
+			goto err_invalid_dis_gpio;
+	} else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK")) {
+		if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
+			qca199x_dev->s_clk  =
+				clk_get(&qca199x_dev->client->dev, "core_clk");
+			if (qca199x_dev->s_clk == NULL)
+				goto err_invalid_dis_gpio;
+		} else {
+			goto err_invalid_dis_gpio;
+		}
+	} else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK2")) {
+		if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
+			qca199x_dev->s_clk  =
+				clk_get(&qca199x_dev->client->dev, "core_clk_pvt");
+			if (qca199x_dev->s_clk == NULL)
+				goto err_invalid_dis_gpio;
+		} else {
+			goto err_invalid_dis_gpio;
+		}
+	} else {
+		qca199x_dev->s_clk = NULL;
+		goto err_invalid_dis_gpio;
+	}
+	if (qca199x_dev->clk_run == false) {
+		/* Set clock rate */
+		if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
+			(!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
+			r = clk_set_rate(qca199x_dev->s_clk, NFC_RF_CLK_FREQ);
+			if (r)
+				goto err_invalid_clk;
+		}
+
+		r = clk_prepare_enable(qca199x_dev->s_clk);
+		if (r)
+			goto err_invalid_clk;
+		qca199x_dev->clk_run = true;
+	}
+	r = 0;
+	return r;
+
+err_invalid_clk:
+	r = -1;
+	return r;
+err_invalid_dis_gpio:
+	r = -2;
+	return r;
+}
+/*
+	Routine to De-Select clocks
+*/
+
+static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev)
+{
+	int r = -1;
+	if (qca199x_dev->s_clk != NULL) {
+		if (qca199x_dev->clk_run == true) {
+			clk_disable_unprepare(qca199x_dev->s_clk);
+			qca199x_dev->clk_run = false;
+		}
+		return 0;
 	}
 	return r;
 }
@@ -743,10 +1140,6 @@
 	if (r)
 		return -EINVAL;
 
-	r = of_property_read_u32(np, "qcom,clk-gpio", &pdata->ven_gpio);
-	if (r)
-		return -EINVAL;
-
 	pdata->dis_gpio = of_get_named_gpio(np, "qcom,dis-gpio", 0);
 	if ((!gpio_is_valid(pdata->dis_gpio)))
 		return -EINVAL;
@@ -755,13 +1148,26 @@
 	if ((!gpio_is_valid(pdata->irq_gpio)))
 		return -EINVAL;
 
-	r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src);
+	r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src_name);
 
-	if ((!strcmp(pdata->clk_src, "GPCLK")) ||
-	    (!strcmp(pdata->clk_src, "GPCLK2")))
-		pdata->clk_src_gpio = of_get_named_gpio(np,
-				"qcom,clk-en-gpio", 0);
+	if (strcmp(pdata->clk_src_name, "GPCLK2")) {
+		r = of_property_read_u32(np, "qcom,clk-gpio",
+					&pdata->clkreq_gpio);
+		if (r)
+			return -EINVAL;
+	}
 
+	if ((!strcmp(pdata->clk_src_name, "GPCLK")) ||
+	    (!strcmp(pdata->clk_src_name, "GPCLK2"))) {
+			pdata->clk_src_gpio = of_get_named_gpio(np,
+					"qcom,clk-src-gpio", 0);
+			if ((!gpio_is_valid(pdata->clk_src_gpio)))
+				return -EINVAL;
+			pdata->irq_gpio_clk_req = of_get_named_gpio(np,
+					"qcom,clk-req-gpio", 0);
+			if ((!gpio_is_valid(pdata->irq_gpio_clk_req)))
+				return -EINVAL;
+	}
 	if (r)
 		return -EINVAL;
 	return r;
@@ -772,7 +1178,6 @@
 {
 	int r = 0;
 	int irqn = 0;
-	struct clk *nfc_clk = NULL;
 	struct device_node *node = client->dev.of_node;
 	struct qca199x_platform_data *platform_data;
 	struct qca199x_dev *qca199x_dev;
@@ -810,33 +1215,17 @@
 		"nfc-nci probe: failed to allocate memory for module data\n");
 		return -ENOMEM;
 	}
-	if (gpio_is_valid(platform_data->irq_gpio)) {
-		r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
-		if (r) {
-			dev_err(&client->dev, "unable to request gpio [%d]\n",
-				platform_data->irq_gpio);
-			goto err_irq;
-		}
-		r = gpio_direction_input(platform_data->irq_gpio);
-		if (r) {
+	qca199x_dev->client = client;
 
-			dev_err(&client->dev,
-			"unable to set direction for gpio [%d]\n",
-				platform_data->irq_gpio);
-			goto err_irq;
-		}
-		gpio_to_irq(0);
-		irqn = gpio_to_irq(platform_data->irq_gpio);
-		if (irqn < 0) {
-			r = irqn;
-			goto err_irq;
-		}
-		client->irq = irqn;
+	/*
+	 * To be efficient we need to test whether nfcc hardware is physically
+	 * present before attempting further hardware initialisation.
+	 * For this we need to be sure the device is in ULPM state by
+	 * setting disable line low early on.
+	 *
+	 */
 
-	} else {
-		dev_err(&client->dev, "irq gpio not provided\n");
-		goto err_free_dev;
-	}
+
 	if (gpio_is_valid(platform_data->dis_gpio)) {
 		r = gpio_request(platform_data->dis_gpio, "nfc_reset_gpio");
 		if (r) {
@@ -854,73 +1243,128 @@
 		}
 	} else {
 		dev_err(&client->dev, "dis gpio not provided\n");
-		goto err_irq;
+		goto err_free_dev;
 	}
-	gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
-	msleep(20);
-	gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
-	if (!strcmp(platform_data->clk_src, "BBCLK2")) {
-		nfc_clk  = clk_get(&client->dev, "ref_clk");
-		if (nfc_clk == NULL)
-			goto err_dis_gpio;
-	} else if (!strcmp(platform_data->clk_src, "RFCLK3")) {
-		nfc_clk  = clk_get(&client->dev, "ref_clk_rf");
-		if (nfc_clk == NULL)
-			goto err_dis_gpio;
-	} else if (!strcmp(platform_data->clk_src, "GPCLK")) {
-		if (gpio_is_valid(platform_data->clk_src_gpio)) {
-			nfc_clk  = clk_get(&client->dev, "core_clk");
-			if (nfc_clk == NULL)
-				goto err_dis_gpio;
-		} else {
-			goto err_dis_gpio;
-		}
-	} else if (!strcmp(platform_data->clk_src, "GPCLK2")) {
-		if (gpio_is_valid(platform_data->clk_src_gpio)) {
-			nfc_clk  = clk_get(&client->dev, "core_clk_pvt");
-			if (nfc_clk == NULL)
-				goto err_dis_gpio;
-		} else {
-			goto err_dis_gpio;
-		}
-	} else {
-		nfc_clk = NULL;
+
+	/* Put device in ULPM */
+	gpio_set_value(platform_data->dis_gpio, 0);
+	r = nfcc_hw_check(client, platform_data->reg);
+	if (r) {
+		/* We don't think there is hardware but just in case HPD */
+		gpio_set_value(platform_data->dis_gpio, 1);
+		goto err_dis_gpio;
 	}
-	r = clk_prepare_enable(nfc_clk);
-	if (r)
-		goto err_clk;
 
-	platform_data->ven_gpio = of_get_named_gpio(node,
-						"qcom,clk-gpio", 0);
-
-	if (gpio_is_valid(platform_data->ven_gpio)) {
-		r = gpio_request(platform_data->ven_gpio, "nfc_ven_gpio");
+	if (gpio_is_valid(platform_data->irq_gpio)) {
+		r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
 		if (r) {
 			dev_err(&client->dev, "unable to request gpio [%d]\n",
-						platform_data->ven_gpio);
-			goto err_ven_gpio;
+				platform_data->irq_gpio);
+			goto err_dis_gpio;
 		}
-		r = gpio_direction_input(platform_data->ven_gpio);
+		r = gpio_direction_input(platform_data->irq_gpio);
 		if (r) {
 
 			dev_err(&client->dev,
 			"unable to set direction for gpio [%d]\n",
-						platform_data->ven_gpio);
-			goto err_ven_gpio;
+				platform_data->irq_gpio);
+			goto err_irq;
 		}
+		irqn = gpio_to_irq(platform_data->irq_gpio);
+		if (irqn < 0) {
+			r = irqn;
+			goto err_irq;
+		}
+		client->irq = irqn;
+
 	} else {
-		dev_err(&client->dev, "ven gpio not provided\n");
-		goto err_clk;
+		dev_err(&client->dev, "irq gpio not provided\n");
+		goto err_dis_gpio;
+	}
+	/* Interrupt from NFCC CLK_REQ to handle REF_CLK
+		o/p gating/selection */
+	if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
+		(!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
+		if (gpio_is_valid(platform_data->irq_gpio_clk_req)) {
+			r = gpio_request(platform_data->irq_gpio_clk_req,
+				"nfc_irq_gpio_clk_en");
+			if (r) {
+				dev_err(&client->dev, "unable to request CLK_EN gpio [%d]\n",
+					platform_data->irq_gpio_clk_req);
+				goto err_irq;
+			}
+			r = gpio_direction_input(
+					platform_data->irq_gpio_clk_req);
+			if (r) {
+				dev_err(&client->dev,
+					"unable to set direction for CLK_EN gpio [%d]\n",
+					platform_data->irq_gpio_clk_req);
+				goto err_irq_clk;
+			}
+			gpio_to_irq(0);
+			irqn = gpio_to_irq(platform_data->irq_gpio_clk_req);
+			if (irqn < 0) {
+				r = irqn;
+				goto err_irq_clk;
+			}
+			platform_data->clk_req_irq_num = irqn;
+		} else {
+			dev_err(&client->dev, "irq CLK_EN gpio not provided\n");
+			goto err_irq;
+		}
+	}
+	/* Get the clock source name and gpio from from Device Tree */
+	qca199x_dev->clk_src_name = platform_data->clk_src_name;
+	qca199x_dev->clk_src_gpio = platform_data->clk_src_gpio;
+	qca199x_dev->clk_run = false;
+	r = qca199x_clock_select(qca199x_dev);
+	if (r != 0) {
+		if (r == -1)
+			goto err_clk;
+		else
+			goto err_irq_clk;
+	}
+
+	if (strcmp(platform_data->clk_src_name, "GPCLK2")) {
+		platform_data->clkreq_gpio =
+			of_get_named_gpio(node, "qcom,clk-gpio", 0);
+
+		if (gpio_is_valid(platform_data->clkreq_gpio)) {
+			r = gpio_request(platform_data->clkreq_gpio,
+				"nfc_clkreq_gpio");
+			if (r) {
+				dev_err(&client->dev, "unable to request gpio [%d]\n",
+						platform_data->clkreq_gpio);
+				goto err_clkreq_gpio;
+			}
+			r = gpio_direction_input(platform_data->clkreq_gpio);
+			if (r) {
+				dev_err(&client->dev,
+						"unable to set direction for gpio [%d]\n",
+						platform_data->clkreq_gpio);
+				goto err_clkreq_gpio;
+			}
+		} else {
+			dev_err(&client->dev, "clkreq gpio not provided\n");
+			goto err_clk;
+		}
+		qca199x_dev->clkreq_gpio = platform_data->clkreq_gpio;
 	}
 	qca199x_dev->dis_gpio = platform_data->dis_gpio;
 	qca199x_dev->irq_gpio = platform_data->irq_gpio;
-	qca199x_dev->ven_gpio = platform_data->ven_gpio;
-	qca199x_dev->client = client;
+	if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
+		(!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
+			qca199x_dev->irq_gpio_clk_req	=
+						platform_data->irq_gpio_clk_req;
+			qca199x_dev->clk_req_irq_num		=
+						platform_data->clk_req_irq_num;
+	}
 
 	/* init mutex and queues */
 	init_waitqueue_head(&qca199x_dev->read_wq);
 	mutex_init(&qca199x_dev->read_mutex);
 	spin_lock_init(&qca199x_dev->irq_enabled_lock);
+	spin_lock_init(&qca199x_dev->irq_enabled_lock_clk_req);
 
 	qca199x_dev->qca199x_device.minor = MISC_DYNAMIC_MINOR;
 	qca199x_dev->qca199x_device.name = "nfc-nci";
@@ -932,6 +1376,27 @@
 		goto err_misc_register;
 	}
 
+
+	/*
+	 * Reboot the NFCC now that all resources are ready
+	 *
+	 * The NFCC takes time to transition between power states.
+	 * We wait 20uS for the NFCC to shutdown. (HPD)
+	 * We wait 100uS for the NFCC to boot into ULPM.
+	 */
+	gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
+	msleep(20);
+	gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
+	msleep(100);
+
+
+	/* Here we perform a second presence check. */
+	r = nfcc_hw_check(client, platform_data->reg);
+	if (r) {
+		/* We don't think there is hardware but just in case HPD */
+		gpio_set_value(platform_data->dis_gpio, 1);
+		goto err_nfcc_not_present;
+	}
 	regulators.regulator = regulator_get(&client->dev, regulators.name);
 	if (IS_ERR(regulators.regulator)) {
 		r = PTR_ERR(regulators.regulator);
@@ -950,12 +1415,7 @@
 	* for reading.  It is cleared when all data has been read.
 	*/
 	device_mode.handle_flavour = UNSOLICITED_MODE;
-	r = nfcc_initialise(client, platform_data->reg);
-	if (r) {
-		dev_err(&client->dev, "nfc-nci probe: request nfcc initialise failed\n");
-		goto err_nfcc_init_failed;
-	}
-
+	/* NFC_INT IRQ */
 	qca199x_dev->irq_enabled = true;
 	r = request_irq(client->irq, qca199x_dev_irq_handler,
 			  IRQF_TRIGGER_RISING, client->name, qca199x_dev);
@@ -964,35 +1424,65 @@
 		goto err_request_irq_failed;
 	}
 	qca199x_disable_irq(qca199x_dev);
+	/* CLK_REQ IRQ */
+	if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
+		(!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
+		r = request_irq(qca199x_dev->clk_req_irq_num,
+				qca199x_dev_irq_handler_clk_req,
+				(IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING),
+						client->name, qca199x_dev);
+		if (r) {
+			dev_err(&client->dev,
+			"nfc-nci probe: request_irq failed. irq no = %d\n, main irq =  %d",
+				qca199x_dev->clk_req_irq_num, client->irq);
+			goto err_request_irq_failed;
+		}
+		qca199x_dev->irq_enabled_clk_req = true;
+		qca199x_disable_irq_clk_req(qca199x_dev);
+
+
+		qca199x_dev->my_wq =
+			create_singlethread_workqueue("qca1990x_CLK_REQ_queue");
+		if (!qca199x_dev->my_wq)
+			goto err_create_workq;
+
+		INIT_WORK(&qca199x_dev->msm_clock_controll_work,
+			clk_req_update);
+	}
 	i2c_set_clientdata(client, qca199x_dev);
+	gpio_set_value(platform_data->dis_gpio, 1);
 	dev_dbg(&client->dev,
 	"nfc-nci probe: %s, probing qca1990 exited successfully\n",
 		 __func__);
 	return 0;
 
-err_nfcc_init_failed:
+err_create_workq:
+	dev_err(&client->dev,
+	"nfc-nci probe: %s, work_queue creation failure\n",
+		 __func__);
+	free_irq(client->irq, qca199x_dev);
+err_nfcc_not_present:
 err_request_irq_failed:
 	misc_deregister(&qca199x_dev->qca199x_device);
 err_misc_register:
 	mutex_destroy(&qca199x_dev->read_mutex);
-err_ven_gpio:
-	gpio_free(platform_data->ven_gpio);
+err_clkreq_gpio:
+	if (strcmp(platform_data->clk_src_name, "GPCLK2"))
+		gpio_free(platform_data->clkreq_gpio);
 err_clk:
-	clk_disable_unprepare(nfc_clk);
-err_dis_gpio:
-	r = gpio_direction_input(platform_data->dis_gpio);
-	if (r)
-		dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
-	if ((!strcmp(platform_data->clk_src, "GPCLK")) ||
-            (!strcmp(platform_data->clk_src, "GPCLK2"))) {
-		r = gpio_direction_input(platform_data->clk_src_gpio);
+		qca199x_clock_deselect(qca199x_dev);
+err_irq_clk:
+	if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
+		(!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
+		r = gpio_direction_input(platform_data->irq_gpio_clk_req);
 		if (r)
 			dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
-		gpio_free(platform_data->clk_src_gpio);
+		gpio_free(platform_data->irq_gpio_clk_req);
 	}
-	gpio_free(platform_data->dis_gpio);
 err_irq:
 	gpio_free(platform_data->irq_gpio);
+err_dis_gpio:
+	gpio_free(platform_data->dis_gpio);
 err_free_dev:
 	kfree(qca199x_dev);
 	return r;
@@ -1007,8 +1497,13 @@
 	misc_deregister(&qca199x_dev->qca199x_device);
 	mutex_destroy(&qca199x_dev->read_mutex);
 	gpio_free(qca199x_dev->irq_gpio);
+	if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
+		(!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
+		gpio_free(qca199x_dev->irq_gpio_clk_req);
+	}
 	gpio_free(qca199x_dev->dis_gpio);
-	gpio_free(qca199x_dev->ven_gpio);
+	if (strcmp(qca199x_dev->clk_src_name, "GPCLK2"))
+		gpio_free(qca199x_dev->clkreq_gpio);
 	kfree(qca199x_dev);
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 1ef1f1b..20603f5 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -205,6 +205,8 @@
 			retval = -EFAULT;
 			break;
 		}
+		/* null terminate the string */
+		nat_mem.dev_name[IPA_RESOURCE_NAME_MAX - 1] = '\0';
 
 		if (allocate_nat_device(&nat_mem)) {
 			retval = -EFAULT;
diff --git a/drivers/platform/msm/ipa/ipa_nat.c b/drivers/platform/msm/ipa/ipa_nat.c
index e2c344f..6ee16fb 100644
--- a/drivers/platform/msm/ipa/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_nat.c
@@ -166,7 +166,7 @@
 
 	nat_ctx->dev =
 	   device_create(nat_ctx->class, NULL, nat_ctx->dev_num, nat_ctx,
-			 mem->dev_name);
+			"%s", mem->dev_name);
 
 	if (IS_ERR(nat_ctx->dev)) {
 		IPAERR("device_create err:%ld\n", PTR_ERR(nat_ctx->dev));
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index b3a6b17..d08ac64 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -22,7 +22,6 @@
 #include <linux/mutex.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
-#include <mach/bam_dmux.h>
 #include <mach/ipa.h>
 #include <mach/sps.h>
 #include "ipa_i.h"
@@ -1780,7 +1779,7 @@
 			break;
 		}
 
-		if (caps.num_protocols < teth_ctx->aggr_caps->num_protocols) {
+		if (caps.num_protocols != teth_ctx->aggr_caps->num_protocols) {
 			caps.num_protocols = teth_ctx->aggr_caps->num_protocols;
 			if (copy_to_user((struct teth_aggr_capabilities *)arg,
 					 &caps,
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index b55b66b..507d02c 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -50,6 +50,8 @@
 #define QPNP_PON_KPDPWR_RESIN_S2_CNTL2(base)	(base + 0x4B)
 #define QPNP_PON_PS_HOLD_RST_CTL(base)		(base + 0x5A)
 #define QPNP_PON_PS_HOLD_RST_CTL2(base)		(base + 0x5B)
+#define QPNP_PON_WD_RST_S2_CTL(base)		(base + 0x56)
+#define QPNP_PON_WD_RST_S2_CTL2(base)		(base + 0x57)
 #define QPNP_PON_TRIGGER_EN(base)		(base + 0x80)
 #define QPNP_PON_S3_DBC_CTL(base)		(base + 0x75)
 
@@ -73,6 +75,7 @@
 #define QPNP_PON_RESIN_BARK_N_SET		BIT(4)
 #define QPNP_PON_KPDPWR_RESIN_BARK_N_SET	BIT(5)
 
+#define QPNP_PON_WD_EN			BIT(7)
 #define QPNP_PON_RESET_EN			BIT(7)
 #define QPNP_PON_POWER_OFF_MASK			0xF
 
@@ -270,6 +273,32 @@
 EXPORT_SYMBOL(qpnp_pon_is_warm_reset);
 
 /**
+ * qpnp_pon_wd_config - Disable the wd in a warm reset.
+ * @enable: to enable or disable the PON watch dog
+ *
+ * Returns = 0 for operate successfully, < 0 for errors
+ */
+int qpnp_pon_wd_config(bool enable)
+{
+	struct qpnp_pon *pon = sys_reset_dev;
+	int rc = 0;
+
+	if (!pon)
+		return -EPROBE_DEFER;
+
+	rc = qpnp_pon_masked_write(pon, QPNP_PON_WD_RST_S2_CTL2(pon->base),
+			QPNP_PON_WD_EN, enable ? QPNP_PON_WD_EN : 0);
+	if (rc)
+		dev_err(&pon->spmi->dev,
+				"Unable to write to addr=%x, rc(%d)\n",
+				QPNP_PON_WD_RST_S2_CTL2(pon->base), rc);
+
+	return rc;
+}
+EXPORT_SYMBOL(qpnp_pon_wd_config);
+
+
+/**
  * qpnp_pon_trigger_config - Configures (enable/disable) the PON trigger source
  * @pon_src: PON source to be configured
  * @enable: to enable or disable the PON trigger
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index c621d2a..55a5a2d 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -184,6 +184,11 @@
 		return -EFAULT;
 	}
 
+	if (buf_size_kb > (INT_MAX/SZ_1K)) {
+		pr_err("sps:debugfs: buffer size is too large\n");
+		return -EFAULT;
+	}
+
 	new_buf_size = buf_size_kb * SZ_1K;
 
 	if (debugfs_record_enabled) {
@@ -2529,21 +2534,8 @@
 		goto device_create_err;
 	}
 
-	sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
-	if (IS_ERR(sps->dfab_clk)) {
-		if (PTR_ERR(sps->dfab_clk) == -EPROBE_DEFER)
-			ret = -EPROBE_DEFER;
-		else
-			SPS_ERR("sps:fail to get dfab_clk.");
-		goto clk_err;
-	} else {
-		ret = clk_set_rate(sps->dfab_clk, 64000000);
-		if (ret) {
-			SPS_ERR("sps:failed to set dfab_clk rate.");
-			clk_put(sps->dfab_clk);
-			goto clk_err;
-		}
-	}
+	if (pdev->dev.of_node)
+		sps->dev->of_node = pdev->dev.of_node;
 
 	if (!d_type) {
 		sps->pmem_clk = clk_get(sps->dev, "mem_clk");
@@ -2552,36 +2544,58 @@
 				ret = -EPROBE_DEFER;
 			else
 				SPS_ERR("sps:fail to get pmem_clk.");
-			goto clk_err;
+			goto pmem_clk_err;
 		} else {
 			ret = clk_prepare_enable(sps->pmem_clk);
 			if (ret) {
 				SPS_ERR("sps:failed to enable pmem_clk.");
-				goto clk_err;
+				goto pmem_clk_en_err;
 			}
 		}
 	}
 
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
+	sps->dfab_clk = clk_get(sps->dev, "dfab_clk");
+	if (IS_ERR(sps->dfab_clk)) {
+		if (PTR_ERR(sps->dfab_clk) == -EPROBE_DEFER)
+			ret = -EPROBE_DEFER;
+		else
+			SPS_ERR("sps:fail to get dfab_clk.");
+		goto dfab_clk_err;
+	} else {
+		ret = clk_set_rate(sps->dfab_clk, 64000000);
+		if (ret) {
+			SPS_ERR("sps:failed to set dfab_clk rate.");
+			clk_put(sps->dfab_clk);
+			goto dfab_clk_err;
+		}
+	}
+
 	sps->bamdma_clk = clk_get(sps->dev, "dma_bam_pclk");
 	if (IS_ERR(sps->bamdma_clk)) {
 		if (PTR_ERR(sps->bamdma_clk) == -EPROBE_DEFER)
 			ret = -EPROBE_DEFER;
 		else
 			SPS_ERR("sps:fail to get bamdma_clk.");
-		goto clk_err;
+		clk_put(sps->dfab_clk);
+		goto dfab_clk_err;
 	} else {
 		ret = clk_prepare_enable(sps->bamdma_clk);
 		if (ret) {
 			SPS_ERR("sps:failed to enable bamdma_clk. ret=%d", ret);
-			goto clk_err;
+			clk_put(sps->bamdma_clk);
+			clk_put(sps->dfab_clk);
+			goto dfab_clk_err;
 		}
 	}
 
 	ret = clk_prepare_enable(sps->dfab_clk);
 	if (ret) {
 		SPS_ERR("sps:failed to enable dfab_clk. ret=%d", ret);
-		goto clk_err;
+		clk_disable_unprepare(sps->bamdma_clk);
+		clk_put(sps->bamdma_clk);
+		clk_put(sps->dfab_clk);
+		goto dfab_clk_err;
 	}
 #endif
 	ret = sps_device_init();
@@ -2590,8 +2604,10 @@
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
 		clk_disable_unprepare(sps->dfab_clk);
 		clk_disable_unprepare(sps->bamdma_clk);
+		clk_put(sps->bamdma_clk);
+		clk_put(sps->dfab_clk);
 #endif
-		goto sps_device_init_err;
+		goto dfab_clk_err;
 	}
 #ifdef CONFIG_SPS_SUPPORT_BAMDMA
 	clk_disable_unprepare(sps->dfab_clk);
@@ -2602,8 +2618,13 @@
 	SPS_INFO("sps:sps is ready.");
 
 	return 0;
-clk_err:
-sps_device_init_err:
+dfab_clk_err:
+	if (!d_type)
+		clk_disable_unprepare(sps->pmem_clk);
+pmem_clk_en_err:
+	if (!d_type)
+		clk_put(sps->pmem_clk);
+pmem_clk_err:
 	device_destroy(sps->dev_class, sps->dev_num);
 device_create_err:
 	unregister_chrdev_region(sps->dev_num, 1);
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index bd4328a..ad5e241 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -169,6 +169,7 @@
 	list_for_each_entry(pipe, &dev->pipes_q, list) {
 		/* Check this pipe's bit in the source mask */
 		if (BAM_PIPE_IS_ASSIGNED(pipe)
+				&& (!pipe->disconnecting)
 				&& (source & pipe->pipe_index_mask)) {
 			/* This pipe has an interrupt pending */
 			pipe_handler(dev, pipe);
@@ -585,6 +586,7 @@
 	pipe->mode = -1;
 	pipe->num_descs = 0;
 	pipe->desc_size = 0;
+	pipe->disconnecting = false;
 	memset(&pipe->sys, 0, sizeof(pipe->sys));
 	INIT_LIST_HEAD(&pipe->sys.events_q);
 }
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index da5dafd..a20156b 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -185,6 +185,7 @@
 	/* System mode control */
 	struct sps_bam_sys_mode sys;
 
+	bool disconnecting;
 };
 
 /* BAM device descriptor */
diff --git a/drivers/platform/msm/sps/sps_rm.c b/drivers/platform/msm/sps/sps_rm.c
index 7d7e1a6..d8c7a4d 100644
--- a/drivers/platform/msm/sps/sps_rm.c
+++ b/drivers/platform/msm/sps/sps_rm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -556,11 +556,8 @@
 {
 	struct sps_connection *map = (void *)pipe->map;
 	struct sps_connect *cfg = &pipe->connect;
-	struct sps_bam *bam = pipe->bam;
-	unsigned long flags;
 
 	mutex_lock(&sps_rm->lock);
-	spin_lock_irqsave(&bam->isr_lock, flags);
 
 	/* Free this connection */
 	if (cfg->mode == SPS_MODE_SRC)
@@ -574,7 +571,6 @@
 
 	sps_rm_remove_ref(map);
 
-	spin_unlock_irqrestore(&bam->isr_lock, flags);
 	mutex_unlock(&sps_rm->lock);
 
 	return 0;
@@ -800,8 +796,9 @@
 			synchronize_irq(bam->props.irq);
 
 		spin_lock_irqsave(&bam->isr_lock, flags);
-		result = sps_bam_pipe_disconnect(pipe->bam, pipe_index);
+		pipe->disconnecting = true;
 		spin_unlock_irqrestore(&bam->isr_lock, flags);
+		result = sps_bam_pipe_disconnect(pipe->bam, pipe_index);
 		if (result) {
 			SPS_ERR("sps:Failed to disconnect BAM 0x%x pipe %d",
 				pipe->bam->props.phys_addr,
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 85a70ea..6cac572 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -757,7 +757,20 @@
 
 static bool is_battery_charging(struct qpnp_bms_chip *chip)
 {
-	return get_battery_status(chip) == POWER_SUPPLY_STATUS_CHARGING;
+	union power_supply_propval ret = {0,};
+
+	if (chip->batt_psy == NULL)
+		chip->batt_psy = power_supply_get_by_name("battery");
+	if (chip->batt_psy) {
+		/* if battery has been registered, use the status property */
+		chip->batt_psy->get_property(chip->batt_psy,
+					POWER_SUPPLY_PROP_CHARGE_TYPE, &ret);
+		return ret.intval != POWER_SUPPLY_CHARGE_TYPE_NONE;
+	}
+
+	/* Default to false if the battery power supply is not registered. */
+	pr_debug("battery power supply is not registered\n");
+	return false;
 }
 
 static bool is_battery_full(struct qpnp_bms_chip *chip)
@@ -2496,7 +2509,7 @@
 		soc = calculate_soc_from_voltage(chip);
 	} else {
 		if (!chip->batfet_closed)
-			qpnp_iadc_calibrate_for_trim(chip->iadc_dev, true);
+			qpnp_iadc_calibrate_for_trim(chip->iadc_dev, false);
 		rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM,
 								&result);
 		if (rc) {
@@ -2548,7 +2561,7 @@
 		soc = calculate_soc_from_voltage(chip);
 	} else {
 		if (!chip->batfet_closed)
-			qpnp_iadc_calibrate_for_trim(chip->iadc_dev, true);
+			qpnp_iadc_calibrate_for_trim(chip->iadc_dev, false);
 		rc = qpnp_vadc_read(chip->vadc_dev, LR_MUX1_BATT_THERM,
 								&result);
 		if (rc) {
@@ -3273,12 +3286,11 @@
 {
 	bool batfet_closed;
 
-	if (chip->iadc_bms_revision2 > CALIB_WRKARND_DIG_MAJOR_MAX)
-		return;
-
 	batfet_closed = is_batfet_closed(chip);
 	if (chip->batfet_closed != batfet_closed) {
 		chip->batfet_closed = batfet_closed;
+		if (chip->iadc_bms_revision2 > CALIB_WRKARND_DIG_MAJOR_MAX)
+			return;
 		if (batfet_closed == false) {
 			/* batfet opened */
 			schedule_work(&chip->batfet_open_work);
@@ -4273,6 +4285,12 @@
 		goto error_setup;
 	}
 
+	rc = bms_request_irqs(chip);
+	if (rc) {
+		pr_err("error requesting bms irqs, rc = %d\n", rc);
+		goto error_setup;
+	}
+
 	battery_insertion_check(chip);
 	batfet_status_check(chip);
 	battery_status_check(chip);
@@ -4306,12 +4324,6 @@
 		goto unregister_dc;
 	}
 
-	rc = bms_request_irqs(chip);
-	if (rc) {
-		pr_err("error requesting bms irqs, rc = %d\n", rc);
-		goto unregister_dc;
-	}
-
 	pr_info("probe success: soc =%d vbatt = %d ocv = %d r_sense_uohm = %u warm_reset = %d\n",
 			get_prop_bms_capacity(chip), vbatt, chip->last_ocv_uv,
 			chip->r_sense_uohm, warm_reset);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 6ea4ea6..40c5568 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -113,6 +113,7 @@
 #define USB_OCP_THR				0x52
 #define USB_OCP_CLR				0x53
 #define BAT_IF_TEMP_STATUS			0x09
+#define BOOST_ILIM				0x78
 
 #define REG_OFFSET_PERP_SUBTYPE			0x05
 
@@ -217,6 +218,7 @@
 struct qpnp_chg_irq {
 	int		irq;
 	unsigned long		disabled;
+	unsigned long		wake_enable;
 };
 
 struct qpnp_chg_regulator {
@@ -247,6 +249,7 @@
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
  * @batt_weak_voltage_mv:	Weak battery voltage threshold
+ * @vbatdet_max_err_mv		resume voltage hysterisis
  * @max_bat_chg_current:	maximum battery charge current in mA
  * @warm_bat_chg_ma:	warm battery maximum charge current in mA
  * @cool_bat_chg_ma:	cool battery maximum charge current in mA
@@ -323,6 +326,7 @@
 	unsigned int			max_voltage_mv;
 	unsigned int			min_voltage_mv;
 	unsigned int			batt_weak_voltage_mv;
+	unsigned int			vbatdet_max_err_mv;
 	int				prev_usb_max_ma;
 	int				set_vddmax_mv;
 	int				delta_vddmax_mv;
@@ -362,6 +366,7 @@
 	struct work_struct		soc_check_work;
 	struct delayed_work		aicl_check_work;
 	struct work_struct		insertion_ocv_work;
+	struct work_struct		ocp_clear_work;
 	struct qpnp_chg_regulator	otg_vreg;
 	struct qpnp_chg_regulator	boost_vreg;
 	struct qpnp_chg_regulator	batfet_vreg;
@@ -529,6 +534,24 @@
 	}
 }
 
+static void
+qpnp_chg_irq_wake_enable(struct qpnp_chg_irq *irq)
+{
+	if (!__test_and_set_bit(0, &irq->wake_enable)) {
+		pr_debug("number = %d\n", irq->irq);
+		enable_irq_wake(irq->irq);
+	}
+}
+
+static void
+qpnp_chg_irq_wake_disable(struct qpnp_chg_irq *irq)
+{
+	if (__test_and_clear_bit(0, &irq->wake_enable)) {
+		pr_debug("number = %d\n", irq->irq);
+		disable_irq_wake(irq->irq);
+	}
+}
+
 #define USB_OTG_EN_BIT	BIT(0)
 static int
 qpnp_chg_is_otg_en_set(struct qpnp_chg_chip *chip)
@@ -832,13 +855,12 @@
 	int rc = 0;
 	u8 usb_reg = 0, temp = 8;
 
-	if (mA < QPNP_CHG_I_MAX_MIN_100
-			|| mA > QPNP_CHG_I_MAX_MAX_MA) {
+	if (mA < 0 || mA > QPNP_CHG_I_MAX_MAX_MA) {
 		pr_err("bad mA=%d asked to set\n", mA);
 		return -EINVAL;
 	}
 
-	if (mA == QPNP_CHG_I_MAX_MIN_100) {
+	if (mA <= QPNP_CHG_I_MAX_MIN_100) {
 		usb_reg = 0x00;
 		pr_debug("current=%d setting %02x\n", mA, usb_reg);
 		return qpnp_chg_write(chip, &usb_reg,
@@ -1198,7 +1220,9 @@
 		pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
 
 	pr_debug("chg_gone triggered\n");
-	if (qpnp_chg_is_usb_chg_plugged_in(chip) && (usb_sts & CHG_GONE_IRQ)) {
+	if ((qpnp_chg_is_usb_chg_plugged_in(chip)
+			|| qpnp_chg_is_dc_chg_plugged_in(chip))
+			&& (usb_sts & CHG_GONE_IRQ)) {
 		qpnp_chg_charge_en(chip, 0);
 		qpnp_chg_force_run_on_batt(chip, 1);
 		schedule_delayed_work(&chip->arb_stop_work,
@@ -1212,10 +1236,36 @@
 qpnp_chg_usb_usb_ocp_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
-	int rc;
 
 	pr_debug("usb-ocp triggered\n");
 
+	schedule_work(&chip->ocp_clear_work);
+
+	return IRQ_HANDLED;
+}
+
+#define BOOST_ILIMIT_MIN	0x07
+#define BOOST_ILIMIT_DEF	0x02
+#define BOOST_ILIMT_MASK	0xFF
+static void
+qpnp_chg_ocp_clear_work(struct work_struct *work)
+{
+	int rc;
+	u8 usb_sts;
+	struct qpnp_chg_chip *chip = container_of(work,
+		struct qpnp_chg_chip, ocp_clear_work);
+
+	if (chip->type == SMBBP) {
+		rc = qpnp_chg_masked_write(chip,
+				chip->boost_base + BOOST_ILIM,
+				BOOST_ILIMT_MASK,
+				BOOST_ILIMIT_MIN, 1);
+		if (rc) {
+			pr_err("Failed to turn configure ilim rc = %d\n", rc);
+			return;
+		}
+	}
+
 	rc = qpnp_chg_masked_write(chip,
 			chip->usb_chgpth_base + USB_OCP_CLR,
 			OCP_CLR_BIT,
@@ -1231,7 +1281,29 @@
 	if (rc)
 		pr_err("Failed to turn off usb ovp rc = %d\n", rc);
 
-	return IRQ_HANDLED;
+	if (chip->type == SMBBP) {
+		/* Wait for OCP circuitry to be powered up */
+		msleep(100);
+		rc = qpnp_chg_read(chip, &usb_sts,
+				INT_RT_STS(chip->usb_chgpth_base), 1);
+		if (rc) {
+			pr_err("failed to read interrupt sts %d\n", rc);
+			return;
+		}
+
+		if (usb_sts & COARSE_DET_USB_IRQ) {
+			rc = qpnp_chg_masked_write(chip,
+				chip->boost_base + BOOST_ILIM,
+				BOOST_ILIMT_MASK,
+				BOOST_ILIMIT_DEF, 1);
+			if (rc) {
+				pr_err("Failed to set ilim rc = %d\n", rc);
+				return;
+			}
+		} else {
+			pr_warn_ratelimited("USB short to GND detected!\n");
+		}
+	}
 }
 
 #define QPNP_CHG_VDDMAX_MIN		3400
@@ -1476,6 +1548,7 @@
 				chip->chg_done = false;
 			}
 			qpnp_chg_usb_suspend_enable(chip, 0);
+			qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
 			chip->prev_usb_max_ma = -EINVAL;
 			chip->aicl_settled = false;
 		} else {
@@ -1516,15 +1589,35 @@
 	return IRQ_HANDLED;
 }
 
+#define TEST_EN_SMBC_LOOP		0xE5
+#define IBAT_REGULATION_DISABLE		BIT(2)
 static irqreturn_t
 qpnp_chg_bat_if_batt_temp_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
-	int batt_temp_good;
+	int batt_temp_good, rc;
 
 	batt_temp_good = qpnp_chg_is_batt_temp_ok(chip);
 	pr_debug("batt-temp triggered: %d\n", batt_temp_good);
 
+	rc = qpnp_chg_masked_write(chip,
+		chip->buck_base + SEC_ACCESS,
+		0xFF,
+		0xA5, 1);
+	if (rc) {
+		pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = qpnp_chg_masked_write(chip,
+		chip->buck_base + TEST_EN_SMBC_LOOP,
+		IBAT_REGULATION_DISABLE,
+		batt_temp_good ? 0 : IBAT_REGULATION_DISABLE, 1);
+	if (rc) {
+		pr_err("failed to write COMP_OVR1 rc=%d\n", rc);
+		return rc;
+	}
+
 	pr_debug("psy changed batt_psy\n");
 	power_supply_changed(&chip->batt_psy);
 	return IRQ_HANDLED;
@@ -1654,6 +1747,8 @@
 	u8 chgr_sts;
 	int rc;
 
+	qpnp_chg_irq_wake_disable(&chip->chg_fastchg);
+
 	rc = qpnp_chg_read(chip, &chgr_sts, INT_RT_STS(chip->chgr_base), 1);
 	if (rc)
 		pr_err("failed to read interrupt sts %d\n", rc);
@@ -1757,6 +1852,17 @@
 	if (!qpnp_chg_is_otg_en_set(chip))
 		return 0;
 
+	if (chip->type == SMBBP) {
+		rc = qpnp_chg_masked_write(chip,
+			chip->boost_base + BOOST_ILIM,
+			BOOST_ILIMT_MASK,
+			BOOST_ILIMIT_DEF, 1);
+		if (rc) {
+			pr_err("Failed to set ilim rc = %d\n", rc);
+			return rc;
+		}
+	}
+
 	/* enable usb ovp fet */
 	rc = qpnp_chg_masked_write(chip,
 			chip->usb_chgpth_base + CHGR_USB_USB_OTG_CTL,
@@ -1780,11 +1886,23 @@
 switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
 {
 	int rc;
+	u8 usb_sts;
 
 	pr_debug("switch to host mode\n");
 	if (qpnp_chg_is_otg_en_set(chip))
 		return 0;
 
+	if (chip->type == SMBBP) {
+		rc = qpnp_chg_masked_write(chip,
+				chip->boost_base + BOOST_ILIM,
+				BOOST_ILIMT_MASK,
+				BOOST_ILIMIT_MIN, 1);
+		if (rc) {
+			pr_err("Failed to turn configure ilim rc = %d\n", rc);
+			return rc;
+		}
+	}
+
 	if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
 		rc = qpnp_chg_force_run_on_batt(chip, 1);
 		if (rc) {
@@ -1803,6 +1921,30 @@
 		return rc;
 	}
 
+	if (chip->type == SMBBP) {
+		/* Wait for OCP circuitry to be powered up */
+		msleep(100);
+		rc = qpnp_chg_read(chip, &usb_sts,
+				INT_RT_STS(chip->usb_chgpth_base), 1);
+		if (rc) {
+			pr_err("failed to read interrupt sts %d\n", rc);
+			return rc;
+		}
+
+		if (usb_sts & COARSE_DET_USB_IRQ) {
+			rc = qpnp_chg_masked_write(chip,
+				chip->boost_base + BOOST_ILIM,
+				BOOST_ILIMT_MASK,
+				BOOST_ILIMIT_DEF, 1);
+			if (rc) {
+				pr_err("Failed to set ilim rc = %d\n", rc);
+				return rc;
+			}
+		} else {
+			pr_warn_ratelimited("USB short to GND detected!\n");
+		}
+	}
+
 	return 0;
 }
 
@@ -1986,6 +2128,24 @@
 	return POWER_SUPPLY_CHARGE_TYPE_NONE;
 }
 
+#define DEFAULT_CAPACITY	50
+static int
+get_batt_capacity(struct qpnp_chg_chip *chip)
+{
+	union power_supply_propval ret = {0,};
+
+	if (chip->fake_battery_soc >= 0)
+		return chip->fake_battery_soc;
+	if (chip->use_default_batt_values || !get_prop_batt_present(chip))
+		return DEFAULT_CAPACITY;
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+				POWER_SUPPLY_PROP_CAPACITY, &ret);
+		return ret.intval;
+	}
+	return DEFAULT_CAPACITY;
+}
+
 static int
 get_prop_batt_status(struct qpnp_chg_chip *chip)
 {
@@ -2009,11 +2169,18 @@
 		return POWER_SUPPLY_CHARGE_TYPE_NONE;
 	}
 
-	if (chgr_sts & TRKL_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
+	if ((chgr_sts & TRKL_CHG_ON_IRQ) && !(bat_if_sts & BAT_FET_ON_IRQ))
 		return POWER_SUPPLY_STATUS_CHARGING;
 	if (chgr_sts & FAST_CHG_ON_IRQ && bat_if_sts & BAT_FET_ON_IRQ)
 		return POWER_SUPPLY_STATUS_CHARGING;
 
+	/* report full if state of charge is 100 and a charger is connected */
+	if ((qpnp_chg_is_usb_chg_plugged_in(chip) ||
+		qpnp_chg_is_dc_chg_plugged_in(chip))
+			&& get_batt_capacity(chip) == 100) {
+		return POWER_SUPPLY_STATUS_FULL;
+	}
+
 	return POWER_SUPPLY_STATUS_DISCHARGING;
 }
 
@@ -2065,7 +2232,6 @@
 	return 0;
 }
 
-#define DEFAULT_CAPACITY	50
 static int
 get_prop_capacity(struct qpnp_chg_chip *chip)
 {
@@ -2100,6 +2266,7 @@
 				&& soc <= chip->soc_resume_limit) {
 			pr_debug("resuming charging at %d%% soc\n", soc);
 			chip->resuming_charging = true;
+			qpnp_chg_irq_wake_enable(&chip->chg_fastchg);
 			qpnp_chg_set_appropriate_vbatdet(chip);
 			qpnp_chg_charge_en(chip, !chip->charging_disabled);
 		}
@@ -3104,12 +3271,13 @@
 		vbat_lower_than_vbatdet = !(chg_sts & VBAT_DET_LOW_IRQ);
 		if (vbat_lower_than_vbatdet && vbat_mv <
 				(chip->max_voltage_mv - chip->resume_delta_mv
-				 - VBATDET_MAX_ERR_MV)) {
+				 - chip->vbatdet_max_err_mv)) {
 			vbat_low_count++;
 			pr_debug("woke up too early vbat_mv = %d, max_mv = %d, resume_mv = %d tolerance_mv = %d low_count = %d\n",
 					vbat_mv, chip->max_voltage_mv,
 					chip->resume_delta_mv,
-					VBATDET_MAX_ERR_MV, vbat_low_count);
+					chip->vbatdet_max_err_mv,
+					vbat_low_count);
 			if (vbat_low_count >= CONSECUTIVE_COUNT) {
 				pr_debug("woke up too early stopping\n");
 				qpnp_chg_enable_irq(&chip->chg_vbatdet_lo);
@@ -3641,7 +3809,8 @@
 		qpnp_batt_system_temp_level_set(chip, val->intval);
 		break;
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
-		qpnp_chg_iusbmax_set(chip, val->intval / 1000);
+		if (qpnp_chg_is_usb_chg_plugged_in(chip))
+			qpnp_chg_iusbmax_set(chip, val->intval / 1000);
 		break;
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
 		qpnp_chg_iusb_trim_set(chip, val->intval);
@@ -3798,10 +3967,10 @@
 				return rc;
 			}
 
-			enable_irq_wake(chip->chg_trklchg.irq);
-			enable_irq_wake(chip->chg_failed.irq);
+			qpnp_chg_irq_wake_enable(&chip->chg_trklchg);
+			qpnp_chg_irq_wake_enable(&chip->chg_failed);
 			qpnp_chg_disable_irq(&chip->chg_vbatdet_lo);
-			enable_irq_wake(chip->chg_vbatdet_lo.irq);
+			qpnp_chg_irq_wake_enable(&chip->chg_vbatdet_lo);
 
 			break;
 		case SMBB_BAT_IF_SUBTYPE:
@@ -3824,7 +3993,7 @@
 				return rc;
 			}
 
-			enable_irq_wake(chip->batt_pres.irq);
+			qpnp_chg_irq_wake_enable(&chip->batt_pres);
 
 			chip->batt_temp_ok.irq = spmi_get_irq_byname(spmi,
 						spmi_resource, "bat-temp-ok");
@@ -3841,8 +4010,9 @@
 						chip->batt_temp_ok.irq, rc);
 				return rc;
 			}
+			qpnp_chg_bat_if_batt_temp_irq_handler(0, chip);
 
-			enable_irq_wake(chip->batt_temp_ok.irq);
+			qpnp_chg_irq_wake_enable(&chip->batt_temp_ok);
 
 			break;
 		case SMBB_BUCK_SUBTYPE:
@@ -3924,11 +4094,11 @@
 					return rc;
 				}
 
-				enable_irq_wake(chip->usb_ocp.irq);
+				qpnp_chg_irq_wake_enable(&chip->usb_ocp);
 			}
 
-			enable_irq_wake(chip->usbin_valid.irq);
-			enable_irq_wake(chip->chg_gone.irq);
+			qpnp_chg_irq_wake_enable(&chip->usbin_valid);
+			qpnp_chg_irq_wake_enable(&chip->chg_gone);
 			break;
 		case SMBB_DC_CHGPTH_SUBTYPE:
 			chip->dcin_valid.irq = spmi_get_irq_byname(spmi,
@@ -3947,7 +4117,7 @@
 				return rc;
 			}
 
-			enable_irq_wake(chip->dcin_valid.irq);
+			qpnp_chg_irq_wake_enable(&chip->dcin_valid);
 			break;
 		}
 	}
@@ -4334,6 +4504,7 @@
 	OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
 	OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
 	OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
+	OF_PROP_READ(chip, vbatdet_max_err_mv, "vbatdet-maxerr-mv", rc, 1);
 
 	if (rc)
 		return rc;
@@ -4352,6 +4523,9 @@
 		}
 	}
 
+	if (!chip->vbatdet_max_err_mv)
+		chip->vbatdet_max_err_mv = VBATDET_MAX_ERR_MV;
+
 	/* Look up JEITA compliance parameters if cool and warm temp provided */
 	if (chip->cool_bat_decidegc || chip->warm_bat_decidegc) {
 		chip->adc_tm_dev = qpnp_get_adc_tm(chip->dev, "chg");
@@ -4472,6 +4646,8 @@
 	INIT_WORK(&chip->reduce_power_stage_work,
 			qpnp_chg_reduce_power_stage_work);
 	mutex_init(&chip->batfet_vreg_lock);
+	INIT_WORK(&chip->ocp_clear_work,
+			qpnp_chg_ocp_clear_work);
 	INIT_WORK(&chip->batfet_lcl_work,
 			qpnp_chg_batfet_lcl_work);
 	INIT_WORK(&chip->insertion_ocv_work,
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index fe5af3a..e9994c2 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -102,6 +102,17 @@
 	  This driver supports the voltage regulators of DA9052-BC and
 	  DA9053-AA/Bx PMIC.
 
+config REGULATOR_FAN53555
+	tristate "Fairchild FAN53555 Regulator"
+	depends on I2C
+	select REGMAP_I2C
+	help
+	  This driver supports Fairchild FAN53555 Digitally Programmable
+	  TinyBuck Regulator. The FAN53555 is a step-down switching voltage
+	  regulator that delivers a digitally programmable output from an
+	  input voltage supply of 2.5V to 5.5V. The output voltage is
+	  programmed through an I2C interface.
+
 config REGULATOR_ANATOP
 	tristate "Freescale i.MX on-chip ANATOP LDO regulators"
 	depends on MFD_ANATOP
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index eb07c97..d96e793 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_REGULATOR_DA9052)	+= da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
+obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
new file mode 100644
index 0000000..6986a52
--- /dev/null
+++ b/drivers/regulator/fan53555.c
@@ -0,0 +1,658 @@
+/*
+ * FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver.
+ *
+ * Supported Part Numbers:
+ * FAN53555UC00X/01X/03X/04X/05X
+ *
+ * Copyright (c) 2012 Marvell Technology Ltd.
+ * Yunfan Zhang <yfzhang@marvell.com>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <linux/regulator/fan53555.h>
+
+/* Voltage setting */
+#define FAN53555_VSEL0		0x00
+#define FAN53555_VSEL1		0x01
+/* Control register */
+#define FAN53555_CONTROL	0x02
+/* IC Type */
+#define FAN53555_ID1		0x03
+/* IC mask version */
+#define FAN53555_ID2		0x04
+/* Monitor register */
+#define FAN53555_MONITOR	0x05
+
+/* VSEL bit definitions */
+#define VSEL_BUCK_EN	(1 << 7)
+#define VSEL_MODE		(1 << 6)
+#define VSEL_NSEL_MASK	0x3F
+#define VSEL_FULL_MASK	0xFF
+/* Chip ID and Verison */
+#define DIE_ID		0x0F	/* ID1 */
+#define DIE_REV		0x0F	/* ID2 */
+#define DIE_13_REV	0x0F	/* DIE Revsion ID of 13 option */
+
+/* Control bit definitions */
+#define CTL_OUTPUT_DISCHG	(1 << 7)
+#define CTL_SLEW_MASK		(0x7 << 4)
+#define CTL_SLEW_SHIFT		4
+#define CTL_RESET			(1 << 2)
+
+#define FAN53555_NVOLTAGES	64	/* Numbers of voltages */
+
+/* IC Type */
+enum {
+	FAN53555_CHIP_ID_00 = 0,
+	FAN53555_CHIP_ID_01,
+	FAN53555_CHIP_ID_02,
+	FAN53555_CHIP_ID_03,
+	FAN53555_CHIP_ID_04,
+	FAN53555_CHIP_ID_05,
+};
+
+static const int slew_rate_plan[] = {
+	64000,
+	32000,
+	16000,
+	8000,
+	4000,
+	2000,
+	1000,
+	500
+};
+
+struct fan53555_device_info {
+	struct regmap *regmap;
+	struct device *dev;
+	struct regulator_desc desc;
+	struct regulator_dev *rdev;
+	struct regulator_init_data *regulator;
+	/* IC Type and Rev */
+	int chip_id;
+	int chip_rev;
+	/* Voltage setting register */
+	unsigned int vol_reg;
+	unsigned int sleep_reg;
+	/* Voltage range and step(linear) */
+	unsigned int vsel_min;
+	unsigned int vsel_step;
+	/* Voltage slew rate limiting */
+	unsigned int slew_rate;
+	/* Sleep voltage cache */
+	unsigned int sleep_vol_cache;
+
+	bool disable_suspend;
+};
+
+static int fan53555_get_voltage(struct regulator_dev *rdev)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	unsigned int val;
+	int rc;
+
+	rc = regmap_read(di->regmap, di->vol_reg, &val);
+	if (rc) {
+		dev_err(di->dev, "Unable to get voltage rc(%d)", rc);
+		return rc;
+	}
+
+	return ((val & VSEL_NSEL_MASK) * di->vsel_step) +
+		di->vsel_min;
+}
+
+static int fan53555_set_voltage(struct regulator_dev *rdev,
+			int min_uv, int max_uv, unsigned *selector)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	int rc, set_val, cur_uv, new_uv;
+
+	set_val = DIV_ROUND_UP(min_uv - di->vsel_min, di->vsel_step);
+	new_uv = (set_val * di->vsel_step) + di->vsel_min;
+
+	if (new_uv > max_uv || max_uv < di->vsel_min) {
+		dev_err(di->dev, "Unable to set voltage (%d %d)\n",
+			min_uv, max_uv);
+	}
+
+	cur_uv = fan53555_get_voltage(rdev);
+	if (cur_uv < 0)
+		return cur_uv;
+
+	rc = regmap_update_bits(di->regmap, di->vol_reg, VSEL_NSEL_MASK,
+				set_val);
+	if (rc) {
+		dev_err(di->dev, "Unable to set voltage (%d %d)\n",
+			min_uv, max_uv);
+	} else {
+		udelay(DIV_ROUND_UP(abs(new_uv - cur_uv),
+			slew_rate_plan[di->slew_rate]));
+		*selector = set_val;
+	}
+
+	return rc;
+}
+
+static int fan53555_list_voltage(struct regulator_dev *rdev,
+						unsigned selector)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+
+	if (selector >= di->desc.n_voltages)
+		return 0;
+
+	return selector * di->vsel_step + di->vsel_min;
+}
+
+static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	int ret, val;
+
+	if (di->sleep_vol_cache == uV)
+		return 0;
+	ret = fan53555_set_voltage(rdev, uV, uV, &val);
+	if (ret < 0)
+		return -EINVAL;
+	ret = regmap_update_bits(di->regmap, di->sleep_reg,
+					VSEL_NSEL_MASK, val);
+	if (ret < 0)
+		return -EINVAL;
+	/* Cache the sleep voltage setting.
+	 * Might not be the real voltage which is rounded */
+	di->sleep_vol_cache = uV;
+
+	return 0;
+}
+
+static int fan53555_enable(struct regulator_dev *rdev)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = regmap_update_bits(di->regmap, di->vol_reg,
+					VSEL_BUCK_EN, VSEL_BUCK_EN);
+	if (ret)
+		dev_err(di->dev, "Unable to enable regulator, ret = %d\n",
+			ret);
+	return ret;
+}
+
+static int fan53555_disable(struct regulator_dev *rdev)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = regmap_update_bits(di->regmap, di->vol_reg,
+					VSEL_BUCK_EN, 0);
+	if (ret)
+		dev_err(di->dev, "Unable to set disable regulator, ret = %d\n",
+			ret);
+	return ret;
+}
+
+static int fan53555_is_enabled(struct regulator_dev *rdev)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	int ret;
+	u32 val;
+
+	ret = regmap_read(di->regmap, di->vol_reg, &val);
+	if (ret) {
+		dev_err(di->dev, "Unable to get regulator status, ret = %d\n",
+			ret);
+		return ret;
+	} else {
+		return val & VSEL_BUCK_EN;
+	}
+}
+
+static int fan53555_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+
+	switch (mode) {
+	case REGULATOR_MODE_FAST:
+		regmap_update_bits(di->regmap, di->vol_reg,
+				VSEL_MODE, VSEL_MODE);
+		break;
+	case REGULATOR_MODE_NORMAL:
+		regmap_update_bits(di->regmap, di->vol_reg, VSEL_MODE, 0);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static unsigned int fan53555_get_mode(struct regulator_dev *rdev)
+{
+	struct fan53555_device_info *di = rdev_get_drvdata(rdev);
+	unsigned int val;
+	int ret = 0;
+
+	ret = regmap_read(di->regmap, di->vol_reg, &val);
+	if (ret < 0)
+		return ret;
+	if (val & VSEL_MODE)
+		return REGULATOR_MODE_FAST;
+	else
+		return REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops fan53555_regulator_ops = {
+	.set_voltage = fan53555_set_voltage,
+	.get_voltage = fan53555_get_voltage,
+	.list_voltage = fan53555_list_voltage,
+	.set_suspend_voltage = fan53555_set_suspend_voltage,
+	.enable = fan53555_enable,
+	.disable = fan53555_disable,
+	.is_enabled = fan53555_is_enabled,
+	.set_mode = fan53555_set_mode,
+	.get_mode = fan53555_get_mode,
+};
+
+static struct regulator_ops fan53555_regulator_disable_suspend_ops = {
+	.set_voltage = fan53555_set_voltage,
+	.get_voltage = fan53555_get_voltage,
+	.list_voltage = fan53555_list_voltage,
+	.enable = fan53555_enable,
+	.disable = fan53555_disable,
+	.is_enabled = fan53555_is_enabled,
+	.set_mode = fan53555_set_mode,
+	.get_mode = fan53555_get_mode,
+};
+
+/* For 00,01,03,05 options:
+ * VOUT = 0.60V + NSELx * 10mV, from 0.60 to 1.23V.
+ * For 04 option:
+ * VOUT = 0.603V + NSELx * 12.826mV, from 0.603 to 1.411V.
+ * For 13 option:
+ * 13 option, its DIE ID is 0x00 and DIE_REV is 0x0F.
+ * VOUT = 0.80V + NSELx * 10mV, from 0.80 to 1.43V.
+ * */
+static int fan53555_device_setup(struct fan53555_device_info *di,
+				struct fan53555_platform_data *pdata)
+{
+	unsigned int reg, data, mask;
+
+	/* Setup voltage control register */
+	switch (pdata->sleep_vsel_id) {
+	case FAN53555_VSEL_ID_0:
+		di->sleep_reg = FAN53555_VSEL0;
+		di->vol_reg = FAN53555_VSEL1;
+		break;
+	case FAN53555_VSEL_ID_1:
+		di->sleep_reg = FAN53555_VSEL1;
+		di->vol_reg = FAN53555_VSEL0;
+		break;
+	default:
+		dev_err(di->dev, "Invalid VSEL ID!\n");
+		return -EINVAL;
+	}
+	/* Init voltage range and step */
+	switch (di->chip_id) {
+	case FAN53555_CHIP_ID_00:
+		if (di->chip_rev == DIE_13_REV) {
+			di->vsel_min = 800000;
+			di->vsel_step = 10000;
+			break;
+		}
+	case FAN53555_CHIP_ID_01:
+	case FAN53555_CHIP_ID_03:
+	case FAN53555_CHIP_ID_05:
+		di->vsel_min = 600000;
+		di->vsel_step = 10000;
+		break;
+	case FAN53555_CHIP_ID_04:
+		di->vsel_min = 603000;
+		di->vsel_step = 12826;
+		break;
+	default:
+		dev_err(di->dev,
+			"Chip ID[%d]\n not supported!\n", di->chip_id);
+		return -EINVAL;
+	}
+	/* Init slew rate */
+	if (pdata->slew_rate & 0x7)
+		di->slew_rate = pdata->slew_rate;
+	else
+		di->slew_rate = FAN53555_SLEW_RATE_64MV;
+	reg = FAN53555_CONTROL;
+	data = di->slew_rate << CTL_SLEW_SHIFT;
+	mask = CTL_SLEW_MASK;
+	return regmap_update_bits(di->regmap, reg, mask, data);
+}
+
+static int fan53555_regulator_register(struct fan53555_device_info *di,
+					struct i2c_client *client)
+{
+	struct regulator_desc *rdesc = &di->desc;
+
+	rdesc->name = "fan53555-reg";
+	if (di->disable_suspend)
+		rdesc->ops = &fan53555_regulator_disable_suspend_ops;
+	else
+		rdesc->ops = &fan53555_regulator_ops;
+	rdesc->type = REGULATOR_VOLTAGE;
+	rdesc->n_voltages = FAN53555_NVOLTAGES;
+	rdesc->owner = THIS_MODULE;
+
+	di->rdev = regulator_register(&di->desc, di->dev,
+			di->regulator, di, client->dev.of_node);
+	return PTR_RET(di->rdev);
+
+}
+
+static struct regmap_config fan53555_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+};
+
+static int fan53555_parse_backup_reg(struct i2c_client *client, u32 *sleep_sel)
+{
+	int rc = -EINVAL;
+
+	rc = of_property_read_u32(client->dev.of_node, "fairchild,backup-vsel",
+				sleep_sel);
+	if (rc) {
+		dev_err(&client->dev, "fairchild,backup-vsel property missing\n");
+	} else {
+		switch (*sleep_sel) {
+		case FAN53555_VSEL_ID_0:
+		case FAN53555_VSEL_ID_1:
+			break;
+		default:
+			dev_err(&client->dev, "Invalid VSEL ID!\n");
+			rc = -EINVAL;
+		}
+	}
+
+	return rc;
+}
+
+static u32 fan53555_get_slew_rate_reg_value(struct i2c_client *client,
+					u32 slew_rate)
+{
+	u32 index;
+
+	for (index = 0; index < ARRAY_SIZE(slew_rate_plan); index++)
+		if (slew_rate == slew_rate_plan[index])
+			break;
+
+	if (index == ARRAY_SIZE(slew_rate_plan)) {
+		dev_err(&client->dev, "invalid slew rate.\n");
+		index = FAN53555_SLEW_RATE_8MV;
+	}
+
+	return index;
+}
+
+static struct fan53555_platform_data *
+	fan53555_get_of_platform_data(struct i2c_client *client)
+{
+	struct fan53555_platform_data *pdata = NULL;
+	struct regulator_init_data *init_data;
+	u32 sleep_sel, slew_rate;
+	int rc;
+
+	init_data = of_get_regulator_init_data(&client->dev,
+			client->dev.of_node);
+	if (!init_data) {
+		dev_err(&client->dev, "regulator init data is missing\n");
+		return pdata;
+	}
+
+	rc = of_property_read_u32(client->dev.of_node, "regulator-ramp-delay",
+					&slew_rate);
+	if (rc)
+		slew_rate = slew_rate_plan[FAN53555_SLEW_RATE_8MV];
+
+	if (fan53555_parse_backup_reg(client, &sleep_sel))
+		return pdata;
+
+	pdata = devm_kzalloc(&client->dev,
+			sizeof(struct fan53555_platform_data), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&client->dev,
+			"fan53555_platform_data allocation failed.\n");
+		return pdata;
+	}
+
+	init_data->constraints.input_uV = init_data->constraints.max_uV;
+	init_data->constraints.valid_ops_mask |=
+		REGULATOR_CHANGE_STATUS	| REGULATOR_CHANGE_VOLTAGE |
+		REGULATOR_CHANGE_MODE;
+	init_data->constraints.valid_modes_mask =
+				REGULATOR_MODE_NORMAL |
+				REGULATOR_MODE_FAST;
+	init_data->constraints.initial_mode = REGULATOR_MODE_NORMAL;
+
+	pdata->regulator = init_data;
+	pdata->slew_rate = fan53555_get_slew_rate_reg_value(client,
+							slew_rate);
+	pdata->sleep_vsel_id = sleep_sel;
+
+	return pdata;
+}
+
+static int fan53555_restore_working_reg(struct device_node *node,
+			struct fan53555_device_info *di)
+{
+	int ret;
+	u32 val;
+
+	/* Restore register from back up register */
+	ret = regmap_read(di->regmap, di->sleep_reg, &val);
+	if (ret < 0) {
+		dev_err(di->dev,
+			"Failed to get backup data from reg %d, ret = %d\n",
+			di->sleep_reg, ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(di->regmap,
+		di->vol_reg, VSEL_FULL_MASK, val);
+	if (ret < 0) {
+		dev_err(di->dev,
+			"Failed to update working reg %d, ret = %d\n",
+			di->vol_reg, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int fan53555_of_init(struct device_node *node,
+			struct fan53555_device_info *di)
+{
+	int ret, gpio;
+	enum of_gpio_flags flags;
+
+	if (of_property_read_bool(node, "fairchild,restore-reg")) {
+		ret = fan53555_restore_working_reg(node, di);
+		if (ret)
+			return ret;
+	}
+
+	if (of_find_property(node, "fairchild,vsel-gpio", NULL)) {
+		gpio = of_get_named_gpio_flags(node, "fairchild,vsel-gpio", 0,
+						&flags);
+
+		if (!gpio_is_valid(gpio)) {
+			if (gpio != -EPROBE_DEFER)
+				dev_err(di->dev, "Could not get vsel, ret = %d\n",
+					gpio);
+			return gpio;
+		}
+
+		ret = devm_gpio_request(di->dev, gpio, "fan53555_vsel");
+		if (ret) {
+			dev_err(di->dev, "Failed to obtain gpio %d ret = %d\n",
+				gpio, ret);
+			return ret;
+		}
+
+		ret = gpio_direction_output(gpio, flags & OF_GPIO_ACTIVE_LOW ?
+							0 : 1);
+		if (ret) {
+			dev_err(di->dev,
+				"Failed to set GPIO %d to: %s, ret = %d",
+				gpio, flags & OF_GPIO_ACTIVE_LOW ?
+				"GPIO_LOW" : "GPIO_HIGH", ret);
+			return ret;
+		}
+	}
+
+	di->disable_suspend = of_property_read_bool(node,
+				"fairchild,disable-suspend");
+
+	return 0;
+}
+
+static int __devinit fan53555_regulator_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct fan53555_device_info *di;
+	struct fan53555_platform_data *pdata;
+	unsigned int val;
+	int ret;
+
+	if (client->dev.of_node)
+		pdata = fan53555_get_of_platform_data(client);
+	else
+		pdata = client->dev.platform_data;
+
+	if (!pdata || !pdata->regulator) {
+		dev_err(&client->dev, "Platform data not found!\n");
+		return -ENODEV;
+	}
+
+	di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
+					GFP_KERNEL);
+	if (!di) {
+		dev_err(&client->dev, "Failed to allocate device info data!\n");
+		return -ENOMEM;
+	}
+	di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
+	if (IS_ERR(di->regmap)) {
+		dev_err(&client->dev, "Failed to allocate regmap!\n");
+		return PTR_ERR(di->regmap);
+	}
+	di->dev = &client->dev;
+	di->regulator = pdata->regulator;
+	i2c_set_clientdata(client, di);
+	/* Get chip ID */
+	ret = regmap_read(di->regmap, FAN53555_ID1, &val);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to get chip ID!\n");
+		return -ENODEV;
+	}
+	di->chip_id = val & DIE_ID;
+	/* Get chip revision */
+	ret = regmap_read(di->regmap, FAN53555_ID2, &val);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to get chip Rev!\n");
+		return -ENODEV;
+	}
+	di->chip_rev = val & DIE_REV;
+	dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n",
+				di->chip_id, di->chip_rev);
+	/* Device init */
+	ret = fan53555_device_setup(di, pdata);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to setup device!\n");
+		return ret;
+	}
+
+	/* Set up from device tree */
+	if (client->dev.of_node) {
+		ret = fan53555_of_init(client->dev.of_node, di);
+		if (ret)
+			return ret;
+	}
+
+	ret = fan53555_regulator_register(di, client);
+	if (ret < 0)
+		dev_err(&client->dev, "Failed to register regulator!\n");
+
+	return ret;
+
+}
+
+static int __devexit fan53555_regulator_remove(struct i2c_client *client)
+{
+	struct fan53555_device_info *di = i2c_get_clientdata(client);
+
+	regulator_unregister(di->rdev);
+	return 0;
+}
+
+static struct of_device_id fan53555_match_table[] = {
+	{ .compatible = "fairchild,fan53555-regulator",},
+	{},
+};
+MODULE_DEVICE_TABLE(of, fan53555_match_table);
+
+static const struct i2c_device_id fan53555_id[] = {
+	{"fan53555", -1},
+	{ },
+};
+
+static struct i2c_driver fan53555_regulator_driver = {
+	.driver = {
+		.name = "fan53555-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = fan53555_match_table,
+	},
+	.probe = fan53555_regulator_probe,
+	.remove = __devexit_p(fan53555_regulator_remove),
+	.id_table = fan53555_id,
+};
+
+/**
+ * fan53555_regulator_init() - initialized fan53555 regulator driver
+ * This function registers the fan53555 regulator platform driver.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int __init fan53555_regulator_init(void)
+{
+	static bool initialized;
+
+	if (initialized)
+		return 0;
+	else
+		initialized = true;
+
+	return i2c_add_driver(&fan53555_regulator_driver);
+}
+EXPORT_SYMBOL(fan53555_regulator_init);
+module_init(fan53555_regulator_init);
+
+static void __exit fan53555_regulator_exit(void)
+{
+	i2c_del_driver(&fan53555_regulator_driver);
+}
+module_exit(fan53555_regulator_exit);
+
+MODULE_AUTHOR("Yunfan Zhang <yfzhang@marvell.com>");
+MODULE_DESCRIPTION("FAN53555 regulator driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/regulator/onsemi-ncp6335d.c b/drivers/regulator/onsemi-ncp6335d.c
index 329ac46..3d4dd04 100644
--- a/drivers/regulator/onsemi-ncp6335d.c
+++ b/drivers/regulator/onsemi-ncp6335d.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -12,12 +12,20 @@
 
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/log2.h>
 #include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/regmap.h>
 #include <linux/regulator/onsemi-ncp6335d.h>
+#include <linux/string.h>
+#include <mach/gpiomux.h>
 
 /* registers */
 #define REG_NCP6335D_PID		0x03
@@ -30,6 +38,7 @@
 /* constraints */
 #define NCP6335D_MIN_VOLTAGE_UV		600000
 #define NCP6335D_STEP_VOLTAGE_UV	6250
+#define NCP6335D_VOLTAGE_STEPS		128
 #define NCP6335D_MIN_SLEW_NS		166
 #define NCP6335D_MAX_SLEW_NS		1333
 
@@ -51,9 +60,15 @@
 	struct regmap *regmap;
 	struct device *dev;
 	unsigned int vsel_reg;
+	unsigned int vsel_backup_reg;
 	unsigned int mode_bit;
 	int curr_voltage;
 	int slew_rate;
+
+	unsigned int step_size;
+	unsigned int min_voltage;
+	unsigned int min_slew_ns;
+	unsigned int max_slew_ns;
 };
 
 static void dump_registers(struct ncp6335d_info *dd,
@@ -71,8 +86,8 @@
 	u8 val;
 	int delay;
 
-	val = abs(prev_uV - new_uV) / NCP6335D_STEP_VOLTAGE_UV;
-	delay =  (val * dd->slew_rate / 1000) + 1;
+	val = abs(prev_uV - new_uV) / dd->step_size;
+	delay = ((val * dd->slew_rate) / 1000) + 1;
 
 	dev_dbg(dd->dev, "Slew Delay = %d\n", delay);
 
@@ -120,8 +135,8 @@
 		dev_err(dd->dev, "Unable to get volatge rc(%d)", rc);
 		return rc;
 	}
-	dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) *
-			NCP6335D_STEP_VOLTAGE_UV) + NCP6335D_MIN_VOLTAGE_UV;
+	dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) * dd->step_size) +
+				dd->min_voltage;
 
 	dump_registers(dd, dd->vsel_reg, __func__);
 
@@ -134,10 +149,8 @@
 	int rc, set_val, new_uV;
 	struct ncp6335d_info *dd = rdev_get_drvdata(rdev);
 
-	set_val = DIV_ROUND_UP(min_uV - NCP6335D_MIN_VOLTAGE_UV,
-					NCP6335D_STEP_VOLTAGE_UV);
-	new_uV = (set_val * NCP6335D_STEP_VOLTAGE_UV) +
-					NCP6335D_MIN_VOLTAGE_UV;
+	set_val = DIV_ROUND_UP(min_uV - dd->min_voltage, dd->step_size);
+	new_uV = (set_val * dd->step_size) + dd->min_voltage;
 	if (new_uV > max_uV) {
 		dev_err(dd->dev, "Unable to set volatge (%d %d)\n",
 							min_uV, max_uV);
@@ -159,6 +172,17 @@
 	return rc;
 }
 
+static int ncp6335d_list_voltage(struct regulator_dev *rdev,
+					unsigned selector)
+{
+	struct ncp6335d_info *dd = rdev_get_drvdata(rdev);
+
+	if (selector >= NCP6335D_VOLTAGE_STEPS)
+		return 0;
+
+	return selector * dd->step_size + dd->min_voltage;
+}
+
 static int ncp6335d_set_mode(struct regulator_dev *rdev,
 					unsigned int mode)
 {
@@ -213,6 +237,7 @@
 static struct regulator_ops ncp6335d_ops = {
 	.set_voltage = ncp6335d_set_voltage,
 	.get_voltage = ncp6335d_get_voltage,
+	.list_voltage = ncp6335d_list_voltage,
 	.enable = ncp6335d_enable,
 	.disable = ncp6335d_disable,
 	.set_mode = ncp6335d_set_mode,
@@ -222,11 +247,98 @@
 static struct regulator_desc rdesc = {
 	.name = "ncp6335d",
 	.owner = THIS_MODULE,
-	.n_voltages = 128,
+	.n_voltages = NCP6335D_VOLTAGE_STEPS,
 	.ops = &ncp6335d_ops,
 };
 
-static int __devinit ncp6335d_init(struct ncp6335d_info *dd,
+static int ncp6335d_restore_working_reg(struct device_node *node,
+					struct ncp6335d_info *dd)
+{
+	int ret;
+	unsigned int val;
+
+	/* Restore register from back up register */
+	ret = regmap_read(dd->regmap, dd->vsel_backup_reg, &val);
+	if (ret < 0) {
+		dev_err(dd->dev, "Failed to get backup data from reg %d, ret = %d\n",
+			dd->vsel_backup_reg, ret);
+		return ret;
+	}
+
+	ret = regmap_update_bits(dd->regmap, dd->vsel_reg,
+					NCP6335D_VOUT_SEL_MASK, val);
+	if (ret < 0) {
+		dev_err(dd->dev, "Failed to update working reg %d, ret = %d\n",
+			dd->vsel_reg,  ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int ncp6335d_parse_gpio(struct device_node *node,
+					struct ncp6335d_info *dd)
+{
+	int ret = 0, gpio;
+	enum of_gpio_flags flags;
+
+	if (!of_find_property(node, "onnn,vsel-gpio", NULL))
+		return ret;
+
+	/* Get GPIO connected to vsel and set its output */
+	gpio = of_get_named_gpio_flags(node,
+			"onnn,vsel-gpio", 0, &flags);
+	if (!gpio_is_valid(gpio)) {
+		if (gpio != -EPROBE_DEFER)
+			dev_err(dd->dev, "Could not get vsel, ret = %d\n",
+				gpio);
+		return gpio;
+	}
+
+	ret = devm_gpio_request(dd->dev, gpio, "ncp6335d_vsel");
+	if (ret) {
+		dev_err(dd->dev, "Failed to obtain gpio %d ret = %d\n",
+				gpio, ret);
+			return ret;
+	}
+
+	ret = gpio_direction_output(gpio, flags & OF_GPIO_ACTIVE_LOW ? 0 : 1);
+	if (ret) {
+		dev_err(dd->dev, "Failed to set GPIO %d to: %s, ret = %d",
+				gpio, flags & OF_GPIO_ACTIVE_LOW ?
+				"GPIO_LOW" : "GPIO_HIGH", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int ncp6335d_parse_tlmm(struct device_node *node,
+				struct ncp6335d_info *dd)
+{
+	int val, ret = 0;
+	u32 tmp[2];
+
+	if (!of_find_property(node, "onnn,tlmm-config", NULL))
+		return ret;
+
+	ret = of_property_read_u32_array(node, "onnn,tlmm-config", tmp, 2);
+	if (ret) {
+		dev_err(dd->dev, "onnn,tlmm-config is misconfigured, ret = %d",
+			ret);
+		return ret;
+	}
+
+	val = msm_tlmm_misc_reg_read(TLMM_SPARE_REG);
+	val &= ~tmp[0];
+	val |= tmp[1] & tmp[0];
+	msm_tlmm_misc_reg_write(TLMM_SPARE_REG, val);
+
+	return ret;
+}
+
+static int __devinit ncp6335d_init(struct i2c_client *client,
+			struct ncp6335d_info *dd,
 			const struct ncp6335d_platform_data *pdata)
 {
 	int rc;
@@ -235,10 +347,12 @@
 	switch (pdata->default_vsel) {
 	case NCP6335D_VSEL0:
 		dd->vsel_reg = REG_NCP6335D_PROGVSEL0;
+		dd->vsel_backup_reg = REG_NCP6335D_PROGVSEL1;
 		dd->mode_bit = NCP6335D_PWM_MODE0;
 	break;
 	case NCP6335D_VSEL1:
 		dd->vsel_reg = REG_NCP6335D_PROGVSEL1;
+		dd->vsel_backup_reg = REG_NCP6335D_PROGVSEL0;
 		dd->mode_bit = NCP6335D_PWM_MODE1;
 	break;
 	default:
@@ -246,6 +360,20 @@
 		return -EINVAL;
 	}
 
+	if (of_property_read_bool(client->dev.of_node, "onnn,restore-reg")) {
+		rc = ncp6335d_restore_working_reg(client->dev.of_node, dd);
+		if (rc)
+			return rc;
+	}
+
+	rc = ncp6335d_parse_gpio(client->dev.of_node, dd);
+	if (rc)
+		return rc;
+
+	rc = ncp6335d_parse_tlmm(client->dev.of_node, dd);
+	if (rc)
+		return rc;
+
 	/* get the current programmed voltage */
 	rc = regmap_read(dd->regmap, dd->vsel_reg, &val);
 	if (rc) {
@@ -253,7 +381,7 @@
 		return rc;
 	}
 	dd->curr_voltage = ((val & NCP6335D_VOUT_SEL_MASK) *
-			NCP6335D_STEP_VOLTAGE_UV) + NCP6335D_MIN_VOLTAGE_UV;
+				dd->step_size) + dd->min_voltage;
 
 	/* set discharge */
 	rc = regmap_update_bits(dd->regmap, REG_NCP6335D_PGOOD,
@@ -266,15 +394,15 @@
 	}
 
 	/* set slew rate */
-	if (pdata->slew_rate_ns < NCP6335D_MIN_SLEW_NS ||
-			pdata->slew_rate_ns > NCP6335D_MAX_SLEW_NS) {
+	if (pdata->slew_rate_ns < dd->min_slew_ns ||
+			pdata->slew_rate_ns > dd->max_slew_ns) {
 		dev_err(dd->dev, "Invalid slew rate %d\n", pdata->slew_rate_ns);
 		return -EINVAL;
 	}
-	val = DIV_ROUND_UP(pdata->slew_rate_ns - NCP6335D_MIN_SLEW_NS,
-						NCP6335D_MIN_SLEW_NS);
-	val >>= 1;
-	dd->slew_rate = val * NCP6335D_MIN_SLEW_NS;
+
+	dd->slew_rate = pdata->slew_rate_ns;
+	val = DIV_ROUND_UP(pdata->slew_rate_ns, dd->min_slew_ns);
+	val = ilog2(val);
 
 	rc = regmap_update_bits(dd->regmap, REG_NCP6335D_TIMING,
 			NCP6335D_SLEW_MASK, val << NCP6335D_SLEW_SHIFT);
@@ -301,6 +429,116 @@
 	.val_bits = 8,
 };
 
+static int ncp6335d_parse_dt(struct i2c_client *client,
+				struct ncp6335d_info *dd)
+{
+	int rc;
+
+	rc = of_property_read_u32(client->dev.of_node,
+			"onnn,step-size", &dd->step_size);
+	if (rc < 0) {
+		dev_err(&client->dev, "step size missing: rc = %d.\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32(client->dev.of_node,
+			"onnn,min-slew-ns", &dd->min_slew_ns);
+	if (rc < 0) {
+		dev_err(&client->dev, "min slew us missing: rc = %d.\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32(client->dev.of_node,
+			"onnn,max-slew-ns", &dd->max_slew_ns);
+	if (rc < 0) {
+		dev_err(&client->dev, "max slew us missing: rc = %d.\n", rc);
+		return rc;
+	}
+
+	rc = of_property_read_u32(client->dev.of_node,
+			"onnn,min-setpoint", &dd->min_voltage);
+	if (rc < 0) {
+		dev_err(&client->dev, "min set point missing: rc = %d.\n", rc);
+		return rc;
+	}
+
+	return rc;
+}
+
+static struct ncp6335d_platform_data *
+	ncp6335d_get_of_platform_data(struct i2c_client *client)
+{
+	struct ncp6335d_platform_data *pdata = NULL;
+	struct regulator_init_data *init_data;
+	const char *mode_name;
+	int rc;
+
+	init_data = of_get_regulator_init_data(&client->dev,
+				client->dev.of_node);
+	if (!init_data) {
+		dev_err(&client->dev, "regulator init data is missing\n");
+		return pdata;
+	}
+
+	pdata = devm_kzalloc(&client->dev,
+			sizeof(struct ncp6335d_platform_data), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(&client->dev, "ncp6335d_platform_data allocation failed.\n");
+		return pdata;
+	}
+
+	rc = of_property_read_u32(client->dev.of_node,
+			"onnn,vsel", &pdata->default_vsel);
+	if (rc < 0) {
+		dev_err(&client->dev, "onnn,vsel property missing: rc = %d.\n",
+			rc);
+		return NULL;
+	}
+
+	rc = of_property_read_u32(client->dev.of_node,
+			"onnn,slew-ns", &pdata->slew_rate_ns);
+	if (rc < 0) {
+		dev_err(&client->dev, "onnn,slew-ns property missing: rc = %d.\n",
+			rc);
+		return NULL;
+	}
+
+	pdata->discharge_enable = of_property_read_bool(client->dev.of_node,
+						"onnn,discharge-enable");
+
+	pdata->sleep_enable = of_property_read_bool(client->dev.of_node,
+						"onnn,sleep-enable");
+
+	pdata->init_data = init_data;
+
+	init_data->constraints.input_uV = init_data->constraints.max_uV;
+	init_data->constraints.valid_ops_mask =
+				REGULATOR_CHANGE_VOLTAGE |
+				REGULATOR_CHANGE_STATUS |
+				REGULATOR_CHANGE_MODE;
+	init_data->constraints.valid_modes_mask =
+				REGULATOR_MODE_NORMAL |
+				REGULATOR_MODE_FAST;
+
+	rc = of_property_read_string(client->dev.of_node, "onnn,mode",
+					&mode_name);
+	if (!rc) {
+		if (strcmp("pwm", mode_name) == 0) {
+			init_data->constraints.initial_mode =
+							REGULATOR_MODE_FAST;
+		} else if (strcmp("auto", mode_name) == 0) {
+			init_data->constraints.initial_mode =
+							REGULATOR_MODE_NORMAL;
+		} else {
+			dev_err(&client->dev, "onnn,mode, unknown regulator mode: %s\n",
+				mode_name);
+			return NULL;
+		}
+	}
+
+	return pdata;
+}
+
 static int __devinit ncp6335d_regulator_probe(struct i2c_client *client,
 					const struct i2c_device_id *id)
 {
@@ -309,7 +547,11 @@
 	struct ncp6335d_info *dd;
 	const struct ncp6335d_platform_data *pdata;
 
-	pdata = client->dev.platform_data;
+	if (client->dev.of_node)
+		pdata = ncp6335d_get_of_platform_data(client);
+	else
+		pdata = client->dev.platform_data;
+
 	if (!pdata) {
 		dev_err(&client->dev, "Platform data not specified\n");
 		return -EINVAL;
@@ -321,6 +563,17 @@
 		return -ENOMEM;
 	}
 
+	if (client->dev.of_node) {
+		rc = ncp6335d_parse_dt(client, dd);
+		if (rc)
+			return rc;
+	} else {
+		dd->step_size	= NCP6335D_STEP_VOLTAGE_UV;
+		dd->min_voltage	= NCP6335D_MIN_VOLTAGE_UV;
+		dd->min_slew_ns	= NCP6335D_MIN_SLEW_NS;
+		dd->max_slew_ns	= NCP6335D_MAX_SLEW_NS;
+	}
+
 	dd->regmap = devm_regmap_init_i2c(client, &ncp6335d_regmap_config);
 	if (IS_ERR(dd->regmap)) {
 		dev_err(&client->dev, "Error allocating regmap\n");
@@ -339,17 +592,19 @@
 	dd->dev = &client->dev;
 	i2c_set_clientdata(client, dd);
 
-	rc = ncp6335d_init(dd, pdata);
+	rc = ncp6335d_init(client, dd, pdata);
 	if (rc) {
 		dev_err(&client->dev, "Unable to intialize the regulator\n");
 		return -EINVAL;
 	}
 
-	dd->regulator = regulator_register(&rdesc, &client->dev,
-					dd->init_data, dd, NULL);
+	dd->regulator = regulator_register(&rdesc, &client->dev, dd->init_data,
+						dd, client->dev.of_node);
+
 	if (IS_ERR(dd->regulator)) {
 		dev_err(&client->dev, "Unable to register regulator rc(%ld)",
 						PTR_ERR(dd->regulator));
+
 		return PTR_ERR(dd->regulator);
 	}
 
@@ -365,6 +620,12 @@
 	return 0;
 }
 
+static struct of_device_id ncp6335d_match_table[] = {
+	{ .compatible = "onnn,ncp6335d-regulator", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, ncp6335d_match_table);
+
 static const struct i2c_device_id ncp6335d_id[] = {
 	{"ncp6335d", -1},
 	{ },
@@ -373,15 +634,32 @@
 static struct i2c_driver ncp6335d_regulator_driver = {
 	.driver = {
 		.name = "ncp6335d-regulator",
+		.owner = THIS_MODULE,
+		.of_match_table = ncp6335d_match_table,
 	},
 	.probe = ncp6335d_regulator_probe,
 	.remove = __devexit_p(ncp6335d_regulator_remove),
 	.id_table = ncp6335d_id,
 };
-static int __init ncp6335d_regulator_init(void)
+
+/**
+ * ncp6335d_regulator_init() - initialized ncp6335d regulator driver
+ * This function registers the ncp6335d regulator platform driver.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int __init ncp6335d_regulator_init(void)
 {
+	static bool initialized;
+
+	if (initialized)
+		return 0;
+	else
+		initialized = true;
+
 	return i2c_add_driver(&ncp6335d_regulator_driver);
 }
+EXPORT_SYMBOL(ncp6335d_regulator_init);
 subsys_initcall(ncp6335d_regulator_init);
 
 static void __exit ncp6335d_regulator_exit(void)
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
index 7d59e28..51e176f 100644
--- a/drivers/rtc/alarm.c
+++ b/drivers/rtc/alarm.c
@@ -553,8 +553,8 @@
 	return;
 
 disable_alarm:
-	rtc_alarm_irq_enable(alarm_rtc_dev, 0);
 	spin_unlock_irqrestore(&alarm_slock, flags);
+	rtc_alarm_irq_enable(alarm_rtc_dev, 0);
 }
 
 static struct rtc_task alarm_rtc_task = {
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 01b0374..c29d98b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -925,6 +925,10 @@
 
 	transport_configure_device(&sdev->sdev_gendev);
 
+	/* The LLD can override auto suspend tunables in ->slave_configure() */
+	sdev->use_rpm_auto = 0;
+	sdev->autosuspend_delay = SCSI_DEFAULT_AUTOSUSPEND_DELAY;
+
 	if (sdev->host->hostt->slave_configure) {
 		ret = sdev->host->hostt->slave_configure(sdev);
 		if (ret) {
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 04c2a27..89a1af1 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -885,7 +885,8 @@
 	device_enable_async_suspend(&sdev->sdev_gendev);
 	scsi_autopm_get_target(starget);
 	pm_runtime_set_active(&sdev->sdev_gendev);
-	pm_runtime_forbid(&sdev->sdev_gendev);
+	if (!sdev->use_rpm_auto)
+		pm_runtime_forbid(&sdev->sdev_gendev);
 	pm_runtime_enable(&sdev->sdev_gendev);
 	scsi_autopm_put_target(starget);
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index f454610..2b09d59 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2612,6 +2612,10 @@
 		gd->events |= DISK_EVENT_MEDIA_CHANGE;
 	}
 
+	blk_pm_runtime_init(sdp->request_queue, dev);
+	if (sdp->autosuspend_delay >= 0)
+		pm_runtime_set_autosuspend_delay(dev, sdp->autosuspend_delay);
+
 	add_disk(gd);
 	sd_dif_config_host(sdkp);
 
@@ -2619,7 +2623,6 @@
 
 	sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n",
 		  sdp->removable ? "removable " : "");
-	blk_pm_runtime_init(sdp->request_queue, dev);
 	scsi_autopm_put_device(sdp);
 	put_device(&sdkp->dev);
 }
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index b743bd6..48959ab 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1773,6 +1773,12 @@
 
 	*hba_handle = hba;
 
+	/*
+	 * The device-initialize-sequence hasn't been invoked yet.
+	 * Set the device to power-off state
+	 */
+	ufshcd_set_ufs_dev_poweroff(hba);
+
 	async_schedule(ufshcd_async_scan, hba);
 
 	return 0;
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 67cf049..e65c8cf 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -268,8 +268,28 @@
 			 * Messages related to data channel management can't
 			 * wait since they are holding reconfiguration lock.
 			 * clk_pause in resume (which can change state back to
-			 * MSM_CTRL_AWAKE), will need that lock
+			 * MSM_CTRL_AWAKE), will need that lock.
+			 * Port disconnection, channel removal calls should pass
+			 * through since there is no activity on the bus and
+			 * those calls are triggered by clients due to
+			 * device_down callback in that situation.
+			 * Returning 0 on the disconnections and
+			 * removals will ensure consistent state of channels,
+			 * ports with the HW
+			 * Remote requests to remove channel/port will be
+			 * returned from the path where they wait on
+			 * acknowledgement from ADSP
 			 */
+			if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
+				((mc == SLIM_USR_MC_CHAN_CTRL ||
+				mc == SLIM_USR_MC_DISCONNECT_PORT ||
+				mc == SLIM_USR_MC_RECONFIG_NOW)))
+				return -EREMOTEIO;
+			if ((txn->mt == SLIM_MSG_MT_CORE) &&
+				((mc == SLIM_MSG_MC_DISCONNECT_PORT ||
+				mc == SLIM_MSG_MC_NEXT_REMOVE_CHANNEL ||
+				mc == SLIM_USR_MC_RECONFIG_NOW)))
+				return 0;
 			if ((txn->mt == SLIM_MSG_MT_CORE) &&
 				((mc >= SLIM_MSG_MC_CONNECT_SOURCE &&
 				mc <= SLIM_MSG_MC_CHANGE_CONTENT) ||
@@ -278,11 +298,11 @@
 				return -EREMOTEIO;
 			if ((txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER) &&
 				((mc >= SLIM_USR_MC_DEFINE_CHAN &&
-				mc <= SLIM_USR_MC_DISCONNECT_PORT)))
+				mc < SLIM_USR_MC_DISCONNECT_PORT)))
 				return -EREMOTEIO;
 			timeout = wait_for_completion_timeout(&dev->ctrl_up,
 							HZ);
-			if (!timeout)
+			if (!timeout && dev->state == MSM_CTRL_DOWN)
 				return -ETIMEDOUT;
 		}
 		msm_slim_get_ctrl(dev);
@@ -487,10 +507,17 @@
 			ret = -ETIMEDOUT;
 		else
 			ret = txn->ec;
+	} else if (ret == -EREMOTEIO &&
+			(txn->mc == SLIM_USR_MC_CHAN_CTRL ||
+			 txn->mc == SLIM_USR_MC_DISCONNECT_PORT)) {
+		/* HW restarting, channel/port removal should succeed */
+		return 0;
 	}
+
 	if (ret) {
 		pr_err("master msg:0x%x,tid:%d ret:%d", txn->mc,
 				txn->tid, ret);
+		WARN(1, "timeout during xfer and wait");
 		mutex_lock(&ctrl->m_ctrl);
 		ctrl->txnt[txn->tid] = NULL;
 		mutex_unlock(&ctrl->m_ctrl);
@@ -973,6 +1000,7 @@
 	struct slim_controller *ctrl = &dev->ctrl;
 	struct slim_device *sbdev;
 	int i;
+	slim_framer_booted(ctrl);
 	mutex_lock(&ctrl->m_ctrl);
 	list_for_each_entry(sbdev, &ctrl->devs, dev_list) {
 		int ret = 0;
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index b074289..96fe2a8 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -313,14 +313,12 @@
 			sbdrv->device_down(sbdev);
 		return;
 	}
-	if (sbdev->notified)
+	if (sbdev->notified || !sbdrv)
 		return;
 	ret = slim_get_logical_addr(sbdev, sbdev->e_addr, 6, &laddr);
 	if (!ret) {
-		if (sbdrv)
-			sbdev->notified = true;
-		if (sbdrv->device_up)
-			sbdrv->device_up(sbdev);
+		sbdev->notified = true;
+		sbdrv->device_up(sbdev);
 	}
 }
 
@@ -650,6 +648,36 @@
 EXPORT_SYMBOL(slim_report_absent);
 
 /*
+ * slim_framer_booted: This function is called by controller after the active
+ * framer has booted (using Bus Reset sequence, or after it has shutdown and has
+ * come back up). Components, devices on the bus may be in undefined state,
+ * and this function triggers their drivers to do the needful
+ * to bring them back in Reset state so that they can acquire sync, report
+ * present and be operational again.
+ */
+void slim_framer_booted(struct slim_controller *ctrl)
+{
+	struct slim_device *sbdev;
+	struct list_head *pos, *next;
+	if (!ctrl)
+		return;
+	mutex_lock(&ctrl->m_ctrl);
+	list_for_each_safe(pos, next, &ctrl->devs) {
+		struct slim_driver *sbdrv;
+		sbdev = list_entry(pos, struct slim_device, dev_list);
+		mutex_unlock(&ctrl->m_ctrl);
+		if (sbdev && sbdev->dev.driver) {
+			sbdrv = to_slim_driver(sbdev->dev.driver);
+			if (sbdrv->reset_device)
+				sbdrv->reset_device(sbdev);
+		}
+		mutex_lock(&ctrl->m_ctrl);
+	}
+	mutex_unlock(&ctrl->m_ctrl);
+}
+EXPORT_SYMBOL(slim_framer_booted);
+
+/*
  * slim_msg_response: Deliver Message response received from a device to the
  *	framework.
  * @ctrl: Controller handle
diff --git a/drivers/spmi/spmi-dbgfs.c b/drivers/spmi/spmi-dbgfs.c
index 27df09333..b0a354b 100644
--- a/drivers/spmi/spmi-dbgfs.c
+++ b/drivers/spmi/spmi-dbgfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -48,9 +48,9 @@
 
 /* Log buffer */
 struct spmi_log_buffer {
-	u32  rpos;	/* Current 'read' position in buffer */
-	u32  wpos;	/* Current 'write' position in buffer */
-	u32  len;	/* Length of the buffer */
+	size_t rpos;	/* Current 'read' position in buffer */
+	size_t wpos;	/* Current 'write' position in buffer */
+	size_t len;	/* Length of the buffer */
 	char data[0];	/* Log buffer */
 };
 
@@ -583,10 +583,10 @@
 
 	pr_debug("Creating SPMI debugfs file-system\n");
 	root = debugfs_create_dir(DFS_ROOT_NAME, NULL);
-	if (IS_ERR(root)) {
+	if (IS_ERR_OR_NULL(root)) {
 		pr_err("Error creating top level directory err:%ld",
 			(long)root);
-		if ((int)root == -ENODEV)
+		if (PTR_ERR(root) == -ENODEV)
 			pr_err("debugfs is not enabled in the kernel");
 		return NULL;
 	}
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index bc328e0..e3284d5 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -223,7 +223,9 @@
 	if (opc < SPMI_CMD_RESET || opc > SPMI_CMD_WAKEUP)
 		return -EINVAL;
 
-	cmd = ((opc | 0x40) << 27) | ((sid & 0xf) << 20);
+	opc -= SPMI_CMD_RESET - PMIC_ARB_OP_RESET;
+
+	cmd = (opc << 27) | ((sid & 0xf) << 20);
 
 	spin_lock_irqsave(&pmic_arb->lock, flags);
 	pmic_arb_write(pmic_arb, PMIC_ARB_CMD(pmic_arb->channel), cmd);
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 348ed3e..43f2710 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -809,8 +809,8 @@
 	if (ret)
 		goto exit;
 
-	dev_dbg(&ctrl->dev, "Bus spmi-%d registered: dev:%x\n",
-					ctrl->nr, (u32)&ctrl->dev);
+	dev_dbg(&ctrl->dev, "Bus spmi-%d registered: dev:0x%p\n",
+					ctrl->nr, &ctrl->dev);
 
 	spmi_dfs_add_controller(ctrl);
 	return 0;
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 42a5a71..7ca247a 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -224,21 +224,29 @@
 
 	/* If size is not set, or set to 0, always return EOF. */
 	if (asma->size == 0)
-		goto out;
+		goto out_unlock;
 
 	if (!asma->file) {
 		ret = -EBADF;
-		goto out;
+		goto out_unlock;
 	}
 
+	mutex_unlock(&ashmem_mutex);
+
+	/*
+	 * asma and asma->file are used outside the lock here.  We assume
+	 * once asma->file is set it will never be changed, and will not
+	 * be destroyed until all references to the file are dropped and
+	 * ashmem_release is called.
+	 */
 	ret = asma->file->f_op->read(asma->file, buf, len, pos);
-	if (ret < 0)
-		goto out;
+	if (ret >= 0) {
+		/** Update backing file pos, since f_ops->read() doesn't */
+		asma->file->f_pos = *pos;
+	}
+	return ret;
 
-	/** Update backing file pos, since f_ops->read() doesn't */
-	asma->file->f_pos = *pos;
-
-out:
+out_unlock:
 	mutex_unlock(&ashmem_mutex);
 	return ret;
 }
@@ -406,50 +414,68 @@
 
 static int set_name(struct ashmem_area *asma, void __user *name)
 {
+	int len;
 	int ret = 0;
+	char local_name[ASHMEM_NAME_LEN];
 
+	/*
+	 * Holding the ashmem_mutex while doing a copy_from_user might cause
+	 * an data abort which would try to access mmap_sem. If another
+	 * thread has invoked ashmem_mmap then it will be holding the
+	 * semaphore and will be waiting for ashmem_mutex, there by leading to
+	 * deadlock. We'll release the mutex  and take the name to a local
+	 * variable that does not need protection and later copy the local
+	 * variable to the structure member with lock held.
+	 */
+	len = strncpy_from_user(local_name, name, ASHMEM_NAME_LEN);
+	if (len < 0)
+		return len;
+	if (len == ASHMEM_NAME_LEN)
+		local_name[ASHMEM_NAME_LEN - 1] = '\0';
 	mutex_lock(&ashmem_mutex);
-
 	/* cannot change an existing mapping's name */
-	if (unlikely(asma->file)) {
+	if (unlikely(asma->file))
 		ret = -EINVAL;
-		goto out;
-	}
+	else
+		strcpy(asma->name + ASHMEM_NAME_PREFIX_LEN, local_name);
 
-	if (unlikely(copy_from_user(asma->name + ASHMEM_NAME_PREFIX_LEN,
-				    name, ASHMEM_NAME_LEN)))
-		ret = -EFAULT;
-	asma->name[ASHMEM_FULL_NAME_LEN-1] = '\0';
-
-out:
 	mutex_unlock(&ashmem_mutex);
-
 	return ret;
 }
 
 static int get_name(struct ashmem_area *asma, void __user *name)
 {
 	int ret = 0;
+	size_t len;
+	/*
+	 * Have a local variable to which we'll copy the content
+	 * from asma with the lock held. Later we can copy this to the user
+	 * space safely without holding any locks. So even if we proceed to
+	 * wait for mmap_sem, it won't lead to deadlock.
+	 */
+	char local_name[ASHMEM_NAME_LEN];
 
 	mutex_lock(&ashmem_mutex);
 	if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') {
-		size_t len;
 
 		/*
 		 * Copying only `len', instead of ASHMEM_NAME_LEN, bytes
 		 * prevents us from revealing one user's stack to another.
 		 */
 		len = strlen(asma->name + ASHMEM_NAME_PREFIX_LEN) + 1;
-		if (unlikely(copy_to_user(name,
-				asma->name + ASHMEM_NAME_PREFIX_LEN, len)))
-			ret = -EFAULT;
+		memcpy(local_name, asma->name + ASHMEM_NAME_PREFIX_LEN, len);
 	} else {
-		if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
-					  sizeof(ASHMEM_NAME_DEF))))
-			ret = -EFAULT;
+		len = sizeof(ASHMEM_NAME_DEF);
+		memcpy(local_name, ASHMEM_NAME_DEF, len);
 	}
 	mutex_unlock(&ashmem_mutex);
 
+	/*
+	 * Now we are just copying from the stack variable to userland
+	 * No lock held
+	 */
+	if (unlikely(copy_to_user(name, local_name, len)))
+		ret = -EFAULT;
 	return ret;
 }
 
diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c
index c366086..891eb2f 100644
--- a/drivers/thermal/msm_thermal.c
+++ b/drivers/thermal/msm_thermal.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -156,7 +156,7 @@
 
 #define VDD_RES_RO_ATTRIB(_rail, ko_attr, j, _name) \
 	ko_attr.attr.name = __stringify(_name); \
-	ko_attr.attr.mode = 444; \
+	ko_attr.attr.mode = 0444; \
 	ko_attr.show = vdd_rstr_reg_##_name##_show; \
 	ko_attr.store = NULL; \
 	sysfs_attr_init(&ko_attr.attr); \
@@ -164,7 +164,7 @@
 
 #define VDD_RES_RW_ATTRIB(_rail, ko_attr, j, _name) \
 	ko_attr.attr.name = __stringify(_name); \
-	ko_attr.attr.mode = 644; \
+	ko_attr.attr.mode = 0644; \
 	ko_attr.show = vdd_rstr_reg_##_name##_show; \
 	ko_attr.store = vdd_rstr_reg_##_name##_store; \
 	sysfs_attr_init(&ko_attr.attr); \
@@ -181,7 +181,7 @@
 
 #define OCR_RW_ATTRIB(_rail, ko_attr, j, _name) \
 	ko_attr.attr.name = __stringify(_name); \
-	ko_attr.attr.mode = 644; \
+	ko_attr.attr.mode = 0644; \
 	ko_attr.show = ocr_reg_##_name##_show; \
 	ko_attr.store = ocr_reg_##_name##_store; \
 	sysfs_attr_init(&ko_attr.attr); \
@@ -189,7 +189,7 @@
 
 #define PSM_RW_ATTRIB(_rail, ko_attr, j, _name) \
 	ko_attr.attr.name = __stringify(_name); \
-	ko_attr.attr.mode = 644; \
+	ko_attr.attr.mode = 0644; \
 	ko_attr.show = psm_reg_##_name##_show; \
 	ko_attr.store = psm_reg_##_name##_store; \
 	sysfs_attr_init(&ko_attr.attr); \
@@ -425,7 +425,7 @@
 
 static struct vdd_rstr_enable vdd_rstr_en = {
 	.ko_attr.attr.name = __stringify(enabled),
-	.ko_attr.attr.mode = 644,
+	.ko_attr.attr.mode = 0644,
 	.ko_attr.show = vdd_rstr_en_show,
 	.ko_attr.store = vdd_rstr_en_store,
 	.enabled = 1,
@@ -2426,8 +2426,8 @@
 
 	key = "qcom,cpu-sensors";
 	cpu_cnt = of_property_count_strings(node, key);
-	if (cpu_cnt != num_possible_cpus()) {
-		pr_err("%s: Wrong number of cpu\n", KBUILD_MODNAME);
+	if (cpu_cnt < num_possible_cpus()) {
+		pr_err("%s: Wrong number of cpu sensors\n", KBUILD_MODNAME);
 		ret = -EINVAL;
 		goto hotplug_node_fail;
 	}
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 739696d..21863e8 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -70,16 +70,19 @@
 
 	list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
 		if (pos->sensor_id == sensor_id)
-			break;
+			return pos;
 	}
 
-	return pos;
+	return NULL;
 }
 
 int sensor_get_id(char *name)
 {
 	struct sensor_info *pos, *var;
 
+	if (!name)
+		return -ENODEV;
+
 	list_for_each_entry_safe(pos, var, &sensor_info_list, sensor_list) {
 		if (!strcmp(pos->tz->type, name))
 			return pos->sensor_id;
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index ecfacc0..066419f 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -551,6 +551,25 @@
 	writel_relaxed(value, uport->membase + offset);
 }
 
+static int sps_rx_disconnect(struct sps_pipe *sps_pipe_handler)
+{
+	struct sps_connect config;
+	int ret;
+
+	ret = sps_get_config(sps_pipe_handler, &config);
+	if (ret) {
+		pr_err("%s: sps_get_config() failed ret %d\n", __func__, ret);
+		return ret;
+	}
+	config.options |= SPS_O_POLL;
+	ret = sps_set_config(sps_pipe_handler, &config);
+	if (ret) {
+		pr_err("%s: sps_set_config() failed ret %d\n", __func__, ret);
+		return ret;
+	}
+	return sps_disconnect(sps_pipe_handler);
+}
+
 static void hex_dump_ipc(char *prefix, char *string, int size)
 {
 	char linebuf[512];
@@ -1191,7 +1210,7 @@
 				ret = wait_event_timeout(msm_uport->rx.wait,
 					msm_uport->rx_bam_inprogress == false,
 					RX_FLUSH_COMPLETE_TIMEOUT);
-			ret = sps_disconnect(sps_pipe_handle);
+			ret = sps_rx_disconnect(sps_pipe_handle);
 			if (ret)
 				MSM_HS_ERR("%s(): sps_disconnect failed\n",
 							__func__);
@@ -1275,7 +1294,7 @@
 	struct sps_pipe *sps_pipe_handle = rx->prod.pipe_handle;
 	int ret = 0;
 
-	ret = sps_disconnect(sps_pipe_handle);
+	ret = sps_rx_disconnect(sps_pipe_handle);
 	if (ret)
 		MSM_HS_ERR("%s(): sps_disconnect failed\n", __func__);
 
@@ -2529,6 +2548,8 @@
 	/* Initialize the tx */
 	tx->tx_ready_int_en = 0;
 	tx->dma_in_flight = 0;
+	msm_uport->tty_flush_receive = false;
+	MSM_HS_DBG("%s: Setting tty_flush_receive to false\n", __func__);
 
 	if (!is_blsp_uart(msm_uport)) {
 		tx->xfer.complete_func = msm_hs_dmov_tx_callback;
diff --git a/drivers/usb/class/Kconfig b/drivers/usb/class/Kconfig
index 2519e32..f7321e5 100644
--- a/drivers/usb/class/Kconfig
+++ b/drivers/usb/class/Kconfig
@@ -50,3 +50,15 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called usbtmc.
+
+config USB_CCID_BRIDGE
+	tristate "USB  Smart Card Class (CCID) support"
+	help
+	  Say Y here if you want to connect a USB Smart Card device that
+	  follows the USB.org specification for Integrated Circuit(s) Cards
+	  Interface Devices to your computer's USB port.  This module
+	  provides a character device interface to exchange the messages.
+	  Ioctls facilitate control transfers and interrupt transfers.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ccid_bridge.
diff --git a/drivers/usb/class/Makefile b/drivers/usb/class/Makefile
index 32e8527..c2ee6f3 100644
--- a/drivers/usb/class/Makefile
+++ b/drivers/usb/class/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_USB_PRINTER)	+= usblp.o
 obj-$(CONFIG_USB_WDM)		+= cdc-wdm.o
 obj-$(CONFIG_USB_TMC)		+= usbtmc.o
+obj-$(CONFIG_USB_CCID_BRIDGE)	+= ccid_bridge.o
diff --git a/drivers/usb/class/ccid_bridge.c b/drivers/usb/class/ccid_bridge.c
new file mode 100644
index 0000000..a3e100a
--- /dev/null
+++ b/drivers/usb/class/ccid_bridge.c
@@ -0,0 +1,885 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <linux/cdev.h>
+
+#include <linux/usb/ccid_bridge.h>
+
+#define CCID_CLASS_DECRIPTOR_TYPE 0x21
+#define CCID_NOTIFY_SLOT_CHANGE	0x50
+#define CCID_NOTIFY_HARDWARE_ERROR 0x51
+#define CCID_ABORT_REQ 0x1
+#define CCID_GET_CLK_FREQ_REQ 0x2
+#define CCID_GET_DATA_RATES 0x3
+
+#define CCID_BRIDGE_MSG_SZ 512
+#define CCID_BRIDGE_OPEN_TIMEOUT 500 /* msec */
+#define CCID_CONTROL_TIMEOUT 500 /* msec */
+#define CCID_BRIDGE_MSG_TIMEOUT 500 /* msec */
+
+struct ccid_bridge {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	unsigned int in_pipe;
+	unsigned int out_pipe;
+	unsigned int int_pipe;
+	struct urb *inturb;
+	struct urb *readurb;
+	struct urb *writeurb;
+
+	bool opened;
+	bool events_supported;
+	bool is_suspended;
+	struct mutex open_mutex;
+	struct mutex write_mutex;
+	struct mutex read_mutex;
+	struct mutex event_mutex;
+	int write_result;
+	int read_result;
+	int event_result;
+	wait_queue_head_t open_wq;
+	wait_queue_head_t write_wq;
+	wait_queue_head_t read_wq;
+	wait_queue_head_t event_wq;
+	struct usb_ccid_event cur_event;
+	void *intbuf;
+
+	dev_t chrdev;
+	struct cdev cdev;
+	struct class *class;
+	struct device *device;
+};
+
+static struct ccid_bridge *__ccid_bridge_dev;
+
+static void ccid_bridge_out_cb(struct urb *urb)
+{
+	struct ccid_bridge *ccid = urb->context;
+
+	if (urb->dev->state == USB_STATE_NOTATTACHED)
+		ccid->write_result = -ENODEV;
+	else
+		ccid->write_result = urb->status ? : urb->actual_length;
+
+	pr_debug("write result = %d", ccid->write_result);
+	wake_up(&ccid->write_wq);
+}
+
+static void ccid_bridge_in_cb(struct urb *urb)
+{
+	struct ccid_bridge *ccid = urb->context;
+
+	if (urb->dev->state == USB_STATE_NOTATTACHED)
+		ccid->read_result = -ENODEV;
+	else
+		ccid->read_result = urb->status ? : urb->actual_length;
+
+	pr_debug("read result = %d", ccid->read_result);
+	wake_up(&ccid->read_wq);
+}
+
+static void ccid_bridge_int_cb(struct urb *urb)
+{
+	struct ccid_bridge *ccid = urb->context;
+	u8 *msg_type;
+	bool wakeup = true;
+
+	if (urb->dev->state == USB_STATE_NOTATTACHED || (urb->status &&
+				urb->status != -ENOENT)) {
+		ccid->event_result = -ENODEV;
+		wakeup = true;
+		goto out;
+	}
+
+	/*
+	 * Don't wakeup the event ioctl process during suspend.
+	 * The suspend state is not visible to user space.
+	 * we wake up the process after resume to send RESUME
+	 * event if the device supports remote wakeup.
+	 */
+	if (urb->status == -ENOENT && !urb->actual_length) {
+		ccid->event_result = -ENOENT;
+		wakeup = false;
+		goto out;
+	}
+
+	ccid->event_result = 0;
+	msg_type = urb->transfer_buffer;
+	switch (*msg_type) {
+	case CCID_NOTIFY_SLOT_CHANGE:
+		pr_debug("NOTIFY_SLOT_CHANGE event arrived");
+		ccid->cur_event.event = USB_CCID_NOTIFY_SLOT_CHANGE_EVENT;
+		ccid->cur_event.u.notify.slot_icc_state = *(++msg_type);
+		break;
+	case CCID_NOTIFY_HARDWARE_ERROR:
+		pr_debug("NOTIFY_HARDWARE_ERROR event arrived");
+		ccid->cur_event.event = USB_CCID_HARDWARE_ERROR_EVENT;
+		ccid->cur_event.u.error.slot = *(++msg_type);
+		ccid->cur_event.u.error.seq = *(++msg_type);
+		ccid->cur_event.u.error.error_code = *(++msg_type);
+		break;
+	default:
+		pr_err("UNKNOWN event arrived\n");
+		ccid->event_result = -EINVAL;
+	}
+
+out:
+	pr_debug("returning %d", ccid->event_result);
+	if (wakeup)
+		wake_up(&ccid->event_wq);
+}
+
+static int ccid_bridge_submit_inturb(struct ccid_bridge *ccid)
+{
+	int ret = 0;
+
+	/*
+	 * Don't resume the bus to submit an interrupt URB.
+	 * We submit the URB in resume path.  This is important.
+	 * Because the device will be in suspend state during
+	 * multiple system suspend/resume cycles.  The user space
+	 * process comes here during system resume after it is
+	 * unfrozen.
+	 */
+	if (!ccid->int_pipe || ccid->is_suspended)
+		goto out;
+
+	ret = usb_autopm_get_interface(ccid->intf);
+	if (ret < 0) {
+		pr_debug("fail to get autopm with %d\n", ret);
+		goto out;
+	}
+	ret = usb_submit_urb(ccid->inturb, GFP_KERNEL);
+	if (ret < 0)
+		pr_err("fail to submit int urb with %d\n", ret);
+	usb_autopm_put_interface(ccid->intf);
+
+out:
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_get_event(struct ccid_bridge *ccid)
+{
+	int ret = 0;
+
+	/*
+	 * The first event returned after the device resume
+	 * will be RESUME event.  This event is set by
+	 * the resume.
+	 */
+	if (ccid->cur_event.event)
+		goto out;
+
+	ccid->event_result = -EINPROGRESS;
+
+	ret = ccid_bridge_submit_inturb(ccid);
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * Wait for the notification on interrupt endpoint
+	 * or remote wakeup event from the resume.  The
+	 * int urb completion handler and resume callback
+	 * take care of setting the current event.
+	 */
+	mutex_unlock(&ccid->event_mutex);
+	ret = wait_event_interruptible(ccid->event_wq,
+			(ccid->event_result != -EINPROGRESS));
+	mutex_lock(&ccid->event_mutex);
+
+	if (ret == -ERESTARTSYS) /* interrupted */
+		usb_kill_urb(ccid->inturb);
+	else
+		ret = ccid->event_result;
+out:
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_open(struct inode *ip, struct file *fp)
+{
+	struct ccid_bridge *ccid = container_of(ip->i_cdev,
+				struct ccid_bridge, cdev);
+	int ret;
+
+	pr_debug("called");
+
+	mutex_lock(&ccid->open_mutex);
+	if (ccid->opened) {
+		ret = -EBUSY;
+		goto out;
+	}
+	mutex_unlock(&ccid->open_mutex);
+
+	ret = wait_event_interruptible_timeout(ccid->open_wq,
+			ccid->intf != NULL, msecs_to_jiffies(
+				CCID_BRIDGE_OPEN_TIMEOUT));
+
+	mutex_lock(&ccid->open_mutex);
+
+	if (ret != -ERESTARTSYS && ccid->intf) {
+		fp->private_data = ccid;
+		ccid->opened = true;
+		ret = 0;
+	} else if (!ret) { /* timed out */
+		ret = -ENODEV;
+	}
+out:
+	mutex_unlock(&ccid->open_mutex);
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static ssize_t ccid_bridge_write(struct file *fp, const char __user *ubuf,
+				 size_t count, loff_t *pos)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+	int ret;
+	char *kbuf;
+
+	pr_debug("called with %d", count);
+
+	if (!ccid->intf) {
+		pr_debug("intf is not active");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ccid->write_mutex);
+
+	if (!count || count > CCID_BRIDGE_MSG_SZ) {
+		pr_err("invalid count");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if (!kbuf) {
+		pr_err("fail to allocate memory");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = copy_from_user(kbuf, ubuf, count);
+	if (ret) {
+		pr_err("fail to copy user buf");
+		ret = -EFAULT;
+		goto free_kbuf;
+	}
+
+	ret = usb_autopm_get_interface(ccid->intf);
+	if (ret) {
+		pr_err("fail to get autopm with %d", ret);
+		goto free_kbuf;
+	}
+
+	ccid->write_result = 0;
+
+	usb_fill_bulk_urb(ccid->writeurb, ccid->udev, ccid->out_pipe,
+			kbuf, count, ccid_bridge_out_cb, ccid);
+	ret = usb_submit_urb(ccid->writeurb, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("urb submit fail with %d", ret);
+		goto put_pm;
+	}
+
+	ret = wait_event_interruptible_timeout(ccid->write_wq,
+			ccid->write_result != 0,
+			msecs_to_jiffies(CCID_BRIDGE_MSG_TIMEOUT));
+	if (!ret || ret == -ERESTARTSYS) { /* timedout or interrupted */
+		usb_kill_urb(ccid->writeurb);
+		if (!ret)
+			ret = -ETIMEDOUT;
+	} else {
+		ret = ccid->write_result;
+	}
+
+	pr_debug("returning %d", ret);
+
+put_pm:
+	if (ret != -ENODEV)
+		usb_autopm_put_interface(ccid->intf);
+free_kbuf:
+	kfree(kbuf);
+out:
+	mutex_unlock(&ccid->write_mutex);
+	return ret;
+
+}
+
+static ssize_t ccid_bridge_read(struct file *fp, char __user *ubuf,
+				 size_t count, loff_t *pos)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+	int ret;
+	char *kbuf;
+
+	pr_debug("called with %d", count);
+	if (!ccid->intf) {
+		pr_debug("intf is not active");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ccid->read_mutex);
+
+	if (!count || count > CCID_BRIDGE_MSG_SZ) {
+		pr_err("invalid count");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	kbuf = kmalloc(count, GFP_KERNEL);
+	if (!kbuf) {
+		pr_err("fail to allocate memory");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = usb_autopm_get_interface(ccid->intf);
+	if (ret) {
+		pr_err("fail to get autopm with %d", ret);
+		goto free_kbuf;
+	}
+
+	ccid->read_result = 0;
+
+	usb_fill_bulk_urb(ccid->readurb, ccid->udev, ccid->in_pipe,
+			kbuf, count, ccid_bridge_in_cb, ccid);
+	ret = usb_submit_urb(ccid->readurb, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("urb submit fail with %d", ret);
+		if (ret != -ENODEV)
+			usb_autopm_put_interface(ccid->intf);
+		goto free_kbuf;
+	}
+
+
+	ret = wait_event_interruptible_timeout(ccid->read_wq,
+			ccid->read_result != 0,
+			msecs_to_jiffies(CCID_BRIDGE_MSG_TIMEOUT));
+	if (!ret || ret == -ERESTARTSYS) { /* timedout or interrupted */
+		usb_kill_urb(ccid->readurb);
+		if (!ret)
+			ret = -ETIMEDOUT;
+	} else {
+		ret = ccid->read_result;
+	}
+
+
+	if (ret > 0) {
+		if (copy_to_user(ubuf, kbuf, ret))
+			ret = -EFAULT;
+	}
+
+	usb_autopm_put_interface(ccid->intf);
+	pr_debug("returning %d", ret);
+
+free_kbuf:
+	kfree(kbuf);
+out:
+	mutex_unlock(&ccid->read_mutex);
+	return ret;
+}
+
+static long
+ccid_bridge_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+	char *buf;
+	struct usb_ccid_data data;
+	struct usb_ccid_abort abort;
+	struct usb_descriptor_header *header;
+	int ret;
+	struct usb_device *udev = ccid->udev;
+	__u8 intf = ccid->intf->cur_altsetting->desc.bInterfaceNumber;
+	__u8 breq = 0;
+
+	if (!ccid->intf) {
+		pr_debug("intf is not active");
+		return -ENODEV;
+	}
+
+	mutex_lock(&ccid->event_mutex);
+	switch (cmd) {
+	case USB_CCID_GET_CLASS_DESC:
+		pr_debug("GET_CLASS_DESC ioctl called");
+		ret = copy_from_user(&data, (void __user *)arg, sizeof(data));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+		ret = __usb_get_extra_descriptor(udev->rawdescriptors[0],
+				le16_to_cpu(udev->config[0].desc.wTotalLength),
+				CCID_CLASS_DECRIPTOR_TYPE, (void **) &buf);
+		if (ret) {
+			ret = -ENOENT;
+			break;
+		}
+		header = (struct usb_descriptor_header *) buf;
+		if (data.length != header->bLength) {
+			ret = -EINVAL;
+			break;
+		}
+		ret = copy_to_user((void __user *)data.data, buf, data.length);
+		if (ret)
+			ret = -EFAULT;
+		break;
+	case USB_CCID_GET_CLOCK_FREQUENCIES:
+		pr_debug("GET_CLOCK_FREQUENCIES ioctl called");
+		breq = CCID_GET_CLK_FREQ_REQ;
+		/* fall through */
+	case USB_CCID_GET_DATA_RATES:
+		if (!breq) {
+			pr_debug("GET_DATA_RATES ioctl called");
+			breq = CCID_GET_DATA_RATES;
+		}
+		ret = copy_from_user(&data, (void __user *)arg, sizeof(data));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+		buf = kmalloc(data.length, GFP_KERNEL);
+		if (!buf) {
+			ret = -ENOMEM;
+			break;
+		}
+		ret = usb_autopm_get_interface(ccid->intf);
+		if (ret < 0) {
+			pr_debug("fail to get autopm with %d", ret);
+			break;
+		}
+		ret = usb_control_msg(ccid->udev,
+				usb_rcvctrlpipe(ccid->udev, 0),
+				breq, (USB_DIR_IN | USB_TYPE_CLASS |
+				 USB_RECIP_INTERFACE), 0, intf, buf,
+				data.length, CCID_CONTROL_TIMEOUT);
+		usb_autopm_put_interface(ccid->intf);
+		if (ret == data.length) {
+			ret = copy_to_user((void __user *)data.data, buf,
+					data.length);
+			if (ret)
+				ret = -EFAULT;
+		} else {
+			if (ret > 0)
+				ret = -EPIPE;
+		}
+		kfree(buf);
+		break;
+	case USB_CCID_ABORT:
+		pr_debug("ABORT ioctl called");
+		breq = CCID_ABORT_REQ;
+		ret = copy_from_user(&abort, (void __user *)arg, sizeof(abort));
+		if (ret) {
+			ret = -EFAULT;
+			break;
+		}
+		ret = usb_autopm_get_interface(ccid->intf);
+		if (ret < 0) {
+			pr_debug("fail to get autopm with %d", ret);
+			break;
+		}
+		ret = usb_control_msg(ccid->udev,
+				usb_sndctrlpipe(ccid->udev, 0),
+				breq, (USB_DIR_OUT | USB_TYPE_CLASS |
+				 USB_RECIP_INTERFACE),
+				(abort.seq << 8) | abort.slot, intf, NULL,
+				0, CCID_CONTROL_TIMEOUT);
+		if (ret < 0)
+			pr_err("abort request failed with err %d\n", ret);
+		usb_autopm_put_interface(ccid->intf);
+		break;
+	case USB_CCID_GET_EVENT:
+		pr_debug("GET_EVENT ioctl called");
+		if (!ccid->events_supported) {
+			ret = -ENOENT;
+			break;
+		}
+		ret = ccid_bridge_get_event(ccid);
+		if (ret == 0) {
+			ret = copy_to_user((void __user *)arg, &ccid->cur_event,
+					sizeof(ccid->cur_event));
+			if (ret)
+				ret = -EFAULT;
+		}
+		ccid->cur_event.event = 0;
+		break;
+	default:
+		pr_err("UNKNOWN ioctl called");
+		ret = -EINVAL;
+		break;
+	}
+
+	mutex_unlock(&ccid->event_mutex);
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_release(struct inode *ip, struct file *fp)
+{
+	struct ccid_bridge *ccid = fp->private_data;
+
+	pr_debug("called");
+
+	usb_kill_urb(ccid->writeurb);
+	usb_kill_urb(ccid->readurb);
+	if (ccid->int_pipe)
+		usb_kill_urb(ccid->inturb);
+
+	ccid->event_result = -EIO;
+	wake_up(&ccid->event_wq);
+
+	mutex_lock(&ccid->open_mutex);
+	ccid->opened = false;
+	mutex_unlock(&ccid->open_mutex);
+	return 0;
+}
+
+static const struct file_operations ccid_bridge_fops = {
+	.owner = THIS_MODULE,
+	.open = ccid_bridge_open,
+	.write = ccid_bridge_write,
+	.read = ccid_bridge_read,
+	.unlocked_ioctl = ccid_bridge_ioctl,
+	.release = ccid_bridge_release,
+};
+
+static int ccid_bridge_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct ccid_bridge *ccid = usb_get_intfdata(intf);
+	int ret = 0;
+
+	pr_debug("called");
+
+	if (!ccid->opened)
+		goto out;
+
+	mutex_lock(&ccid->event_mutex);
+	if (ccid->int_pipe) {
+		usb_kill_urb(ccid->inturb);
+		if (ccid->event_result != -ENOENT) {
+			ret = -EBUSY;
+			goto rel_mutex;
+		}
+	}
+
+	ccid->is_suspended = true;
+rel_mutex:
+	mutex_unlock(&ccid->event_mutex);
+out:
+	pr_debug("returning %d", ret);
+	return ret;
+}
+
+static int ccid_bridge_resume(struct usb_interface *intf)
+{
+	struct ccid_bridge *ccid = usb_get_intfdata(intf);
+	int ret;
+
+	pr_debug("called");
+
+	if (!ccid->opened)
+		goto out;
+
+	mutex_lock(&ccid->event_mutex);
+
+	ccid->is_suspended = false;
+
+	if (device_can_wakeup(&ccid->udev->dev)) {
+		ccid->event_result = 0;
+		ccid->cur_event.event = USB_CCID_RESUME_EVENT;
+		wake_up(&ccid->event_wq);
+	} else if (ccid->int_pipe) {
+		ccid->event_result = -EINPROGRESS;
+		ret = usb_submit_urb(ccid->inturb, GFP_KERNEL);
+		if (ret < 0)
+			pr_debug("fail to submit inturb with %d\n", ret);
+	}
+
+	mutex_unlock(&ccid->event_mutex);
+out:
+	return 0;
+}
+
+static int
+ccid_bridge_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct ccid_bridge *ccid = __ccid_bridge_dev;
+	struct usb_host_interface *intf_desc;
+	struct usb_endpoint_descriptor *ep_desc;
+	struct usb_host_endpoint *ep;
+	__u8 epin_addr = 0, epout_addr = 0, epint_addr = 0;
+	int i, ret;
+
+	intf_desc = intf->cur_altsetting;
+
+	if (intf_desc->desc.bNumEndpoints > 3)
+		return -ENODEV;
+
+	for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+		ep_desc = &intf_desc->endpoint[i].desc;
+
+		if (usb_endpoint_is_bulk_in(ep_desc))
+			epin_addr = ep_desc->bEndpointAddress;
+		else if (usb_endpoint_is_bulk_out(ep_desc))
+			epout_addr = ep_desc->bEndpointAddress;
+		else if (usb_endpoint_is_int_in(ep_desc))
+			epint_addr = ep_desc->bEndpointAddress;
+		else
+			return -ENODEV;
+	}
+
+	if (!epin_addr || !epout_addr)
+		return -ENODEV;
+
+	ccid->udev = usb_get_dev(interface_to_usbdev(intf));
+	ccid->in_pipe = usb_rcvbulkpipe(ccid->udev, epin_addr);
+	ccid->out_pipe = usb_sndbulkpipe(ccid->udev, epout_addr);
+	if (epint_addr)
+		ccid->int_pipe = usb_rcvbulkpipe(ccid->udev, epint_addr);
+
+	ccid->writeurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ccid->writeurb) {
+		pr_err("fail to allocate write urb");
+		ret = -ENOMEM;
+		goto put_udev;
+	}
+	ccid->readurb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!ccid->readurb) {
+		pr_err("fail to allocate read urb");
+		ret = -ENOMEM;
+		goto free_writeurb;
+	}
+
+	if (ccid->int_pipe) {
+		pr_debug("interrupt endpoint is present");
+		ep = usb_pipe_endpoint(ccid->udev, ccid->int_pipe);
+		ccid->inturb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!ccid->inturb) {
+			pr_err("fail to allocate int urb");
+			ret = -ENOMEM;
+			goto free_readurb;
+		}
+		ccid->intbuf = kmalloc(usb_endpoint_maxp(&ep->desc),
+				GFP_KERNEL);
+		if (!ccid->intbuf) {
+			pr_err("fail to allocated int buf");
+			ret = -ENOMEM;
+			goto free_inturb;
+		}
+		usb_fill_int_urb(ccid->inturb, ccid->udev,
+				usb_rcvintpipe(ccid->udev, epint_addr),
+				ccid->intbuf, usb_endpoint_maxp(&ep->desc),
+				ccid_bridge_int_cb, ccid,
+				ep->desc.bInterval);
+	}
+
+	if (ccid->int_pipe || device_can_wakeup(&ccid->udev->dev)) {
+		pr_debug("event support is present");
+		ccid->events_supported = true;
+	}
+
+	usb_set_intfdata(intf, ccid);
+
+	mutex_lock(&ccid->open_mutex);
+	ccid->intf = intf;
+	wake_up(&ccid->open_wq);
+	mutex_unlock(&ccid->open_mutex);
+
+	pr_info("success");
+	return 0;
+
+free_inturb:
+	if (ccid->int_pipe)
+		usb_free_urb(ccid->inturb);
+free_readurb:
+	usb_free_urb(ccid->readurb);
+free_writeurb:
+	usb_free_urb(ccid->writeurb);
+put_udev:
+	usb_put_dev(ccid->udev);
+	return ret;
+}
+
+static void ccid_bridge_disconnect(struct usb_interface *intf)
+{
+	struct ccid_bridge *ccid = usb_get_intfdata(intf);
+
+	pr_debug("called");
+
+	usb_kill_urb(ccid->writeurb);
+	usb_kill_urb(ccid->readurb);
+	if (ccid->int_pipe)
+		usb_kill_urb(ccid->inturb);
+
+	ccid->event_result = -ENODEV;
+	wake_up(&ccid->event_wq);
+
+	/*
+	 * This would synchronize any ongoing read/write/ioctl.
+	 * After acquiring the mutex, we can safely set
+	 * intf to NULL.
+	 */
+	mutex_lock(&ccid->open_mutex);
+	mutex_lock(&ccid->write_mutex);
+	mutex_lock(&ccid->read_mutex);
+	mutex_lock(&ccid->event_mutex);
+
+	usb_free_urb(ccid->writeurb);
+	usb_free_urb(ccid->readurb);
+	if (ccid->int_pipe) {
+		usb_free_urb(ccid->inturb);
+		kfree(ccid->intbuf);
+		ccid->int_pipe = 0;
+	}
+
+	ccid->intf = NULL;
+
+	mutex_unlock(&ccid->event_mutex);
+	mutex_unlock(&ccid->read_mutex);
+	mutex_unlock(&ccid->write_mutex);
+	mutex_unlock(&ccid->open_mutex);
+
+}
+
+static const struct usb_device_id ccid_bridge_ids[] = {
+	{ USB_INTERFACE_INFO(USB_CLASS_CSCID, 0, 0) },
+
+	{} /* terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ccid_bridge_ids);
+
+static struct usb_driver ccid_bridge_driver = {
+	.name = "ccid_bridge",
+	.probe = ccid_bridge_probe,
+	.disconnect = ccid_bridge_disconnect,
+	.suspend = ccid_bridge_suspend,
+	.resume = ccid_bridge_resume,
+	.id_table = ccid_bridge_ids,
+	.supports_autosuspend = 1,
+};
+
+static int __init ccid_bridge_init(void)
+{
+	int ret;
+	struct ccid_bridge *ccid;
+
+	ccid = kzalloc(sizeof(*ccid), GFP_KERNEL);
+	if (!ccid) {
+		pr_err("Fail to allocate ccid");
+		ret = -ENOMEM;
+		goto out;
+	}
+	__ccid_bridge_dev = ccid;
+
+	mutex_init(&ccid->open_mutex);
+	mutex_init(&ccid->write_mutex);
+	mutex_init(&ccid->read_mutex);
+	mutex_init(&ccid->event_mutex);
+
+	init_waitqueue_head(&ccid->open_wq);
+	init_waitqueue_head(&ccid->write_wq);
+	init_waitqueue_head(&ccid->read_wq);
+	init_waitqueue_head(&ccid->event_wq);
+
+	ret = usb_register(&ccid_bridge_driver);
+	if (ret < 0) {
+		pr_err("Fail to register ccid usb driver with %d", ret);
+		goto free_ccid;
+	}
+
+	ret = alloc_chrdev_region(&ccid->chrdev, 0, 1, "ccid_bridge");
+	if (ret < 0) {
+		pr_err("Fail to allocate ccid char dev region with %d", ret);
+		goto unreg_driver;
+	}
+	ccid->class = class_create(THIS_MODULE, "ccid_bridge");
+	if (IS_ERR(ccid->class)) {
+		ret = PTR_ERR(ccid->class);
+		pr_err("Fail to create ccid class with %d", ret);
+		goto unreg_chrdev;
+	}
+	cdev_init(&ccid->cdev, &ccid_bridge_fops);
+	ccid->cdev.owner = THIS_MODULE;
+
+	ret = cdev_add(&ccid->cdev, ccid->chrdev, 1);
+	if (ret < 0) {
+		pr_err("Fail to add ccid cdev with %d", ret);
+		goto destroy_class;
+	}
+	ccid->device = device_create(ccid->class,
+					NULL, ccid->chrdev, NULL,
+					"ccid_bridge");
+	if (IS_ERR(ccid->device)) {
+		ret = PTR_ERR(ccid->device);
+		pr_err("Fail to create ccid device with %d", ret);
+		goto del_cdev;
+	}
+
+	pr_info("success");
+
+	return 0;
+
+del_cdev:
+	cdev_del(&ccid->cdev);
+destroy_class:
+	class_destroy(ccid->class);
+unreg_chrdev:
+	unregister_chrdev_region(ccid->chrdev, 1);
+unreg_driver:
+	usb_deregister(&ccid_bridge_driver);
+free_ccid:
+	mutex_destroy(&ccid->open_mutex);
+	mutex_destroy(&ccid->write_mutex);
+	mutex_destroy(&ccid->read_mutex);
+	mutex_destroy(&ccid->event_mutex);
+	kfree(ccid);
+	__ccid_bridge_dev = NULL;
+out:
+	return ret;
+}
+
+static void __exit ccid_bridge_exit(void)
+{
+	struct ccid_bridge *ccid = __ccid_bridge_dev;
+
+	pr_debug("called");
+	device_destroy(ccid->class, ccid->chrdev);
+	cdev_del(&ccid->cdev);
+	class_destroy(ccid->class);
+	unregister_chrdev_region(ccid->chrdev, 1);
+
+	usb_deregister(&ccid_bridge_driver);
+
+	mutex_destroy(&ccid->open_mutex);
+	mutex_destroy(&ccid->write_mutex);
+	mutex_destroy(&ccid->read_mutex);
+	mutex_destroy(&ccid->event_mutex);
+
+	kfree(ccid);
+	__ccid_bridge_dev = NULL;
+}
+
+module_init(ccid_bridge_init);
+module_exit(ccid_bridge_exit);
+
+MODULE_DESCRIPTION("USB CCID bridge driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d97d548..827ac9d 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3159,7 +3159,8 @@
 	for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) {
 		if (USE_NEW_SCHEME(retry_counter) &&
 			!(hcd->driver->flags & HCD_USB3) &&
-			!(hcd->driver->flags & HCD_OLD_ENUM)) {
+			!((hcd->driver->flags & HCD_RT_OLD_ENUM) &&
+				!hdev->parent)) {
 			struct usb_device_descriptor *buf;
 			int r = 0;
 
@@ -3261,7 +3262,8 @@
 			msleep(10);
 			if (USE_NEW_SCHEME(retry_counter) &&
 				!(hcd->driver->flags & HCD_USB3) &&
-				!(hcd->driver->flags & HCD_OLD_ENUM))
+				!((hcd->driver->flags & HCD_RT_OLD_ENUM) &&
+					!hdev->parent))
 				break;
   		}
 
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 1be2550..4e84b94 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -631,6 +631,7 @@
 
 	u8			epnum;
 	struct dwc3_trb		*trb;
+	struct dwc3_trb		*ztrb;
 	dma_addr_t		trb_dma;
 
 	unsigned		direction:1;
diff --git a/drivers/usb/dwc3/debug.h b/drivers/usb/dwc3/debug.h
index 4901f4b..57d27cd 100644
--- a/drivers/usb/dwc3/debug.h
+++ b/drivers/usb/dwc3/debug.h
@@ -48,15 +48,17 @@
 extern void dwc3_debugfs_exit(struct dwc3 *);
 extern void dbg_print_reg(const char *name, int reg);
 #else
-static inline void dbg_event(u8, const char*, int)
+static inline void dbg_event(u8 ep_num, const char *name, int status)
 {  }
-static inline void dbg_print(u8, const char*, int, const char*)
+static inline void dbg_print(u8 ep_num, const char *name, int status,
+			     const char *extra)
 {  }
-static inline void dbg_done(u8, const u32, int)
+static inline void dbg_done(u8 ep_num, const u32 count, int status)
 {  }
-static inline void dbg_queue(u8, const struct usb_request*, int)
+static inline void dbg_queue(u8 ep_num, const struct usb_request *req,
+			     int status)
 {  }
-static inline void dbg_setup(u8, const struct usb_ctrlrequest*)
+static inline void dbg_setup(u8 ep_num, const struct usb_ctrlrequest *req)
 {  }
 static inline void dbg_print_reg(const char *name, int reg)
 {  }
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index a2580fc..a192398 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -794,9 +794,9 @@
 	.release		= single_release,
 };
 
-static unsigned int ep_addr_rxdbg_mask;
+static unsigned int ep_addr_rxdbg_mask = 1;
 module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
-static unsigned int ep_addr_txdbg_mask;
+static unsigned int ep_addr_txdbg_mask = 1;
 module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
 
 /* Maximum debug message length */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 97592c4..667a8a2 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -1512,6 +1512,7 @@
 	case DWC3_CONTROLLER_ERROR_EVENT:
 		dev_info(mdwc->dev, "DWC3_CONTROLLER_ERROR_EVENT received\n");
 		dwc3_msm_dump_phy_info(mdwc);
+		dwc3_msm_write_reg(mdwc->base, DWC3_DEVTEN, 0);
 		/*
 		 * schedule work for doing block reset for recovery from erratic
 		 * error event.
@@ -1567,10 +1568,23 @@
 {
 	struct dwc3_msm *mdwc = container_of(w, struct dwc3_msm,
 						usb_block_reset_work);
+	u32 reg;
 
 	dev_dbg(mdwc->dev, "%s\n", __func__);
 
 	dwc3_msm_block_reset(&mdwc->ext_xceiv, true);
+
+	reg = (DWC3_DEVTEN_EVNTOVERFLOWEN |
+			DWC3_DEVTEN_CMDCMPLTEN |
+			DWC3_DEVTEN_ERRTICERREN |
+			DWC3_DEVTEN_WKUPEVTEN |
+			DWC3_DEVTEN_ULSTCNGEN |
+			DWC3_DEVTEN_CONNECTDONEEN |
+			DWC3_DEVTEN_USBRSTEN |
+			DWC3_DEVTEN_DISCONNEVTEN);
+	dwc3_msm_write_reg(mdwc->base, DWC3_DEVTEN, reg);
+
+
 }
 
 static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -1791,6 +1805,11 @@
 		return;
 	}
 
+	/* Skip if charger type was already detected externally */
+	if (mdwc->chg_state == USB_CHG_STATE_DETECTED &&
+		charger->chg_type != DWC3_INVALID_CHARGER)
+		return;
+
 	mdwc->chg_state = USB_CHG_STATE_UNDEFINED;
 	charger->chg_type = DWC3_INVALID_CHARGER;
 	queue_delayed_work(system_nrt_wq, &mdwc->chg_work, 0);
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 0cfd515..c07f18c 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -291,6 +291,7 @@
 	struct dwc3_ep			*dep = to_dwc3_ep(ep);
 	struct dwc3			*dwc = dep->dwc;
 
+	dbg_event(dep->number, "EP0STAL", value);
 	dwc3_ep0_stall_and_restart(dwc);
 
 	return 0;
@@ -752,8 +753,10 @@
 		dwc->delayed_status = true;
 
 out:
-	if (ret < 0)
+	if (ret < 0) {
+		dbg_event(0x0, "ERRSTAL", ret);
 		dwc3_ep0_stall_and_restart(dwc);
+	}
 }
 
 bool zlp_required;
@@ -819,7 +822,7 @@
 
 	if ((epnum & 1) && ur->actual < ur->length) {
 		/* for some reason we did not get everything out */
-
+		dbg_event(epnum, "INDATSTAL", 0);
 		dwc3_ep0_stall_and_restart(dwc);
 	} else {
 		/*
@@ -855,6 +858,7 @@
 		if (ret < 0) {
 			dev_dbg(dwc->dev, "Invalid Test #%d\n",
 					dwc->test_mode_nr);
+			dbg_event(0x00, "INVALTEST", ret);
 			dwc3_ep0_stall_and_restart(dwc);
 			return;
 		}
@@ -1034,6 +1038,7 @@
 
 			dev_vdbg(dwc->dev, "Wrong direction for Data phase\n");
 			dwc3_ep0_end_control_data(dwc, dep);
+			dbg_event(epnum, "WRONGDR", 0);
 			dwc3_ep0_stall_and_restart(dwc);
 			return;
 		}
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index ad3a3a9..4be032a 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -294,6 +294,15 @@
 		if (((dep->busy_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
 				usb_endpoint_xfer_isoc(dep->endpoint.desc))
 			dep->busy_slot++;
+
+		if (req->request.zero && req->ztrb) {
+			dep->busy_slot++;
+			req->ztrb = NULL;
+			if (((dep->busy_slot & DWC3_TRB_MASK) ==
+				DWC3_TRB_NUM - 1) &&
+				usb_endpoint_xfer_isoc(dep->endpoint.desc))
+				dep->busy_slot++;
+		}
 	}
 	list_del(&req->list);
 	req->trb = NULL;
@@ -864,6 +873,7 @@
 		req->trb_dma = dwc3_trb_dma_offset(dep, trb);
 	}
 
+update_trb:
 	trb->size = DWC3_TRB_SIZE_LENGTH(length);
 	trb->bpl = lower_32_bits(dma);
 	trb->bph = upper_32_bits(dma);
@@ -898,15 +908,31 @@
 	} else {
 		if (chain)
 			trb->ctrl |= DWC3_TRB_CTRL_CHN;
-
-		if (last)
-			trb->ctrl |= DWC3_TRB_CTRL_LST;
 	}
 
 	if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable)
 		trb->ctrl |= DWC3_TRB_CTRL_SID_SOFN(req->request.stream_id);
 
 	trb->ctrl |= DWC3_TRB_CTRL_HWO;
+
+	if (req->request.zero && length &&
+			(length % usb_endpoint_maxp(dep->endpoint.desc) == 0)) {
+		trb = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
+		dep->free_slot++;
+
+		/* Skip the LINK-TRB on ISOC */
+		if (((dep->free_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
+			usb_endpoint_xfer_isoc(dep->endpoint.desc))
+			dep->free_slot++;
+
+		req->ztrb = trb;
+		length = 0;
+
+		goto update_trb;
+	}
+
+	if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) && last)
+		trb->ctrl |= DWC3_TRB_CTRL_LST;
 }
 
 /*
@@ -1007,12 +1033,25 @@
 			}
 			dbg_queue(dep->number, &req->request, 0);
 		} else {
+			struct dwc3_request	*req1;
+			int maxpkt_size = usb_endpoint_maxp(dep->endpoint.desc);
+
 			dma = req->request.dma;
 			length = req->request.length;
 			trbs_left--;
 
-			if (!trbs_left)
+			if (req->request.zero && length &&
+						(length % maxpkt_size == 0))
+				trbs_left--;
+
+			if (!trbs_left) {
 				last_one = 1;
+			} else if (dep->direction && (trbs_left <= 1)) {
+				req1 = next_request(&req->list);
+				if (req1->request.zero && req1->request.length
+				 && (req1->request.length % maxpkt_size == 0))
+					last_one = 1;
+			}
 
 			/* Is this the last request? */
 			if (list_is_last(&req->list, &dep->request_list))
@@ -2052,6 +2091,8 @@
 				s_pkt = 1;
 		}
 
+		if (req->ztrb)
+			trb = req->ztrb;
 		/*
 		 * We assume here we will always receive the entire data block
 		 * which we should receive. Meaning, if we program RX to
@@ -2163,6 +2204,7 @@
 			return;
 		}
 
+		dbg_event(dep->number, "XFRCOMP", 0);
 		dwc3_endpoint_transfer_complete(dwc, dep, event, 1);
 		break;
 	case DWC3_DEPEVT_XFERINPROGRESS:
@@ -2172,9 +2214,11 @@
 			return;
 		}
 
+		dbg_event(dep->number, "XFRPROG", 0);
 		dwc3_endpoint_transfer_complete(dwc, dep, event, 0);
 		break;
 	case DWC3_DEPEVT_XFERNOTREADY:
+		dbg_event(dep->number, "XFRNRDY", 0);
 		if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
 			dwc3_gadget_start_isoc(dwc, dep, event);
 		} else {
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
index c1ab552..69f4b1c 100644
--- a/drivers/usb/gadget/f_qc_rndis.c
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -6,7 +6,7 @@
  * Copyright (C) 2008 Nokia Corporation
  * Copyright (C) 2009 Samsung Electronics
  *			Author: Michal Nazarewicz (mina86@mina86.com)
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -347,7 +347,7 @@
 };
 
 static struct usb_descriptor_header *eth_qc_ss_function[] = {
-	(struct usb_descriptor_header *) &rndis_iad_descriptor,
+	(struct usb_descriptor_header *) &rndis_qc_iad_descriptor,
 
 	/* control interface matches ACM, not Ethernet */
 	(struct usb_descriptor_header *) &rndis_qc_control_intf,
@@ -615,7 +615,6 @@
 		/* read the request; process it later */
 		value = w_length;
 		req->complete = rndis_qc_command_complete;
-		req->context = rndis;
 		/* later, rndis_response_available() sends a notification */
 		break;
 
@@ -651,6 +650,7 @@
 		DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
 			w_value, w_index, w_length);
+		req->context = rndis;
 		req->zero = (value < w_length);
 		req->length = value;
 		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index 7e474f3..4ecfeac 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -1,7 +1,7 @@
 /*
  * f_qdss.c -- QDSS function Driver
  *
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -415,6 +415,8 @@
 
 	pr_debug("qdss_unbind\n");
 
+	flush_workqueue(qdss->wq);
+
 	if (gadget_is_dwc3(gadget))
 		dwc3_tx_fifo_resize_request(qdss->data, false);
 
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 843c207..4bd7f39 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -54,28 +54,31 @@
 
 #define DL_INTR_THRESHOLD			20
 
-unsigned int bam_mux_tx_pkt_drop_thld = BAM_MUX_TX_PKT_DROP_THRESHOLD;
+static unsigned int bam_pending_limit = BAM_PENDING_LIMIT;
+module_param(bam_pending_limit, uint, S_IRUGO | S_IWUSR);
+
+static unsigned int bam_mux_tx_pkt_drop_thld = BAM_MUX_TX_PKT_DROP_THRESHOLD;
 module_param(bam_mux_tx_pkt_drop_thld, uint, S_IRUGO | S_IWUSR);
 
-unsigned int bam_mux_rx_fctrl_en_thld = BAM_MUX_RX_PKT_FCTRL_EN_TSHOLD;
+static unsigned int bam_mux_rx_fctrl_en_thld = BAM_MUX_RX_PKT_FCTRL_EN_TSHOLD;
 module_param(bam_mux_rx_fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
 
-unsigned int bam_mux_rx_fctrl_support = BAM_MUX_RX_PKT_FLOW_CTRL_SUPPORT;
+static unsigned int bam_mux_rx_fctrl_support = BAM_MUX_RX_PKT_FLOW_CTRL_SUPPORT;
 module_param(bam_mux_rx_fctrl_support, uint, S_IRUGO | S_IWUSR);
 
-unsigned int bam_mux_rx_fctrl_dis_thld = BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD;
+static unsigned int bam_mux_rx_fctrl_dis_thld = BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD;
 module_param(bam_mux_rx_fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
 
-unsigned int bam_mux_tx_q_size = BAM_MUX_TX_Q_SIZE;
+static unsigned int bam_mux_tx_q_size = BAM_MUX_TX_Q_SIZE;
 module_param(bam_mux_tx_q_size, uint, S_IRUGO | S_IWUSR);
 
-unsigned int bam_mux_rx_q_size = BAM_MUX_RX_Q_SIZE;
+static unsigned int bam_mux_rx_q_size = BAM_MUX_RX_Q_SIZE;
 module_param(bam_mux_rx_q_size, uint, S_IRUGO | S_IWUSR);
 
-unsigned int bam_mux_rx_req_size = BAM_MUX_RX_REQ_SIZE;
+static unsigned int bam_mux_rx_req_size = BAM_MUX_RX_REQ_SIZE;
 module_param(bam_mux_rx_req_size, uint, S_IRUGO | S_IWUSR);
 
-unsigned int dl_intr_threshold = DL_INTR_THRESHOLD;
+static unsigned int dl_intr_threshold = DL_INTR_THRESHOLD;
 module_param(dl_intr_threshold, uint, S_IRUGO | S_IWUSR);
 
 #define BAM_CH_OPENED	BIT(0)
@@ -113,6 +116,10 @@
 	unsigned int		rx_len;
 	unsigned long		to_modem;
 	unsigned long		to_host;
+	unsigned int		rx_flow_control_disable;
+	unsigned int		rx_flow_control_enable;
+	unsigned int		rx_flow_control_triggered;
+	unsigned int		max_num_pkts_pending_with_bam;
 };
 
 struct gbam_port {
@@ -324,7 +331,7 @@
 		return;
 	}
 
-	while (d->pending_with_bam < BAM_PENDING_LIMIT) {
+	while (d->pending_with_bam < bam_pending_limit) {
 		skb =  __skb_dequeue(&d->rx_skb_q);
 		if (!skb)
 			break;
@@ -347,14 +354,21 @@
 			dev_kfree_skb_any(skb);
 			break;
 		}
+		if (d->pending_with_bam > d->max_num_pkts_pending_with_bam)
+			d->max_num_pkts_pending_with_bam = d->pending_with_bam;
 	}
 
 	qlen = d->rx_skb_q.qlen;
 
 	spin_unlock_irqrestore(&port->port_lock_ul, flags);
 
-	if (qlen < BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD)
+	if (qlen < bam_mux_rx_fctrl_dis_thld) {
+		if (d->rx_flow_control_triggered) {
+			d->rx_flow_control_disable++;
+			d->rx_flow_control_triggered = 0;
+		}
 		gbam_start_rx(port);
+	}
 }
 /*-------------------------------------------------------------*/
 
@@ -435,7 +449,10 @@
 	 */
 	if (bam_mux_rx_fctrl_support &&
 		d->rx_skb_q.qlen >= bam_mux_rx_fctrl_en_thld) {
-
+		if (!d->rx_flow_control_triggered) {
+			d->rx_flow_control_triggered = 1;
+			d->rx_flow_control_enable++;
+		}
 		list_add_tail(&req->list, &d->rx_idle);
 		spin_unlock(&port->port_lock_ul);
 		return;
@@ -1223,6 +1240,10 @@
 				"dpkts_pwith_bam: %u\n"
 				"to_usbhost_dcnt:  %u\n"
 				"tomodem__dcnt:  %u\n"
+				"rx_flow_control_disable_count: %u\n"
+				"rx_flow_control_enable_count: %u\n"
+				"rx_flow_control_triggered: %u\n"
+				"max_num_pkts_pending_with_bam: %u\n"
 				"tx_buf_len:	 %u\n"
 				"rx_buf_len:	 %u\n"
 				"data_ch_open:   %d\n"
@@ -1231,6 +1252,10 @@
 				d->to_host, d->to_modem,
 				d->pending_with_bam,
 				d->tohost_drp_cnt, d->tomodem_drp_cnt,
+				d->rx_flow_control_disable,
+				d->rx_flow_control_enable,
+				d->rx_flow_control_triggered,
+				d->max_num_pkts_pending_with_bam,
 				d->tx_skb_q.qlen, d->rx_skb_q.qlen,
 				test_bit(BAM_CH_OPENED, &d->flags),
 				test_bit(BAM_CH_READY, &d->flags));
@@ -1269,6 +1294,10 @@
 		d->pending_with_bam = 0;
 		d->tohost_drp_cnt = 0;
 		d->tomodem_drp_cnt = 0;
+		d->rx_flow_control_disable = 0;
+		d->rx_flow_control_enable = 0;
+		d->rx_flow_control_triggered = 0;
+		d->max_num_pkts_pending_with_bam = 0;
 
 		spin_unlock(&port->port_lock_dl);
 		spin_unlock_irqrestore(&port->port_lock_ul, flags);
@@ -1434,6 +1463,10 @@
 		d->pending_with_bam = 0;
 		d->tohost_drp_cnt = 0;
 		d->tomodem_drp_cnt = 0;
+		d->rx_flow_control_disable = 0;
+		d->rx_flow_control_enable = 0;
+		d->rx_flow_control_triggered = 0;
+		d->max_num_pkts_pending_with_bam = 0;
 	}
 
 	spin_unlock(&port->port_lock_dl);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 299f620c..95b6fbc7 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -689,18 +689,20 @@
 }
 
 static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head,
-		int num, int size, void (*fn)(struct usb_ep *, struct usb_request *),
+		int queue_size, int req_size,
+		void (*fn)(struct usb_ep *, struct usb_request *),
 		int *allocated)
 {
 	int			i;
 	struct usb_request	*req;
+	int n = allocated ? queue_size - *allocated : queue_size;
 
 	/* Pre-allocate up to QUEUE_SIZE transfers, but if we can't
 	 * do quite that many this time, don't fail ... we just won't
 	 * be as speedy as we might otherwise be.
 	 */
-	for (i = 0; i < num; i++) {
-		req = gs_alloc_req(ep, size, GFP_ATOMIC);
+	for (i = 0; i < n; i++) {
+		req = gs_alloc_req(ep, req_size, GFP_ATOMIC);
 		if (!req)
 			return list_empty(head) ? -ENOMEM : 0;
 		req->complete = fn;
@@ -941,22 +943,6 @@
 			port->port_num, tty, file);
 
 	wake_up_interruptible(&port->close_wait);
-
-	/*
-	 * Freeing the previously queued requests as they are
-	 * allocated again as a part of gs_open()
-	 */
-	if (port->port_usb) {
-		spin_unlock_irq(&port->port_lock);
-		usb_ep_fifo_flush(gser->out);
-		usb_ep_fifo_flush(gser->in);
-		spin_lock_irq(&port->port_lock);
-		gs_free_requests(gser->out, &port->read_queue, NULL);
-		gs_free_requests(gser->out, &port->read_pool, NULL);
-		gs_free_requests(gser->in, &port->write_pool, NULL);
-	}
-	port->read_allocated = port->read_started =
-		port->write_allocated = port->write_started = 0;
 exit:
 	spin_unlock_irq(&port->port_lock);
 }
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 5f20ad1..a89ac06 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1,6 +1,6 @@
 /* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
  *
- * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
  *
  * Partly derived from ehci-fsl.c and ehci-hcd.c
  * Copyright (c) 2000-2004 by David Brownell
@@ -1486,7 +1486,7 @@
 	 * generic hardware linkage
 	 */
 	.irq			= msm_hsic_irq,
-	.flags			= HCD_USB2 | HCD_MEMORY | HCD_OLD_ENUM,
+	.flags			= HCD_USB2 | HCD_MEMORY | HCD_RT_OLD_ENUM,
 
 	.reset			= ehci_hsic_reset,
 	.start			= ehci_run,
@@ -2263,6 +2263,9 @@
 	iounmap(hcd->regs);
 	usb_put_hcd(hcd);
 
+	if (pdev->dev.of_node)
+		pdev->dev.platform_data = NULL;
+
 	return 0;
 }
 
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 75fce2f..262b6c2 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2014, 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
@@ -26,10 +26,6 @@
 #include <asm/unaligned.h>
 #include <mach/usb_bridge.h>
 
-/* polling interval for Interrupt ep */
-#define HS_INTERVAL		7
-#define FS_LS_INTERVAL		3
-
 #define ACM_CTRL_DTR		(1 << 0)
 #define DEFAULT_READ_URB_LENGTH	4096
 
@@ -719,8 +715,7 @@
 		goto free_inturb;
 	}
 
-	interval =
-		(udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL;
+	interval = int_in->desc.bInterval;
 
 	usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
 				dev->intbuf, wMaxPacketSize,
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 8287ad7..47b8e59 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2013, Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2014, 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
@@ -2551,6 +2551,8 @@
 	bool work = 0, srp_reqd, dcp;
 
 	pm_runtime_resume(otg->phy->dev);
+	if (motg->pm_done)
+		pm_runtime_get_sync(otg->phy->dev);
 	pr_debug("%s work\n", otg_state_string(otg->phy->state));
 	switch (otg->phy->state) {
 	case OTG_STATE_UNDEFINED:
@@ -2696,6 +2698,7 @@
 			 */
 			pm_runtime_mark_last_busy(otg->phy->dev);
 			pm_runtime_autosuspend(otg->phy->dev);
+			motg->pm_done = 1;
 		}
 		break;
 	case OTG_STATE_B_SRP_INIT:
@@ -4842,6 +4845,7 @@
 
 	dev_dbg(dev, "OTG runtime resume\n");
 	pm_runtime_get_noresume(dev);
+	motg->pm_done = 0;
 	return msm_otg_resume(motg);
 }
 #endif
@@ -4869,6 +4873,7 @@
 
 	dev_dbg(dev, "OTG PM resume\n");
 
+	motg->pm_done = 0;
 	atomic_set(&motg->pm_suspended, 0);
 	if (motg->async_int || motg->sm_work_pending) {
 		pm_runtime_get_noresume(dev);
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index a324a5d..669fca9 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -230,6 +230,11 @@
 					US_FL_SCM_MULT_TARG)) &&
 				us->protocol == USB_PR_BULK)
 			us->use_last_sector_hacks = 1;
+
+		if (us->sdev_autosuspend_delay >= 0) {
+			sdev->use_rpm_auto = 1;
+			sdev->autosuspend_delay = us->sdev_autosuspend_delay;
+		}
 	} else {
 
 		/* Non-disk-type devices don't need to blacklist any pages
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 2653e73..be7044b 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -742,6 +742,28 @@
 	return 0;
 }
 
+/* Initialize SCSI device auto-suspend timeout here */
+static void usb_stor_set_scsi_autosuspend(struct us_data *us)
+{
+	struct usb_device *udev = us->pusb_dev;
+	struct usb_host_config *config = udev->actconfig;
+	struct usb_host_interface *intf;
+	int i;
+
+	/*
+	 * Some USB UICC devices has Mass storage interface along
+	 * with CCID interface.  These cards are inserted all the
+	 * time.  Enable SCSI auto-suspend for such devices.
+	 */
+	for (i = 0; i < config->desc.bNumInterfaces; i++) {
+		intf = config->interface[i]->cur_altsetting;
+		if (intf->desc.bInterfaceClass == USB_CLASS_CSCID) {
+			us->sdev_autosuspend_delay = 2000; /* msec */
+			return;
+		}
+	}
+}
+
 /* Initialize all the dynamic resources we need */
 static int usb_stor_acquire_resources(struct us_data *us)
 {
@@ -990,6 +1012,10 @@
 	result = usb_stor_acquire_resources(us);
 	if (result)
 		goto BadDevice;
+
+	us->sdev_autosuspend_delay = -1;
+	usb_stor_set_scsi_autosuspend(us);
+
 	snprintf(us->scsi_name, sizeof(us->scsi_name), "usb-storage %s",
 					dev_name(&us->pusb_intf->dev));
 	result = scsi_add_host(us_to_host(us), dev);
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 75f70f0..db75080 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -161,6 +161,7 @@
 	/* hacks for READ CAPACITY bug handling */
 	int			use_last_sector_hacks;
 	int			last_sector_retries;
+	int			sdev_autosuspend_delay;
 };
 
 /* Convert between us_data and the corresponding Scsi_Host */
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 25ee3e4..ca7f199 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -524,8 +524,11 @@
 	if (readl_poll_timeout((ctrl_base + DSI_STATUS),
 				status,
 				((status & 0x02) == 0),
-				DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US))
+				DSI_POLL_SLEEP_US, DSI_POLL_TIMEOUT_US)) {
 		pr_err("%s: DSI status=%x failed\n", __func__, status);
+		pr_err("%s: Doing sw reset\n", __func__);
+		msm_dsi_sw_reset();
+	}
 
 	/* Check for x_HS_FIFO_EMPTY */
 	if (readl_poll_timeout((ctrl_base + DSI_FIFO_STATUS),
@@ -959,11 +962,17 @@
 
 	msm_dsi_clk_ctrl(&ctrl->panel_data, 1);
 
+	if (0 == (req->flags & CMD_REQ_LP_MODE))
+		dsi_set_tx_power_mode(0);
+
 	if (req->flags & CMD_REQ_RX)
 		msm_dsi_cmdlist_rx(ctrl, req);
 	else
 		msm_dsi_cmdlist_tx(ctrl, req);
 
+	if (0 == (req->flags & CMD_REQ_LP_MODE))
+		dsi_set_tx_power_mode(1);
+
 	msm_dsi_clk_ctrl(&ctrl->panel_data, 0);
 
 	mutex_unlock(&ctrl->cmd_mutex);
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 02bd7e9..0cf1093 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2007 Google Incorporated
  *
  * This software is licensed under the terms of the GNU General Public
@@ -1667,69 +1667,79 @@
 		return xres * bpp;
 }
 
-static int mdp3_alloc(size_t size, void **virt, unsigned long *phys)
+static int mdp3_alloc(struct msm_fb_data_type *mfd)
 {
-	int ret = 0;
+	int ret;
+	int dom;
+	void *virt;
+	unsigned long phys;
+	u32 offsets[2];
+	size_t size;
+	struct platform_device *pdev = mfd->pdev;
 
-	if (mdp3_res->ion_handle) {
-		pr_debug("memory already alloc\n");
-		*virt = mdp3_res->virt;
-		*phys = mdp3_res->phys;
-		return 0;
+	mfd->fbi->screen_base = NULL;
+	mfd->fbi->fix.smem_start = 0;
+	mfd->fbi->fix.smem_len = 0;
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+				"qcom,memblock-reserve", offsets, 2);
+
+	if (ret) {
+		pr_err("fail to parse splash memory address\n");
+		return ret;
 	}
 
-	mdp3_res->ion_handle = ion_alloc(mdp3_res->ion_client, size,
-					SZ_1M,
-					ION_HEAP(ION_QSECOM_HEAP_ID), 0);
+	phys = offsets[0];
+	size = PAGE_ALIGN(mfd->fbi->fix.line_length *
+		mfd->fbi->var.yres_virtual);
 
-	if (!IS_ERR_OR_NULL(mdp3_res->ion_handle)) {
-		*virt = ion_map_kernel(mdp3_res->ion_client,
-					mdp3_res->ion_handle);
-		if (IS_ERR(*virt)) {
-			pr_err("map kernel error\n");
-			goto ion_map_kernel_err;
-		}
+	if (size > offsets[1]) {
+		pr_err("reserved splash memory size too small\n");
+		return -EINVAL;
+	}
 
-		ret = ion_phys(mdp3_res->ion_client, mdp3_res->ion_handle,
-				phys, &size);
-		if (ret) {
-			pr_err("%s ion_phys error\n", __func__);
-			goto ion_map_phys_err;
-		}
-
-		mdp3_res->virt = *virt;
-		mdp3_res->phys = *phys;
-		mdp3_res->size = size;
-	} else {
-		pr_err("%s ion alloc fail\n", __func__);
-		mdp3_res->ion_handle = NULL;
+	virt = phys_to_virt(phys);
+	if (unlikely(!virt)) {
+		pr_err("unable to map in splash memory\n");
 		return -ENOMEM;
 	}
 
-	return 0;
+	dom = mdp3_res->domains[MDP3_DMA_IOMMU_DOMAIN].domain_idx;
+	ret = msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
+					&mfd->iova);
 
-ion_map_phys_err:
-	ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
-ion_map_kernel_err:
-	ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
-	mdp3_res->ion_handle = NULL;
-	mdp3_res->virt = NULL;
-	mdp3_res->phys = 0;
-	mdp3_res->size = 0;
-	return -ENOMEM;
+	if (ret) {
+		pr_err("fail to map to IOMMU %d\n", ret);
+		return ret;
+	}
+	pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
+		size, virt, phys, mfd->index);
+
+	mfd->fbi->screen_base = virt;
+	mfd->fbi->fix.smem_start = phys;
+	mfd->fbi->fix.smem_len = size;
+
+	return 0;
 }
 
-void mdp3_free(void)
+void mdp3_free(struct msm_fb_data_type *mfd)
 {
-	pr_debug("mdp3_fbmem_free\n");
-	if (mdp3_res->ion_handle) {
-		ion_unmap_kernel(mdp3_res->ion_client, mdp3_res->ion_handle);
-		ion_free(mdp3_res->ion_client, mdp3_res->ion_handle);
-		mdp3_res->ion_handle = NULL;
-		mdp3_res->virt = NULL;
-		mdp3_res->phys = 0;
-		mdp3_res->size = 0;
+	size_t size = 0;
+	int dom;
+
+	if (!mfd->iova || !mfd->fbi->screen_base) {
+		pr_info("no fbmem allocated\n");
+		return;
 	}
+
+	size = mfd->fbi->fix.smem_len;
+	dom = mdp3_res->domains[MDP3_DMA_IOMMU_DOMAIN].domain_idx;
+	msm_iommu_unmap_contig_buffer(mfd->iova, dom, 0, size);
+
+	mfd->fbi->screen_base = NULL;
+	mfd->fbi->fix.smem_start = 0;
+	mfd->fbi->fix.smem_len = 0;
+	mfd->iova = 0;
 }
 
 int mdp3_parse_dt_splash(struct msm_fb_data_type *mfd)
@@ -1752,16 +1762,17 @@
 	mdp3_res->splash_mem_addr = offsets[0];
 	mdp3_res->splash_mem_size = offsets[1];
 
-	pr_debug("memaddr=%x size=%x\n", mdp3_res->splash_mem_addr,
+	pr_debug("memaddr=%lx size=%x\n", mdp3_res->splash_mem_addr,
 		mdp3_res->splash_mem_size);
 
 	return rc;
 }
 
-void mdp3_release_splash_memory(void)
+void mdp3_release_splash_memory(struct msm_fb_data_type *mfd)
 {
 	/* Give back the reserved memory to the system */
 	if (mdp3_res->splash_mem_addr) {
+		mdp3_free(mfd);
 		pr_debug("mdp3_release_splash_memory\n");
 		memblock_free(mdp3_res->splash_mem_addr,
 				mdp3_res->splash_mem_size);
@@ -1811,44 +1822,6 @@
 	return mdp3_res->cont_splash_en;
 }
 
-int mdp3_continuous_splash_copy(struct mdss_panel_data *pdata)
-{
-	unsigned long splash_phys, phys;
-	void *splash_virt, *virt;
-	u32 height, width, rgb_size, stride;
-	size_t size;
-	int rc;
-
-	if (pdata->panel_info.type != MIPI_VIDEO_PANEL) {
-		pr_debug("cmd mode panel, no need to copy splash image\n");
-		return 0;
-	}
-
-	rgb_size = MDP3_REG_READ(MDP3_REG_DMA_P_SIZE);
-	stride = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_Y_STRIDE);
-	stride = stride & 0x3FFF;
-	splash_phys = MDP3_REG_READ(MDP3_REG_DMA_P_IBUF_ADDR);
-
-	height = (rgb_size >> 16) & 0xffff;
-	width  = rgb_size & 0xffff;
-	size = PAGE_ALIGN(height * stride);
-	pr_debug("splash_height=%d splash_width=%d Buffer size=%d\n",
-		height, width, size);
-
-	rc = mdp3_alloc(size, &virt, &phys);
-	if (rc) {
-		pr_err("fail to allocate memory for continuous splash image\n");
-		return rc;
-	}
-
-	splash_virt = ioremap(splash_phys, stride * height);
-	memcpy(virt, splash_virt, stride * height);
-	iounmap(splash_virt);
-	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_ADDR, phys);
-
-	return 0;
-}
-
 static int mdp3_is_display_on(struct mdss_panel_data *pdata)
 {
 	int rc = 0;
@@ -1883,6 +1856,9 @@
 	mdp3_clk_set_rate(MDP3_CLK_VSYNC, MDP_VSYNC_CLK_RATE,
 			MDP3_CLIENT_DMA_P);
 
+	mdp3_clk_set_rate(MDP3_CLK_CORE, MDP_CORE_CLK_RATE,
+			MDP3_CLIENT_DMA_P);
+
 	rc = mdp3_clk_prepare();
 	if (rc) {
 		pr_err("fail to prepare clk\n");
@@ -2171,6 +2147,7 @@
 	.fb_mem_get_iommu_domain = mdp3_fb_mem_get_iommu_domain,
 	.panel_register_done = mdp3_panel_register_done,
 	.fb_stride = mdp3_fb_stride,
+	.fb_mem_alloc_fnc = mdp3_alloc,
 	};
 
 	struct mdp3_intr_cb underrun_cb = {
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index f1f0455..a253d8f 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2007 Google Incorporated
  *
  * This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,7 @@
 #include "mdss_fb.h"
 
 #define MDP_VSYNC_CLK_RATE	19200000
+#define MDP_CORE_CLK_RATE	100000000
 #define KOFF_TIMEOUT msecs_to_jiffies(84)
 
 enum  {
@@ -136,9 +137,6 @@
 	struct ion_handle *ion_handle;
 	struct mutex iommu_lock;
 	struct rb_root iommu_root;
-	void *virt;
-	unsigned long phys;
-	size_t size;
 
 	struct mdp3_dma dma[MDP3_DMA_MAX];
 	struct mdp3_intf intf[MDP3_DMA_OUTPUT_SEL_MAX];
@@ -153,7 +151,7 @@
 
 	struct early_suspend suspend_handler;
 	struct mdss_panel_cfg pan_cfg;
-	u32 splash_mem_addr;
+	unsigned long splash_mem_addr;
 	u32 splash_mem_size;
 
 	int clk_prepare_count;
@@ -194,9 +192,9 @@
 int mdp3_iommu_enable(int client);
 int mdp3_iommu_disable(int client);
 int mdp3_iommu_is_attached(int client);
-void mdp3_free(void);
+void mdp3_free(struct msm_fb_data_type *mfd);
 int mdp3_parse_dt_splash(struct msm_fb_data_type *mfd);
-void mdp3_release_splash_memory(void);
+void mdp3_release_splash_memory(struct msm_fb_data_type *mfd);
 int mdp3_create_sysfs_link(struct device *dev);
 int mdp3_get_cont_spash_en(void);
 int mdp3_get_mdp_dsi_clk(void);
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index 6fc6195..8b390ca 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,10 +25,12 @@
 #include "mdp3.h"
 #include "mdp3_ppp.h"
 
-#define MDP_CORE_CLK_RATE	100000000
 #define VSYNC_EXPIRE_TICK	4
 
-static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd);
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd,
+					struct mdp_overlay *req,
+					int image_size,
+					int *pipe_ndx);
 static int mdp3_overlay_unset(struct msm_fb_data_type *mfd, int ndx);
 static int mdp3_histogram_stop(struct mdp3_session_data *session,
 					u32 block);
@@ -214,7 +216,8 @@
 	 * active or when dsi clocks are currently off
 	 */
 	if (enable && mdp3_session->status == 1
-			&& mdp3_session->vsync_before_commit) {
+			&& (mdp3_session->vsync_before_commit ||
+			!mdp3_session->intf->active)) {
 		mod_timer(&mdp3_session->vsync_timer,
 			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
 	} else if (enable && !mdp3_session->clk_on) {
@@ -230,7 +233,8 @@
 void mdp3_vsync_timer_func(unsigned long arg)
 {
 	struct mdp3_session_data *session = (struct mdp3_session_data *)arg;
-	if (session->status == 1 && session->vsync_before_commit) {
+	if (session->status == 1 && (session->vsync_before_commit ||
+			!session->intf->active)) {
 		pr_debug("mdp3_vsync_timer_func trigger\n");
 		vsync_notify_handler(session);
 		mod_timer(&session->vsync_timer,
@@ -402,10 +406,10 @@
 	return type;
 }
 
-static int mdp3_ctrl_get_source_format(struct msm_fb_data_type *mfd)
+static int mdp3_ctrl_get_source_format(u32 imgType)
 {
 	int format;
-	switch (mfd->fb_imgType) {
+	switch (imgType) {
 	case MDP_RGB_565:
 		format = MDP3_DMA_IBUF_FORMAT_RGB565;
 		break;
@@ -511,7 +515,7 @@
 	fix = &fbi->fix;
 	var = &fbi->var;
 
-	sourceConfig.format = mdp3_ctrl_get_source_format(mfd);
+	sourceConfig.format = mdp3_ctrl_get_source_format(mfd->fb_imgType);
 	sourceConfig.width = panel_info->xres;
 	sourceConfig.height = panel_info->yres;
 	sourceConfig.x = 0;
@@ -623,17 +627,8 @@
 	}
 
 	mdp3_session->clk_on = 1;
-	pr_debug("mdp3_ctrl_on dma start\n");
-	if (mfd->fbi->screen_base) {
-		rc = mdp3_session->dma->start(mdp3_session->dma,
-						mdp3_session->intf);
-		if (rc) {
-			pr_err("fail to start the MDP display interface\n");
-			goto on_error;
-		}
-	} else {
-		mdp3_session->first_commit = true;
-	}
+
+	mdp3_session->first_commit = true;
 
 on_error:
 	if (!rc)
@@ -713,9 +708,11 @@
 off_error:
 	mdp3_session->status = 0;
 	mdp3_bufq_deinit(&mdp3_session->bufq_out);
+	if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST) {
+		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+		mdp3_bufq_deinit(&mdp3_session->bufq_in);
+	}
 	mutex_unlock(&mdp3_session->lock);
-	if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST)
-		mdp3_overlay_unset(mfd, mdp3_session->overlay.id);
 	return 0;
 }
 
@@ -759,10 +756,7 @@
 	if (vsync_client.handler)
 		mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);
 
-	if (mfd->fbi->screen_base)
-		rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
-	else
-		mdp3_session->first_commit = true;
+	mdp3_session->first_commit = true;
 
 reset_error:
 	mutex_unlock(&mdp3_session->lock);
@@ -850,10 +844,7 @@
 	if (vsync_client.handler)
 		mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);
 
-	if (mfd->fbi->screen_base)
-		rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
-	else
-		mdp3_session->first_commit = true;
+	mdp3_session->first_commit = true;
 
 reset_error:
 	mutex_unlock(&mdp3_session->lock);
@@ -883,14 +874,15 @@
 {
 	int rc = 0;
 	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
-	struct fb_var_screeninfo *var;
+	struct mdp3_dma *dma = mdp3_session->dma;
 	struct fb_fix_screeninfo *fix;
 	struct fb_info *fbi = mfd->fbi;
 	int stride;
+	int format;
 
 	fix = &fbi->fix;
-	var = &fbi->var;
-	stride = req->src.width * var->bits_per_pixel/8;
+	stride = req->src.width * ppp_bpp(req->src.format);
+	format = mdp3_ctrl_get_source_format(req->src.format);
 
 	mutex_lock(&mdp3_session->lock);
 
@@ -899,9 +891,14 @@
 
 	mdp3_session->overlay = *req;
 	if (req->id == MSMFB_NEW_REQUEST) {
-		if (fix->line_length != stride)
-			mdp3_session->dma->config_stride(
-						mdp3_session->dma, stride);
+		if (dma->source_config.stride != stride ||
+				dma->source_config.format != format) {
+			dma->source_config.format = format;
+			dma->source_config.stride = stride;
+			mdp3_clk_enable(1, 0);
+			mdp3_session->dma->dma_config_source(dma);
+			mdp3_clk_enable(0, 0);
+		}
 		mdp3_session->overlay.id = 1;
 		req->id = 1;
 	}
@@ -917,13 +914,19 @@
 	struct mdp3_session_data *mdp3_session = mfd->mdp.private1;
 	struct fb_info *fbi = mfd->fbi;
 	struct fb_fix_screeninfo *fix;
+	int format;
 
 	fix = &fbi->fix;
+	format = mdp3_ctrl_get_source_format(mfd->fb_imgType);
 	mutex_lock(&mdp3_session->lock);
 
 	if (mdp3_session->overlay.id == ndx && ndx == 1) {
-		mdp3_session->dma->config_stride(mdp3_session->dma,
-							fix->line_length);
+		struct mdp3_dma *dma = mdp3_session->dma;
+		dma->source_config.format = format;
+		dma->source_config.stride = fix->line_length;
+		mdp3_clk_enable(1, 0);
+		mdp3_session->dma->dma_config_source(dma);
+		mdp3_clk_enable(0, 0);
 		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
 		mdp3_bufq_deinit(&mdp3_session->bufq_in);
 	} else {
@@ -1007,7 +1010,6 @@
 		mdp3_ctrl_reset(mfd);
 		reset_done = true;
 	}
-	mdp3_release_splash_memory();
 
 	mutex_lock(&mdp3_session->lock);
 
@@ -1042,6 +1044,7 @@
 	}
 
 	if (mdp3_bufq_count(&mdp3_session->bufq_out) > 1) {
+		mdp3_release_splash_memory(mfd);
 		data = mdp3_bufq_pop(&mdp3_session->bufq_out);
 		mdp3_put_img(data, MDP3_CLIENT_DMA_P);
 	}
@@ -1063,7 +1066,10 @@
 	return 0;
 }
 
-static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd)
+static void mdp3_ctrl_pan_display(struct msm_fb_data_type *mfd,
+					struct mdp_overlay *req,
+					int image_size,
+					int *pipe_ndx)
 {
 	struct fb_info *fbi;
 	struct mdp3_session_data *mdp3_session;
@@ -1084,7 +1090,6 @@
 		pr_debug("continuous splash screen, IOMMU not attached\n");
 		mdp3_ctrl_reset(mfd);
 	}
-	mdp3_release_splash_memory();
 
 	mutex_lock(&mdp3_session->lock);
 
@@ -1615,7 +1620,8 @@
 
 	req = &mdp3_session->req_overlay;
 
-	if (!mdp3_session->status && cmd != MSMFB_METADATA_GET) {
+	if (!mdp3_session->status && cmd != MSMFB_METADATA_GET &&
+		cmd != MSMFB_HISTOGRAM_STOP) {
 		pr_err("mdp3_ctrl_ioctl_handler, display off!\n");
 		return -EPERM;
 	}
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 5cae2de..36d5cf1 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -295,23 +295,6 @@
 	return 0;
 }
 
-static void mdp3_dma_stride_config(struct mdp3_dma *dma, int stride)
-{
-	struct mdp3_dma_source *source_config;
-	u32 dma_stride_offset;
-
-	if (dma->dma_sel == MDP3_DMA_P)
-		dma_stride_offset = MDP3_REG_DMA_P_IBUF_Y_STRIDE;
-	else
-		dma_stride_offset = MDP3_REG_DMA_S_IBUF_Y_STRIDE;
-
-	source_config = &dma->source_config;
-	source_config->stride = stride;
-	pr_debug("%s: Update the fb stride for DMA to %d", __func__,
-						(u32)source_config->stride);
-	MDP3_REG_WRITE(dma_stride_offset, source_config->stride);
-}
-
 static int mdp3_dmap_config(struct mdp3_dma *dma,
 			struct mdp3_dma_source *source_config,
 			struct mdp3_dma_output_config *output_config)
@@ -348,6 +331,22 @@
 	return 0;
 }
 
+static void mdp3_dmap_config_source(struct mdp3_dma *dma)
+{
+	struct mdp3_dma_source *source_config = &dma->source_config;
+	u32 dma_p_cfg_reg, dma_p_size;
+
+	dma_p_cfg_reg = MDP3_REG_READ(MDP3_REG_DMA_P_CONFIG);
+	dma_p_cfg_reg &= ~MDP3_DMA_IBUF_FORMAT_MASK;
+	dma_p_cfg_reg |= source_config->format << 25;
+
+	dma_p_size = source_config->width | (source_config->height << 16);
+
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_CONFIG, dma_p_cfg_reg);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_SIZE, dma_p_size);
+	MDP3_REG_WRITE(MDP3_REG_DMA_P_IBUF_Y_STRIDE, source_config->stride);
+}
+
 static int mdp3_dmas_config(struct mdp3_dma *dma,
 			struct mdp3_dma_source *source_config,
 			struct mdp3_dma_output_config *output_config)
@@ -383,6 +382,22 @@
 	return 0;
 }
 
+static void mdp3_dmas_config_source(struct mdp3_dma *dma)
+{
+	struct mdp3_dma_source *source_config = &dma->source_config;
+	u32 dma_s_cfg_reg, dma_s_size;
+
+	dma_s_cfg_reg = MDP3_REG_READ(MDP3_REG_DMA_S_CONFIG);
+	dma_s_cfg_reg &= ~MDP3_DMA_IBUF_FORMAT_MASK;
+	dma_s_cfg_reg |= source_config->format << 25;
+
+	dma_s_size = source_config->width | (source_config->height << 16);
+
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_CONFIG, dma_s_cfg_reg);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_SIZE, dma_s_size);
+	MDP3_REG_WRITE(MDP3_REG_DMA_S_IBUF_Y_STRIDE, source_config->stride);
+}
+
 static int mdp3_dmap_cursor_config(struct mdp3_dma *dma,
 				struct mdp3_dma_cursor *cursor)
 {
@@ -901,6 +916,7 @@
 	switch (dma->dma_sel) {
 	case MDP3_DMA_P:
 		dma->dma_config = mdp3_dmap_config;
+		dma->dma_config_source = mdp3_dmap_config_source;
 		dma->config_cursor = mdp3_dmap_cursor_config;
 		dma->config_ccs = mdp3_dmap_ccs_config;
 		dma->config_histo = mdp3_dmap_histo_config;
@@ -913,10 +929,10 @@
 		dma->dma_done_notifier = mdp3_dma_done_notifier;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
-		dma->config_stride = mdp3_dma_stride_config;
 		break;
 	case MDP3_DMA_S:
 		dma->dma_config = mdp3_dmas_config;
+		dma->dma_config_source = mdp3_dmas_config_source;
 		dma->config_cursor = NULL;
 		dma->config_ccs = NULL;
 		dma->config_histo = NULL;
@@ -928,7 +944,6 @@
 		dma->vsync_enable = mdp3_dma_vsync_enable;
 		dma->start = mdp3_dma_start;
 		dma->stop = mdp3_dma_stop;
-		dma->config_stride = mdp3_dma_stride_config;
 		break;
 	case MDP3_DMA_E:
 	default:
diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h
index 04955d4..207168f 100644
--- a/drivers/video/msm/mdss/mdp3_dma.h
+++ b/drivers/video/msm/mdss/mdp3_dma.h
@@ -264,6 +264,8 @@
 			struct mdp3_dma_source *source_config,
 			struct mdp3_dma_output_config *output_config);
 
+	void (*dma_config_source)(struct mdp3_dma *dma);
+
 	int (*start)(struct mdp3_dma *dma, struct mdp3_intf *intf);
 
 	int (*stop)(struct mdp3_dma *dma, struct mdp3_intf *intf);
@@ -290,8 +292,6 @@
 
 	int (*histo_op)(struct mdp3_dma *dma, u32 op);
 
-	void (*config_stride)(struct mdp3_dma *dma, int stride);
-
 	void (*vsync_enable)(struct mdp3_dma *dma,
 			struct mdp3_notification *vsync_client);
 
diff --git a/drivers/video/msm/mdss/mdp3_hwio.h b/drivers/video/msm/mdss/mdp3_hwio.h
index b457c10..39690ef 100644
--- a/drivers/video/msm/mdss/mdp3_hwio.h
+++ b/drivers/video/msm/mdss/mdp3_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -118,6 +118,9 @@
 #define MDP3_REG_DMA_S_IBUF_Y_STRIDE			0xA000C
 #define MDP3_REG_DMA_S_OUT_XY				0xA0010
 
+/*DMA MASK*/
+#define MDP3_DMA_IBUF_FORMAT_MASK 0x06000000
+
 /*MISR*/
 #define MDP3_REG_MODE_CLK				0x000D0000
 #define MDP3_REG_MISR_RESET_CLK			0x000D0004
@@ -269,6 +272,8 @@
 
 #define MDP3_PPP_BLEND_BG_ALPHA_SEL	0x70010
 
+#define MDP3_PPP_ACTIVE BIT(0)
+
 /*interrupt mask*/
 
 #define MDP3_INTR_DP0_ROI_DONE_BIT			BIT(0)
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index d778af8..8cc29da8 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -83,9 +83,7 @@
 };
 
 struct ppp_status {
-	int busy;
 	bool wait_for_pop;
-	spinlock_t ppp_lock;
 	struct completion ppp_comp;
 	struct completion pop_q_comp;
 	struct mutex req_mutex; /* Protect request queue */
@@ -101,6 +99,7 @@
 	struct timer_list free_bw_timer;
 	struct work_struct free_bw_work;
 	bool bw_on;
+	bool bw_optimal;
 };
 
 static struct ppp_status *ppp_stat;
@@ -271,24 +270,16 @@
 int mdp3_ppp_pipe_wait(void)
 {
 	int ret = 1;
-	int wait;
-	unsigned long flag;
 
 	/*
-	 * wait 5 secs for operation to complete before declaring
+	 * wait 40 ms for ppp operation to complete before declaring
 	 * the MDP hung
 	 */
-	spin_lock_irqsave(&ppp_stat->ppp_lock, flag);
-	wait = ppp_stat->busy;
-	spin_unlock_irqrestore(&ppp_stat->ppp_lock, flag);
-
-	if (wait) {
-		ret = wait_for_completion_interruptible_timeout(
-		   &ppp_stat->ppp_comp, 5 * HZ);
-		if (!ret)
-			pr_err("%s: Timed out waiting for the MDP.\n",
-				__func__);
-	}
+	ret = wait_for_completion_timeout(
+	  &ppp_stat->ppp_comp, msecs_to_jiffies(40));
+	if (!ret)
+		pr_err("%s: Timed out waiting for the MDP.\n",
+			__func__);
 
 	return ret;
 }
@@ -321,11 +312,7 @@
 
 static void mdp3_ppp_intr_handler(int type, void *arg)
 {
-	spin_lock(&ppp_stat->ppp_lock);
-	ppp_stat->busy = false;
-	spin_unlock(&ppp_stat->ppp_lock);
 	complete(&ppp_stat->ppp_comp);
-	mdp3_irq_disable_nosync(type);
 }
 
 static int mdp3_ppp_callback_setup(void)
@@ -342,34 +329,61 @@
 
 void mdp3_ppp_kickoff(void)
 {
-	unsigned long flag;
-	mdp3_irq_enable(MDP3_PPP_DONE);
-
 	init_completion(&ppp_stat->ppp_comp);
-
-	spin_lock_irqsave(&ppp_stat->ppp_lock, flag);
-	ppp_stat->busy = true;
-	spin_unlock_irqrestore(&ppp_stat->ppp_lock, flag);
+	mdp3_irq_enable(MDP3_PPP_DONE);
 	ppp_enable();
-
 	mdp3_ppp_pipe_wait();
+	mdp3_irq_disable(MDP3_PPP_DONE);
+}
+
+int mdp3_ppp_vote_update(struct msm_fb_data_type *mfd)
+{
+	struct mdss_panel_info *panel_info = mfd->panel_info;
+	uint64_t req_bw = 0, ab = 0, ib = 0;
+	int rate = 0;
+	int rc = 0;
+	if (!ppp_stat->bw_on)
+		pr_err("%s: PPP vote update in wrong state\n", __func__);
+
+	rate = MDP_BLIT_CLK_RATE;
+	req_bw = panel_info->xres * panel_info->yres *
+		panel_info->mipi.frame_rate *
+		MDP_PPP_MAX_BPP *
+		MDP_PPP_DYNAMIC_FACTOR *
+		MDP_PPP_MAX_READ_WRITE;
+	ib = (req_bw * 3) / 2;
+
+	if (ppp_stat->bw_optimal)
+		ab = ib / 2;
+	else
+		ab = req_bw;
+	rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+	if (rc < 0) {
+		pr_err("%s: scale_set_quota failed\n", __func__);
+		return rc;
+	}
+	return rc;
 }
 
 int mdp3_ppp_turnon(struct msm_fb_data_type *mfd, int on_off)
 {
 	struct mdss_panel_info *panel_info = mfd->panel_info;
-	uint64_t ab = 0, ib = 0;
+	uint64_t req_bw = 0, ab = 0, ib = 0;
 	int rate = 0;
 	int rc;
 
 	if (on_off) {
 		rate = MDP_BLIT_CLK_RATE;
-		ab = panel_info->xres * panel_info->yres *
+		req_bw = panel_info->xres * panel_info->yres *
 			panel_info->mipi.frame_rate *
 			MDP_PPP_MAX_BPP *
 			MDP_PPP_DYNAMIC_FACTOR *
 			MDP_PPP_MAX_READ_WRITE;
-		ib = (ab * 3) / 2;
+		ib = (req_bw * 3) / 2;
+		if (ppp_stat->bw_optimal)
+			ab = ib / 2;
+		else
+			ab = req_bw;
 	}
 	mdp3_clk_set_rate(MDP3_CLK_CORE, rate, MDP3_CLIENT_PPP);
 	rc = mdp3_clk_enable(on_off, 0);
@@ -387,10 +401,21 @@
 	return 0;
 }
 
+bool mdp3_optimal_bw(int req_cnt)
+{
+	if (req_cnt == 1 && ppp_stat->req_q.count == 1)
+		return true;
+	return false;
+}
+
 void mdp3_start_ppp(struct ppp_blit_op *blit_op)
 {
 	/* Wait for the pipe to clear */
-	do { } while (mdp3_ppp_pipe_wait() <= 0);
+	if (MDP3_REG_READ(MDP3_REG_DISPLAY_STATUS) &
+			MDP3_PPP_ACTIVE) {
+		pr_err("ppp core is hung up on previous request\n");
+		return;
+	}
 	config_ppp_op_mode(blit_op);
 	if (blit_op->solid_fill) {
 		MDP3_REG_WRITE(0x10138, 0x10000000);
@@ -1046,6 +1071,7 @@
 			pr_err("%s: mdp3_iommu_enable failed\n", __func__);
 			return;
 		}
+		ppp_stat->bw_optimal = mdp3_optimal_bw(req->count);
 		mdp3_ppp_turnon(mfd, 1);
 		if (rc < 0) {
 			mdp3_iommu_disable(MDP3_CLIENT_PPP);
@@ -1079,6 +1105,10 @@
 		if (ppp_stat->wait_for_pop)
 			complete(&ppp_stat->pop_q_comp);
 		mutex_unlock(&ppp_stat->req_mutex);
+		if (req && (ppp_stat->bw_optimal != mdp3_optimal_bw(req->count))) {
+			ppp_stat->bw_optimal = !ppp_stat->bw_optimal;
+			mdp3_ppp_vote_update(mfd);
+		}
 	}
 	mod_timer(&ppp_stat->free_bw_timer, jiffies +
 		msecs_to_jiffies(MDP_RELEASE_BW_TIMEOUT));
@@ -1099,7 +1129,7 @@
 	while (req_q->count >= MDP3_PPP_MAX_LIST_REQ) {
 		ppp_stat->wait_for_pop = true;
 		mutex_unlock(&ppp_stat->req_mutex);
-		rc = wait_for_completion_interruptible_timeout(
+		rc = wait_for_completion_timeout(
 		   &ppp_stat->pop_q_comp, 5 * HZ);
 		if (rc == 0) {
 			/* This will only occur if there is serious problem */
@@ -1211,13 +1241,11 @@
 	INIT_WORK(&ppp_stat->blit_work, mdp3_ppp_blit_wq_handler);
 	INIT_WORK(&ppp_stat->free_bw_work, mdp3_free_bw_wq_handler);
 	init_completion(&ppp_stat->pop_q_comp);
-	spin_lock_init(&ppp_stat->ppp_lock);
 	mutex_init(&ppp_stat->req_mutex);
 	mutex_init(&ppp_stat->config_ppp_mutex);
 	init_timer(&ppp_stat->free_bw_timer);
 	ppp_stat->free_bw_timer.function = mdp3_free_fw_timer_func;
 	ppp_stat->free_bw_timer.data = 0;
-	ppp_stat->busy = false;
 	ppp_stat->mfd = mfd;
 	mdp3_ppp_callback_setup();
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index ce4005e..ada1281 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -79,6 +79,21 @@
 	spinlock_t lock;
 };
 
+struct mdss_fudge_factor {
+	u32 numer;
+	u32 denom;
+};
+
+struct mdss_prefill_data {
+	u32 ot_bytes;
+	u32 y_buf_bytes;
+	u32 y_scaler_lines_bilinear;
+	u32 y_scaler_lines_caf;
+	u32 post_scaler_pixels;
+	u32 pp_pixels;
+	u32 fbc_lines;
+};
+
 struct mdss_data_type {
 	u32 mdp_rev;
 	struct clk *mdp_clk[MDSS_MAX_CLK];
@@ -93,6 +108,8 @@
 	size_t mdp_reg_size;
 	char __iomem *vbif_base;
 
+	struct mutex reg_lock;
+
 	u32 irq;
 	u32 irq_mask;
 	u32 irq_ena;
@@ -102,6 +119,7 @@
 	u8 has_wfd_blk;
 	u8 has_wb_ad;
 
+	u32 rotator_ot_limit;
 	u32 mdp_irq_mask;
 	u32 mdp_hist_irq_mask;
 
@@ -112,8 +130,8 @@
 	unsigned long min_mdp_clk;
 
 	u32 res_init;
-	u32 bus_hdl;
 
+	u32 highest_bank_bit;
 	u32 smp_mb_cnt;
 	u32 smp_mb_size;
 	u32 smp_mb_per_pipe;
@@ -123,6 +141,15 @@
 	u32 max_bw_low;
 	u32 max_bw_high;
 
+	u32 axi_port_cnt;
+	u32 curr_bw_uc_idx;
+	u32 bus_hdl;
+	struct msm_bus_scale_pdata *bus_scale_table;
+
+	struct mdss_fudge_factor ab_factor;
+	struct mdss_fudge_factor ib_factor;
+	struct mdss_fudge_factor clk_factor;
+
 	struct mdss_hw_settings *hw_settings;
 
 	struct mdss_mdp_pipe *vig_pipes;
@@ -160,9 +187,11 @@
 
 	struct early_suspend early_suspend;
 	struct mdss_debug_inf debug_inf;
-	int current_bus_idx;
 	bool mixer_switched;
 	struct mdss_panel_cfg pan_cfg;
+
+	int handoff_pending;
+	struct mdss_prefill_data prefill_data;
 };
 extern struct mdss_data_type *mdss_res;
 
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 54c8a06..44cc4a2 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -642,33 +642,58 @@
 
 	if (new_fps !=
 		ctrl_pdata->panel_data.panel_info.mipi.frame_rate) {
-		rc = mdss_dsi_clk_div_config
-			(&ctrl_pdata->panel_data.panel_info, new_fps);
-		if (rc) {
-			pr_err("%s: unable to initialize the clk dividers\n",
-							__func__);
-			return rc;
-		}
-		ctrl_pdata->pclk_rate =
-			ctrl_pdata->panel_data.panel_info.mipi.dsi_pclk_rate;
-		ctrl_pdata->byte_clk_rate =
-			ctrl_pdata->panel_data.panel_info.clk_rate / 8;
-
 		if (pdata->panel_info.dfps_update
-				== DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
-			dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) +
-					    0x0004);
-			ctrl_pdata->panel_data.panel_info.mipi.frame_rate =
-									new_fps;
-			dsi_ctrl &= ~0x2;
-			MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
-							dsi_ctrl);
-			mdss_dsi_controller_cfg(true, pdata);
-			mdss_dsi_clk_ctrl(ctrl_pdata, 0);
-			mdss_dsi_clk_ctrl(ctrl_pdata, 1);
-			dsi_ctrl |= 0x2;
-			MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
-							dsi_ctrl);
+			== DFPS_IMMEDIATE_PORCH_UPDATE_MODE) {
+			u32 hsync_period, vsync_period;
+			u32 new_dsi_v_total, current_dsi_v_total;
+			vsync_period =
+				mdss_panel_get_vtotal(&pdata->panel_info);
+			hsync_period =
+				mdss_panel_get_htotal(&pdata->panel_info);
+			current_dsi_v_total =
+				MIPI_INP((ctrl_pdata->ctrl_base) + 0x2C);
+			new_dsi_v_total =
+				((vsync_period - 1) << 16) | (hsync_period - 1);
+			MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
+				(current_dsi_v_total | 0x8000000));
+			if (new_dsi_v_total & 0x8000000) {
+				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
+					new_dsi_v_total);
+			} else {
+				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
+					(new_dsi_v_total | 0x8000000));
+				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x2C,
+					(new_dsi_v_total & 0x7ffffff));
+			}
+			pdata->panel_info.mipi.frame_rate = new_fps;
+		} else {
+			rc = mdss_dsi_clk_div_config
+				(&ctrl_pdata->panel_data.panel_info, new_fps);
+			if (rc) {
+				pr_err("%s: unable to initialize the clk dividers\n",
+								__func__);
+				return rc;
+			}
+			ctrl_pdata->pclk_rate =
+				pdata->panel_info.mipi.dsi_pclk_rate;
+			ctrl_pdata->byte_clk_rate =
+				pdata->panel_info.clk_rate / 8;
+
+			if (pdata->panel_info.dfps_update
+					== DFPS_IMMEDIATE_CLK_UPDATE_MODE) {
+				dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) +
+						    0x0004);
+				pdata->panel_info.mipi.frame_rate = new_fps;
+				dsi_ctrl &= ~0x2;
+				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
+								dsi_ctrl);
+				mdss_dsi_controller_cfg(true, pdata);
+				mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+				mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+				dsi_ctrl |= 0x2;
+				MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
+								dsi_ctrl);
+			}
 		}
 	} else {
 		pr_debug("%s: Panel is already at this FPS\n", __func__);
@@ -1196,6 +1221,12 @@
 						DFPS_IMMEDIATE_CLK_UPDATE_MODE;
 				pr_debug("%s: dfps mode: Immediate clk\n",
 								__func__);
+			} else if (!strcmp(data,
+					    "dfps_immediate_porch_mode")) {
+				pinfo->dfps_update =
+					DFPS_IMMEDIATE_PORCH_UPDATE_MODE;
+				pr_debug("%s: dfps mode: Immediate porch\n",
+								__func__);
 			} else {
 				pr_debug("%s: dfps to default mode\n",
 								__func__);
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 855ec6c..b89a935 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -330,7 +330,8 @@
 void mdss_dsi_phy_enable(struct mdss_dsi_ctrl_pdata *ctrl, int on);
 void mdss_dsi_phy_init(struct mdss_panel_data *pdata);
 void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base);
-void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata);
+void mdss_dsi_cmd_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_video_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl);
 
 void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl);
diff --git a/drivers/video/msm/mdss/mdss_dsi_cmd.h b/drivers/video/msm/mdss/mdss_dsi_cmd.h
index c480756..f806e78 100644
--- a/drivers/video/msm/mdss/mdss_dsi_cmd.h
+++ b/drivers/video/msm/mdss/mdss_dsi_cmd.h
@@ -98,6 +98,7 @@
 #define CMD_REQ_COMMIT  0x0002
 #define CMD_CLK_CTRL    0x0004
 #define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+#define CMD_REQ_LP_MODE 0x0010
 
 struct dcs_cmd_req {
 	struct dsi_cmd_desc *cmds;
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 65e6214..bd156fc 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -200,28 +200,34 @@
 	spin_unlock(&ctrl->irq_lock);
 }
 
-void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata)
+void mdss_dsi_video_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl)
 {
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	int i;
 
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return;
-	}
-
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x015c, 0x201);
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x016c, 0xff0000); /* red */
+	MIPI_OUTP((ctrl->ctrl_base) + 0x015c, 0x021);
+	MIPI_OUTP((ctrl->ctrl_base) + 0x0164, 0xff0000); /* red */
 	i = 0;
 	while (i++ < 50) {
-		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0184, 0x1);
+		MIPI_OUTP((ctrl->ctrl_base) + 0x0180, 0x1);
 		/* Add sleep to get ~50 fps frame rate*/
 		msleep(20);
 	}
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x015c, 0x0);
+	MIPI_OUTP((ctrl->ctrl_base) + 0x015c, 0x0);
+}
+
+void mdss_dsi_cmd_test_pattern(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	int i;
+
+	MIPI_OUTP((ctrl->ctrl_base) + 0x015c, 0x201);
+	MIPI_OUTP((ctrl->ctrl_base) + 0x016c, 0xff0000); /* red */
+	i = 0;
+	while (i++ < 50) {
+		MIPI_OUTP((ctrl->ctrl_base) + 0x0184, 0x1);
+		/* Add sleep to get ~50 fps frame rate*/
+		msleep(20);
+	}
+	MIPI_OUTP((ctrl->ctrl_base) + 0x015c, 0x0);
 }
 
 void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 8c3e470..6e44099 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -118,6 +118,11 @@
 	cmdreq.cmds = pcmds->cmds;
 	cmdreq.cmds_cnt = pcmds->cmd_cnt;
 	cmdreq.flags = CMD_REQ_COMMIT;
+
+	/*Panel ON/Off commands should be sent in DSI Low Power Mode*/
+	if (pcmds->link_state == DSI_LP_MODE)
+		cmdreq.flags  |= CMD_REQ_LP_MODE;
+
 	cmdreq.rlen = 0;
 	cmdreq.cb = NULL;
 
@@ -824,7 +829,7 @@
 	rc = of_property_read_u32(np, "qcom,mdss-dsi-virtual-channel-id", &tmp);
 	pinfo->mipi.vc = (!rc ? tmp : 0);
 	pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
-	data = of_get_property(np, "mdss-dsi-color-order", NULL);
+	data = of_get_property(np, "qcom,mdss-dsi-color-order", NULL);
 	if (data) {
 		if (!strcmp(data, "rgb_swap_rbg"))
 			pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RBG;
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 95c746e..eca73a8 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -33,8 +33,6 @@
 #include <mach/dma.h>
 
 #include "mdss.h"
-#include "mdss_panel.h"
-#include "mdss_mdp.h"
 #include "mdss_edp.h"
 #include "mdss_debug.h"
 
@@ -198,6 +196,7 @@
 	int ret = 0;
 	struct mdss_edp_drv_pdata *edp_drv = NULL;
 	int bl_max;
+	int period_ns;
 
 	edp_drv = container_of(pdata, struct mdss_edp_drv_pdata, panel_data);
 	if (!edp_drv) {
@@ -210,13 +209,29 @@
 		if (bl_level > bl_max)
 			bl_level = bl_max;
 
-		ret = pwm_config_us(edp_drv->bl_pwm,
-				bl_level * edp_drv->pwm_period / bl_max,
-				edp_drv->pwm_period);
-		if (ret) {
-			pr_err("%s: pwm_config_us() failed err=%d.\n", __func__,
-					ret);
-			return;
+		/* In order to avoid overflow, use the microsecond version
+		 * of pwm_config if the pwm_period is greater than or equal
+		 * to 1 second.
+		 */
+		if (edp_drv->pwm_period >= USEC_PER_SEC) {
+			ret = pwm_config_us(edp_drv->bl_pwm,
+					bl_level * edp_drv->pwm_period / bl_max,
+					edp_drv->pwm_period);
+			if (ret) {
+				pr_err("%s: pwm_config_us() failed err=%d.\n",
+						__func__, ret);
+				return;
+			}
+		} else {
+			period_ns = edp_drv->pwm_period * NSEC_PER_USEC;
+			ret = pwm_config(edp_drv->bl_pwm,
+					bl_level * period_ns / bl_max,
+					period_ns);
+			if (ret) {
+				pr_err("%s: pwm_config() failed err=%d.\n",
+						__func__, ret);
+				return;
+			}
 		}
 
 		ret = pwm_enable(edp_drv->bl_pwm);
@@ -375,6 +390,7 @@
 void mdss_edp_clock_synchrous(struct mdss_edp_drv_pdata *ep, int sync)
 {
 	u32 data;
+	u32 color;
 
 	/* EDP_MISC1_MISC0 */
 	data = edp_read(ep->base + 0x02c);
@@ -384,6 +400,20 @@
 	else
 		data &= ~0x01;
 
+	/* only legacy rgb mode supported */
+	color = 0; /* 6 bits */
+	if (ep->edid.color_depth == 8)
+		color = 0x01;
+	else if (ep->edid.color_depth == 10)
+		color = 0x02;
+	else if (ep->edid.color_depth == 12)
+		color = 0x03;
+	else if (ep->edid.color_depth == 16)
+		color = 0x04;
+
+	color <<= 5;    /* bit 5 to bit 7 */
+
+	data |= color;
 	/* EDP_MISC1_MISC0 */
 	edp_write(ep->base + 0x2c, data);
 }
@@ -515,8 +545,6 @@
 
 	pr_debug("%s:+, cont_splash=%d\n", __func__, edp_drv->cont_splash);
 
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-
 	if (!edp_drv->cont_splash) { /* vote for clocks */
 		mdss_edp_phy_pll_reset(edp_drv);
 		mdss_edp_aux_reset(edp_drv);
@@ -576,6 +604,8 @@
 	}
 	pr_debug("%s:+, cont_splash=%d\n", __func__, edp_drv->cont_splash);
 
+	/* wait until link training is completed */
+	mutex_lock(&edp_drv->train_mutex);
 
 	INIT_COMPLETION(edp_drv->idle_comp);
 	mdss_edp_state_ctrl(edp_drv, ST_PUSH_IDLE);
@@ -605,12 +635,12 @@
 	mdss_edp_clk_disable(edp_drv);
 	mdss_edp_unprepare_clocks(edp_drv);
 
-	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-
 	mdss_edp_aux_ctrl(edp_drv, 0);
 
 	pr_debug("%s-: state_ctrl=%x\n", __func__,
 				edp_read(edp_drv->base + 0x8));
+
+	mutex_unlock(&edp_drv->train_mutex);
 	return 0;
 }
 
@@ -707,6 +737,9 @@
 	edp_drv->panel_data.panel_info.brightness_max =
 		(!ret ? tmp : MDSS_MAX_BL_BRIGHTNESS);
 
+	edp_drv->panel_data.panel_info.edp.frame_rate =
+				DEFAULT_FRAME_RATE;/* 60 fps */
+
 	edp_drv->panel_data.event_handler = mdss_edp_event_handler;
 	edp_drv->panel_data.set_backlight = mdss_edp_set_backlight;
 
@@ -792,7 +825,6 @@
 	if (ep->cont_splash)
 		return;
 
-	INIT_COMPLETION(ep->train_comp);
 	mdss_edp_link_train(ep);
 }
 
@@ -1073,10 +1105,6 @@
 
 	pr_debug("%s:cont_splash=%d\n", __func__, edp_drv->cont_splash);
 
-	/* need mdss clock to receive irq */
-	if (!edp_drv->cont_splash)
-		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
-
 	/* only need aux and ahb clock for aux channel */
 	mdss_edp_prepare_aux_clocks(edp_drv);
 	mdss_edp_aux_clk_enable(edp_drv);
@@ -1105,9 +1133,6 @@
 	mdss_edp_aux_clk_disable(edp_drv);
 	mdss_edp_unprepare_aux_clocks(edp_drv);
 
-	if (!edp_drv->cont_splash)
-		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-
 	if (edp_drv->cont_splash) { /* vote for clocks */
 		mdss_edp_prepare_clocks(edp_drv);
 		mdss_edp_clk_enable(edp_drv);
diff --git a/drivers/video/msm/mdss/mdss_edp.h b/drivers/video/msm/mdss/mdss_edp.h
index 0c0200d..12e3be7 100644
--- a/drivers/video/msm/mdss/mdss_edp.h
+++ b/drivers/video/msm/mdss/mdss_edp.h
@@ -293,6 +293,7 @@
 	struct clk *pixel_clk;
 	struct clk *ahb_clk;
 	struct clk *link_clk;
+	struct clk *mdp_core_clk;
 	int clk_on;
 
 	/* gpios */
@@ -314,6 +315,7 @@
 	struct completion idle_comp;
 	struct completion video_comp;
 	struct mutex aux_mutex;
+	struct mutex train_mutex;
 	u32 aux_cmd_busy;
 	u32 aux_cmd_i2c;
 	int aux_trans_num;
diff --git a/drivers/video/msm/mdss/mdss_edp_aux.c b/drivers/video/msm/mdss/mdss_edp_aux.c
index bbcee19..1c36ab0 100644
--- a/drivers/video/msm/mdss/mdss_edp_aux.c
+++ b/drivers/video/msm/mdss/mdss_edp_aux.c
@@ -1196,7 +1196,6 @@
 static void edp_clear_training_pattern(struct mdss_edp_drv_pdata *ep)
 {
 	pr_debug("%s:\n", __func__);
-	edp_write(ep->base + EDP_STATE_CTRL, 0);
 	edp_train_pattern_set_write(ep, 0);
 	usleep(ep->dpcd.training_read_interval);
 }
@@ -1224,6 +1223,7 @@
 	mdss_edp_config_ctrl(ep);
 	mdss_edp_lane_power_ctrl(ep, 1);
 
+	mdss_edp_state_ctrl(ep, 0);
 	edp_clear_training_pattern(ep);
 	usleep(ep->dpcd.training_read_interval);
 
@@ -1240,6 +1240,7 @@
 
 	pr_debug("%s: Training 1 completed successfully", __func__);
 
+	mdss_edp_state_ctrl(ep, 0);
 	edp_clear_training_pattern(ep);
 	ret = edp_start_link_train_2(ep);
 	if (ret < 0) {
@@ -1312,12 +1313,18 @@
 
 int mdss_edp_link_train(struct mdss_edp_drv_pdata *ep)
 {
-	return edp_aux_link_train(ep);
+	int ret;
+
+	mutex_lock(&ep->train_mutex);
+	ret = edp_aux_link_train(ep);
+	mutex_unlock(&ep->train_mutex);
+	return ret;
 }
 
 void mdss_edp_aux_init(struct mdss_edp_drv_pdata *ep)
 {
 	mutex_init(&ep->aux_mutex);
+	mutex_init(&ep->train_mutex);
 	init_completion(&ep->aux_comp);
 	init_completion(&ep->train_comp);
 	init_completion(&ep->idle_comp);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index c2db15c..41aaf61 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -2,7 +2,7 @@
  * Core MDSS framebuffer driver.
  *
  * Copyright (C) 2007 Google Incorporated
- * Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2014, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -121,20 +121,28 @@
 	if (notify > NOTIFY_UPDATE_POWER_OFF)
 		return -EINVAL;
 
-	if (notify == NOTIFY_UPDATE_START) {
+	if (mfd->update.is_suspend) {
+		to_user = NOTIFY_TYPE_SUSPEND;
+		mfd->update.is_suspend = 0;
+		ret = 1;
+	} else if (notify == NOTIFY_UPDATE_START) {
 		INIT_COMPLETION(mfd->update.comp);
-		ret = wait_for_completion_interruptible_timeout(
+		ret = wait_for_completion_timeout(
 						&mfd->update.comp, 4 * HZ);
 		to_user = (unsigned int)mfd->update.value;
+		if (mfd->update.type == NOTIFY_TYPE_SUSPEND) {
+			to_user = (unsigned int)mfd->update.type;
+			ret = 1;
+		}
 	} else if (notify == NOTIFY_UPDATE_STOP) {
 		INIT_COMPLETION(mfd->no_update.comp);
-		ret = wait_for_completion_interruptible_timeout(
+		ret = wait_for_completion_timeout(
 						&mfd->no_update.comp, 4 * HZ);
 		to_user = (unsigned int)mfd->no_update.value;
 	} else {
 		if (mfd->panel_power_on) {
 			INIT_COMPLETION(mfd->power_off_comp);
-			ret = wait_for_completion_interruptible_timeout(
+			ret = wait_for_completion_timeout(
 						&mfd->power_off_comp, 1 * HZ);
 		}
 	}
@@ -146,6 +154,47 @@
 	return ret;
 }
 
+static int mdss_fb_splash_thread(void *data)
+{
+	struct msm_fb_data_type *mfd = data;
+	int ret = -EINVAL;
+	struct fb_info *fbi = NULL;
+	int ov_index[2];
+
+	if (!mfd || !mfd->fbi || !mfd->mdp.splash_fnc) {
+		pr_err("Invalid input parameter\n");
+		goto end;
+	}
+
+	fbi = mfd->fbi;
+
+	ret = mdss_fb_open(fbi, current->tgid);
+	if (ret) {
+		pr_err("fb_open failed\n");
+		goto end;
+	}
+
+	mfd->bl_updated = true;
+	mdss_fb_set_backlight(mfd, mfd->panel_info->bl_max >> 1);
+
+	ret = mfd->mdp.splash_fnc(mfd, ov_index, MDP_CREATE_SPLASH_OV);
+	if (ret) {
+		pr_err("Splash image failed\n");
+		goto splash_err;
+	}
+
+	do {
+		schedule_timeout_interruptible(SPLASH_THREAD_WAIT_TIMEOUT * HZ);
+	} while (!kthread_should_stop());
+
+	mfd->mdp.splash_fnc(mfd, ov_index, MDP_REMOVE_SPLASH_OV);
+
+splash_err:
+	mdss_fb_release(fbi, current->tgid);
+end:
+	return ret;
+}
+
 static int lcd_backlight_registered;
 
 static void mdss_fb_set_bl_brightness(struct led_classdev *led_cdev,
@@ -219,10 +268,14 @@
 	return ret;
 }
 
-static void mdss_fb_parse_dt_split(struct msm_fb_data_type *mfd)
+static void mdss_fb_parse_dt(struct msm_fb_data_type *mfd)
 {
 	u32 data[2];
 	struct platform_device *pdev = mfd->pdev;
+
+	mfd->splash_logo_enabled = of_property_read_bool(pdev->dev.of_node,
+				"qcom,mdss-fb-splash-logo-enabled");
+
 	if (of_property_read_u32_array(pdev->dev.of_node, "qcom,mdss-fb-split",
 				       data, 2))
 		return;
@@ -394,17 +447,37 @@
 		 mfd->mdp_sync_pt_data.timeline =
 				sw_sync_timeline_create(timeline_name);
 		if (mfd->mdp_sync_pt_data.timeline == NULL) {
-			pr_err("%s: cannot create time line", __func__);
+			pr_err("cannot create release fence time line\n");
 			return -ENOMEM;
 		}
 		mfd->mdp_sync_pt_data.notifier.notifier_call =
 			__mdss_fb_sync_buf_done_callback;
 	}
-	if ((mfd->panel.type == WRITEBACK_PANEL) ||
-			(mfd->panel.type == MIPI_CMD_PANEL))
+
+	switch (mfd->panel.type) {
+	case WRITEBACK_PANEL:
 		mfd->mdp_sync_pt_data.threshold = 1;
-	else
+		mfd->mdp_sync_pt_data.retire_threshold = 0;
+		break;
+	case MIPI_CMD_PANEL:
+		mfd->mdp_sync_pt_data.threshold = 1;
+		mfd->mdp_sync_pt_data.retire_threshold = 1;
+		break;
+	default:
 		mfd->mdp_sync_pt_data.threshold = 2;
+		mfd->mdp_sync_pt_data.retire_threshold = 0;
+		break;
+	}
+
+	if (mfd->splash_logo_enabled) {
+		mfd->splash_thread = kthread_run(mdss_fb_splash_thread, mfd,
+				"mdss_fb_splash");
+		if (IS_ERR(mfd->splash_thread)) {
+			pr_err("unable to start splash thread %d\n",
+				mfd->index);
+			mfd->splash_thread = NULL;
+		}
+	}
 
 	return rc;
 }
@@ -718,6 +791,7 @@
 			}
 			mutex_lock(&mfd->update.lock);
 			mfd->update.type = NOTIFY_TYPE_UPDATE;
+			mfd->update.is_suspend = 0;
 			mutex_unlock(&mfd->update.lock);
 		}
 		break;
@@ -732,7 +806,9 @@
 
 			mutex_lock(&mfd->update.lock);
 			mfd->update.type = NOTIFY_TYPE_SUSPEND;
+			mfd->update.is_suspend = 1;
 			mutex_unlock(&mfd->update.lock);
+			complete(&mfd->update.comp);
 			del_timer(&mfd->no_update.timer);
 			mfd->no_update.value = NOTIFY_TYPE_SUSPEND;
 			complete(&mfd->no_update.comp);
@@ -1089,7 +1165,7 @@
 	mfd->panel_power_on = false;
 	mfd->dcm_state = DCM_UNINIT;
 
-	mdss_fb_parse_dt_split(mfd);
+	mdss_fb_parse_dt(mfd);
 
 	if (mdss_fb_alloc_fbmem(mfd)) {
 		pr_err("unable to allocate framebuffer memory\n");
@@ -1191,6 +1267,12 @@
 	pinfo->ref_cnt++;
 	mfd->ref_cnt++;
 
+	/* Stop the splash thread once userspace open the fb node */
+	if (mfd->splash_thread && mfd->ref_cnt > 1) {
+		kthread_stop(mfd->splash_thread);
+		mfd->splash_thread = NULL;
+	}
+
 	return 0;
 
 blank_error:
@@ -1568,7 +1650,7 @@
 		(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
 
 	if (mfd->mdp.dma_fnc)
-		mfd->mdp.dma_fnc(mfd);
+		mfd->mdp.dma_fnc(mfd, NULL, 0, NULL);
 	else
 		pr_warn("dma function not set for panel type=%d\n",
 				mfd->panel.type);
@@ -1932,42 +2014,37 @@
 }
 
 /**
- * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline
- * @sync_pt_data:	Sync pt structure holding timeline and fence info.
+ * mdss_fb_sync_get_fence() - get fence from timeline
+ * @timeline:	Timeline to create the fence on
+ * @fence_name:	Name of the fence that will be created for debugging
+ * @val:	Timeline value at which the fence will be signaled
  *
- * Function returns a release fence on the timeline associated with the
- * sync pt struct given and it's associated information. The release fence
- * created can be used to signal when buffers provided will be released.
+ * Function returns a fence on the timeline given with the name provided.
+ * The fence created will be signaled when the timeline is advanced.
  */
-static struct sync_fence *__mdss_fb_sync_get_rel_fence(
-		struct msm_sync_pt_data *sync_pt_data)
+struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline,
+		const char *fence_name, int val)
 {
-	struct sync_pt *rel_sync_pt;
-	struct sync_fence *rel_fence;
-	int val;
+	struct sync_pt *sync_pt;
+	struct sync_fence *fence;
 
-	val = sync_pt_data->timeline_value + sync_pt_data->threshold +
-		atomic_read(&sync_pt_data->commit_cnt);
+	pr_debug("%s: buf sync fence timeline=%d\n", fence_name, val);
 
-	pr_debug("%s: buf sync rel fence timeline=%d\n",
-		sync_pt_data->fence_name, val);
-
-	rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val);
-	if (rel_sync_pt == NULL) {
-		pr_err("%s: cannot create sync point\n",
-				sync_pt_data->fence_name);
+	sync_pt = sw_sync_pt_create(timeline, val);
+	if (sync_pt == NULL) {
+		pr_err("%s: cannot create sync point\n", fence_name);
 		return NULL;
 	}
 
 	/* create fence */
-	rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt);
-	if (rel_fence == NULL) {
-		sync_pt_free(rel_sync_pt);
-		pr_err("%s: cannot create fence\n", sync_pt_data->fence_name);
+	fence = sync_fence_create(fence_name, sync_pt);
+	if (fence == NULL) {
+		sync_pt_free(sync_pt);
+		pr_err("%s: cannot create fence\n", fence_name);
 		return NULL;
 	}
 
-	return rel_fence;
+	return fence;
 }
 
 static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data,
@@ -1975,8 +2052,10 @@
 {
 	int i, ret = 0;
 	int acq_fen_fd[MDP_MAX_FENCE_FD];
-	struct sync_fence *fence, *rel_fence;
+	struct sync_fence *fence, *rel_fence, *retire_fence;
 	int rel_fen_fd;
+	int retire_fen_fd;
+	int val;
 
 	if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
 				(sync_pt_data->timeline == NULL))
@@ -2013,7 +2092,12 @@
 	if (ret)
 		goto buf_sync_err_1;
 
-	rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data);
+	val = sync_pt_data->timeline_value + sync_pt_data->threshold +
+			atomic_read(&sync_pt_data->commit_cnt);
+
+	/* Set release fence */
+	rel_fence = mdss_fb_sync_get_fence(sync_pt_data->timeline,
+			sync_pt_data->fence_name, val);
 	if (IS_ERR_OR_NULL(rel_fence)) {
 		pr_err("%s: unable to retrieve release fence\n",
 				sync_pt_data->fence_name);
@@ -2037,6 +2121,50 @@
 		pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name);
 		goto buf_sync_err_3;
 	}
+
+	if (!(buf_sync->flags & MDP_BUF_SYNC_FLAG_RETIRE_FENCE))
+		goto skip_retire_fence;
+
+	if (sync_pt_data->get_retire_fence)
+		retire_fence = sync_pt_data->get_retire_fence(sync_pt_data);
+	else
+		retire_fence = NULL;
+
+	if (IS_ERR_OR_NULL(retire_fence)) {
+		val += sync_pt_data->retire_threshold;
+		retire_fence = mdss_fb_sync_get_fence(
+			sync_pt_data->timeline, "mdp-retire", val);
+	}
+
+	if (IS_ERR_OR_NULL(retire_fence)) {
+		pr_err("%s: unable to retrieve retire fence\n",
+				sync_pt_data->fence_name);
+		ret = retire_fence ? PTR_ERR(rel_fence) : -ENOMEM;
+		goto buf_sync_err_3;
+	}
+	retire_fen_fd = get_unused_fd_flags(0);
+
+	if (retire_fen_fd < 0) {
+		pr_err("%s: get_unused_fd_flags failed for retire fence\n",
+				sync_pt_data->fence_name);
+		ret = -EIO;
+		sync_fence_put(retire_fence);
+		goto buf_sync_err_3;
+	}
+
+	sync_fence_install(retire_fence, retire_fen_fd);
+
+	ret = copy_to_user(buf_sync->retire_fen_fd, &retire_fen_fd,
+			sizeof(int));
+	if (ret) {
+		pr_err("%s: copy_to_user failed for retire fence\n",
+				sync_pt_data->fence_name);
+		put_unused_fd(retire_fen_fd);
+		sync_fence_put(retire_fence);
+		goto buf_sync_err_3;
+	}
+
+skip_retire_fence:
 	mutex_unlock(&sync_pt_data->sync_mutex);
 
 	if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
@@ -2294,3 +2422,27 @@
 }
 
 module_init(mdss_fb_init);
+
+int mdss_fb_suspres_panel(struct device *dev, void *data)
+{
+	struct msm_fb_data_type *mfd;
+	int rc;
+	u32 event;
+
+	if (!data) {
+		pr_err("Device state not defined\n");
+		return -EINVAL;
+	}
+	mfd = dev_get_drvdata(dev);
+	if (!mfd)
+		return 0;
+
+	event = *((bool *) data) ? MDSS_EVENT_RESUME : MDSS_EVENT_SUSPEND;
+
+	rc = mdss_fb_send_panel_event(mfd, event, NULL);
+	if (rc)
+		pr_warn("unable to %s fb%d (%d)\n",
+			event == MDSS_EVENT_RESUME ? "resume" : "suspend",
+			mfd->index, rc);
+	return rc;
+}
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index e245dd3..2e024c9 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -33,6 +33,8 @@
 #define WAIT_DISP_OP_TIMEOUT ((WAIT_FENCE_FIRST_TIMEOUT + \
 		WAIT_FENCE_FINAL_TIMEOUT) * MDP_MAX_FENCE_FD)
 
+#define SPLASH_THREAD_WAIT_TIMEOUT 3
+
 #ifndef MAX
 #define  MAX(x, y) (((x) > (y)) ? (x) : (y))
 #endif
@@ -67,6 +69,11 @@
 	MDP_NOTIFY_FRAME_TIMEOUT,
 };
 
+enum mdp_splash_event {
+	MDP_CREATE_SPLASH_OV = 0,
+	MDP_REMOVE_SPLASH_OV,
+};
+
 struct disp_info_type_suspend {
 	int op_enable;
 	int panel_power_on;
@@ -78,6 +85,7 @@
 	struct completion comp;
 	struct mutex lock;
 	int value;
+	int is_suspend;
 };
 
 struct msm_sync_pt_data {
@@ -88,13 +96,16 @@
 	struct sw_sync_timeline *timeline;
 	int timeline_value;
 	u32 threshold;
-
+	u32 retire_threshold;
 	atomic_t commit_cnt;
 	bool flushed;
 	bool async_wait_fences;
 
 	struct mutex sync_mutex;
 	struct notifier_block notifier;
+
+	struct sync_fence *(*get_retire_fence)
+		(struct msm_sync_pt_data *sync_pt_data);
 };
 
 struct msm_fb_data_type;
@@ -110,7 +121,8 @@
 	int (*kickoff_fnc)(struct msm_fb_data_type *mfd,
 					struct mdp_display_commit *data);
 	int (*ioctl_handler)(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
-	void (*dma_fnc)(struct msm_fb_data_type *mfd);
+	void (*dma_fnc)(struct msm_fb_data_type *mfd, struct mdp_overlay *req,
+				int image_len, int *pipe_ndx);
 	int (*cursor_update)(struct msm_fb_data_type *mfd,
 				struct fb_cursor *cursor);
 	int (*lut_update)(struct msm_fb_data_type *mfd, struct fb_cmap *cmap);
@@ -119,6 +131,7 @@
 	int (*update_ad_input)(struct msm_fb_data_type *mfd);
 	int (*panel_register_done)(struct mdss_panel_data *pdata);
 	u32 (*fb_stride)(u32 fb_index, u32 xres, int bpp);
+	int (*splash_fnc) (struct msm_fb_data_type *mfd, int *index, int req);
 	struct msm_sync_pt_data *(*get_sync_fnc)(struct msm_fb_data_type *mfd,
 				const struct mdp_buf_sync *buf_sync);
 	void *private1;
@@ -201,6 +214,9 @@
 	wait_queue_head_t idle_wait_q;
 	bool shutdown_pending;
 
+	struct task_struct *splash_thread;
+	bool splash_logo_enabled;
+
 	struct msm_fb_backup_type msm_fb_backup;
 	struct completion power_set_comp;
 	u32 is_power_setting;
@@ -233,6 +249,9 @@
 void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
 void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data);
 void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data);
+struct sync_fence *mdss_fb_sync_get_fence(struct sw_sync_timeline *timeline,
+				const char *fence_name, int val);
 int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp);
 int mdss_fb_dcm(struct msm_fb_data_type *mfd, int req_state);
+int mdss_fb_suspres_panel(struct device *dev, void *data);
 #endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
index 410f2b3..9d85070 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_cec.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -366,7 +366,7 @@
 	DSS_REG_W(io, HDMI_CEC_CTRL, BIT(0) | BIT(1) |
 		((msg->frame_size & 0x1F) << 4) | BIT(9));
 
-	if (!wait_for_completion_interruptible_timeout(
+	if (!wait_for_completion_timeout(
 		&cec_ctrl->cec_msg_wr_done, HZ)) {
 		DEV_ERR("%s: timedout", __func__);
 		hdmi_cec_dump_msg(cec_ctrl, msg);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index 8ff9059..e56e9fa 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -520,7 +520,7 @@
 	/* Write R0' to HDCP registers and check to see if it is a match */
 	INIT_COMPLETION(hdcp_ctrl->r0_checked);
 	DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA2_0, (((u32)buf[1]) << 8) | buf[0]);
-	timeout_count = wait_for_completion_interruptible_timeout(
+	timeout_count = wait_for_completion_timeout(
 		&hdcp_ctrl->r0_checked, HZ*2);
 	link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
 	is_match = link0_status & BIT(12);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index b45a446..79afdca 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -20,6 +20,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_platform.h>
 #include <linux/types.h>
+#include <linux/msm_hdmi.h>
 #include <mach/msm_hdmi_audio_codec.h>
 
 #define REG_DUMP 0
@@ -70,6 +71,24 @@
 #define MSM_HDMI_AUDIO_CHANNEL_7	7
 #define MSM_HDMI_AUDIO_CHANNEL_8	8
 
+#define NUM_MODES_AVI 20
+
+/* AVI Infoframe data byte 3, bit 7 (msb) represents ITC bit */
+#define SET_ITC_BIT(byte)  (byte = (byte | BIT(7)))
+#define CLR_ITC_BIT(byte)  (byte = (byte & ~BIT(7)))
+
+/*
+ * CN represents IT content type, if ITC bit in infoframe data byte 3
+ * is set, CN bits will represent content type as below:
+ * 0b00 Graphics
+ * 0b01 Photo
+ * 0b10 Cinema
+ * 0b11 Game
+*/
+#define CONFIG_CN_BITS(bits, byte) \
+		(byte = (byte & ~(BIT(4) | BIT(5))) |\
+			((bits & (BIT(0) | BIT(1))) << 4))
+
 enum msm_hdmi_supported_audio_sample_rates {
 	AUDIO_SAMPLE_RATE_32KHZ,
 	AUDIO_SAMPLE_RATE_44_1KHZ,
@@ -101,6 +120,7 @@
 static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
 	int val, bool force);
 static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
+static void hdmi_tx_en_encryption(struct hdmi_tx_ctrl *hdmi_ctrl, u32 on);
 
 struct mdss_hw hdmi_tx_hw = {
 	.hw_ndx = MDSS_HW_HDMI,
@@ -115,6 +135,7 @@
 };
 
 struct dss_gpio ddc_gpio_config[] = {
+	{0, 1, COMPATIBLE_NAME "-ddc-mux-sel"},
 	{0, 1, COMPATIBLE_NAME "-ddc-clk"},
 	{0, 1, COMPATIBLE_NAME "-ddc-data"}
 };
@@ -137,12 +158,6 @@
 	}
 } /* hdmi_pm_name */
 
-static DEFINE_MUTEX(avi_iframe_lut_lock);
-#define NUM_MODES_AVI 20
-#define SET_ITC_BIT(byte)  (byte | 0x80)
-#define CLR_ITC_BIT(byte)  (byte & 0x7F)
-#define CONFIG_CN_BITS(bits, byte)  ((byte & ~(0x03 << 4)) | (bits << 4))
-
 static u8 hdmi_tx_avi_iframe_lut[][NUM_MODES_AVI] = {
 	{0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,
 	 0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,	0x10,
@@ -210,54 +225,76 @@
 		{20480, 247500} } },
 };
 
-/* To statically config ITC bit from sysfs attribute */
-static int hdmi_tx_config_itc_bit(int itc)
+int register_hdmi_cable_notification(struct hdmi_cable_notify *handler)
 {
-	int ret = 0, loop = NUM_MODES_AVI;
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+	struct list_head *pos;
 
-	if (mutex_lock_interruptible(&avi_iframe_lut_lock)) {
-		ret = -ERESTARTSYS;
-		goto signal_intr;
+	if (!hdmi_tx_hw.ptr) {
+		DEV_WARN("%s: HDMI Tx core not ready\n", __func__);
+		return -EPROBE_DEFER;
 	}
 
-	do {
-		--loop;
-		if (itc == 0)
-			hdmi_tx_avi_iframe_lut[2][loop] =
-				CLR_ITC_BIT(hdmi_tx_avi_iframe_lut[2][loop]);
-		if (itc == 1)
-			hdmi_tx_avi_iframe_lut[2][loop] =
-				SET_ITC_BIT(hdmi_tx_avi_iframe_lut[2][loop]);
-	} while (loop);
-
-	mutex_unlock(&avi_iframe_lut_lock);
-
-signal_intr:
-	return ret;
-}
-
-/* To configure CN0_1 bits from sysfs attribute */
-static int hdmi_tx_config_cn_bits(int cns)
-{
-	int ret = 0, loop = NUM_MODES_AVI;
-
-	if (mutex_lock_interruptible(&avi_iframe_lut_lock)) {
-		ret = -ERESTARTSYS;
-		goto signal_intr;
+	if (!handler) {
+		DEV_ERR("%s: Empty handler\n", __func__);
+		return -ENODEV;
 	}
 
-	do {
-		--loop;
-		hdmi_tx_avi_iframe_lut[4][loop] =
-			CONFIG_CN_BITS(cns, hdmi_tx_avi_iframe_lut[4][loop]);
-	} while (loop);
+	hdmi_ctrl = (struct hdmi_tx_ctrl *) hdmi_tx_hw.ptr;
 
-	mutex_unlock(&avi_iframe_lut_lock);
+	mutex_lock(&hdmi_ctrl->cable_notify_mutex);
+	handler->status = hdmi_ctrl->hpd_state;
+	list_for_each(pos, &hdmi_ctrl->cable_notify_handlers);
+	list_add_tail(&handler->link, pos);
+	mutex_unlock(&hdmi_ctrl->cable_notify_mutex);
 
-signal_intr:
-	return ret;
-}
+	return handler->status;
+} /* register_hdmi_cable_notification */
 
+int unregister_hdmi_cable_notification(struct hdmi_cable_notify *handler)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+
+	if (!hdmi_tx_hw.ptr) {
+		DEV_WARN("%s: HDMI Tx core not ready\n", __func__);
+		return -ENODEV;
+	}
+
+	if (!handler) {
+		DEV_ERR("%s: Empty handler\n", __func__);
+		return -ENODEV;
+	}
+
+	hdmi_ctrl = (struct hdmi_tx_ctrl *) hdmi_tx_hw.ptr;
+
+	mutex_lock(&hdmi_ctrl->cable_notify_mutex);
+	list_del(&handler->link);
+	mutex_unlock(&hdmi_ctrl->cable_notify_mutex);
+
+	return 0;
+} /* unregister_hdmi_cable_notification */
+
+static void hdmi_tx_cable_notify_work(struct work_struct *work)
+{
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+	struct hdmi_cable_notify *pos;
+
+	hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, cable_notify_work);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid hdmi data\n", __func__);
+		return;
+	}
+
+	mutex_lock(&hdmi_ctrl->cable_notify_mutex);
+	list_for_each_entry(pos, &hdmi_ctrl->cable_notify_handlers, link) {
+		if (pos->status != hdmi_ctrl->hpd_state) {
+			pos->status = hdmi_ctrl->hpd_state;
+			pos->hpd_notify(pos);
+		}
+	}
+	mutex_unlock(&hdmi_ctrl->cable_notify_mutex);
+} /* hdmi_tx_cable_notify_work */
 
 static bool hdmi_tx_is_cea_format(int mode)
 {
@@ -364,6 +401,9 @@
 
 	if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
 		switch_set_state(&hdmi_ctrl->sdev, val);
+
+	/* Notify all registered modules of cable connection status */
+	schedule_work(&hdmi_ctrl->cable_notify_work);
 } /* hdmi_tx_send_cable_notification */
 
 static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -682,53 +722,80 @@
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	ssize_t ret = strnlen(buf, PAGE_SIZE);
-	int err = 0;
-	int itc = 0, rc = 0;
+	u8 *avi_byte3 = hdmi_tx_avi_iframe_lut[2];
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+	int loop = 0, itc = 0, rc = 0;
+
+	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
 
 	rc = kstrtoint(buf, 10, &itc);
 	if (rc) {
-		DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+		DEV_ERR("%s: kstrtoint failed. rc =%d\n", __func__, rc);
 		return rc;
 	}
 
-	if (itc == 0 || itc == 1) {
-		if (hdmi_tx_config_itc_bit(itc))
-			ret = err;
-		else
-			DEV_DBG("%s: '%d is configured'!\n", __func__, itc);
-	} else {
-		DEV_ERR("%s: unknown ITC '%d', should be either 0 or 1\n",
-				__func__, itc);
+	if (itc < 0 || itc > 1) {
+		DEV_ERR("%s: Invalid ITC %d\n", __func__, itc);
+		return ret;
 	}
 
+	if (mutex_lock_interruptible(&hdmi_ctrl->lut_lock))
+		return -ERESTARTSYS;
+
+	for (loop = 0; loop < NUM_MODES_AVI; loop++) {
+		if (itc)
+			SET_ITC_BIT(avi_byte3[loop]);
+		else
+			CLR_ITC_BIT(avi_byte3[loop]);
+	}
+
+	mutex_unlock(&hdmi_ctrl->lut_lock);
+
 	return ret;
 } /* hdmi_tx_sysfs_wta_avi_itc */
 
-static ssize_t hdmi_tx_sysfs_wta_avi_cn0_1(struct device *dev,
+static ssize_t hdmi_tx_sysfs_wta_avi_cn_bits(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
 	ssize_t ret = strnlen(buf, PAGE_SIZE);
-	int err = 0;
-	int cns = 0, rc = 0;
+	u8 *avi_byte5 = hdmi_tx_avi_iframe_lut[4];
+	struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+	int loop = 0, cn_bits = 0, rc = 0;
 
-	rc = kstrtoint(buf, 10, &cns);
+	hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+	if (!hdmi_ctrl) {
+		DEV_ERR("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = kstrtoint(buf, 10, &cn_bits);
 	if (rc) {
 		DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
 		return rc;
 	}
 
-	if (cns == 0 || cns == 1 || cns == 2 || cns == 3) {
-		if (hdmi_tx_config_cn_bits(cns))
-			ret = err;
-		else
-			DEV_DBG("%s: '%d is configured'!\n", __func__, cns);
-	} else {
-		DEV_ERR("%s: unknown CN '%d' should be either 0 or 1, 2 ,3\n",
-				__func__, cns);
+	/* As per CEA-861-E, CN is a positive number and can be max 3 */
+	if (cn_bits < 0 || cn_bits > 3) {
+		DEV_ERR("%s: Invalid CN %d\n", __func__, cn_bits);
+		return ret;
 	}
 
+	if (mutex_lock_interruptible(&hdmi_ctrl->lut_lock))
+		return -ERESTARTSYS;
+
+	for (loop = 0; loop < NUM_MODES_AVI; loop++)
+		CONFIG_CN_BITS(cn_bits, avi_byte5[loop]);
+
+	mutex_unlock(&hdmi_ctrl->lut_lock);
+
 	return ret;
-} /* hdmi_tx_sysfs_wta_avi_cn0_1 */
+} /* hdmi_tx_sysfs_wta_cn_bits */
 
 static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
 static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
@@ -739,7 +806,7 @@
 	hdmi_tx_sysfs_rda_product_description,
 	hdmi_tx_sysfs_wta_product_description);
 static DEVICE_ATTR(avi_itc, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_itc);
-static DEVICE_ATTR(avi_cn0_1, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_cn0_1);
+static DEVICE_ATTR(avi_cn0_1, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_cn_bits);
 
 static struct attribute *hdmi_tx_fs_attrs[] = {
 	&dev_attr_connected.attr,
@@ -850,11 +917,11 @@
 	switch (status) {
 	case HDCP_STATE_AUTHENTICATED:
 		if (hdmi_ctrl->hpd_state) {
-			/* Clear AV Mute */
-			rc = hdmi_tx_config_avmute(hdmi_ctrl, 0);
-			if (rc)
-				DEV_ERR("%s: Failed to clear av mute. rc=%d\n",
-					__func__, rc);
+			if (hdmi_ctrl->pdata.primary)
+				hdmi_tx_en_encryption(hdmi_ctrl, true);
+			else
+				/* Clear AV Mute */
+				rc = hdmi_tx_config_avmute(hdmi_ctrl, 0);
 			hdmi_tx_set_audio_switch_node(hdmi_ctrl, 1, false);
 		}
 		break;
@@ -862,11 +929,11 @@
 		hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
 
 		if (hdmi_ctrl->hpd_state) {
-			/* Set AV Mute */
-			rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
-			if (rc)
-				DEV_ERR("%s: Failed to set av mute. rc=%d\n",
-					__func__, rc);
+			if (hdmi_ctrl->pdata.primary)
+				hdmi_tx_en_encryption(hdmi_ctrl, false);
+			else
+				/* Set AV Mute */
+				rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
 
 			DEV_DBG("%s: Reauthenticating\n", __func__);
 			rc = hdmi_hdcp_reauthenticate(
@@ -1580,6 +1647,28 @@
 	DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control);
 } /* hdmi_tx_set_spd_infoframe */
 
+static void hdmi_tx_en_encryption(struct hdmi_tx_ctrl *hdmi_ctrl, u32 on)
+{
+	u32 reg_val;
+	struct dss_io_data *io = NULL;
+
+	if (!hdmi_ctrl->hdcp_feature_on || !hdmi_ctrl->present_hdcp)
+		return;
+
+	io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+
+	mutex_lock(&hdmi_ctrl->mutex);
+	reg_val = DSS_REG_R_ND(io, HDMI_CTRL);
+
+	if (on)
+		reg_val |= BIT(2);
+	else
+		reg_val &= ~BIT(2);
+	DSS_REG_W(io, HDMI_CTRL, reg_val);
+
+	mutex_unlock(&hdmi_ctrl->mutex);
+} /* hdmi_tx_en_encryption */
+
 static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
 {
 	struct dss_io_data *io = NULL;
@@ -1596,12 +1685,14 @@
 		return;
 	}
 
+	mutex_lock(&hdmi_ctrl->mutex);
 	if (power_on) {
 		/* Enable the block */
 		reg_val |= BIT(0);
 
 		/* HDMI Encryption, if HDCP is enabled */
-		if (hdmi_ctrl->hdcp_feature_on && hdmi_ctrl->present_hdcp)
+		if (hdmi_ctrl->hdcp_feature_on &&
+			hdmi_ctrl->present_hdcp && !hdmi_ctrl->pdata.primary)
 			reg_val |= BIT(2);
 
 		/* Set transmission mode to DVI based in EDID info */
@@ -1611,6 +1702,7 @@
 	}
 
 	DSS_REG_W(io, HDMI_CTRL, reg_val);
+	mutex_unlock(&hdmi_ctrl->mutex);
 
 	DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
 		power_on ? "Enable" : "Disable", reg_val);
@@ -2546,7 +2638,7 @@
 	flush_work_sync(&hdmi_ctrl->power_off_work);
 
 	if (hdmi_ctrl->pdata.primary) {
-		timeout = wait_for_completion_interruptible_timeout(
+		timeout = wait_for_completion_timeout(
 			&hdmi_ctrl->hpd_done, HZ);
 		if (!timeout) {
 			DEV_ERR("%s: cable connection hasn't happened yet\n",
@@ -2576,6 +2668,11 @@
 	hdmi_ctrl->panel_power_on = true;
 	mutex_unlock(&hdmi_ctrl->mutex);
 
+	if (hdmi_ctrl->pdata.primary) {
+		if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, true))
+			DEV_ERR("%s: Failed to enable ddc power\n", __func__);
+	}
+
 	hdmi_cec_config(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
 
 	if (hdmi_ctrl->hpd_state) {
@@ -2844,6 +2941,8 @@
 	switch_dev_unregister(&hdmi_ctrl->sdev);
 	if (hdmi_ctrl->workq)
 		destroy_workqueue(hdmi_ctrl->workq);
+	mutex_destroy(&hdmi_ctrl->lut_lock);
+	mutex_destroy(&hdmi_ctrl->cable_notify_mutex);
 	mutex_destroy(&hdmi_ctrl->mutex);
 
 	hdmi_tx_hw.ptr = NULL;
@@ -2872,6 +2971,11 @@
 
 	hdmi_setup_video_mode_lut();
 	mutex_init(&hdmi_ctrl->mutex);
+	mutex_init(&hdmi_ctrl->lut_lock);
+	mutex_init(&hdmi_ctrl->cable_notify_mutex);
+
+	INIT_LIST_HEAD(&hdmi_ctrl->cable_notify_handlers);
+
 	hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
 	if (!hdmi_ctrl->workq) {
 		DEV_ERR("%s: hdmi_tx_workq creation failed.\n", __func__);
@@ -2889,8 +2993,9 @@
 	hdmi_ctrl->hpd_initialized = false;
 	hdmi_ctrl->hpd_off_pending = false;
 	init_completion(&hdmi_ctrl->hpd_done);
-	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
 
+	INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
+	INIT_WORK(&hdmi_ctrl->cable_notify_work, hdmi_tx_cable_notify_work);
 	INIT_WORK(&hdmi_ctrl->power_off_work, hdmi_tx_power_off_work);
 
 	spin_lock_init(&hdmi_ctrl->hpd_state_lock);
@@ -2920,6 +3025,7 @@
 fail_create_workq:
 	if (hdmi_ctrl->workq)
 		destroy_workqueue(hdmi_ctrl->workq);
+	mutex_destroy(&hdmi_ctrl->lut_lock);
 	mutex_destroy(&hdmi_ctrl->mutex);
 fail_no_hdmi:
 	return rc;
@@ -3010,7 +3116,7 @@
 			u32 timeout;
 			hdmi_ctrl->panel_suspend = false;
 
-			timeout = wait_for_completion_interruptible_timeout(
+			timeout = wait_for_completion_timeout(
 				&hdmi_ctrl->hpd_done, HZ/10);
 			if (!timeout & !hdmi_ctrl->hpd_state) {
 				DEV_INFO("%s: cable removed during suspend\n",
@@ -3034,10 +3140,10 @@
 	case MDSS_EVENT_PANEL_ON:
 		if (hdmi_ctrl->hdcp_feature_on && hdmi_ctrl->present_hdcp) {
 			/* Set AV Mute before starting authentication */
-			rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
-			if (rc)
-				DEV_ERR("%s: Failed to set av mute. rc=%d\n",
-					__func__, rc);
+			if (hdmi_ctrl->pdata.primary)
+				hdmi_tx_en_encryption(hdmi_ctrl, false);
+			else
+				rc = hdmi_tx_config_avmute(hdmi_ctrl, 1);
 
 			DEV_DBG("%s: Starting HDCP authentication\n", __func__);
 			rc = hdmi_hdcp_authenticate(
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 66071e9..8233ba8 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2014, 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
@@ -54,6 +54,9 @@
 	struct hdmi_audio audio_data;
 
 	struct mutex mutex;
+	struct mutex lut_lock;
+	struct mutex cable_notify_mutex;
+	struct list_head cable_notify_handlers;
 	struct kobject *kobj;
 	struct switch_dev sdev;
 	struct switch_dev audio_sdev;
@@ -77,6 +80,7 @@
 	struct work_struct hpd_int_work;
 
 	struct work_struct power_off_work;
+	struct work_struct cable_notify_work;
 
 	bool hdcp_feature_on;
 	u32 present_hdcp;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 711ec68..6f6c805 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -46,6 +46,7 @@
 int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in)
 {
 	int i, vic = -1;
+	struct msm_hdmi_mode_timing_info *supported_timing;
 
 	if (!timing_in) {
 		DEV_ERR("%s: invalid input\n", __func__);
@@ -54,8 +55,7 @@
 
 	/* active_low_h, active_low_v and interlaced are not checked against */
 	for (i = 0; i < HDMI_VFRMT_MAX; i++) {
-		struct msm_hdmi_mode_timing_info *supported_timing =
-			&hdmi_supported_video_mode_lut[i];
+		supported_timing = &hdmi_supported_video_mode_lut[i];
 
 		if (!supported_timing->supported)
 			continue;
@@ -84,8 +84,24 @@
 		break;
 	}
 
-	if (vic < 0)
-		DEV_ERR("%s: timing asked is not yet supported\n", __func__);
+	if (vic < 0) {
+		for (i = 0; i < HDMI_VFRMT_MAX; i++) {
+			supported_timing = &hdmi_supported_video_mode_lut[i];
+			if (!supported_timing->supported)
+				continue;
+			if (timing_in->active_h != supported_timing->active_h)
+				continue;
+			if (timing_in->active_v != supported_timing->active_v)
+				continue;
+			vic = (int)supported_timing->video_format;
+			break;
+		}
+	}
+
+	if (vic < 0) {
+		DEV_ERR("%s: timing is not supported h=%d v=%d\n",
+			__func__, timing_in->active_h, timing_in->active_v);
+	}
 
 exit:
 	DEV_DBG("%s: vic = %d timing = %s\n", __func__, vic,
@@ -296,7 +312,7 @@
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
 
-	time_out_count = wait_for_completion_interruptible_timeout(
+	time_out_count = wait_for_completion_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1));
 	if (!time_out_count) {
@@ -547,7 +563,7 @@
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(21));
 
-	time_out_count = wait_for_completion_interruptible_timeout(
+	time_out_count = wait_for_completion_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 
 	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
@@ -721,7 +737,7 @@
 	INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
 	DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
 
-	time_out_count = wait_for_completion_interruptible_timeout(
+	time_out_count = wait_for_completion_timeout(
 		&ddc_ctrl->ddc_sw_done, HZ/2);
 
 	reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 3269eec..088472f 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -1,7 +1,7 @@
 /*
  * MDSS MDP Interface (used by framebuffer core)
  *
- * Copyright (c) 2007-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2014, The Linux Foundation. All rights reserved.
  * Copyright (C) 2007 Google Incorporated
  *
  * This software is licensed under the terms of the GNU General Public
@@ -80,21 +80,7 @@
 static DEFINE_SPINLOCK(mdp_lock);
 static DEFINE_MUTEX(mdp_clk_lock);
 static DEFINE_MUTEX(bus_bw_lock);
-
-#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)		\
-	{						\
-		.src = MSM_BUS_MASTER_MDP_PORT0,	\
-		.dst = MSM_BUS_SLAVE_EBI_CH0,		\
-		.ab = (ab_val),				\
-		.ib = (ib_val),				\
-	}
-
-static struct msm_bus_vectors mdp_bus_vectors[] = {
-	MDP_BUS_VECTOR_ENTRY(0, 0),
-	MDP_BUS_VECTOR_ENTRY(SZ_128M, SZ_256M),
-	MDP_BUS_VECTOR_ENTRY(SZ_256M, SZ_512M),
-};
-static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)];
+static DEFINE_MUTEX(mdp_iommu_lock);
 
 static struct mdss_panel_intf pan_types[] = {
 	{"dsi", MDSS_PANEL_INTF_DSI},
@@ -102,12 +88,6 @@
 	{"hdmi", MDSS_PANEL_INTF_HDMI},
 };
 
-static struct msm_bus_scale_pdata mdp_bus_scale_table = {
-	.usecase = mdp_bus_usecases,
-	.num_usecases = ARRAY_SIZE(mdp_bus_usecases),
-	.name = "mdss_mdp",
-};
-
 struct mdss_iommu_map_type mdss_iommu_map[MDSS_IOMMU_MAX_DOMAIN] = {
 	[MDSS_IOMMU_DOMAIN_UNSECURE] = {
 		.client_name = "mdp_ns",
@@ -153,8 +133,10 @@
 static int mdss_mdp_parse_dt_prop_len(struct platform_device *pdev,
 				       char *prop_name);
 static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_prefill(struct platform_device *pdev);
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
 static int mdss_mdp_parse_dt_ad_cfg(struct platform_device *pdev);
+static int mdss_mdp_parse_dt_bus_scale(struct platform_device *pdev);
 
 u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
 {
@@ -331,23 +313,17 @@
 static int mdss_mdp_bus_scale_register(struct mdss_data_type *mdata)
 {
 	if (!mdata->bus_hdl) {
-		struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table;
-		int i;
-
-		for (i = 0; i < bus_pdata->num_usecases; i++) {
-			mdp_bus_usecases[i].num_paths = 1;
-			mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i];
-		}
-
-		mdata->bus_hdl = msm_bus_scale_register_client(bus_pdata);
-		if (!mdata->bus_hdl) {
-			pr_err("not able to get bus scale\n");
-			return -ENOMEM;
+		mdata->bus_hdl =
+			msm_bus_scale_register_client(mdata->bus_scale_table);
+		if (IS_ERR_VALUE(mdata->bus_hdl)) {
+			pr_err("bus_client register failed\n");
+			return -EINVAL;
 		}
 
 		pr_debug("register bus_hdl=%x\n", mdata->bus_hdl);
 	}
-	return 0;
+
+	return mdss_mdp_bus_scale_set_quota(AB_QUOTA, IB_QUOTA);
 }
 
 static void mdss_mdp_bus_scale_unregister(struct mdss_data_type *mdata)
@@ -360,7 +336,7 @@
 
 int mdss_mdp_bus_scale_set_quota(u64 ab_quota, u64 ib_quota)
 {
-	int bus_idx;
+	int new_uc_idx;
 
 	if (mdss_res->bus_hdl < 1) {
 		pr_err("invalid bus handle %d\n", mdss_res->bus_hdl);
@@ -368,32 +344,50 @@
 	}
 
 	if ((ab_quota | ib_quota) == 0) {
-		bus_idx = 0;
+		new_uc_idx = 0;
 	} else {
-		int num_cases = mdp_bus_scale_table.num_usecases;
+		int i;
 		struct msm_bus_vectors *vect = NULL;
+		struct msm_bus_scale_pdata *bw_table =
+			mdss_res->bus_scale_table;
+		unsigned long size;
 
-		bus_idx = (mdss_res->current_bus_idx % (num_cases - 1)) + 1;
-
-		vect = mdp_bus_scale_table.usecase[mdss_res->current_bus_idx].
-			vectors;
-
-		/* avoid performing updates for small changes */
-		if ((ALIGN(ab_quota, SZ_64M) == ALIGN(vect->ab, SZ_64M)) &&
-			(ALIGN(ib_quota, SZ_64M) == ALIGN(vect->ib, SZ_64M))) {
-			pr_debug("skip bus scaling, no change in vectors\n");
-			return 0;
+		if (!bw_table || !mdss_res->axi_port_cnt) {
+			pr_err("invalid input\n");
+			return -EINVAL;
 		}
 
-		vect = mdp_bus_scale_table.usecase[bus_idx].vectors;
-		vect->ab = ab_quota;
-		vect->ib = ib_quota;
+		size = SZ_64M / mdss_res->axi_port_cnt;
 
-		pr_debug("bus scale idx=%d ab=%llu ib=%llu\n", bus_idx,
-				vect->ab, vect->ib);
+		ab_quota = div_u64(ab_quota, mdss_res->axi_port_cnt);
+		ib_quota = div_u64(ib_quota, mdss_res->axi_port_cnt);
+
+		new_uc_idx = (mdss_res->curr_bw_uc_idx %
+			(bw_table->num_usecases - 1)) + 1;
+
+		for (i = 0; i < mdss_res->axi_port_cnt; i++) {
+			vect = &bw_table->usecase[mdss_res->curr_bw_uc_idx].
+				vectors[i];
+
+			/* avoid performing updates for small changes */
+			if ((ALIGN(ab_quota, size) == ALIGN(vect->ab, size)) &&
+			    (ALIGN(ib_quota, size) == ALIGN(vect->ib, size))) {
+				pr_debug("skip bus scaling, no changes\n");
+				return 0;
+			}
+
+			vect = &bw_table->usecase[new_uc_idx].vectors[i];
+			vect->ab = ab_quota;
+			vect->ib = ib_quota;
+
+			pr_debug("uc_idx=%d path_idx=%d ab=%llu ib=%llu\n",
+				new_uc_idx, i, vect->ab, vect->ib);
+		}
 	}
-	mdss_res->current_bus_idx = bus_idx;
-	return msm_bus_scale_client_update_request(mdss_res->bus_hdl, bus_idx);
+	mdss_res->curr_bw_uc_idx = new_uc_idx;
+
+	return msm_bus_scale_client_update_request(mdss_res->bus_hdl,
+		new_uc_idx);
 }
 
 static inline u32 mdss_mdp_irq_mask(u32 intr_type, u32 intf_num)
@@ -546,6 +540,8 @@
 	if (clk) {
 		pr_debug("clk=%d en=%d\n", clk_idx, enable);
 		if (enable) {
+			if (clk_idx == MDSS_CLK_MDP_VSYNC)
+				clk_set_rate(clk, 19200000);
 			ret = clk_prepare_enable(clk);
 		} else {
 			clk_disable_unprepare(clk);
@@ -651,7 +647,9 @@
 		} else {
 			pm_runtime_get_sync(&mdata->pdev->dev);
 			msm_bus_scale_client_update_request(
-				mdata->bus_hdl, mdata->current_bus_idx);
+				mdata->bus_hdl, mdata->curr_bw_uc_idx);
+			if (!mdata->handoff_pending)
+				mdss_iommu_attach(mdata);
 		}
 	}
 
@@ -782,8 +780,10 @@
 	struct mdss_iommu_map_type *iomap;
 	int i;
 
+	mutex_lock(&mdp_iommu_lock);
 	if (mdata->iommu_attached) {
 		pr_debug("mdp iommu already attached\n");
+		mutex_unlock(&mdp_iommu_lock);
 		return 0;
 	}
 
@@ -800,6 +800,7 @@
 	}
 
 	mdata->iommu_attached = true;
+	mutex_unlock(&mdp_iommu_lock);
 
 	return 0;
 }
@@ -810,8 +811,10 @@
 	struct mdss_iommu_map_type *iomap;
 	int i;
 
+	mutex_lock(&mdp_iommu_lock);
 	if (!mdata->iommu_attached) {
 		pr_debug("mdp iommu already dettached\n");
+		mutex_unlock(&mdp_iommu_lock);
 		return 0;
 	}
 
@@ -828,6 +831,7 @@
 	}
 
 	mdata->iommu_attached = false;
+	mutex_unlock(&mdp_iommu_lock);
 
 	return 0;
 }
@@ -904,7 +908,8 @@
 	int i, total = 0;
 
 	for (i = 0; i < mdata->nctl; i++)
-		total += mdss_debug_stat_ctl_dump(mdata->ctl_off + i, buf, len);
+		total += mdss_debug_stat_ctl_dump(mdata->ctl_off + i,
+			buf + total, len - total);
 
 	total += scnprintf(buf + total, len - total, "\n");
 
@@ -1045,11 +1050,13 @@
 	if (mdata != NULL) {
 		if (on) {
 			pr_debug("Enable MDP FS for splash.\n");
+			mdata->handoff_pending = true;
 			regulator_enable(mdata->fs);
 			mdss_hw_init(mdata);
 		} else {
 			pr_debug("Disable MDP FS for splash.\n");
 			regulator_disable(mdata->fs);
+			mdata->handoff_pending = false;
 		}
 	} else {
 		pr_warn("mdss mdata not initialized\n");
@@ -1084,6 +1091,8 @@
 		SPRINT(" bwc");
 	if (mdata->has_decimation)
 		SPRINT(" decimation");
+	if (mdata->highest_bank_bit)
+		SPRINT(" tile_format");
 	SPRINT("\n");
 
 	return cnt;
@@ -1134,6 +1143,7 @@
 	mdata->pdev = pdev;
 	platform_set_drvdata(pdev, mdata);
 	mdss_res = mdata;
+	mutex_init(&mdata->reg_lock);
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
 	if (!res) {
@@ -1203,7 +1213,6 @@
 		pr_err("unable to register bus scaling\n");
 		goto probe_done;
 	}
-	mdss_mdp_bus_scale_set_quota(AB_QUOTA, IB_QUOTA);
 
 	rc = mdss_mdp_debug_init(mdata);
 	if (rc) {
@@ -1232,6 +1241,7 @@
 	if (IS_ERR_VALUE(rc)) {
 		mdss_mdp_hw.ptr = NULL;
 		mdss_mdp_pp_term(&pdev->dev);
+		mutex_destroy(&mdata->reg_lock);
 		mdss_res = NULL;
 	}
 
@@ -1523,6 +1533,12 @@
 		return rc;
 	}
 
+	rc = mdss_mdp_parse_dt_prefill(pdev);
+	if (rc) {
+		pr_err("Error in device tree : prefill\n");
+		return rc;
+	}
+
 	rc = mdss_mdp_parse_dt_misc(pdev);
 	if (rc) {
 		pr_err("Error in device tree : misc\n");
@@ -1542,6 +1558,12 @@
 		return rc;
 	}
 
+	rc = mdss_mdp_parse_dt_bus_scale(pdev);
+	if (rc) {
+		pr_err("Error in device tree : bus scale\n");
+		return rc;
+	}
+
 	return 0;
 }
 
@@ -1550,8 +1572,8 @@
 {
 	u32 npipes, dma_off;
 	int rc = 0;
-	u32 nids = 0, setup_cnt = 0, len;
-	u32 *offsets = NULL, *ftch_id = NULL;
+	u32 nfids = 0, setup_cnt = 0, len, nxids = 0;
+	u32 *offsets = NULL, *ftch_id = NULL, *xin_id = NULL;
 
 	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
 
@@ -1562,33 +1584,47 @@
 	mdata->ndma_pipes = mdss_mdp_parse_dt_prop_len(pdev,
 				"qcom,mdss-pipe-dma-off");
 
-	nids  += mdss_mdp_parse_dt_prop_len(pdev,
-			"qcom,mdss-pipe-vig-fetch-id");
-	nids  += mdss_mdp_parse_dt_prop_len(pdev,
-			"qcom,mdss-pipe-rgb-fetch-id");
-	nids  += mdss_mdp_parse_dt_prop_len(pdev,
-			"qcom,mdss-pipe-dma-fetch-id");
-
 	npipes = mdata->nvig_pipes + mdata->nrgb_pipes + mdata->ndma_pipes;
 
-	if (npipes != nids) {
+	nfids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-vig-fetch-id");
+	nfids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-rgb-fetch-id");
+	nfids  += mdss_mdp_parse_dt_prop_len(pdev,
+			"qcom,mdss-pipe-dma-fetch-id");
+	if (npipes != nfids) {
 		pr_err("device tree err: unequal number of pipes and smp ids");
 		return -EINVAL;
 	}
 
+	nxids += mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-pipe-vig-xin-id");
+	nxids += mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-pipe-rgb-xin-id");
+	nxids += mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-pipe-dma-xin-id");
+	if (npipes != nxids) {
+		pr_err("device tree err: unequal number of pipes and xin ids");
+		return -EINVAL;
+	}
+
 	offsets = kzalloc(sizeof(u32) * npipes, GFP_KERNEL);
 	if (!offsets) {
 		pr_err("no mem assigned for offsets: kzalloc fail\n");
 		return -ENOMEM;
 	}
 
-	ftch_id = kzalloc(sizeof(u32) * nids, GFP_KERNEL);
+	ftch_id = kzalloc(sizeof(u32) * nfids, GFP_KERNEL);
 	if (!ftch_id) {
 		pr_err("no mem assigned for ftch_id: kzalloc fail\n");
 		rc = -ENOMEM;
 		goto ftch_alloc_fail;
 	}
 
+	xin_id = kzalloc(sizeof(u32) * nxids, GFP_KERNEL);
+	if (!xin_id) {
+		pr_err("no mem assigned for xin_id: kzalloc fail\n");
+		rc = -ENOMEM;
+		goto xin_alloc_fail;
+	}
+
 	mdata->vig_pipes = devm_kzalloc(&mdata->pdev->dev,
 		sizeof(struct mdss_mdp_pipe) * mdata->nvig_pipes, GFP_KERNEL);
 	if (!mdata->vig_pipes) {
@@ -1616,7 +1652,12 @@
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-fetch-id",
 		ftch_id, mdata->nvig_pipes);
 	if (rc)
-		goto parse_done;
+		goto parse_fail;
+
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-xin-id",
+		xin_id, mdata->nvig_pipes);
+	if (rc)
+		goto parse_fail;
 
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-vig-off",
 		offsets, mdata->nvig_pipes);
@@ -1625,7 +1666,7 @@
 
 	len = min_t(int, DEFAULT_TOTAL_VIG_PIPES, (int)mdata->nvig_pipes);
 	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->vig_pipes, offsets, ftch_id,
-		MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, len);
+		xin_id, MDSS_MDP_PIPE_TYPE_VIG, MDSS_MDP_SSPP_VIG0, len);
 	if (rc)
 		goto parse_fail;
 
@@ -1636,6 +1677,11 @@
 	if (rc)
 		goto parse_fail;
 
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-xin-id",
+		xin_id + mdata->nvig_pipes, mdata->nrgb_pipes);
+	if (rc)
+		goto parse_fail;
+
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-rgb-off",
 		offsets + mdata->nvig_pipes, mdata->nrgb_pipes);
 	if (rc)
@@ -1644,7 +1690,8 @@
 	len = min_t(int, DEFAULT_TOTAL_RGB_PIPES, (int)mdata->nrgb_pipes);
 	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->rgb_pipes,
 		offsets + mdata->nvig_pipes, ftch_id + mdata->nvig_pipes,
-		MDSS_MDP_PIPE_TYPE_RGB, MDSS_MDP_SSPP_RGB0, len);
+		xin_id + mdata->nvig_pipes, MDSS_MDP_PIPE_TYPE_RGB,
+		MDSS_MDP_SSPP_RGB0, len);
 	if (rc)
 		goto parse_fail;
 
@@ -1656,6 +1703,11 @@
 	if (rc)
 		goto parse_fail;
 
+	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-xin-id",
+		xin_id + dma_off, mdata->ndma_pipes);
+	if (rc)
+		goto parse_fail;
+
 	rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pipe-dma-off",
 		offsets + dma_off, mdata->ndma_pipes);
 	if (rc)
@@ -1663,8 +1715,8 @@
 
 	len = mdata->ndma_pipes;
 	rc = mdss_mdp_pipe_addr_setup(mdata, mdata->dma_pipes,
-		 offsets + dma_off, ftch_id + dma_off, MDSS_MDP_PIPE_TYPE_DMA,
-		 MDSS_MDP_SSPP_DMA0, len);
+		offsets + dma_off, ftch_id + dma_off, xin_id + dma_off,
+		MDSS_MDP_PIPE_TYPE_DMA, MDSS_MDP_SSPP_DMA0, len);
 	if (rc)
 		goto parse_fail;
 
@@ -1675,6 +1727,7 @@
 			mdata->vig_pipes + DEFAULT_TOTAL_VIG_PIPES,
 			offsets + DEFAULT_TOTAL_VIG_PIPES,
 			ftch_id + DEFAULT_TOTAL_VIG_PIPES,
+			xin_id + DEFAULT_TOTAL_VIG_PIPES,
 			MDSS_MDP_PIPE_TYPE_VIG, setup_cnt,
 			mdata->nvig_pipes - DEFAULT_TOTAL_VIG_PIPES);
 		if (rc)
@@ -1688,6 +1741,7 @@
 			mdata->rgb_pipes + DEFAULT_TOTAL_RGB_PIPES,
 			offsets + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
 			ftch_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
+			xin_id + mdata->nvig_pipes + DEFAULT_TOTAL_RGB_PIPES,
 			MDSS_MDP_PIPE_TYPE_RGB, setup_cnt,
 			mdata->nrgb_pipes - DEFAULT_TOTAL_RGB_PIPES);
 		if (rc)
@@ -1706,6 +1760,8 @@
 	kfree(mdata->vig_pipes);
 parse_done:
 vig_alloc_fail:
+	kfree(xin_id);
+xin_alloc_fail:
 	kfree(ftch_id);
 ftch_alloc_fail:
 	kfree(offsets);
@@ -1964,6 +2020,84 @@
 	return rc;
 }
 
+static void mdss_mdp_parse_dt_fudge_factors(struct platform_device *pdev,
+	char *prop_name, struct mdss_fudge_factor *ff)
+{
+	int rc;
+	u32 data[2] = {1, 1};
+
+	rc = mdss_mdp_parse_dt_handler(pdev, prop_name, data, 2);
+	if (rc) {
+		pr_err("err reading %s\n", prop_name);
+	} else {
+		ff->numer = data[0];
+		ff->denom = data[1];
+	}
+}
+
+static int mdss_mdp_parse_dt_prefill(struct platform_device *pdev)
+{
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+	struct mdss_prefill_data *prefill = &mdata->prefill_data;
+	int rc;
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-outstanding-buffer-bytes",
+		&prefill->ot_bytes);
+	if (rc) {
+		pr_err("prefill outstanding buffer bytes not specified\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-y-buffer-bytes", &prefill->y_buf_bytes);
+	if (rc) {
+		pr_err("prefill y buffer bytes not specified\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-scaler-buffer-lines-bilinear",
+		&prefill->y_scaler_lines_bilinear);
+	if (rc) {
+		pr_err("prefill scaler lines for bilinear not specified\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-scaler-buffer-lines-caf",
+		&prefill->y_scaler_lines_caf);
+	if (rc) {
+		pr_debug("prefill scaler lines for caf not specified\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-post-scaler-buffer-pixels",
+		&prefill->post_scaler_pixels);
+	if (rc) {
+		pr_err("prefill post scaler buffer pixels not specified\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-pingpong-buffer-pixels",
+		&prefill->pp_pixels);
+	if (rc) {
+		pr_err("prefill pingpong buffer lines not specified\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-prefill-fbc-lines", &prefill->fbc_lines);
+	if (rc) {
+		pr_err("prefill FBC lines not specified\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
 {
 	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@@ -1975,6 +2109,10 @@
 		&data);
 	mdata->rot_block_size = (!rc ? data : 128);
 
+	rc = of_property_read_u32(pdev->dev.of_node,
+		"qcom,mdss-rotator-ot-limit", &data);
+	mdata->rotator_ot_limit = (!rc ? data : 0);
+
 	mdata->has_bwc = of_property_read_bool(pdev->dev.of_node,
 					       "qcom,mdss-has-bwc");
 	mdata->has_decimation = of_property_read_bool(pdev->dev.of_node,
@@ -1983,6 +2121,34 @@
 		"qcom,mdss-has-wfd-blk");
 	prop = of_find_property(pdev->dev.of_node, "batfet-supply", NULL);
 	mdata->batfet_required = prop ? true : false;
+	rc = of_property_read_u32(pdev->dev.of_node,
+		 "qcom,mdss-highest-bank-bit", &(mdata->highest_bank_bit));
+	if (rc)
+		pr_debug("Could not read optional property: highest bank bit\n");
+
+	/*
+	 * 2x factor on AB because bus driver will divide by 2
+	 * due to 2x ports to BIMC
+	 */
+	mdata->ab_factor.numer = 2;
+	mdata->ab_factor.denom = 1;
+	mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-ab-factor",
+		&mdata->ab_factor);
+
+	/*
+	 * 1.2 factor on ib as default value. This value is
+	 * experimentally determined and should be tuned in device
+	 * tree.
+	 */
+	mdata->ib_factor.numer = 6;
+	mdata->ib_factor.denom = 5;
+	mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-ib-factor",
+		&mdata->ib_factor);
+
+	mdata->clk_factor.numer = 1;
+	mdata->clk_factor.denom = 1;
+	mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-clk-factor",
+		&mdata->clk_factor);
 
 	rc = of_property_read_u32(pdev->dev.of_node,
 			"qcom,max-bandwidth-low-kbps", &mdata->max_bw_low);
@@ -2037,6 +2203,31 @@
 	return rc;
 }
 
+static int mdss_mdp_parse_dt_bus_scale(struct platform_device *pdev)
+{
+	int rc;
+	struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+
+	rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-bus,num-paths",
+		&mdata->axi_port_cnt);
+	if (rc) {
+		pr_err("Error. qcom,msm-bus,num-paths prop not found.rc=%d\n",
+			rc);
+		return rc;
+	}
+
+	mdata->bus_scale_table = msm_bus_cl_get_pdata(pdev);
+	if (IS_ERR_OR_NULL(mdata->bus_scale_table)) {
+		rc = PTR_ERR(mdata->bus_scale_table);
+		if (!rc)
+			rc = -EINVAL;
+		pr_err("msm_bus_cl_get_pdata failed. rc=%d\n", rc);
+		mdata->bus_scale_table = NULL;
+	}
+
+	return rc;
+}
+
 static int mdss_mdp_parse_dt_handler(struct platform_device *pdev,
 		char *prop_name, u32 *offsets, int len)
 {
@@ -2116,7 +2307,7 @@
 	int rc;
 
 	if (!mdss_res || !mdss_res->pan_cfg.init_done)
-		rc = -EPROBE_DEFER;
+		return -EPROBE_DEFER;
 	if (mdss_res->pan_cfg.lk_cfg)
 		rc = 1;
 	else
@@ -2300,11 +2491,12 @@
 static int mdss_mdp_runtime_resume(struct device *dev)
 {
 	struct mdss_data_type *mdata = dev_get_drvdata(dev);
+	bool device_on = true;
 	if (!mdata)
 		return -ENODEV;
 
 	dev_dbg(dev, "pm_runtime: resuming...\n");
-
+	device_for_each_child(dev, &device_on, mdss_fb_suspres_panel);
 	mdss_mdp_footswitch_ctrl(mdata, true);
 
 	return 0;
@@ -2324,6 +2516,7 @@
 static int mdss_mdp_runtime_suspend(struct device *dev)
 {
 	struct mdss_data_type *mdata = dev_get_drvdata(dev);
+	bool device_on = false;
 	if (!mdata)
 		return -ENODEV;
 	dev_dbg(dev, "pm_runtime: suspending...\n");
@@ -2332,6 +2525,7 @@
 		pr_err("MDP suspend failed\n");
 		return -EBUSY;
 	}
+	device_for_each_child(dev, &device_on, mdss_fb_suspres_panel);
 	mdss_mdp_footswitch_ctrl(mdata, false);
 
 	return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index fad6b0c..9d200b9 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -32,7 +32,7 @@
 #define MDP_CLK_DEFAULT_RATE	200000000
 #define PHASE_STEP_SHIFT	21
 #define MAX_MIXER_WIDTH		2048
-#define MAX_MIXER_HEIGHT	2400
+#define MAX_MIXER_HEIGHT	0xFFFF
 #define MAX_IMG_WIDTH		0x3FFF
 #define MAX_IMG_HEIGHT		0x3FFF
 #define MAX_DST_W		MAX_MIXER_WIDTH
@@ -145,6 +145,14 @@
 	MDSS_MDP_WB_CTL_TYPE_LINE
 };
 
+struct mdss_mdp_perf_params {
+	u64 bw_overlap;
+	u64 bw_prefill;
+	u32 prefill_bytes;
+	u64 bw_ctl;
+	u32 mdp_clk_rate;
+};
+
 struct mdss_mdp_ctl {
 	u32 num;
 	char __iomem *base;
@@ -168,11 +176,11 @@
 	u32 dst_format;
 	bool is_secure;
 
-	u32 bus_ab_quota;
-	u32 bus_ib_quota;
 	u32 clk_rate;
-	u32 perf_changed;
 	int force_screen_state;
+	struct mdss_mdp_perf_params cur_perf;
+	struct mdss_mdp_perf_params new_perf;
+	int perf_status;
 
 	struct mdss_data_type *mdata;
 	struct msm_fb_data_type *mfd;
@@ -180,6 +188,7 @@
 	struct mdss_mdp_mixer *mixer_right;
 	struct mutex lock;
 	struct mutex *shared_lock;
+	spinlock_t spin_lock;
 
 	struct mdss_panel_data *panel_data;
 	struct mdss_mdp_vsync_handler vsync_handler;
@@ -198,7 +207,8 @@
 					struct mdss_mdp_vsync_handler *);
 	int (*remove_vsync_handler) (struct mdss_mdp_ctl *,
 					struct mdss_mdp_vsync_handler *);
-	int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, int new_fps);
+	int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl,
+				struct mdss_mdp_ctl *sctl, int new_fps);
 
 	struct blocking_notifier_head notifier_head;
 
@@ -237,7 +247,7 @@
 	u8 unpack_count;	/* 0 = 1 component, 1 = 2 component ... */
 	u8 bpp;
 	u8 alpha_enable;	/*  source has alpha */
-
+	u8 tile;
 	u8 bits[MAX_PLANES];
 	u8 element[MAX_PLANES];
 };
@@ -274,7 +284,6 @@
 	u32 hist_cnt_sent;
 	u32 hist_cnt_time;
 	u32 frame_cnt;
-	u32 is_kick_ready;
 	struct completion comp;
 	u32 data[HIST_V_SIZE];
 	struct mutex hist_mutex;
@@ -345,6 +354,7 @@
 	u32 ndx;
 	char __iomem *base;
 	u32 ftch_id;
+	u32 xin_id;
 	atomic_t ref_cnt;
 	u32 play_cnt;
 	int pid;
@@ -369,7 +379,6 @@
 	u8 overfetch_disable;
 	u32 transp;
 	u32 bg_color;
-	u8 has_buf;
 
 	struct msm_fb_data_type *mfd;
 	struct mdss_mdp_mixer *mixer;
@@ -423,12 +432,11 @@
 	u32 splash_mem_addr;
 	u32 splash_mem_size;
 	u32 sd_enabled;
-};
 
-struct mdss_mdp_perf_params {
-	u32 ib_quota;
-	u32 ab_quota;
-	u32 mdp_clk_rate;
+	struct sw_sync_timeline *vsync_timeline;
+	struct mdss_mdp_vsync_handler vsync_retire_handler;
+	struct work_struct retire_work;
+	int retire_cnt;
 };
 
 /**
@@ -521,7 +529,7 @@
 int mdss_mdp_ctl_stop(struct mdss_mdp_ctl *ctl);
 int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
 int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
-		struct mdss_mdp_perf_params *perf);
+	struct mdss_mdp_perf_params *perf, struct mdss_mdp_img_rect *roi);
 int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event);
 void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
 	struct notifier_block *notifier);
@@ -530,8 +538,13 @@
 
 int mdss_mdp_mixer_handoff(struct mdss_mdp_ctl *ctl, u32 num,
 	struct mdss_mdp_pipe *pipe);
+
 int mdss_mdp_scan_pipes(void);
 
+void mdss_mdp_ctl_perf_taken(struct mdss_mdp_ctl *ctl);
+void mdss_mdp_ctl_perf_done(struct mdss_mdp_ctl *ctl);
+void mdss_mdp_ctl_perf_release_bw(struct mdss_mdp_ctl *ctl);
+
 struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator);
 int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer);
 struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux);
@@ -599,13 +612,14 @@
 void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe);
 struct mdss_mdp_pipe *mdss_mdp_pipe_alloc_dma(struct mdss_mdp_mixer *mixer);
 
+u32 mdss_mdp_smp_get_size(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_smp_reserve(struct mdss_mdp_pipe *pipe);
 void mdss_mdp_smp_unreserve(struct mdss_mdp_pipe *pipe);
 void mdss_mdp_smp_release(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
-	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_y_id, u32 type,
-	u32 num_base, u32 len);
+	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_y_id, u32 *xin_id,
+	u32 type, u32 num_base, u32 len);
 int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
 		u32 *dspp_offsets, u32 *pingpong_offsets, u32 type, u32 len);
 int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
@@ -614,6 +628,7 @@
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe);
 int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
 			     struct mdss_mdp_data *src_data);
+int mdss_mdp_pipe_fetch_halt(struct mdss_mdp_pipe *pipe);
 
 int mdss_mdp_data_check(struct mdss_mdp_data *data,
 			struct mdss_mdp_plane_sizes *ps);
@@ -632,6 +647,10 @@
 void mdss_mdp_intersect_rect(struct mdss_mdp_img_rect *res_rect,
 	const struct mdss_mdp_img_rect *dst_rect,
 	const struct mdss_mdp_img_rect *sci_rect);
+void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
+	struct mdss_mdp_img_rect *dst_rect,
+	const struct mdss_mdp_img_rect *sci_rect);
+
 
 int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd);
 int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index d57e4fb..1a4885c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -18,30 +18,26 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/sort.h>
 
 #include "mdss_fb.h"
 #include "mdss_mdp.h"
 
-/* truncate at 1k */
-#define MDSS_MDP_BUS_FACTOR_SHIFT 10
-/* 1.5 bus fudge factor */
-#define MDSS_MDP_BUS_FUDGE_FACTOR_IB(val) (((val) / 2) * 3)
-#define MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(val) (val << 1)
-#define MDSS_MDP_BUS_FUDGE_FACTOR_AB(val) (val << 1)
-#define MDSS_MDP_BUS_FLOOR_BW (1600000000ULL >> MDSS_MDP_BUS_FACTOR_SHIFT)
+static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
+{
+	u64 result = (val * (u64)numer);
+	do_div(result, denom);
+	return result;
+}
 
-/* 1.25 clock fudge factor */
-#define MDSS_MDP_CLK_FUDGE_FACTOR(val) (((val) * 5) / 4)
+#define AB_FUDGE_FACTOR(val)		fudge_factor((val),		\
+	(mdss_res->ab_factor.numer), (mdss_res->ab_factor.denom))
 
-enum {
-	MDSS_MDP_PERF_UPDATE_SKIP,
-	MDSS_MDP_PERF_UPDATE_EARLY,
-	MDSS_MDP_PERF_UPDATE_LATE,
-};
+#define IB_FUDGE_FACTOR(val)		fudge_factor((val),		\
+	(mdss_res->ib_factor.numer), (mdss_res->ib_factor.denom))
 
-#define MDSS_MDP_PERF_UPDATE_CLK BIT(0)
-#define MDSS_MDP_PERF_UPDATE_BUS BIT(1)
-#define MDSS_MDP_PERF_UPDATE_ALL -1
+#define CLK_FUDGE_FACTOR(val)		fudge_factor((val),		\
+	(mdss_res->clk_factor.numer), (mdss_res->clk_factor.denom))
 
 static DEFINE_MUTEX(mdss_mdp_ctl_lock);
 
@@ -63,112 +59,243 @@
 		pinfo->clk_rate;
 }
 
-static u32 __mdss_mdp_ctrl_perf_ovrd_helper(struct mdss_mdp_mixer *mixer,
-		u32 *npipe)
+static inline u32 mdss_mdp_clk_fudge_factor(struct mdss_mdp_mixer *mixer,
+						u32 rate)
 {
-	struct mdss_panel_info *pinfo;
-	struct mdss_mdp_pipe *pipe;
-	u32 mnum, ovrd = 0;
+	struct mdss_panel_info *pinfo = &mixer->ctl->panel_data->panel_info;
 
-	if (!mixer || !mixer->ctl->panel_data)
-		return 0;
+	rate = CLK_FUDGE_FACTOR(rate);
 
-	pinfo = &mixer->ctl->panel_data->panel_info;
-	for (mnum = 0; mnum < MDSS_MDP_MAX_STAGE; mnum++) {
-		pipe = mixer->stage_pipe[mnum];
-		if (pipe && pinfo) {
-			*npipe = *npipe + 1;
-			if ((pipe->src.w >= pipe->src.h) &&
-					(pipe->src.w >= pinfo->xres))
-				ovrd = 1;
-		}
-	}
+	/*
+	 * If the panel is video mode and its back porch period is
+	 * small, the workaround of increasing mdp clk is needed to
+	 * avoid underrun.
+	 */
+	if (mixer->ctl->is_video_mode && pinfo &&
+		(pinfo->lcdc.v_back_porch < MDP_MIN_VBP))
+		rate = CLK_FUDGE_FACTOR(rate);
 
-	return ovrd;
+	return rate;
 }
 
-/**
- * mdss_mdp_ctrl_perf_ovrd() - Determines if performance override is needed
- * @mdata:	Struct containing references to all MDP5 hardware structures
- *		and status info such as interupts, target caps etc.
- * @ab_quota:	Arbitrated bandwidth quota
- * @ib_quota:	Instantaneous bandwidth quota
- *
- * Function calculates the minimum required MDP and BIMC clocks to avoid MDP
- * underflow during portrait video playback. The calculations are based on the
- * way MDP fetches (bandwidth requirement) and processes data through
- * MDP pipeline (MDP clock requirement) based on frame size and scaling
- * requirements.
- */
-static void __mdss_mdp_ctrl_perf_ovrd(struct mdss_data_type *mdata,
-	u64 *ab_quota, u64 *ib_quota)
+struct mdss_mdp_prefill_params {
+	u32 smp_bytes;
+	u32 xres;
+	u32 src_w;
+	u32 dst_w;
+	u32 src_h;
+	u32 dst_h;
+	u32 dst_y;
+	u32 bpp;
+	bool is_yuv;
+	bool is_caf;
+	bool is_fbc;
+	bool is_bwc;
+	bool is_tile;
+	bool is_hflip;
+};
+
+static inline bool mdss_mdp_perf_is_caf(struct mdss_mdp_pipe *pipe)
 {
-	struct mdss_mdp_ctl *ctl;
-	u32 i, npipe = 0, ovrd = 0;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 
-	for (i = 0; i < mdata->nctl; i++) {
-		ctl = mdata->ctl_off + i;
-		if (!ctl->power_on)
-			continue;
-		ovrd |= __mdss_mdp_ctrl_perf_ovrd_helper(
-				ctl->mixer_left, &npipe);
-		ovrd |= __mdss_mdp_ctrl_perf_ovrd_helper(
-				ctl->mixer_right, &npipe);
-	}
+	/*
+	 * CAF mode filter is enabled when format is yuv and
+	 * upscaling. Post processing had the decision to use CAF
+	 * under these conditions.
+	 */
+	return ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+		pipe->src_fmt->is_yuv && ((pipe->src.h >> pipe->vert_deci) <=
+			pipe->dst.h));
+}
 
-	*ab_quota = MDSS_MDP_BUS_FUDGE_FACTOR_AB(*ab_quota);
-	if (npipe > 1)
-		*ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_HIGH_IB(*ib_quota);
-	else
-		*ib_quota = MDSS_MDP_BUS_FUDGE_FACTOR_IB(*ib_quota);
+static inline u32 mdss_mdp_calc_y_scaler_bytes(struct mdss_mdp_prefill_params
+	*params, struct mdss_prefill_data *prefill)
+{
+	u32 y_scaler_bytes = 0, y_scaler_lines = 0;
 
-	if (ovrd && (*ib_quota < MDSS_MDP_BUS_FLOOR_BW)) {
-		*ib_quota = MDSS_MDP_BUS_FLOOR_BW;
-		pr_debug("forcing the BIMC clock to 200 MHz : %llu bytes",
-			*ib_quota);
+	if (params->is_yuv) {
+		if (params->src_h != params->dst_h) {
+			y_scaler_lines = (params->is_caf) ?
+				prefill->y_scaler_lines_caf :
+				prefill->y_scaler_lines_bilinear;
+			/*
+			 * y is src_width, u is src_width/2 and v is
+			 * src_width/2, so the total is scaler_lines *
+			 * src_w * 2
+			 */
+			y_scaler_bytes = y_scaler_lines * params->src_w * 2;
+		}
 	} else {
-		pr_debug("ib quota : %llu bytes", *ib_quota);
-	}
-}
-
-static int mdss_mdp_ctl_perf_commit(struct mdss_data_type *mdata, u32 flags)
-{
-	struct mdss_mdp_ctl *ctl;
-	int cnum;
-	unsigned long clk_rate = 0;
-	u64 bus_ab_quota = 0, bus_ib_quota = 0;
-
-	if (!flags) {
-		pr_err("nothing to update\n");
-		return -EINVAL;
-	}
-
-	mutex_lock(&mdss_mdp_ctl_lock);
-	for (cnum = 0; cnum < mdata->nctl; cnum++) {
-		ctl = mdata->ctl_off + cnum;
-		if (ctl->power_on) {
-			bus_ab_quota += ctl->bus_ab_quota;
-			bus_ib_quota += ctl->bus_ib_quota;
-
-			if (ctl->clk_rate > clk_rate)
-				clk_rate = ctl->clk_rate;
+		if (params->src_h != params->dst_h) {
+			y_scaler_lines = prefill->y_scaler_lines_bilinear;
+			y_scaler_bytes = y_scaler_lines * params->src_w *
+				params->bpp;
 		}
 	}
-	if (flags & MDSS_MDP_PERF_UPDATE_BUS) {
-		bus_ab_quota = bus_ib_quota;
-		__mdss_mdp_ctrl_perf_ovrd(mdata, &bus_ab_quota, &bus_ib_quota);
-		bus_ib_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
-		bus_ab_quota <<= MDSS_MDP_BUS_FACTOR_SHIFT;
-		mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
-	}
-	if (flags & MDSS_MDP_PERF_UPDATE_CLK) {
-		clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(clk_rate);
-		pr_debug("update clk rate = %lu HZ\n", clk_rate);
-		mdss_mdp_set_clk_rate(clk_rate);
-	}
-	mutex_unlock(&mdss_mdp_ctl_lock);
 
-	return 0;
+	return y_scaler_bytes;
+}
+
+static inline u32 mdss_mdp_calc_latency_buf_bytes(struct mdss_mdp_prefill_params
+	*params, struct mdss_prefill_data *prefill)
+{
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	u32 latency_lines, latency_buf_bytes;
+
+	if (params->is_yuv) {
+		if (params->is_bwc) {
+			latency_lines = 4;
+			latency_buf_bytes = params->src_w * params->bpp *
+				latency_lines;
+		} else {
+			latency_lines = 2;
+			latency_buf_bytes = ALIGN(params->src_w * params->bpp *
+				latency_lines, mdata->smp_mb_size) * 2;
+		}
+	} else {
+		if (params->is_tile) {
+			latency_lines = 8;
+			latency_buf_bytes = params->src_w * params->bpp *
+				latency_lines;
+		} else if (params->is_bwc) {
+			latency_lines = 4;
+			latency_buf_bytes = params->src_w * params->bpp *
+				latency_lines;
+		} else {
+			latency_lines = 2;
+			latency_buf_bytes = ALIGN(params->src_w * params->bpp *
+				latency_lines, mdata->smp_mb_size);
+		}
+	}
+
+	return latency_buf_bytes;
+}
+
+static inline u32 mdss_mdp_calc_scaling_w_h(u32 val, u32 src_h, u32 dst_h,
+	u32 src_w, u32 dst_w)
+{
+	if (dst_h)
+		val = mult_frac(val, src_h, dst_h);
+	if (dst_w)
+		val = mult_frac(val, src_w, dst_w);
+
+	return val;
+}
+
+static u32 mdss_mdp_perf_calc_pipe_prefill_video(struct mdss_mdp_prefill_params
+	*params)
+{
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	struct mdss_prefill_data *prefill = &mdata->prefill_data;
+	u32 prefill_bytes;
+	u32 latency_buf_bytes;
+	u32 y_buf_bytes = 0;
+	u32 y_scaler_bytes;
+	u32 pp_bytes = 0, pp_lines = 0;
+	u32 post_scaler_bytes;
+	u32 fbc_bytes = 0;
+
+	prefill_bytes = prefill->ot_bytes;
+
+	latency_buf_bytes = mdss_mdp_calc_latency_buf_bytes(params, prefill);
+	prefill_bytes += latency_buf_bytes;
+	pr_debug("latency_buf_bytes bw_calc=%d actual=%d\n", latency_buf_bytes,
+		params->smp_bytes);
+
+	if (params->is_yuv)
+		y_buf_bytes = prefill->y_buf_bytes;
+
+	y_scaler_bytes = mdss_mdp_calc_y_scaler_bytes(params, prefill);
+
+	prefill_bytes += y_buf_bytes + y_scaler_bytes;
+
+	post_scaler_bytes = prefill->post_scaler_pixels * params->bpp;
+	post_scaler_bytes = mdss_mdp_calc_scaling_w_h(post_scaler_bytes,
+		params->src_h, params->dst_h, params->src_w, params->dst_w);
+	prefill_bytes += post_scaler_bytes;
+
+	if (params->xres)
+		pp_lines = DIV_ROUND_UP(prefill->pp_pixels, params->xres);
+	if (params->xres && params->dst_h && (params->dst_y <= pp_lines))
+		pp_bytes = ((params->src_w * params->bpp * prefill->pp_pixels /
+				params->xres) * params->src_h) / params->dst_h;
+	prefill_bytes += pp_bytes;
+
+	if (params->is_fbc) {
+		fbc_bytes = prefill->fbc_lines * params->bpp;
+		fbc_bytes = mdss_mdp_calc_scaling_w_h(fbc_bytes, params->src_h,
+			params->dst_h, params->src_w, params->dst_w);
+	}
+	prefill_bytes += fbc_bytes;
+
+	pr_debug("ot=%d y_buf=%d pp_lines=%d pp=%d post_sc=%d fbc_bytes=%d\n",
+		prefill->ot_bytes, y_buf_bytes, pp_lines, pp_bytes,
+		post_scaler_bytes, fbc_bytes);
+
+	return prefill_bytes;
+}
+
+static u32 mdss_mdp_perf_calc_pipe_prefill_cmd(struct mdss_mdp_prefill_params
+	*params)
+{
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	struct mdss_prefill_data *prefill = &mdata->prefill_data;
+	u32 prefill_bytes;
+	u32 ot_bytes = 0;
+	u32 latency_lines, latency_buf_bytes;
+	u32 y_buf_bytes = 0;
+	u32 y_scaler_bytes;
+	u32 fbc_cmd_lines = 0, fbc_cmd_bytes = 0;
+	u32 post_scaler_bytes = 0;
+
+	/* y_scaler_bytes are same for the first or non first line */
+	y_scaler_bytes = mdss_mdp_calc_y_scaler_bytes(params, prefill);
+	prefill_bytes = y_scaler_bytes;
+
+	/* 1st line if fbc is not enabled and 2nd line if fbc is enabled */
+	if (((params->dst_y == 0) && !params->is_fbc) ||
+		((params->dst_y <= 1) && params->is_fbc)) {
+		if (params->is_bwc || params->is_tile)
+			latency_lines = 4;
+		else if (!params->is_caf && params->is_hflip)
+			latency_lines = 1;
+		else
+			latency_lines = 0;
+		latency_buf_bytes = params->src_w * params->bpp * latency_lines;
+		prefill_bytes += latency_buf_bytes;
+
+		fbc_cmd_lines++;
+		if (params->is_fbc)
+			fbc_cmd_lines++;
+		fbc_cmd_bytes = params->bpp * params->dst_w * fbc_cmd_lines;
+		fbc_cmd_bytes = mdss_mdp_calc_scaling_w_h(fbc_cmd_bytes,
+			params->src_h, params->dst_h, params->src_w,
+			params->dst_w);
+		prefill_bytes += fbc_cmd_bytes;
+	} else {
+		ot_bytes = prefill->ot_bytes;
+		prefill_bytes += ot_bytes;
+
+		latency_buf_bytes = mdss_mdp_calc_latency_buf_bytes(params,
+			prefill);
+		prefill_bytes += latency_buf_bytes;
+
+		if (params->is_yuv)
+			y_buf_bytes = prefill->y_buf_bytes;
+		prefill_bytes += y_buf_bytes;
+
+		post_scaler_bytes = prefill->post_scaler_pixels * params->bpp;
+		post_scaler_bytes = mdss_mdp_calc_scaling_w_h(post_scaler_bytes,
+			params->src_h, params->dst_h, params->src_w,
+			params->dst_w);
+		prefill_bytes += post_scaler_bytes;
+	}
+
+	pr_debug("ot=%d bwc=%d smp=%d y_buf=%d fbc=%d\n", ot_bytes,
+		params->is_bwc, latency_buf_bytes, y_buf_bytes, fbc_cmd_bytes);
+
+	return prefill_bytes;
 }
 
 /**
@@ -183,16 +310,22 @@
  * (MDP clock requirement) based on frame size and scaling requirements.
  */
 int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
-		struct mdss_mdp_perf_params *perf)
+	struct mdss_mdp_perf_params *perf, struct mdss_mdp_img_rect *roi)
 {
 	struct mdss_mdp_mixer *mixer;
 	int fps = DEFAULT_FRAME_RATE;
-	u32 quota, rate, v_total, src_h;
+	u32 quota, rate, v_total, src_h, xres = 0;
+	struct mdss_mdp_img_rect src, dst;
+	bool is_fbc = false;
+	struct mdss_mdp_prefill_params prefill_params;
 
 	if (!pipe || !perf || !pipe->mixer)
 		return -EINVAL;
 
 	mixer = pipe->mixer;
+	dst = pipe->dst;
+	src = pipe->src;
+
 	if (mixer->rotator_mode) {
 		v_total = pipe->flags & MDP_ROT_90 ? pipe->dst.w : pipe->dst.h;
 	} else if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
@@ -201,18 +334,31 @@
 		pinfo = &mixer->ctl->panel_data->panel_info;
 		fps = mdss_panel_get_framerate(pinfo);
 		v_total = mdss_panel_get_vtotal(pinfo);
+		xres = pinfo->xres;
+		is_fbc = pinfo->fbc.enabled;
 	} else {
 		v_total = mixer->height;
+		xres = mixer->width;
 	}
 
+	if (roi)
+		mdss_mdp_crop_rect(&src, &dst, roi);
+
+	pr_debug("v_total=%d, xres=%d fps=%d\n", v_total, xres, fps);
+
 	/*
 	 * when doing vertical decimation lines will be skipped, hence there is
 	 * no need to account for these lines in MDP clock or request bus
 	 * bandwidth to fetch them.
 	 */
-	src_h = pipe->src.h >> pipe->vert_deci;
+	src_h = src.h >> pipe->vert_deci;
 
-	quota = fps * pipe->src.w * src_h;
+	quota = fps * src.w * src_h;
+
+	pr_debug("src(w,h)(%d,%d) dst(w,h)(%d,%d) dst_y=%d bpp=%d yuv=%d\n",
+		 pipe->src.w, src_h, pipe->dst.w, pipe->dst.h, pipe->dst.y,
+		 pipe->src_fmt->bpp, pipe->src_fmt->is_yuv);
+
 	if (pipe->src_fmt->chroma_sample == MDSS_MDP_CHROMA_420)
 		/*
 		 * with decimation, chroma is not downsampled, this means we
@@ -225,41 +371,76 @@
 	else
 		quota *= pipe->src_fmt->bpp;
 
-	rate = pipe->dst.w;
-	if (src_h > pipe->dst.h)
-		rate = (rate * src_h) / pipe->dst.h;
+	rate = dst.w;
+	if (src_h > dst.h)
+		rate = (rate * src_h) / dst.h;
 
 	rate *= v_total * fps;
 	if (mixer->rotator_mode) {
 		rate /= 4; /* block mode fetch at 4 pix/clk */
 		quota *= 2; /* bus read + write */
-		perf->ib_quota = quota;
+		perf->bw_overlap = quota;
 	} else {
-		perf->ib_quota = (quota / pipe->dst.h) * v_total;
+		perf->bw_overlap = (quota / dst.h) * v_total;
 	}
-	perf->ab_quota = quota;
-	perf->mdp_clk_rate = rate;
 
-	pr_debug("mixer=%d pnum=%d clk_rate=%u bus ab=%u ib=%u\n",
-		 mixer->num, pipe->num, rate, perf->ab_quota, perf->ib_quota);
+	perf->mdp_clk_rate = mdss_mdp_clk_fudge_factor(mixer, rate);
+
+	prefill_params.smp_bytes = mdss_mdp_smp_get_size(pipe);
+	prefill_params.xres = xres;
+	prefill_params.src_w = src.w;
+	prefill_params.src_h = src_h;
+	prefill_params.dst_w = dst.w;
+	prefill_params.dst_h = dst.h;
+	prefill_params.dst_y = dst.y;
+	prefill_params.bpp = pipe->src_fmt->bpp;
+	prefill_params.is_yuv = pipe->src_fmt->is_yuv;
+	prefill_params.is_caf = mdss_mdp_perf_is_caf(pipe);
+	prefill_params.is_fbc = is_fbc;
+	prefill_params.is_bwc = pipe->bwc_mode;
+	prefill_params.is_tile = pipe->src_fmt->tile;
+	prefill_params.is_hflip = pipe->flags & MDP_FLIP_LR;
+
+	if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
+		perf->prefill_bytes = (mixer->ctl->is_video_mode) ?
+			mdss_mdp_perf_calc_pipe_prefill_video(&prefill_params) :
+			mdss_mdp_perf_calc_pipe_prefill_cmd(&prefill_params);
+	}
+	else
+		perf->prefill_bytes = 0;
+
+	pr_debug("mixer=%d pnum=%d clk_rate=%u bw_overlap=%llu prefill=%d\n",
+		 mixer->num, pipe->num, perf->mdp_clk_rate, perf->bw_overlap,
+		 perf->prefill_bytes);
 
 	return 0;
 }
 
-static void mdss_mdp_perf_mixer_update(struct mdss_mdp_mixer *mixer,
-				       u32 *bus_ab_quota, u32 *bus_ib_quota,
-				       u32 *clk_rate)
+static inline int mdss_mdp_perf_is_overlap(u32 y00, u32 y01, u32 y10, u32 y11)
+{
+	return (y10 < y00 && y11 >= y01) || (y10 >= y00 && y10 <= y01);
+}
+
+static inline int cmpu32(const void *a, const void *b)
+{
+	return (*(u32 *)a < *(u32 *)b) ? -1 : 0;
+}
+
+static void mdss_mdp_perf_calc_mixer(struct mdss_mdp_mixer *mixer,
+		struct mdss_mdp_perf_params *perf)
 {
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_panel_info *pinfo = NULL;
 	int fps = DEFAULT_FRAME_RATE;
-	u32 v_total;
+	u32 v_total = 0;
 	int i;
-	u32 max_clk_rate = 0, ab_total = 0, ib_total = 0;
+	u32 max_clk_rate = 0;
+	u64 bw_overlap_max = 0;
+	u64 bw_overlap[MDSS_MDP_MAX_STAGE];
+	u32 v_region[MDSS_MDP_MAX_STAGE * 2];
+	u32 prefill_bytes = 0;
 
-	*bus_ab_quota = 0;
-	*bus_ib_quota = 0;
-	*clk_rate = 0;
+	memset(perf, 0, sizeof(*perf));
 
 	if (!mixer->rotator_mode) {
 		if (mixer->type == MDSS_MDP_MIXER_TYPE_INTF) {
@@ -272,100 +453,392 @@
 		} else {
 			v_total = mixer->height;
 		}
-		*clk_rate = mixer->width * v_total * fps;
-		if (pinfo && pinfo->lcdc.v_back_porch < MDP_MIN_VBP)
-			*clk_rate = MDSS_MDP_CLK_FUDGE_FACTOR(*clk_rate);
 
-		if (!pinfo) {
-			/* perf for bus writeback */
-			*bus_ab_quota = fps * mixer->width * mixer->height * 3;
-			*bus_ab_quota >>= MDSS_MDP_BUS_FACTOR_SHIFT;
-			*bus_ib_quota = *bus_ab_quota;
-		}
+		perf->mdp_clk_rate = mixer->width * v_total * fps;
+		perf->mdp_clk_rate =
+			mdss_mdp_clk_fudge_factor(mixer, perf->mdp_clk_rate);
+
+		if (!pinfo)	/* perf for bus writeback */
+			perf->bw_overlap =
+				fps * mixer->width * mixer->height * 3;
 	}
 
+	memset(bw_overlap, 0, sizeof(u64) * MDSS_MDP_MAX_STAGE);
+	memset(v_region, 0, sizeof(u32) * MDSS_MDP_MAX_STAGE * 2);
+
 	for (i = 0; i < MDSS_MDP_MAX_STAGE; i++) {
-		struct mdss_mdp_perf_params perf;
+		struct mdss_mdp_perf_params tmp;
 		pipe = mixer->stage_pipe[i];
 		if (pipe == NULL)
 			continue;
 
-		if (mdss_mdp_perf_calc_pipe(pipe, &perf))
+		if (mdss_mdp_perf_calc_pipe(pipe, &tmp, &mixer->roi))
 			continue;
-
-		ab_total += perf.ab_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
-		ib_total += perf.ib_quota >> MDSS_MDP_BUS_FACTOR_SHIFT;
-		if (perf.mdp_clk_rate > max_clk_rate)
-			max_clk_rate = perf.mdp_clk_rate;
+		prefill_bytes += tmp.prefill_bytes;
+		bw_overlap[i] = tmp.bw_overlap;
+		v_region[2*i] = pipe->dst.y;
+		v_region[2*i + 1] = pipe->dst.y + pipe->dst.h;
+		if (tmp.mdp_clk_rate > max_clk_rate)
+			max_clk_rate = tmp.mdp_clk_rate;
 	}
 
-	*bus_ab_quota += ab_total;
-	*bus_ib_quota += ib_total;
-	if (max_clk_rate > *clk_rate)
-		*clk_rate = max_clk_rate;
+	/*
+	 * Sort the v_region array so the total display area can be
+	 * divided into individual regions. Check how many pipes fetch
+	 * data for each region and sum them up, then the worst case
+	 * of all regions is ib request.
+	 */
+	sort(v_region, MDSS_MDP_MAX_STAGE * 2, sizeof(u32), cmpu32, NULL);
+	for (i = 1; i < MDSS_MDP_MAX_STAGE * 2; i++) {
+		int j;
+		u64 bw_max_region = 0;
+		u32 y0, y1;
+		pr_debug("v_region[%d]%d\n", i, v_region[i]);
+		if (v_region[i] == v_region[i-1])
+			continue;
+		y0 = (v_region[i-1]) ? v_region[i-1] + 1 : 0;
+		y1 = v_region[i];
+		for (j = 0; j < MDSS_MDP_MAX_STAGE; j++) {
+			if (!bw_overlap[j])
+				continue;
+			pipe = mixer->stage_pipe[j];
+			if (mdss_mdp_perf_is_overlap(y0, y1, pipe->dst.y,
+				(pipe->dst.y + pipe->dst.h)))
+				bw_max_region += bw_overlap[j];
+			pr_debug("v[%d](%d,%d)pipe[%d](%d,%d)bw(%llu %llu)\n",
+				i, y0, y1, j, pipe->dst.y,
+				pipe->dst.y + pipe->dst.h, bw_overlap[j],
+				bw_max_region);
+		}
+		bw_overlap_max = max(bw_overlap_max, bw_max_region);
+	}
 
-	pr_debug("final mixer=%d clk_rate=%u bus ab=%u ib=%u\n", mixer->num,
-		 *clk_rate, *bus_ab_quota, *bus_ib_quota);
+	perf->bw_overlap += bw_overlap_max;
+	perf->prefill_bytes += prefill_bytes;
+
+	if (max_clk_rate > perf->mdp_clk_rate)
+		perf->mdp_clk_rate = max_clk_rate;
+
+	pr_debug("final mixer=%d video=%d clk_rate=%u bw=%llu prefill=%d\n",
+		mixer->num, mixer->ctl->is_video_mode, perf->mdp_clk_rate,
+		perf->bw_overlap, perf->prefill_bytes);
+
 }
 
-static int mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl)
+static u32 mdss_mdp_get_vbp_factor(struct mdss_mdp_ctl *ctl)
 {
-	int ret = MDSS_MDP_PERF_UPDATE_SKIP;
-	u32 clk_rate, ab_quota, ib_quota;
-	u32 max_clk_rate = 0, total_ab_quota = 0, total_ib_quota = 0;
+	u32 fps, v_total, vbp, vbp_fac;
+	struct mdss_panel_info *pinfo;
+
+	if (!ctl || !ctl->panel_data)
+		return 0;
+
+	pinfo = &ctl->panel_data->panel_info;
+	fps = mdss_panel_get_framerate(pinfo);
+	v_total = mdss_panel_get_vtotal(pinfo);
+	vbp = pinfo->lcdc.v_back_porch + pinfo->lcdc.v_pulse_width;
+	vbp_fac = (vbp) ? fps * v_total / vbp : 0;
+	pr_debug("vbp_fac=%d vbp=%d v_total=%d\n", vbp_fac, vbp, v_total);
+
+	return vbp_fac;
+}
+
+static u32 mdss_mdp_get_vbp_factor_max(struct mdss_mdp_ctl *ctl)
+{
+	u32 vbp_max = 0;
+	int i;
+	struct mdss_data_type *mdata;
+
+	if (!ctl || !ctl->mdata)
+		return 0;
+
+	mdata = ctl->mdata;
+	for (i = 0; i < mdata->nctl; i++) {
+		struct mdss_mdp_ctl *ctl = mdata->ctl_off + i;
+		u32 vbp_fac;
+
+		if (ctl->power_on) {
+			vbp_fac = mdss_mdp_get_vbp_factor(ctl);
+			vbp_max = max(vbp_max, vbp_fac);
+		}
+	}
+
+	return vbp_max;
+}
+
+static void mdss_mdp_perf_calc_ctl(struct mdss_mdp_ctl *ctl,
+		struct mdss_mdp_perf_params *perf)
+{
+	struct mdss_mdp_perf_params tmp;
+
+	memset(perf, 0, sizeof(*perf));
 
 	if (ctl->mixer_left) {
-		mdss_mdp_perf_mixer_update(ctl->mixer_left, &ab_quota,
-					   &ib_quota, &clk_rate);
-		total_ab_quota += ab_quota;
-		total_ib_quota += ib_quota;
-		max_clk_rate = clk_rate;
+		mdss_mdp_perf_calc_mixer(ctl->mixer_left, &tmp);
+		perf->bw_overlap += tmp.bw_overlap;
+		perf->prefill_bytes += tmp.prefill_bytes;
+		perf->mdp_clk_rate = tmp.mdp_clk_rate;
 	}
 
 	if (ctl->mixer_right) {
-		mdss_mdp_perf_mixer_update(ctl->mixer_right, &ab_quota,
-					   &ib_quota, &clk_rate);
-		total_ab_quota += ab_quota;
-		total_ib_quota += ib_quota;
-		if (clk_rate > max_clk_rate)
-			max_clk_rate = clk_rate;
+		mdss_mdp_perf_calc_mixer(ctl->mixer_right, &tmp);
+		perf->bw_overlap += tmp.bw_overlap;
+		perf->prefill_bytes += tmp.prefill_bytes;
+		if (tmp.mdp_clk_rate > perf->mdp_clk_rate)
+			perf->mdp_clk_rate = tmp.mdp_clk_rate;
 
 		if (ctl->intf_type) {
-			clk_rate = mdss_mdp_get_pclk_rate(ctl);
+			u32 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)
-				max_clk_rate = clk_rate;
+			if (clk_rate > perf->mdp_clk_rate)
+				perf->mdp_clk_rate = clk_rate;
 		}
 	}
 
 	/* request minimum bandwidth to have bus clock on when display is on */
-	if (total_ib_quota == 0)
-		total_ib_quota = SZ_16M >> MDSS_MDP_BUS_FACTOR_SHIFT;
+	if (perf->bw_overlap == 0)
+		perf->bw_overlap = SZ_16M;
 
-	if (max_clk_rate != ctl->clk_rate) {
-		if (max_clk_rate > ctl->clk_rate)
-			ret = MDSS_MDP_PERF_UPDATE_EARLY;
-		else
-			ret = MDSS_MDP_PERF_UPDATE_LATE;
-		ctl->clk_rate = max_clk_rate;
-		ctl->perf_changed |= MDSS_MDP_PERF_UPDATE_CLK;
+	if (ctl->intf_type != MDSS_MDP_NO_INTF) {
+		u32 vbp_fac = mdss_mdp_get_vbp_factor_max(ctl);
+
+		perf->bw_prefill = perf->prefill_bytes;
+		/*
+		 * Prefill bandwidth equals the amount of data (number
+		 * of prefill_bytes) divided by the the amount time
+		 * available (blanking period). It is equivalent that
+		 * prefill bytes times a factor in unit Hz, which is
+		 * the reciprocal of time.
+		 */
+		perf->bw_prefill *= vbp_fac;
 	}
 
-	if ((total_ab_quota != ctl->bus_ab_quota) ||
-			(total_ib_quota != ctl->bus_ib_quota)) {
-		if (ret == MDSS_MDP_PERF_UPDATE_SKIP) {
-			if (total_ib_quota >= ctl->bus_ib_quota)
-				ret = MDSS_MDP_PERF_UPDATE_EARLY;
-			else
-				ret = MDSS_MDP_PERF_UPDATE_LATE;
+	perf->bw_ctl = max(perf->bw_prefill, perf->bw_overlap);
+
+	if (ctl->is_video_mode)
+		perf->bw_ctl = IB_FUDGE_FACTOR(perf->bw_ctl);
+
+	pr_debug("ctl=%d clk_rate=%u\n", ctl->num, perf->mdp_clk_rate);
+	pr_debug("bw_overlap=%llu bw_prefill=%llu prefill_byptes=%d\n",
+		 perf->bw_overlap, perf->bw_prefill, perf->prefill_bytes);
+}
+
+static bool mdss_mdp_ctl_perf_bw_released(struct mdss_mdp_ctl *ctl)
+{
+	unsigned long flags;
+	bool released = false;
+
+	if (!ctl || !ctl->panel_data ||
+		(ctl->panel_data->panel_info.type != MIPI_CMD_PANEL))
+		return released;
+
+	spin_lock_irqsave(&ctl->spin_lock, flags);
+	if (ctl->perf_status == 0) {
+		released = true;
+		ctl->perf_status++;
+	} else if (ctl->perf_status <= 2) {
+		ctl->perf_status++;
+	} else {
+		pr_err("pervious commit was not done\n");
+	}
+
+	pr_debug("perf_status=%d\n", ctl->perf_status);
+	spin_unlock_irqrestore(&ctl->spin_lock, flags);
+
+	return released;
+}
+
+/**
+ * @mdss_mdp_ctl_perf_taken() - indicates a committed buffer is taken
+ *                              by h/w
+ * @ctl - pointer to ctl data structure
+ *
+ * A committed buffer to be displayed is taken at a vsync or reader
+ * pointer interrupt by h/w. This function must be called in vsync
+ * interrupt context to indicate the buf status is changed.
+ */
+void mdss_mdp_ctl_perf_taken(struct mdss_mdp_ctl *ctl)
+{
+	if (!ctl || !ctl->panel_data ||
+		(ctl->panel_data->panel_info.type != MIPI_CMD_PANEL))
+		return;
+
+	spin_lock(&ctl->spin_lock);
+	if (ctl->perf_status)
+		ctl->perf_status++;
+	pr_debug("perf_status=%d\n", ctl->perf_status);
+	spin_unlock(&ctl->spin_lock);
+}
+
+/**
+ * @mdss_mdp_ctl_perf_done() - indicates a committed buffer is
+ *                             displayed, so resources such as
+ *                             bandwidth that are associated to this
+ *                             buffer can be released.
+ * @ctl - pointer to a ctl
+ *
+ * When pingping done interrupt is trigged, mdp finishes displaying a
+ * buffer which was committed by user and taken by h/w and calling
+ * this function to clear those two states. This function must be
+ * called in pinppong done interrupt context.
+ */
+void mdss_mdp_ctl_perf_done(struct mdss_mdp_ctl *ctl)
+{
+	if (!ctl || !ctl->panel_data ||
+		(ctl->panel_data->panel_info.type != MIPI_CMD_PANEL))
+		return;
+
+	spin_lock(&ctl->spin_lock);
+	if (ctl->perf_status) {
+		ctl->perf_status--;
+		if (ctl->perf_status)
+			ctl->perf_status--;
+	}
+	pr_debug("perf_status=%d\n", ctl->perf_status);
+	spin_unlock(&ctl->spin_lock);
+}
+
+static inline void mdss_mdp_ctl_perf_update_bus(struct mdss_mdp_ctl *ctl)
+{
+	u64 bw_sum_of_intfs = 0;
+	u64 bus_ab_quota, bus_ib_quota;
+	struct mdss_data_type *mdata;
+	int i;
+
+	if (!ctl || !ctl->mdata)
+		return;
+
+	mdata = ctl->mdata;
+	for (i = 0; i < mdata->nctl; i++) {
+		struct mdss_mdp_ctl *ctl;
+		ctl = mdata->ctl_off + i;
+		if (ctl->power_on) {
+			bw_sum_of_intfs += ctl->cur_perf.bw_ctl;
+			pr_debug("c=%d bw=%llu\n", ctl->num,
+				ctl->cur_perf.bw_ctl);
 		}
-		ctl->bus_ab_quota = total_ab_quota;
-		ctl->bus_ib_quota = total_ib_quota;
-		ctl->perf_changed |= MDSS_MDP_PERF_UPDATE_BUS;
+	}
+	bus_ib_quota = bw_sum_of_intfs;
+	bus_ab_quota = AB_FUDGE_FACTOR(bw_sum_of_intfs);
+	mdss_mdp_bus_scale_set_quota(bus_ab_quota, bus_ib_quota);
+	pr_debug("ab=%llu ib=%llu\n", bus_ab_quota, bus_ib_quota);
+}
+
+/**
+ * @mdss_mdp_ctl_perf_release_bw() - request zero bandwidth
+ * @ctl - pointer to a ctl
+ *
+ * Function checks a state variable for the ctl, if all pending commit
+ * requests are done, meanning no more bandwidth is needed, release
+ * bandwidth request.
+ */
+void mdss_mdp_ctl_perf_release_bw(struct mdss_mdp_ctl *ctl)
+{
+	unsigned long flags;
+	int need_release = 0;
+	struct mdss_data_type *mdata;
+	int i;
+
+	/* only do this for command panel */
+	if (!ctl || !ctl->mdata || !ctl->panel_data ||
+		(ctl->panel_data->panel_info.type != MIPI_CMD_PANEL))
+		return;
+
+	mutex_lock(&mdss_mdp_ctl_lock);
+	mdata = ctl->mdata;
+	/*
+	 * If video interface present, cmd panel bandwidth cannot be
+	 * released.
+	 */
+	for (i = 0; i < mdata->nctl; i++) {
+		struct mdss_mdp_ctl *ctl = mdata->ctl_off + i;
+
+		if (ctl->power_on && ctl->is_video_mode) {
+			mutex_unlock(&mdss_mdp_ctl_lock);
+			return;
+		}
 	}
 
-	return ret;
+	spin_lock_irqsave(&ctl->spin_lock, flags);
+	if (!ctl->perf_status)
+		need_release = 1;
+	pr_debug("need release=%d\n", need_release);
+	spin_unlock_irqrestore(&ctl->spin_lock, flags);
+
+	if (need_release) {
+		ctl->cur_perf.bw_ctl = 0;
+		ctl->new_perf.bw_ctl = 0;
+		mdss_mdp_ctl_perf_update_bus(ctl);
+	}
+	mutex_unlock(&mdss_mdp_ctl_lock);
+}
+
+static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl,
+		int params_changed)
+{
+	struct mdss_mdp_perf_params *new, *old;
+	int update_bus = 0, update_clk = 0;
+	struct mdss_data_type *mdata;
+
+	if (!ctl || !ctl->mdata)
+		return;
+
+	mutex_lock(&mdss_mdp_ctl_lock);
+
+	mdata = ctl->mdata;
+	old = &ctl->cur_perf;
+	new = &ctl->new_perf;
+
+	if (ctl->power_on) {
+		if (params_changed || mdss_mdp_ctl_perf_bw_released(ctl))
+			mdss_mdp_perf_calc_ctl(ctl, new);
+		/*
+		 * if params have just changed delay the update until
+		 * later once the hw configuration has been flushed to
+		 * MDP
+		 */
+		if ((params_changed && (new->bw_ctl > old->bw_ctl)) ||
+		    (!params_changed && (new->bw_ctl < old->bw_ctl))) {
+			pr_debug("c=%d p=%d new_bw=%llu,old_bw=%llu\n",
+				ctl->num, params_changed, new->bw_ctl,
+				old->bw_ctl);
+			old->bw_ctl = new->bw_ctl;
+			update_bus = 1;
+		}
+
+		if ((params_changed && (new->mdp_clk_rate > old->mdp_clk_rate))
+		    || (!params_changed && (new->mdp_clk_rate <
+					    old->mdp_clk_rate))) {
+			old->mdp_clk_rate = new->mdp_clk_rate;
+			update_clk = 1;
+		}
+	} else {
+		memset(old, 0, sizeof(old));
+		memset(new, 0, sizeof(new));
+		update_bus = 1;
+		update_clk = 1;
+	}
+
+	if (update_bus)
+		mdss_mdp_ctl_perf_update_bus(ctl);
+
+	if (update_clk) {
+		u32 clk_rate = 0;
+		int i;
+
+		for (i = 0; i < mdata->nctl; i++) {
+			struct mdss_mdp_ctl *ctl;
+			ctl = mdata->ctl_off + i;
+			if (ctl->power_on)
+				clk_rate = max(ctl->cur_perf.mdp_clk_rate,
+					       clk_rate);
+		}
+		mdss_mdp_set_clk_rate(clk_rate);
+		pr_debug("update clk rate = %d HZ\n", clk_rate);
+	}
+
+	mutex_unlock(&mdss_mdp_ctl_lock);
 }
 
 static struct mdss_mdp_ctl *mdss_mdp_ctl_alloc(struct mdss_data_type *mdata,
@@ -385,6 +858,7 @@
 			ctl->ref_cnt++;
 			ctl->mdata = mdata;
 			mutex_init(&ctl->lock);
+			spin_lock_init(&ctl->spin_lock);
 			BLOCKING_INIT_NOTIFIER_HEAD(&ctl->notifier_head);
 			pr_debug("alloc ctl_num=%d\n", ctl->num);
 			break;
@@ -606,7 +1080,7 @@
 
 	mdss_mdp_ctl_free(ctl);
 
-	mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
+	mdss_mdp_ctl_perf_update(ctl, 0);
 
 	return 0;
 }
@@ -1142,9 +1616,7 @@
 	if (!handoff)
 		ctl->power_on = true;
 
-	ctl->bus_ab_quota = 0;
-	ctl->bus_ib_quota = 0;
-	ctl->clk_rate = 0;
+	memset(&ctl->cur_perf, 0, sizeof(ctl->cur_perf));
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 
@@ -1233,8 +1705,7 @@
 
 		ctl->power_on = false;
 		ctl->play_cnt = 0;
-		ctl->clk_rate = 0;
-		mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
+		mdss_mdp_ctl_perf_update(ctl, 0);
 	}
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
@@ -1459,6 +1930,8 @@
 
 	if (mixer->num == MDSS_MDP_INTF_LAYERMIXER3)
 		ctl->flush_bits |= BIT(20);
+	else if (mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
+		ctl->flush_bits |= BIT(9) << mixer->num;
 	else
 		ctl->flush_bits |= BIT(6) << mixer->num;
 
@@ -1727,9 +2200,12 @@
 int mdss_mdp_ctl_update_fps(struct mdss_mdp_ctl *ctl, int fps)
 {
 	int ret = 0;
+	struct mdss_mdp_ctl *sctl = NULL;
+
+	sctl = mdss_mdp_get_split_ctl(ctl);
 
 	if (ctl->config_fps_fnc)
-		ret = ctl->config_fps_fnc(ctl, fps);
+		ret = ctl->config_fps_fnc(ctl, sctl, fps);
 
 	return ret;
 }
@@ -1820,10 +2296,7 @@
 	if (ctl->wait_fnc)
 		ret = ctl->wait_fnc(ctl, NULL);
 
-	if (ctl->perf_changed) {
-		mdss_mdp_ctl_perf_commit(ctl->mdata, ctl->perf_changed);
-		ctl->perf_changed = 0;
-	}
+	mdss_mdp_ctl_perf_update(ctl, 0);
 
 	mutex_unlock(&ctl->lock);
 
@@ -1856,7 +2329,6 @@
 	struct mdss_mdp_ctl *sctl = NULL;
 	int mixer1_changed, mixer2_changed;
 	int ret = 0;
-	int perf_update = MDSS_MDP_PERF_UPDATE_SKIP;
 
 	if (!ctl) {
 		pr_err("display function not set\n");
@@ -1877,10 +2349,9 @@
 	mixer2_changed = (ctl->mixer_right && ctl->mixer_right->params_changed);
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
 	if (mixer1_changed || mixer2_changed
 			|| ctl->force_screen_state) {
-		perf_update = mdss_mdp_ctl_perf_update(ctl);
-
 		if (ctl->prepare_fnc)
 			ret = ctl->prepare_fnc(ctl, arg);
 		if (ret) {
@@ -1888,10 +2359,7 @@
 			goto done;
 		}
 
-		if (perf_update == MDSS_MDP_PERF_UPDATE_EARLY) {
-			mdss_mdp_ctl_perf_commit(ctl->mdata, ctl->perf_changed);
-			ctl->perf_changed = 0;
-		}
+		mdss_mdp_ctl_perf_update(ctl, 1);
 
 		if (mixer1_changed)
 			mdss_mdp_mixer_update(ctl->mixer_left);
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h
index a2edf90..dcbff88 100644
--- a/drivers/video/msm/mdss/mdss_mdp_formats.h
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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,25 @@
 		},						\
 	}
 
+#define FMT_RGB_8888_TILE(fmt, alpha_en, e0, e1, e2, e3)	\
+	{							\
+		.format = (fmt),				\
+		.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,	\
+		.unpack_tight = 1,				\
+		.unpack_align_msb = 0,				\
+		.alpha_enable = (alpha_en),			\
+		.unpack_count = 4,				\
+		.bpp = 4,					\
+		.tile = 1,					\
+		.element = { (e0), (e1), (e2), (e3) },		\
+		.bits = {					\
+			[C3_ALPHA] = COLOR_8BIT,		\
+			[C2_R_Cr] = COLOR_8BIT,			\
+			[C0_G_Y] = COLOR_8BIT,			\
+			[C1_B_Cb] = COLOR_8BIT,			\
+		},						\
+	}
+
 #define FMT_YUV_COMMON(fmt)					\
 		.format = (fmt),				\
 		.is_yuv = 1,					\
@@ -125,6 +144,22 @@
 	FMT_RGB_8888(MDP_RGBX_8888, 0, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
 	FMT_RGB_8888(MDP_BGRA_8888, 1, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
 	FMT_RGB_8888(MDP_BGRX_8888, 0, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
+	FMT_RGB_8888_TILE(MDP_RGBA_8888_TILE, 1, C2_R_Cr, C0_G_Y, C1_B_Cb,
+			C3_ALPHA),
+	FMT_RGB_8888_TILE(MDP_ARGB_8888_TILE, 1, C3_ALPHA, C2_R_Cr, C0_G_Y,
+			C1_B_Cb),
+	FMT_RGB_8888_TILE(MDP_ABGR_8888_TILE, 1, C3_ALPHA, C1_B_Cb, C0_G_Y,
+			C2_R_Cr),
+	FMT_RGB_8888_TILE(MDP_BGRA_8888_TILE, 1, C1_B_Cb, C0_G_Y, C2_R_Cr,
+			C3_ALPHA),
+	FMT_RGB_8888_TILE(MDP_RGBX_8888_TILE, 0, C2_R_Cr, C0_G_Y, C1_B_Cb,
+			C3_ALPHA),
+	FMT_RGB_8888_TILE(MDP_XRGB_8888_TILE, 0, C3_ALPHA, C2_R_Cr, C0_G_Y,
+			C1_B_Cb),
+	FMT_RGB_8888_TILE(MDP_XBGR_8888_TILE, 0, C3_ALPHA, C1_B_Cb, C0_G_Y,
+			C2_R_Cr),
+	FMT_RGB_8888_TILE(MDP_BGRX_8888_TILE, 0, C1_B_Cb, C0_G_Y, C2_R_Cr,
+			C3_ALPHA),
 
 	FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V1, MDSS_MDP_CHROMA_RGB, C2_R_Cr, C1_B_Cb),
 	FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V1, MDSS_MDP_CHROMA_RGB, C1_B_Cb, C2_R_Cr),
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index bcd3cf4..bff56d2 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -20,12 +20,13 @@
 #define GC_LUT_SEGMENTS	16
 #define ENHIST_LUT_ENTRIES 256
 #define HIST_V_SIZE	256
-#define SIX_ZONE_LUT_ENTRIES 384
 
 #define MDSS_MDP_HW_REV_100		0x10000000
 #define MDSS_MDP_HW_REV_102		0x10020000
 #define MDSS_MDP_HW_REV_103		0x10030000
 
+#define MDSS_MDP_FETCH_CONFIG_RESET_VALUE	0x00000087
+
 #define MDSS_REG_HW_VERSION				0x0
 #define MDSS_REG_HW_INTR_STATUS				0x10
 
@@ -439,6 +440,7 @@
 #define MDSS_MDP_REG_DSPP_HIST_CTL_BASE			0x210
 #define MDSS_MDP_REG_DSPP_HIST_LUT_BASE			0x230
 #define MDSS_MDP_REG_DSPP_PA_BASE			0x238
+#define MDSS_MDP_REG_DSPP_SIX_ZONE_BASE			0x248
 #define MDSS_MDP_REG_DSPP_GAMUT_BASE			0x2DC
 #define MDSS_MDP_REG_DSPP_GC_BASE			0x2B0
 
@@ -580,4 +582,8 @@
 #define MDSS_MDP_LP_MISR_SEL_LMIX4_BLEND	0x10
 #define MDSS_MDP_LP_MISR_SEL_LMIX4_GC		0x11
 
+/* following offsets are with respect to MDP VBIF base */
+#define MMSS_VBIF_XIN_HALT_CTRL0	0x200
+#define MMSS_VBIF_XIN_HALT_CTRL1	0x204
+
 #endif
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index c4a0645..ce0b757 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -247,6 +247,8 @@
 		return;
 	}
 
+	mdss_mdp_ctl_perf_taken(ctl);
+
 	vsync_time = ktime_get();
 	ctl->vsync_cnt++;
 
@@ -308,6 +310,8 @@
 		return;
 	}
 
+	mdss_mdp_ctl_perf_done(ctl);
+
 	spin_lock(&ctx->clk_lock);
 	list_for_each_entry(tmp, &ctx->vsync_handlers, list) {
 		if (tmp->enabled && tmp->cmd_post_flush)
@@ -340,9 +344,12 @@
 	struct mdss_mdp_cmd_ctx *ctx =
 		container_of(work, typeof(*ctx), pp_done_work);
 
-	if (ctx->ctl)
+	if (ctx->ctl) {
 		while (atomic_add_unless(&ctx->pp_done_cnt, -1, 0))
 			mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_DONE);
+
+		mdss_mdp_ctl_perf_release_bw(ctx->ctl);
+	}
 }
 
 static void clk_ctrl_work(struct work_struct *work)
@@ -427,9 +434,6 @@
 
 	pdata->panel_info.cont_splash_enabled = 0;
 
-	ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_FINISH,
-			NULL);
-
 	mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)0);
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index bd1c3eb..7304694 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -62,6 +62,7 @@
 
 	atomic_t vsync_ref;
 	spinlock_t vsync_lock;
+	struct mutex vsync_mtx;
 	struct list_head vsync_handlers;
 };
 
@@ -216,19 +217,23 @@
 {
 	struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
 
+	mutex_lock(&ctx->vsync_mtx);
 	if (atomic_inc_return(&ctx->vsync_ref) == 1)
 		mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
 	else if (clear)
 		mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
 				ctl->intf_num);
+	mutex_unlock(&ctx->vsync_mtx);
 }
 
 static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl)
 {
 	struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
 
+	mutex_lock(&ctx->vsync_mtx);
 	if (atomic_dec_return(&ctx->vsync_ref) == 0)
 		mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+	mutex_unlock(&ctx->vsync_mtx);
 }
 
 static int mdss_mdp_video_add_vsync_handler(struct mdss_mdp_ctl *ctl,
@@ -461,7 +466,63 @@
 			ctl->underrun_cnt);
 }
 
-static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl, int new_fps)
+static int mdss_mdp_video_vfp_fps_update(struct mdss_mdp_ctl *ctl, int new_fps)
+{
+	int curr_fps;
+	u32 add_v_lines = 0;
+	u32 current_vsync_period_f0, new_vsync_period_f0;
+	struct mdss_panel_data *pdata;
+	struct mdss_mdp_video_ctx *ctx;
+	u32 vsync_period, hsync_period;
+
+	ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
+	if (!ctx) {
+		pr_err("invalid ctx\n");
+		return -ENODEV;
+	}
+
+	pdata = ctl->panel_data;
+	if (pdata == NULL) {
+		pr_err("%s: Invalid panel data\n", __func__);
+		return -EINVAL;
+	}
+
+	vsync_period = mdss_panel_get_vtotal(&pdata->panel_info);
+	hsync_period = mdss_panel_get_htotal(&pdata->panel_info);
+	curr_fps = mdss_panel_get_framerate(&pdata->panel_info);
+
+	if (curr_fps > new_fps) {
+		add_v_lines = mult_frac(vsync_period,
+				(curr_fps - new_fps), new_fps);
+		pdata->panel_info.lcdc.v_front_porch += add_v_lines;
+	} else {
+		add_v_lines = mult_frac(vsync_period,
+				(new_fps - curr_fps), new_fps);
+		pdata->panel_info.lcdc.v_front_porch -= add_v_lines;
+	}
+
+	vsync_period = mdss_panel_get_vtotal(&pdata->panel_info);
+	current_vsync_period_f0 = mdp_video_read(ctx,
+		MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0);
+	new_vsync_period_f0 = (vsync_period * hsync_period);
+
+	mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
+			current_vsync_period_f0 | 0x800000);
+	if (new_vsync_period_f0 & 0x800000) {
+		mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
+			new_vsync_period_f0);
+	} else {
+		mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
+			new_vsync_period_f0 | 0x800000);
+		mdp_video_write(ctx, MDSS_MDP_REG_INTF_VSYNC_PERIOD_F0,
+			new_vsync_period_f0 & 0x7fffff);
+	}
+
+	return 0;
+}
+
+static int mdss_mdp_video_config_fps(struct mdss_mdp_ctl *ctl,
+					struct mdss_mdp_ctl *sctl, int new_fps)
 {
 	struct mdss_mdp_video_ctx *ctx;
 	struct mdss_panel_data *pdata;
@@ -524,6 +585,40 @@
 			ctl->force_screen_state = MDSS_SCREEN_DEFAULT;
 			mdss_mdp_display_commit(ctl, NULL);
 			mdss_mdp_display_wait4comp(ctl);
+		} else if (pdata->panel_info.dfps_update
+				== DFPS_IMMEDIATE_PORCH_UPDATE_MODE){
+			if (!ctx->timegen_en) {
+				pr_err("TG is OFF. DFPS mode invalid\n");
+				return -EINVAL;
+			}
+
+			video_vsync_irq_enable(ctl, true);
+			INIT_COMPLETION(ctx->vsync_comp);
+			rc = wait_for_completion_timeout(&ctx->vsync_comp,
+				usecs_to_jiffies(VSYNC_TIMEOUT_US));
+			WARN(rc <= 0, "timeout (%d) vsync interrupt on ctl=%d\n",
+				rc, ctl->num);
+			rc = 0;
+			video_vsync_irq_disable(ctl);
+
+			rc = mdss_mdp_video_vfp_fps_update(ctl, new_fps);
+			if (rc < 0) {
+				pr_err("%s: Error during DFPS\n", __func__);
+				return rc;
+			}
+			if (sctl) {
+				rc = mdss_mdp_video_vfp_fps_update(sctl,
+								new_fps);
+				if (rc < 0) {
+					pr_err("%s: DFPS error\n", __func__);
+					return rc;
+				}
+			}
+			rc = mdss_mdp_ctl_intf_event(ctl,
+						MDSS_EVENT_PANEL_UPDATE_FPS,
+						(void *)new_fps);
+			WARN(rc, "intf %d panel fps update error (%d)\n",
+							ctl->intf_num, rc);
 		} else {
 			pr_err("intf %d panel, unknown FPS mode\n",
 							ctl->intf_num);
@@ -684,6 +779,7 @@
 	ctx->intf_type = ctl->intf_type;
 	init_completion(&ctx->vsync_comp);
 	spin_lock_init(&ctx->vsync_lock);
+	mutex_init(&ctx->vsync_mtx);
 	atomic_set(&ctx->vsync_ref, 0);
 
 	mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index ff55c57..27a7707 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -17,6 +17,9 @@
 #include "mdss_mdp_rotator.h"
 #include "mdss_panel.h"
 
+#define VBIF_WR_LIM_CONF    0xC0
+#define MDSS_DEFAULT_OT_SETTING    0x10
+
 enum mdss_mdp_writeback_type {
 	MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
 	MDSS_MDP_WRITEBACK_TYPE_LINE,
@@ -34,6 +37,9 @@
 	u32 intr_type;
 	u32 intf_num;
 
+	u32 xin_id;
+	u32 wr_lim;
+
 	u32 opmode;
 	struct mdss_mdp_format_params *dst_fmt;
 	u16 width;
@@ -55,26 +61,31 @@
 		.type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
 		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
 		.intf_num = 0,
+		.xin_id = 3,
 	},
 	{
 		.type = MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
 		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
 		.intf_num = 1,
+		.xin_id = 11,
 	},
 	{
 		.type = MDSS_MDP_WRITEBACK_TYPE_LINE,
 		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
 		.intf_num = 0,
+		.xin_id = 3,
 	},
 	{
 		.type = MDSS_MDP_WRITEBACK_TYPE_LINE,
 		.intr_type = MDSS_MDP_IRQ_WB_ROT_COMP,
 		.intf_num = 1,
+		.xin_id = 11,
 	},
 	{
 		.type = MDSS_MDP_WRITEBACK_TYPE_WFD,
 		.intr_type = MDSS_MDP_IRQ_WB_WFD,
 		.intf_num = 0,
+		.xin_id = 6,
 	},
 };
 
@@ -438,9 +449,12 @@
 {
 	struct mdss_mdp_writeback_ctx *ctx;
 	struct mdss_mdp_writeback_arg *wb_args;
-	u32 flush_bits;
+	u32 flush_bits, val, off;
 	int ret;
 
+	if (!ctl || !ctl->mdata)
+		return -ENODEV;
+
 	ctx = (struct mdss_mdp_writeback_ctx *) ctl->priv_data;
 	if (!ctx)
 		return -ENODEV;
@@ -451,6 +465,18 @@
 		return -EPERM;
 	}
 
+	if (ctl->mdata->rotator_ot_limit) {
+		if (ctx->type == MDSS_MDP_WRITEBACK_TYPE_ROTATOR)
+			ctx->wr_lim = ctl->mdata->rotator_ot_limit;
+		else
+			ctx->wr_lim = MDSS_DEFAULT_OT_SETTING;
+		off = (ctx->xin_id % 4) * 8;
+		val = readl_relaxed(ctl->mdata->vbif_base + VBIF_WR_LIM_CONF);
+		val &= ~(0xFF << off);
+		val |= (ctx->wr_lim) << off;
+		writel_relaxed(val, ctl->mdata->vbif_base + VBIF_WR_LIM_CONF);
+	}
+
 	wb_args = (struct mdss_mdp_writeback_arg *) arg;
 	if (!wb_args)
 		return -ENOENT;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 4c89064..9365be8 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -23,6 +23,7 @@
 #include <linux/delay.h>
 #include <linux/msm_mdp.h>
 #include <linux/memblock.h>
+#include <linux/sw_sync.h>
 
 #include <mach/iommu_domains.h>
 #include <mach/event_timer.h>
@@ -34,6 +35,8 @@
 #include "mdss_mdp.h"
 #include "mdss_mdp_rotator.h"
 
+#include "splash.h"
+
 #define VSYNC_PERIOD 16
 #define BORDERFILL_NDX	0x0BF000BF
 #define CHECK_BOUNDS(offset, size, max_size) \
@@ -44,6 +47,8 @@
 
 #define MEM_PROTECT_SD_CTRL 0xF
 
+#define INVALID_PIPE_INDEX 0xFFFF
+
 struct sd_ctrl_req {
 	unsigned int enable;
 } __attribute__ ((__packed__));
@@ -257,7 +262,7 @@
 	int rc;
 
 	for (;;) {
-		rc = mdss_mdp_perf_calc_pipe(pipe, &perf);
+		rc = mdss_mdp_perf_calc_pipe(pipe, &perf, NULL);
 
 		if (!rc && (perf.mdp_clk_rate <= mdata->max_mdp_clk_rate))
 			break;
@@ -288,7 +293,10 @@
 	memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
 	rc = mdss_mdp_calc_phase_step(src, pipe->dst.w,
 			&pipe->scale.phase_step_x[0]);
-	if (rc) {
+	if (rc == -EOVERFLOW) {
+		/* overflow on horizontal direction is acceptable */
+		rc = 0;
+	} else if (rc) {
 		pr_err("Horizontal scaling calculation failed=%d! %d->%d\n",
 				rc, src, pipe->dst.w);
 		return rc;
@@ -297,7 +305,11 @@
 	src = pipe->src.h >> pipe->vert_deci;
 	rc = mdss_mdp_calc_phase_step(src, pipe->dst.h,
 			&pipe->scale.phase_step_y[0]);
-	if (rc) {
+
+	if ((rc == -EOVERFLOW) && (pipe->type == MDSS_MDP_PIPE_TYPE_VIG)) {
+		/* overflow on Qseed2 scaler is acceptable */
+		rc = 0;
+	} else if (rc) {
 		pr_err("Vertical scaling calculation failed=%d! %d->%d\n",
 				rc, src, pipe->dst.h);
 		return rc;
@@ -306,7 +318,7 @@
 					(1 << PHASE_STEP_SHIFT)) / 2;
 	pipe->scale.init_phase_y[0] = (pipe->scale.phase_step_y[0] -
 					(1 << PHASE_STEP_SHIFT)) / 2;
-	return 0;
+	return rc;
 }
 
 static inline void __mdss_mdp_overlay_set_chroma_sample(
@@ -587,12 +599,6 @@
 		!mdp5_data->mdata->has_wfd_blk)
 		mdss_mdp_smp_release(pipe);
 
-	/*
-	 * Clear previous SMP reservations and reserve according to the
-	 * latest configuration
-	 */
-	mdss_mdp_smp_unreserve(pipe);
-
 	ret = mdss_mdp_smp_reserve(pipe);
 	if (ret) {
 		pr_debug("mdss_mdp_smp_reserve failed. ret=%d\n", ret);
@@ -600,7 +606,6 @@
 	}
 
 	pipe->params_changed++;
-	pipe->has_buf = 0;
 
 	req->vert_deci = pipe->vert_deci;
 
@@ -758,6 +763,7 @@
 	list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup,
 				cleanup_list) {
 		list_move(&pipe->cleanup_list, &destroy_pipes);
+		mdss_mdp_pipe_fetch_halt(pipe);
 		mdss_mdp_overlay_free_buf(&pipe->back_buf);
 		__mdss_mdp_overlay_free_list_add(mfd, &pipe->front_buf);
 		pipe->mfd = NULL;
@@ -831,8 +837,7 @@
 	if (ctl->power_on) {
 		if (!mdp5_data->mdata->batfet)
 			mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
-		if (!is_mdss_iommu_attached() &&
-					!mfd->panel_info->cont_splash_enabled)
+		if (!mfd->panel_info->cont_splash_enabled)
 			mdss_iommu_attach(mdp5_data->mdata);
 		return 0;
 	}
@@ -952,9 +957,6 @@
 	int ret = 0;
 	int sd_in_pipe = 0;
 
-	if (!is_mdss_iommu_attached() && !mfd->panel_info->cont_splash_enabled)
-		mdss_iommu_attach(mdp5_data->mdata);
-
 	if (ctl->shared_lock)
 		mutex_lock(ctl->shared_lock);
 
@@ -1254,9 +1256,15 @@
 
 	pr_debug("ov queue pnum=%d\n", pipe->num);
 
+	if (pipe->flags & MDP_SOLID_FILL)
+		pr_warn("Unexpected buffer queue to a solid fill pipe\n");
+
 	flags = (pipe->flags & MDP_SECURE_OVERLAY_SESSION);
 	flags |= (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION);
 
+	if (!mfd->panel_info->cont_splash_enabled)
+		mdss_iommu_attach(mdata);
+
 	src_data = &pipe->back_buf;
 	if (src_data->num_planes) {
 		pr_warn("dropped buffer pnum=%d play=%d addr=0x%x\n",
@@ -1268,7 +1276,6 @@
 	if (IS_ERR_VALUE(ret)) {
 		pr_err("src_data pmem error\n");
 	}
-	pipe->has_buf = 1;
 	mdss_mdp_pipe_unmap(pipe);
 
 	return ret;
@@ -1375,18 +1382,18 @@
 
 static int mdss_mdp_overlay_get_fb_pipe(struct msm_fb_data_type *mfd,
 					struct mdss_mdp_pipe **ppipe,
-					int mixer_mux)
+					int mixer_mux,
+					struct mdp_overlay *req_ov)
 {
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	struct mdss_mdp_pipe *pipe;
+	int ret;
 
 	pipe = mdss_mdp_mixer_stage_pipe(mdp5_data->ctl, mixer_mux,
 					 MDSS_MDP_STAGE_BASE);
+
 	if (pipe == NULL) {
-		struct mdp_overlay req;
-		struct fb_info *fbi = mfd->fbi;
 		struct mdss_mdp_mixer *mixer;
-		int ret, bpp;
 
 		mixer = mdss_mdp_mixer_get(mdp5_data->ctl,
 					MDSS_MDP_MIXER_MUX_LEFT);
@@ -1395,49 +1402,73 @@
 			return -ENODEV;
 		}
 
-		memset(&req, 0, sizeof(req));
+		if (req_ov == NULL) {
+			struct mdp_overlay req;
+			struct fb_info *fbi = mfd->fbi;
+			int bpp;
 
-		bpp = fbi->var.bits_per_pixel / 8;
-		req.id = MSMFB_NEW_REQUEST;
-		req.src.format = mfd->fb_imgType;
-		req.src.height = fbi->var.yres;
-		req.src.width = fbi->fix.line_length / bpp;
-		if (mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT) {
-			if (req.src.width <= mixer->width) {
-				pr_warn("right fb pipe not needed\n");
-				return -EINVAL;
+			memset(&req, 0, sizeof(req));
+
+			bpp = fbi->var.bits_per_pixel / 8;
+			req.id = MSMFB_NEW_REQUEST;
+			req.src.format = mfd->fb_imgType;
+			req.src.height = fbi->var.yres;
+			req.src.width = fbi->fix.line_length / bpp;
+			if (mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT) {
+				if (req.src.width <= mixer->width) {
+					pr_warn("right fb pipe not needed\n");
+					return -EINVAL;
+				}
+
+				req.flags |= MDSS_MDP_RIGHT_MIXER;
+				req.src_rect.x = mixer->width;
+				req.src_rect.w = fbi->var.xres - mixer->width;
+			} else {
+				req.src_rect.x = 0;
+				req.src_rect.w = MIN(fbi->var.xres,
+								mixer->width);
 			}
 
-			req.flags |= MDSS_MDP_RIGHT_MIXER;
-			req.src_rect.x = mixer->width;
-			req.src_rect.w = fbi->var.xres - mixer->width;
+			req.src_rect.y = 0;
+			req.src_rect.h = req.src.height;
+			req.dst_rect.x = 0;
+			req.dst_rect.y = 0;
+			req.dst_rect.w = req.src_rect.w;
+			req.dst_rect.h = req.src_rect.h;
+			req.z_order = MDSS_MDP_STAGE_BASE;
+
+			pr_debug("allocating base pipe mux=%d\n", mixer_mux);
+
+			ret = mdss_mdp_overlay_pipe_setup(mfd, &req, &pipe);
+			if (ret)
+				return ret;
 		} else {
-			req.src_rect.x = 0;
-			req.src_rect.w = MIN(fbi->var.xres, mixer->width);
+			if (mixer_mux == MDSS_MDP_MIXER_MUX_RIGHT) {
+				req_ov->id = MSMFB_NEW_REQUEST;
+				req_ov->flags |= MDSS_MDP_RIGHT_MIXER;
+				req_ov->src_rect.w = MIN(mixer->width,
+						req_ov->src_rect.w >> 1);
+				req_ov->dst_rect.w = req_ov->src_rect.w;
+				req_ov->src_rect.x = req_ov->src_rect.w;
+				req_ov->dst_rect.x = 0;
+			}
+
+			ret = mdss_mdp_overlay_pipe_setup(mfd, req_ov, &pipe);
+			if (ret)
+				return ret;
 		}
-
-		req.src_rect.y = 0;
-		req.src_rect.h = req.src.height;
-		req.dst_rect.x = 0;
-		req.dst_rect.y = 0;
-		req.dst_rect.w = req.src_rect.w;
-		req.dst_rect.h = req.src_rect.h;
-		req.z_order = MDSS_MDP_STAGE_BASE;
-
-		pr_debug("allocating base pipe mux=%d\n", mixer_mux);
-
-		ret = mdss_mdp_overlay_pipe_setup(mfd, &req, &pipe);
-		if (ret)
-			return ret;
-
-		pr_debug("ctl=%d pnum=%d\n", mdp5_data->ctl->num, pipe->num);
 	}
 
+	pr_debug("ctl=%d pnum=%d\n", mdp5_data->ctl->num, pipe->num);
+
 	*ppipe = pipe;
 	return 0;
 }
 
-static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
+static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd,
+					struct mdp_overlay *req,
+					int image_size,
+					int *pipe_ndx)
 {
 	struct mdss_mdp_data *buf;
 	struct mdss_mdp_pipe *pipe;
@@ -1485,8 +1516,8 @@
 		goto pan_display_error;
 	}
 
-
-	ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe, MDSS_MDP_MIXER_MUX_LEFT);
+	ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
+					MDSS_MDP_MIXER_MUX_LEFT, req);
 	if (ret) {
 		pr_err("unable to allocate base pipe\n");
 		goto pan_display_error;
@@ -1496,12 +1527,14 @@
 		pr_err("unable to map base pipe\n");
 		goto pan_display_error;
 	}
+	if (pipe_ndx)
+		pipe_ndx[0] = pipe->ndx;
 
 	buf = &pipe->back_buf;
 	if (is_mdss_iommu_attached()) {
 		if (!mfd->iova) {
 			pr_err("mfd iova is zero\n");
-			goto pan_display_error;
+			goto attach_err;
 		}
 		buf->p[0].addr = mfd->iova;
 	} else {
@@ -1509,24 +1542,28 @@
 	}
 
 	buf->p[0].addr += offset;
-	buf->p[0].len = fbi->fix.smem_len - offset;
+	if (image_size)
+		buf->p[0].len = image_size;
+	else
+		buf->p[0].len = fbi->fix.smem_len - offset;
 	buf->num_planes = 1;
-	pipe->has_buf = 1;
 	mdss_mdp_pipe_unmap(pipe);
 
 	if (fbi->var.xres > MAX_MIXER_WIDTH || mfd->split_display) {
 		ret = mdss_mdp_overlay_get_fb_pipe(mfd, &pipe,
-						   MDSS_MDP_MIXER_MUX_RIGHT);
+					   MDSS_MDP_MIXER_MUX_RIGHT, req);
 		if (ret) {
 			pr_err("unable to allocate right base pipe\n");
-			goto pan_display_error;
+			goto attach_err;
 		}
 		if (mdss_mdp_pipe_map(pipe)) {
 			pr_err("unable to map right base pipe\n");
-			goto pan_display_error;
+			goto attach_err;
 		}
+		if (pipe_ndx)
+			pipe_ndx[1] = pipe->ndx;
+
 		pipe->back_buf = *buf;
-		pipe->has_buf = 1;
 		mdss_mdp_pipe_unmap(pipe);
 	}
 	mutex_unlock(&mdp5_data->ov_lock);
@@ -1537,6 +1574,12 @@
 
 	return;
 
+attach_err:
+	mutex_unlock(&mdp5_data->ov_lock);
+	mdss_mdp_overlay_unset(mfd, pipe->ndx);
+	if (pipe_ndx)
+		pipe_ndx[0] = INVALID_PIPE_INDEX;
+	return;
 pan_display_error:
 	mutex_unlock(&mdp5_data->ov_lock);
 }
@@ -2502,8 +2545,8 @@
 	 * increasing ref_cnt to help balance clocks once done.
 	 */
 	if (pdata->panel_info.cont_splash_enabled) {
-		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 		mdss_mdp_footswitch_ctrl_splash(1);
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 	}
 	return 0;
 }
@@ -2604,6 +2647,164 @@
 	return rc;
 }
 
+static int mdss_mdp_overlay_splash_image(struct msm_fb_data_type *mfd,
+						int *pipe_ndx, int splash_event)
+{
+	struct mdp_overlay req;
+	int rc = 0;
+	struct fb_info *fbi = NULL;
+	int image_len = 0;
+
+	if (!mfd || !mfd->fbi || !mfd->fbi->screen_base || !pipe_ndx) {
+		pr_err("Invalid input parameter\n");
+		return -EINVAL;
+	}
+
+	fbi = mfd->fbi;
+	image_len = SPLASH_IMAGE_WIDTH * SPLASH_IMAGE_HEIGHT * SPLASH_IMAGE_BPP;
+
+	if (SPLASH_IMAGE_WIDTH > fbi->var.xres ||
+			SPLASH_IMAGE_HEIGHT > fbi->var.yres ||
+			SPLASH_IMAGE_BPP > fbi->var.bits_per_pixel / 8 ||
+			image_len > fbi->fix.smem_len) {
+		pr_err("Invalid splash parameter configuration\n");
+		return -EINVAL;
+	}
+
+	if (splash_event == MDP_CREATE_SPLASH_OV) {
+		pipe_ndx[0] = INVALID_PIPE_INDEX;
+		pipe_ndx[1] = INVALID_PIPE_INDEX;
+
+		memset(&req, 0, sizeof(struct mdp_overlay));
+		req.src.width = req.dst_rect.w = req.src_rect.w =
+				SPLASH_IMAGE_WIDTH;
+		req.src.height = req.dst_rect.h = req.src_rect.h =
+				SPLASH_IMAGE_HEIGHT;
+		req.src.format = SPLASH_IMAGE_FORMAT;
+		req.id = MSMFB_NEW_REQUEST;
+		req.z_order = MDSS_MDP_STAGE_0;
+		req.is_fg = 1;
+		req.alpha = 0xff;
+		req.transp_mask = MDP_TRANSP_NOP;
+		req.dst_rect.x =
+			(fbi->var.xres >> 1) - (SPLASH_IMAGE_WIDTH >> 1);
+		req.dst_rect.y =
+			(fbi->var.yres >> 1) - (SPLASH_IMAGE_HEIGHT >> 1);
+
+		memcpy(fbi->screen_base, splash_bgr888_image, image_len);
+		mdss_mdp_overlay_pan_display(mfd, &req, image_len, pipe_ndx);
+
+	} else if (splash_event == MDP_REMOVE_SPLASH_OV) {
+		if (pipe_ndx[0] != INVALID_PIPE_INDEX)
+			mdss_mdp_overlay_unset(mfd, pipe_ndx[0]);
+		if (pipe_ndx[1] != INVALID_PIPE_INDEX)
+			mdss_mdp_overlay_unset(mfd, pipe_ndx[1]);
+	}
+
+	return rc;
+}
+
+static void __vsync_retire_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t)
+{
+	struct msm_fb_data_type *mfd = ctl->mfd;
+	struct mdss_overlay_private *mdp5_data;
+
+	if (!mfd || !mfd->mdp.private1) {
+		pr_warn("Invalid handle for vsync\n");
+		return;
+	}
+
+	mdp5_data = mfd_to_mdp5_data(mfd);
+	schedule_work(&mdp5_data->retire_work);
+}
+
+static void __vsync_retire_work_handler(struct work_struct *work)
+{
+	struct mdss_overlay_private *mdp5_data =
+		container_of(work, typeof(*mdp5_data), retire_work);
+	struct msm_sync_pt_data *sync_pt_data;
+
+	if (!mdp5_data->ctl || !mdp5_data->ctl->mfd)
+		return;
+
+	if (!mdp5_data->ctl->remove_vsync_handler)
+		return;
+
+	sync_pt_data = &mdp5_data->ctl->mfd->mdp_sync_pt_data;
+	mutex_lock(&sync_pt_data->sync_mutex);
+	if (mdp5_data->retire_cnt > 0) {
+		sw_sync_timeline_inc(mdp5_data->vsync_timeline, 1);
+
+		mdp5_data->retire_cnt--;
+		if (mdp5_data->retire_cnt == 0) {
+			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+			mdp5_data->ctl->remove_vsync_handler(mdp5_data->ctl,
+					&mdp5_data->vsync_retire_handler);
+			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+		}
+	}
+	mutex_unlock(&sync_pt_data->sync_mutex);
+}
+
+static struct sync_fence *
+__vsync_retire_get_fence(struct msm_sync_pt_data *sync_pt_data)
+{
+	struct msm_fb_data_type *mfd;
+	struct mdss_overlay_private *mdp5_data;
+	struct mdss_mdp_ctl *ctl;
+	int rc, value;
+
+	mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data);
+	mdp5_data = mfd_to_mdp5_data(mfd);
+
+	if (!mdp5_data || !mdp5_data->ctl)
+		return ERR_PTR(-ENODEV);
+
+	ctl = mdp5_data->ctl;
+	if (!ctl->add_vsync_handler)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	if (!ctl->power_on) {
+		pr_debug("fb%d vsync pending first update\n", mfd->index);
+		return ERR_PTR(-EPERM);
+	}
+
+	if (mdp5_data->retire_cnt == 0) {
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+		rc = ctl->add_vsync_handler(ctl,
+				&mdp5_data->vsync_retire_handler);
+		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+		if (IS_ERR_VALUE(rc))
+			return ERR_PTR(rc);
+	}
+	value = mdp5_data->vsync_timeline->value + 1 + mdp5_data->retire_cnt;
+	mdp5_data->retire_cnt++;
+
+	return mdss_fb_sync_get_fence(mdp5_data->vsync_timeline,
+			"mdp-retire", value);
+}
+
+static int __vsync_retire_setup(struct msm_fb_data_type *mfd)
+{
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+	char name[24];
+
+	snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
+	mdp5_data->vsync_timeline = sw_sync_timeline_create(name);
+	if (mdp5_data->vsync_timeline == NULL) {
+		pr_err("cannot vsync create time line");
+		return -ENOMEM;
+	}
+	mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence;
+
+	mdp5_data->vsync_retire_handler.vsync_handler =
+		__vsync_retire_handle_vsync;
+	mdp5_data->vsync_retire_handler.cmd_post_flush = false;
+	INIT_WORK(&mdp5_data->retire_work, __vsync_retire_work_handler);
+
+	return 0;
+}
+
 int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
 {
 	struct device *dev = mfd->fbi->dev;
@@ -2621,6 +2822,7 @@
 	mdp5_interface->panel_register_done = mdss_panel_register_done;
 	mdp5_interface->kickoff_fnc = mdss_mdp_overlay_kickoff;
 	mdp5_interface->get_sync_fnc = mdss_mdp_rotator_sync_pt_get;
+	mdp5_interface->splash_fnc = mdss_mdp_overlay_splash_image;
 
 	mdp5_data = kmalloc(sizeof(struct mdss_overlay_private), GFP_KERNEL);
 	if (!mdp5_data) {
@@ -2669,6 +2871,12 @@
 			pr_err("Error dfps sysfs creation ret=%d\n", rc);
 			goto init_fail;
 		}
+	} else if (mfd->panel_info->type == MIPI_CMD_PANEL) {
+		rc = __vsync_retire_setup(mfd);
+		if (IS_ERR_VALUE(rc)) {
+			pr_err("unable to create vsync timeline\n");
+			goto init_fail;
+		}
 	}
 	mfd->mdp_sync_pt_data.async_wait_fences = true;
 	rc = sysfs_create_link_nowarn(&dev->kobj,
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 0abd4d5..4999103 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -15,6 +15,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/errno.h>
+#include <linux/iopoll.h>
 #include <linux/mutex.h>
 
 #include "mdss_mdp.h"
@@ -25,10 +26,14 @@
 #define SMP_MB_ENTRY_SIZE	16
 #define MAX_BPP 4
 
+#define PIPE_HALT_TIMEOUT_US	0x4000
+
 static DEFINE_MUTEX(mdss_mdp_sspp_lock);
 static DEFINE_MUTEX(mdss_mdp_smp_lock);
 
 static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
+static int mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp);
+static void mdss_mdp_smp_mmb_free(unsigned long *smp, bool write);
 static struct mdss_mdp_pipe *mdss_mdp_pipe_search_by_client_id(
 	struct mdss_data_type *mdata, int client_id);
 
@@ -55,8 +60,27 @@
 	else
 		n -= fixed_cnt;
 
-	/* reserve more blocks if needed, but can't free mmb at this point */
-	for (i = bitmap_weight(smp_map->allocated, SMP_MB_CNT); i < n; i++) {
+	i = bitmap_weight(smp_map->allocated, SMP_MB_CNT);
+
+	/*
+	 * SMP programming is not double buffered. Fail the request,
+	 * that calls for change in smp configuration (addition/removal
+	 * of smp blocks), so that fallback solution happens.
+	 */
+	if (i != 0 && n != i) {
+		pr_debug("Can't change mmb config, num_blks: %d alloc: %d\n",
+			n, i);
+		return 0;
+	}
+
+	/*
+	 * Clear previous SMP reservations and reserve according to the
+	 * latest configuration
+	 */
+	mdss_mdp_smp_mmb_free(smp_map->reserved, false);
+
+	/* Reserve mmb blocks*/
+	for (; i < n; i++) {
 		if (bitmap_full(mdata->mmb_alloc_map, SMP_MB_CNT))
 			break;
 
@@ -105,6 +129,26 @@
 	}
 }
 
+/**
+ * @mdss_mdp_smp_get_size - get allocated smp size for a pipe
+ * @pipe: pointer to a pipe
+ *
+ * Function counts number of blocks that are currently allocated for a
+ * pipe, then smp buffer size is number of blocks multiplied by block
+ * size.
+ */
+u32 mdss_mdp_smp_get_size(struct mdss_mdp_pipe *pipe)
+{
+	int i, mb_cnt = 0;
+
+	for (i = 0; i < MAX_PLANES; i++) {
+		mb_cnt += bitmap_weight(pipe->smp_map[i].allocated, SMP_MB_CNT);
+		mb_cnt += bitmap_weight(pipe->smp_map[i].fixed, SMP_MB_CNT);
+	}
+
+	return mb_cnt * SMP_MB_SIZE;
+}
+
 static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
 {
 	u32 fetch_size, val, wm[3];
@@ -176,6 +220,31 @@
 			pipe->src_fmt, &ps);
 		if (rc)
 			return rc;
+		/*
+		 * Override fetch strides with SMP buffer size for both the
+		 * planes
+		 */
+		if (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+			/*
+			 * BWC line buffer needs to be divided into 16
+			 * segments and every segment is aligned to format
+			 * specific RAU size
+			 */
+			ps.ystride[0] = ALIGN(pipe->src.w / 16 , 32) * 16 *
+				ps.rau_h[0] * pipe->src_fmt->bpp;
+			ps.ystride[1] = 0;
+		} else {
+			u32 bwc_width = ALIGN(pipe->src.w / 16, 64) * 16;
+			ps.ystride[0] = bwc_width * ps.rau_h[0];
+			ps.ystride[1] = bwc_width * ps.rau_h[1];
+			/*
+			 * Since chroma for H1V2 is not subsampled it needs
+			 * to be accounted for with bpp factor
+			 */
+			if (pipe->src_fmt->chroma_sample ==
+				MDSS_MDP_CHROMA_H1V2)
+				ps.ystride[1] *= 2;
+		}
 		pr_debug("BWC SMP strides ystride0=%x ystride1=%x\n",
 			ps.ystride[0], ps.ystride[1]);
 	} else {
@@ -221,9 +290,21 @@
 		}
 	}
 
-	nlines = pipe->bwc_mode ? 1 : 2;
+	if (pipe->src_fmt->tile)
+		nlines = 8;
+	else
+		nlines = pipe->bwc_mode ? 1 : 2;
 
 	mutex_lock(&mdss_mdp_smp_lock);
+	for (i = (MAX_PLANES - 1); i >= ps.num_planes; i--) {
+		if (bitmap_weight(pipe->smp_map[i].allocated, SMP_MB_CNT)) {
+			pr_debug("Extra mmb identified for pnum=%d plane=%d\n",
+				pipe->num, i);
+			mutex_unlock(&mdss_mdp_smp_lock);
+			return -EAGAIN;
+		}
+	}
+
 	for (i = 0; i < ps.num_planes; i++) {
 		if (rot_mode) {
 			num_blks = 1;
@@ -460,6 +541,13 @@
 		pipe = NULL;
 	}
 
+	if (pipe && mdss_mdp_pipe_fetch_halt(pipe)) {
+		pr_err("%d failed because vbif client is in bad state\n",
+			pipe->num);
+		atomic_dec(&pipe->ref_cnt);
+		return NULL;
+	}
+
 	if (pipe) {
 		pr_debug("type=%x   pnum=%d\n", pipe->type, pipe->num);
 		mutex_init(&pipe->pp_res.hist.hist_mutex);
@@ -470,7 +558,7 @@
 		 * shared as long as its attached to a writeback mixer
 		 */
 		pipe = mdata->dma_pipes + mixer->num;
-		mdss_mdp_pipe_map(pipe);
+		atomic_inc(&pipe->ref_cnt);
 		pr_debug("pipe sharing for pipe=%d\n", pipe->num);
 	} else {
 		pr_err("no %d type pipes available\n", type);
@@ -589,6 +677,7 @@
 	mdss_mdp_smp_free(pipe);
 	pipe->flags = 0;
 	pipe->bwc_mode = 0;
+	pipe->mfd = NULL;
 	memset(&pipe->scale, 0, sizeof(struct mdp_scale_data));
 
 	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
@@ -596,6 +685,64 @@
 	return 0;
 }
 
+/**
+ * mdss_mdp_pipe_fetch_halt() - Halt VBIF client corresponding to specified pipe
+ * @pipe: pointer to the pipe data structure which needs to be halted.
+ *
+ * Check if VBIF client corresponding to specified pipe is idle or not. If not
+ * send a halt request for the client in question and wait for it be idle.
+ *
+ * This function would typically be called after pipe is unstaged or before it
+ * is initialized. On success it should be assumed that pipe is in idle state
+ * and would not fetch any more data. This function cannot be called from
+ * interrupt context.
+ */
+int mdss_mdp_pipe_fetch_halt(struct mdss_mdp_pipe *pipe)
+{
+	bool is_idle;
+	int rc = 0;
+	u32 reg_val, idle_mask, status;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+	idle_mask = BIT(pipe->xin_id + 16);
+	reg_val = readl_relaxed(mdata->vbif_base + MMSS_VBIF_XIN_HALT_CTRL1);
+
+	is_idle = (reg_val & idle_mask) ? true : false;
+	if (!is_idle) {
+		pr_debug("%pS: pipe%d is not idle. xin_id=%d halt_ctrl1=0x%x\n",
+			__builtin_return_address(0), pipe->num, pipe->xin_id,
+			reg_val);
+
+		mutex_lock(&mdata->reg_lock);
+		reg_val = readl_relaxed(mdata->vbif_base +
+			MMSS_VBIF_XIN_HALT_CTRL0);
+		writel_relaxed(reg_val | BIT(pipe->xin_id),
+			mdata->vbif_base + MMSS_VBIF_XIN_HALT_CTRL0);
+		mutex_unlock(&mdata->reg_lock);
+
+		rc = readl_poll_timeout(mdata->vbif_base +
+			MMSS_VBIF_XIN_HALT_CTRL1, status, (status & idle_mask),
+			1000, PIPE_HALT_TIMEOUT_US);
+		if (rc == -ETIMEDOUT)
+			pr_err("VBIF client %d not halting. TIMEDOUT.\n",
+				pipe->xin_id);
+		else
+			pr_debug("VBIF client %d is halted\n", pipe->xin_id);
+
+		mutex_lock(&mdata->reg_lock);
+		reg_val = readl_relaxed(mdata->vbif_base +
+			MMSS_VBIF_XIN_HALT_CTRL0);
+		writel_relaxed(reg_val & ~BIT(pipe->xin_id),
+			mdata->vbif_base + MMSS_VBIF_XIN_HALT_CTRL0);
+		mutex_unlock(&mdata->reg_lock);
+	}
+	mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+	return rc;
+}
+
 int mdss_mdp_pipe_destroy(struct mdss_mdp_pipe *pipe)
 {
 	int tmp;
@@ -674,25 +821,7 @@
 	return rc;
 }
 
-void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
-	struct mdss_mdp_img_rect *dst_rect,
-	const struct mdss_mdp_img_rect *sci_rect)
-{
-	struct mdss_mdp_img_rect res;
-	mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
 
-	if (res.w && res.h) {
-		if ((res.w != dst_rect->w) || (res.h != dst_rect->h)) {
-			src_rect->x = src_rect->x + (res.x - dst_rect->x);
-			src_rect->y = src_rect->y + (res.y - dst_rect->y);
-			src_rect->w = res.w;
-			src_rect->h = res.h;
-		}
-		*dst_rect = (struct mdss_mdp_img_rect)
-			{(res.x - sci_rect->x), (res.y - sci_rect->y),
-			res.w, res.h};
-	}
-}
 
 static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
 					struct mdss_mdp_data *data)
@@ -795,6 +924,7 @@
 	u32 chroma_samp, unpack, src_format;
 	u32 secure = 0;
 	u32 opmode;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 
 	fmt = pipe->src_fmt;
 
@@ -825,6 +955,9 @@
 		     (fmt->bits[C1_B_Cb] << 2) |
 		     (fmt->bits[C0_G_Y] << 0);
 
+	if (fmt->tile)
+		src_format |= BIT(30);
+
 	if (pipe->flags & MDP_ROT_90)
 		src_format |= BIT(11); /* ROT90 */
 
@@ -844,6 +977,11 @@
 	if (pipe->scale.enable_pxl_ext)
 		opmode |= (1 << 31);
 
+	if (fmt->tile && mdata->highest_bank_bit) {
+		mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_FETCH_CONFIG,
+			MDSS_MDP_FETCH_CONFIG_RESET_VALUE |
+				 mdata->highest_bank_bit << 18);
+	}
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack);
 	mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
@@ -853,8 +991,8 @@
 }
 
 int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata,
-	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_id, u32 type,
-	u32 num_base, u32 len)
+	struct mdss_mdp_pipe *head, u32 *offsets, u32 *ftch_id, u32 *xin_id,
+	u32 type, u32 num_base, u32 len)
 {
 	u32 i;
 
@@ -866,6 +1004,7 @@
 	for (i = 0; i < len; i++) {
 		head[i].type = type;
 		head[i].ftch_id  = ftch_id[i];
+		head[i].xin_id = xin_id[i];
 		head[i].num = i + num_base;
 		head[i].ndx = BIT(i + num_base);
 		head[i].base = mdata->mdp_base + offsets[i];
@@ -972,7 +1111,7 @@
 			 (pipe->mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
 			 && (ctl->mdata->mixer_switched)) ||
 			 ctl->roi_changed;
-	if (src_data == NULL || !pipe->has_buf) {
+	if (src_data == NULL || (pipe->flags & MDP_SOLID_FILL)) {
 		pipe->params_changed = 0;
 		mdss_mdp_pipe_solidfill_setup(pipe);
 		goto update_nobuf;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 23c7994..9b6d130 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -174,10 +174,13 @@
 	GAMUT_T5_SIZE + GAMUT_T6_SIZE + GAMUT_T7_SIZE)
 
 #define MDSS_MDP_PA_SIZE		0xC
+#define MDSS_MDP_SIX_ZONE_SIZE		0xC
+#define MDSS_MDP_MEM_COL_SIZE		0x3C
 #define MDSS_MDP_GC_SIZE		0x28
 #define MDSS_MDP_PCC_SIZE		0xB8
 #define MDSS_MDP_GAMUT_SIZE		0x5C
-#define MDSS_MDP_IGC_DSPP_COLORS	0x3
+#define MDSS_MDP_IGC_DSPP_SIZE		0x28
+#define MDSS_MDP_IGC_SSPP_SIZE		0x88
 #define TOTAL_BLEND_STAGES		0x4
 
 #define PP_FLAGS_DIRTY_PA	0x1
@@ -293,8 +296,8 @@
 	u32 enhist_lut[MDSS_BLOCK_DISP_NUM][ENHIST_LUT_ENTRIES];
 	struct mdp_pa_cfg pa_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_pa_v2_data pa_v2_disp_cfg[MDSS_BLOCK_DISP_NUM];
-	u32 six_zone_lut_curve_p0[MDSS_BLOCK_DISP_NUM][SIX_ZONE_LUT_ENTRIES];
-	u32 six_zone_lut_curve_p1[MDSS_BLOCK_DISP_NUM][SIX_ZONE_LUT_ENTRIES];
+	u32 six_zone_lut_curve_p0[MDSS_BLOCK_DISP_NUM][MDP_SIX_ZONE_LUT_SIZE];
+	u32 six_zone_lut_curve_p1[MDSS_BLOCK_DISP_NUM][MDP_SIX_ZONE_LUT_SIZE];
 	struct mdp_pcc_cfg_data pcc_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_igc_lut_data igc_disp_cfg[MDSS_BLOCK_DISP_NUM];
 	struct mdp_pgc_lut_data argc_disp_cfg[MDSS_BLOCK_DISP_NUM];
@@ -643,7 +646,7 @@
 				data, addr);
 
 		/* Remove Index Update */
-		for (i = 1; i < SIX_ZONE_LUT_ENTRIES; i++) {
+		for (i = 1; i < MDP_SIX_ZONE_LUT_SIZE; i++) {
 			addr += 4;
 			writel_relaxed(pa_v2_config->six_zone_curve_p1[i],
 					addr);
@@ -1089,7 +1092,7 @@
 
 		/*program pixel extn values for the SSPP*/
 		mdss_mdp_pipe_program_pixel_extn(pipe);
-	} else {
+	} else if (pipe->type == MDSS_MDP_PIPE_TYPE_VIG) {
 		writel_relaxed(phasex_step, pipe->base +
 		   MDSS_MDP_REG_SCALE_PHASE_STEP_X);
 		writel_relaxed(phasey_step, pipe->base +
@@ -1098,6 +1101,11 @@
 			MDSS_MDP_REG_SCALE_INIT_PHASE_X);
 		writel_relaxed(init_phasey, pipe->base +
 			MDSS_MDP_REG_SCALE_INIT_PHASE_Y);
+	} else {
+		writel_relaxed(phasex_step, pipe->base +
+		   MDSS_MDP_REG_SCALE_PHASE_STEP_X);
+		writel_relaxed(phasey_step, pipe->base +
+		   MDSS_MDP_REG_SCALE_PHASE_STEP_Y);
 	}
 
 	writel_relaxed(scale_config, pipe->base +
@@ -1302,10 +1310,7 @@
 		mutex_lock(&hist_info->hist_mutex);
 		spin_lock_irqsave(&hist_info->hist_lock, flag);
 		col_state = hist_info->col_state;
-		if (hist_info->is_kick_ready &&
-			((col_state == HIST_IDLE) ||
-			((false == hist_info->read_request) &&
-				col_state == HIST_READY))) {
+		if (col_state == HIST_IDLE) {
 			/* Kick off collection */
 			writel_relaxed(1, base + kick_base);
 			hist_info->col_state = HIST_START;
@@ -1941,10 +1946,13 @@
 
 	/* Six zone LUT and thresh data */
 	if (pa_v2_config->flags & MDP_PP_PA_SIX_ZONE_ENABLE) {
+		if (pa_v2_config->six_zone_len != MDP_SIX_ZONE_LUT_SIZE)
+			return -EINVAL;
+
 		data = (3 << 25);
 		writel_relaxed(data, addr);
 
-		for (i = 0; i < SIX_ZONE_LUT_ENTRIES; i++) {
+		for (i = 0; i < MDP_SIX_ZONE_LUT_SIZE; i++) {
 			addr += 4;
 			mdss_pp_res->six_zone_lut_curve_p1[disp_num][i] =
 				readl_relaxed(addr);
@@ -1955,13 +1963,13 @@
 
 		if (copy_to_user(pa_v2_config->six_zone_curve_p0,
 			&mdss_pp_res->six_zone_lut_curve_p0[disp_num][0],
-			SIX_ZONE_LUT_ENTRIES * sizeof(u32))) {
+			pa_v2_config->six_zone_len * sizeof(u32))) {
 			return -EFAULT;
 		}
 
 		if (copy_to_user(pa_v2_config->six_zone_curve_p1,
 			&mdss_pp_res->six_zone_lut_curve_p1[disp_num][0],
-			SIX_ZONE_LUT_ENTRIES * sizeof(u32))) {
+			pa_v2_config->six_zone_len * sizeof(u32))) {
 			return -EFAULT;
 		}
 
@@ -2006,14 +2014,17 @@
 static int pp_copy_pa_six_zone_lut(struct mdp_pa_v2_cfg_data *pa_v2_config,
 				u32 disp_num)
 {
+	if (pa_v2_config->pa_v2_data.six_zone_len != MDP_SIX_ZONE_LUT_SIZE)
+		return -EINVAL;
+
 	if (copy_from_user(&mdss_pp_res->six_zone_lut_curve_p0[disp_num][0],
 			pa_v2_config->pa_v2_data.six_zone_curve_p0,
-			SIX_ZONE_LUT_ENTRIES * sizeof(u32))) {
+			pa_v2_config->pa_v2_data.six_zone_len * sizeof(u32))) {
 		return -EFAULT;
 	}
 	if (copy_from_user(&mdss_pp_res->six_zone_lut_curve_p1[disp_num][0],
 			pa_v2_config->pa_v2_data.six_zone_curve_p1,
-			SIX_ZONE_LUT_ENTRIES * sizeof(u32))) {
+			pa_v2_config->pa_v2_data.six_zone_len * sizeof(u32))) {
 		return -EFAULT;
 	}
 
@@ -2364,7 +2375,7 @@
 {
 	int i, start_idx, idx;
 
-	start_idx = (readl_relaxed(addr) >> 16) & 0xF;
+	start_idx = ((readl_relaxed(addr) >> 16) & 0xF) + 1;
 	for (i = start_idx; i < GC_LUT_SEGMENTS; i++) {
 		idx = min((uint8_t)i, (uint8_t)(num_stages-1));
 		writel_relaxed(lut_data[idx].x_start, addr);
@@ -2374,7 +2385,7 @@
 		writel_relaxed(lut_data[idx].x_start, addr);
 	}
 	addr += 4;
-	start_idx = (readl_relaxed(addr) >> 16) & 0xF;
+	start_idx = ((readl_relaxed(addr) >> 16) & 0xF) + 1;
 	for (i = start_idx; i < GC_LUT_SEGMENTS; i++) {
 		idx = min((uint8_t)i, (uint8_t)(num_stages-1));
 		writel_relaxed(lut_data[idx].slope, addr);
@@ -2384,7 +2395,7 @@
 		writel_relaxed(lut_data[idx].slope, addr);
 	}
 	addr += 4;
-	start_idx = (readl_relaxed(addr) >> 16) & 0xF;
+	start_idx = ((readl_relaxed(addr) >> 16) & 0xF) + 1;
 	for (i = start_idx; i < GC_LUT_SEGMENTS; i++) {
 		idx = min((uint8_t)i, (uint8_t)(num_stages-1));
 		writel_relaxed(lut_data[idx].offset, addr);
@@ -2498,15 +2509,17 @@
 		argc_addr = mdss_mdp_get_mixer_addr_off(dspp_num) +
 			MDSS_MDP_REG_LM_GC_LUT_BASE;
 		pgc_ptr = &mdss_pp_res->argc_disp_cfg[disp_num];
-		mdss_pp_res->pp_disp_flags[disp_num] |=
-			PP_FLAGS_DIRTY_ARGC;
+		if (config->flags & MDP_PP_OPS_WRITE)
+			mdss_pp_res->pp_disp_flags[disp_num] |=
+				PP_FLAGS_DIRTY_ARGC;
 		break;
 	case MDSS_PP_DSPP_CFG:
 		argc_addr = mdss_mdp_get_dspp_addr_off(dspp_num) +
 					MDSS_MDP_REG_DSPP_GC_BASE;
 		pgc_ptr = &mdss_pp_res->pgc_disp_cfg[disp_num];
-		mdss_pp_res->pp_disp_flags[disp_num] |=
-			PP_FLAGS_DIRTY_PGC;
+		if (config->flags & MDP_PP_OPS_WRITE)
+			mdss_pp_res->pp_disp_flags[disp_num] |=
+				PP_FLAGS_DIRTY_PGC;
 		break;
 	default:
 		goto argc_config_exit;
@@ -2882,11 +2895,10 @@
 	hist_info->hist_cnt_sent = 0;
 	hist_info->hist_cnt_time = 0;
 	spin_lock_irqsave(&hist_info->hist_lock, flag);
-	hist_info->read_request = false;
+	hist_info->read_request = 0;
 	hist_info->col_state = HIST_RESET;
 	hist_info->col_en = true;
 	spin_unlock_irqrestore(&hist_info->hist_lock, flag);
-	hist_info->is_kick_ready = true;
 	mdss_mdp_hist_intr_req(&mdata->hist_intr, 3 << shift_bit, true);
 	writel_relaxed(req->frame_cnt, ctl_base + 8);
 	/* Kick out reset start */
@@ -3007,7 +3019,6 @@
 	hist_info->col_en = false;
 	hist_info->col_state = HIST_UNKNOWN;
 	spin_unlock_irqrestore(&hist_info->hist_lock, flag);
-	hist_info->is_kick_ready = false;
 	mdss_mdp_hist_intr_req(&mdata->hist_intr, done_bit, false);
 	writel_relaxed(BIT(1), ctl_base);/* cancel */
 	ret = 0;
@@ -3257,7 +3268,6 @@
 	spin_lock_irqsave(&hist_info->hist_lock, flag);
 	/* wait for hist done if cache has no data */
 	if (hist_info->col_state != HIST_READY) {
-		hist_info->read_request = true;
 		spin_unlock_irqrestore(&hist_info->hist_lock, flag);
 		timeout = HIST_WAIT_TIMEOUT(hist_info->frame_cnt);
 		mutex_unlock(&hist_info->hist_mutex);
@@ -3297,9 +3307,11 @@
 		}
 		if (hist_info->col_state != HIST_READY) {
 			ret = -ENODATA;
+			spin_lock_irqsave(&hist_info->hist_lock, flag);
+			hist_info->col_state = HIST_READY;
+			spin_unlock_irqrestore(&hist_info->hist_lock, flag);
 			pr_debug("%s: state is not ready: %d",
 					__func__, hist_info->col_state);
-			goto hist_collect_exit;
 		}
 	} else {
 		spin_unlock_irqrestore(&hist_info->hist_lock, flag);
@@ -3312,9 +3324,7 @@
 		sum = pp_hist_read(v_base, hist_info);
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
 		spin_lock_irqsave(&hist_info->hist_lock, flag);
-		if (!expect_sum || sum == expect_sum)
-			hist_info->read_request = false;
-		else
+		if (expect_sum && sum != expect_sum)
 			ret = -ENODATA;
 		hist_info->col_state = HIST_IDLE;
 	}
@@ -3326,8 +3336,9 @@
 
 int mdss_mdp_hist_collect(struct mdp_histogram_data *hist)
 {
-	int i, j, off, ret = 0;
+	int i, j, off, ret = 0, temp_ret = 0;
 	struct pp_hist_col_info *hist_info;
+	struct pp_hist_col_info *hists[MDSS_MDP_INTF_MAX_LAYERMIXER];
 	u32 dspp_num, disp_num;
 	char __iomem *ctl_base;
 	u32 hist_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
@@ -3338,6 +3349,7 @@
 	u32 exp_sum = 0;
 	struct mdss_mdp_pipe *pipe;
 	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+	unsigned long flag;
 
 	if ((PP_BLOCK(hist->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
 		(PP_BLOCK(hist->block) >= MDP_BLOCK_MAX))
@@ -3358,20 +3370,41 @@
 		ret = -EPERM;
 		goto hist_collect_exit;
 	}
+
 	if (PP_LOCAT(hist->block) == MDSS_PP_DSPP_CFG) {
-		hist_info = &mdss_pp_res->dspp_hist[disp_num];
 		for (i = 0; i < hist_cnt; i++) {
 			dspp_num = mixer_id[i];
-			hist_info = &mdss_pp_res->dspp_hist[dspp_num];
+			hists[i] = &mdss_pp_res->dspp_hist[dspp_num];
+		}
+		for (i = 0; i < hist_cnt; i++) {
+			spin_lock_irqsave(&hists[i]->hist_lock, flag);
+			/* mark that collect is ready to handle completions */
+			hists[i]->read_request = 1;
+			spin_unlock_irqrestore(&hists[i]->hist_lock, flag);
+		}
+		for (i = 0; i < hist_cnt; i++) {
+			dspp_num = mixer_id[i];
 			ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
 				MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
 			exp_sum = (mdata->mixer_intf[dspp_num].width *
 					mdata->mixer_intf[dspp_num].height);
-			ret = pp_hist_collect(hist, hist_info, ctl_base,
-								exp_sum);
 			if (ret)
-				goto hist_collect_exit;
+				temp_ret = ret;
+			ret = pp_hist_collect(hist, hists[i], ctl_base,
+								exp_sum);
 		}
+		for (i = 0; i < hist_cnt; i++) {
+			/* reset read requests and re-intialize completions */
+			spin_lock_irqsave(&hists[i]->hist_lock, flag);
+			hists[i]->read_request = 0;
+			INIT_COMPLETION(hists[i]->comp);
+			spin_unlock_irqrestore(&hists[i]->hist_lock, flag);
+		}
+		if (ret || temp_ret) {
+			ret = ret ? ret : temp_ret;
+			goto hist_collect_exit;
+		}
+
 		if (hist->bin_cnt != HIST_V_SIZE) {
 			pr_err("User not expecting size %d output",
 							HIST_V_SIZE);
@@ -3387,19 +3420,19 @@
 			}
 			memset(hist_concat, 0, HIST_V_SIZE * sizeof(u32));
 			for (i = 0; i < hist_cnt; i++) {
-				dspp_num = mixer_id[i];
-				hist_info = &mdss_pp_res->dspp_hist[dspp_num];
-				mutex_lock(&hist_info->hist_mutex);
+				mutex_lock(&hists[i]->hist_mutex);
 				for (j = 0; j < HIST_V_SIZE; j++)
-					hist_concat[j] += hist_info->data[j];
-				mutex_unlock(&hist_info->hist_mutex);
+					hist_concat[j] += hists[i]->data[j];
+				mutex_unlock(&hists[i]->hist_mutex);
 			}
 			hist_data_addr = hist_concat;
 		} else {
-			hist_data_addr = hist_info->data;
+			hist_data_addr = hists[0]->data;
 		}
-		hist_info = &mdss_pp_res->dspp_hist[disp_num];
-		hist_info->hist_cnt_sent++;
+
+		for (i = 0; i < hist_cnt; i++)
+			hists[i]->hist_cnt_sent++;
+
 	} else if (PP_LOCAT(hist->block) == MDSS_PP_SSPP_CFG) {
 
 		hist_cnt = MDSS_PP_ARG_MASK & hist->block;
@@ -3435,14 +3468,50 @@
 				continue;
 			}
 			hist_info = &pipe->pp_res.hist;
+			spin_lock_irqsave(&hist_info->hist_lock, flag);
+			hist_info->read_request = 1;
+			spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+		}
+		for (i = pipe_num; i < MDSS_PP_ARG_NUM; i++) {
+			if (!PP_ARG(i, hist->block))
+				continue;
+			pipe_cnt++;
+			pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+			if (IS_ERR_OR_NULL(pipe) ||
+					pipe->num > MDSS_MDP_SSPP_VIG2) {
+				pr_warn("Invalid Hist pipe (%d)", i);
+				continue;
+			}
+			hist_info = &pipe->pp_res.hist;
 			ctl_base = pipe->base +
 				MDSS_MDP_REG_VIG_HIST_CTL_BASE;
+			if (ret)
+				temp_ret = ret;
 			ret = pp_hist_collect(hist, hist_info, ctl_base,
 								exp_sum);
 			mdss_mdp_pipe_unmap(pipe);
-			if (ret)
-				goto hist_collect_exit;
 		}
+		for (i = pipe_num; i < MDSS_PP_ARG_NUM; i++) {
+			if (!PP_ARG(i, hist->block))
+				continue;
+			pipe_cnt++;
+			pipe = mdss_mdp_pipe_get(mdata, BIT(i));
+			if (IS_ERR_OR_NULL(pipe) ||
+					pipe->num > MDSS_MDP_SSPP_VIG2) {
+				pr_warn("Invalid Hist pipe (%d)", i);
+				continue;
+			}
+			hist_info = &pipe->pp_res.hist;
+			spin_lock_irqsave(&hist_info->hist_lock, flag);
+			hist_info->read_request = 0;
+			INIT_COMPLETION(hist_info->comp);
+			spin_unlock_irqrestore(&hist_info->hist_lock, flag);
+		}
+		if (ret || temp_ret) {
+			ret = ret ? ret : temp_ret;
+			goto hist_collect_exit;
+		}
+
 		if (pipe_cnt != 0 &&
 			(hist->bin_cnt != (HIST_V_SIZE * pipe_cnt))) {
 			pr_err("User not expecting size %d output",
@@ -3540,8 +3609,10 @@
 			spin_lock(&hist_info->hist_lock);
 			hist_info->col_state = HIST_READY;
 			spin_unlock(&hist_info->hist_lock);
-			if (hist_info->read_request)
+			if (hist_info->read_request == 1) {
 				complete(&hist_info->comp);
+				hist_info->read_request++;
+			}
 		}
 		/* Histogram Reset Done Interrupt */
 		if ((isr_blk & 0x2) &&
@@ -3709,7 +3780,6 @@
 			struct mdss_ad_init_cfg *init_cfg)
 {
 	struct mdss_ad_info *ad;
-	struct mdss_mdp_ctl *ctl;
 	struct msm_fb_data_type *bl_mfd;
 	int lin_ret = -1, inv_ret = -1, ret = 0;
 	u32 ratio_temp, shift = 0, last_ops;
@@ -3737,10 +3807,12 @@
 		if (init_cfg->params.init.bl_lin_len == AD_BL_LIN_LEN) {
 			lin_ret = copy_from_user(&ad->bl_lin,
 				init_cfg->params.init.bl_lin,
-				AD_BL_LIN_LEN * sizeof(uint32_t));
+				init_cfg->params.init.bl_lin_len *
+				sizeof(uint32_t));
 			inv_ret = copy_from_user(&ad->bl_lin_inv,
 				init_cfg->params.init.bl_lin_inv,
-				AD_BL_LIN_LEN * sizeof(uint32_t));
+				init_cfg->params.init.bl_lin_len *
+				sizeof(uint32_t));
 			if (lin_ret || inv_ret)
 				ret = -ENOMEM;
 			ratio_temp =  mfd->panel_info->bl_max / AD_BL_LIN_LEN;
@@ -3749,13 +3821,14 @@
 				shift++;
 			}
 			ad->bl_bright_shift = shift;
-		} else if (init_cfg->params.init.bl_lin_len) {
+		} else {
 			ret = -EINVAL;
 		}
-		if (!lin_ret && !inv_ret)
+		if (ret) {
+			ad->state &= ~PP_AD_STATE_BL_LIN;
+			goto ad_config_exit;
+		} else
 			ad->state |= PP_AD_STATE_BL_LIN;
-		else
-			ad->state &= !PP_AD_STATE_BL_LIN;
 
 		ad->sts |= PP_AD_STS_DIRTY_INIT;
 	} else if (init_cfg->ops & MDP_PP_AD_CFG) {
@@ -3797,8 +3870,8 @@
 		ad->mfd = mfd;
 		ad->bl_mfd = bl_mfd;
 	}
+ad_config_exit:
 	mutex_unlock(&ad->lock);
-	ctl = mfd_to_ctl(mfd);
 	return ret;
 }
 
@@ -3892,7 +3965,7 @@
 			mutex_unlock(&ad->lock);
 		}
 		if (wait) {
-			ret = wait_for_completion_interruptible_timeout(
+			ret = wait_for_completion_timeout(
 					&ad->comp, HIST_WAIT_TIMEOUT(1));
 			if (ret == 0)
 				ret = -ETIMEDOUT;
@@ -4352,8 +4425,7 @@
 						MDSS_MDP_REG_AD_BL_OUT);
 				if (ad->state & PP_AD_STATE_BL_LIN) {
 					bl = bl >> ad->bl_bright_shift;
-					bl = min_t(u32, bl,
-						MDSS_MAX_BL_BRIGHTNESS);
+					bl = min_t(u32, bl, (AD_BL_LIN_LEN-1));
 					bl = ad->bl_lin_inv[bl];
 					bl = bl << ad->bl_bright_shift;
 				}
@@ -4516,6 +4588,14 @@
 		} else if ((ptr == base + MDSS_MDP_REG_DSPP_DITHER_DEPTH)) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
+		/* Six zone and mem color */
+		} else if (mdss_res->mdp_rev >= MDSS_MDP_HW_REV_103 &&
+			(ptr >= base + MDSS_MDP_REG_DSPP_SIX_ZONE_BASE) &&
+			(ptr <= base + MDSS_MDP_REG_DSPP_SIX_ZONE_BASE +
+					MDSS_MDP_SIX_ZONE_SIZE +
+					MDSS_MDP_MEM_COL_SIZE)) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
 		}
 	}
 
@@ -4532,7 +4612,10 @@
 		pipe = mdss_res->vig_pipes + counter;
 		base = pipe->base;
 
-		if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
+		if (ptr == base + MDSS_MDP_REG_VIG_OP_MODE) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_FORMAT) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
 		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_CONSTANT_COLOR) {
@@ -4541,6 +4624,9 @@
 		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_OP_MODE) {
+			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+			break;
 		} else if ((ptr == base + MDSS_MDP_REG_VIG_QSEED2_SHARP)) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
@@ -4550,10 +4636,11 @@
 						MDSS_MDP_PA_SIZE)) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
-		/* IGC range */
-		} else if ((ptr >= base + MDSS_MDP_REG_IGC_VIG_BASE) &&
-				(ptr <= base + MDSS_MDP_REG_IGC_VIG_BASE +
-						MDSS_MDP_GC_SIZE)) {
+		/* Mem color range */
+		} else if (mdss_res->mdp_rev >= MDSS_MDP_HW_REV_103 &&
+			(ptr >= base + MDSS_MDP_REG_VIG_MEM_COL_BASE) &&
+				(ptr <= base + MDSS_MDP_REG_VIG_MEM_COL_BASE +
+						MDSS_MDP_MEM_COL_SIZE)) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
 		}
@@ -4581,10 +4668,7 @@
 		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
-		/* IGC range */
-		} else if ((ptr >= base + MDSS_MDP_REG_IGC_RGB_BASE) &&
-				(ptr <= base + MDSS_MDP_REG_IGC_RGB_BASE +
-						MDSS_MDP_GC_SIZE)) {
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_OP_MODE) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
 		}
@@ -4612,10 +4696,7 @@
 		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
-		/* IGC range */
-		} else if ((ptr >= base + MDSS_MDP_REG_IGC_DMA_BASE) &&
-				(ptr <= base + MDSS_MDP_REG_IGC_DMA_BASE +
-						MDSS_MDP_GC_SIZE)) {
+		} else if (ptr == base + MDSS_MDP_REG_SSPP_SRC_OP_MODE) {
 			ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 			break;
 		}
@@ -4684,9 +4765,15 @@
 	} else if (ptr == (mdss_res->mdp_base + MDSS_MDP_REG_HW_VERSION) ||
 	    ptr == (mdss_res->mdp_base + MDSS_MDP_REG_DISP_INTF_SEL)) {
 		ret = MDP_PP_OPS_READ;
+	/* IGC DSPP range */
 	} else if (ptr >= (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE) &&
-		    ptr < (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE +
-						MDSS_MDP_IGC_DSPP_COLORS)) {
+		    ptr <= (mdss_res->mdp_base + MDSS_MDP_REG_IGC_DSPP_BASE +
+						MDSS_MDP_IGC_DSPP_SIZE)) {
+		ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
+	/* IGC SSPP range */
+	} else if (ptr >= (mdss_res->mdp_base + MDSS_MDP_REG_IGC_VIG_BASE) &&
+		    ptr <= (mdss_res->mdp_base + MDSS_MDP_REG_IGC_VIG_BASE +
+						MDSS_MDP_IGC_SSPP_SIZE)) {
 		ret = MDP_PP_OPS_READ | MDP_PP_OPS_WRITE;
 	} else if (ptr >= dspp_base && ptr < (dspp_base +
 		(mdss_res->nmixers_intf * MDSS_MDP_DSPP_ADDRESS_OFFSET))) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index e2e41bb..91e6373 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -48,6 +48,8 @@
 			rot->ref_cnt++;
 			rot->session_id = i | MDSS_MDP_ROT_SESSION_MASK;
 			mutex_init(&rot->lock);
+			INIT_LIST_HEAD(&rot->head);
+			INIT_LIST_HEAD(&rot->list);
 			break;
 		}
 	}
@@ -104,8 +106,11 @@
 	if (!pipe) {
 		mdss_mdp_wb_mixer_destroy(mixer);
 		pr_debug("dma pipe allocation failed\n");
+		return NULL;
 	}
 
+	pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;
+
 	return pipe;
 }
 
@@ -125,7 +130,6 @@
 		if (ctl->shared_lock)
 			mutex_unlock(ctl->shared_lock);
 	}
-	mdss_mdp_smp_release(rot->pipe);
 	mutex_unlock(&rot->lock);
 
 	return 0;
@@ -167,7 +171,6 @@
 		if (rot->pipe) {
 			pr_debug("use new rotator pipe=%d\n", rot->pipe->num);
 
-			rot->pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;
 			list_add_tail(&rot->head, &rotator_queue);
 		} else if (!list_empty(&rotator_queue)) {
 			tmp = list_first_entry(&rotator_queue,
@@ -197,12 +200,45 @@
 	return 0;
 }
 
+/**
+ * __mdss_mdp_rotator_to_pipe() - setup pipe according to rotator session params
+ * @rot:	Pointer to rotator session
+ * @pipe:	Pointer to pipe driving structure
+ *
+ * After calling this the pipe structure will contain all parameters required
+ * to use rotator pipe. Note that this function assumes rotator pipe is idle.
+ */
+static int __mdss_mdp_rotator_to_pipe(struct mdss_mdp_rotator_session *rot,
+		struct mdss_mdp_pipe *pipe)
+{
+	int ret;
+
+	pipe->flags = rot->flags;
+	pipe->src_fmt = mdss_mdp_get_format_params(rot->format);
+	pipe->img_width = rot->img_width;
+	pipe->img_height = rot->img_height;
+	pipe->src = rot->src_rect;
+	pipe->dst = rot->src_rect;
+	pipe->dst.x = 0;
+	pipe->dst.y = 0;
+	pipe->params_changed++;
+	rot->params_changed = 0;
+
+	ret = mdss_mdp_smp_reserve(pipe);
+	if (ret) {
+		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
+		return ret;
+	}
+
+	return 0;
+}
+
 static int mdss_mdp_rotator_queue_sub(struct mdss_mdp_rotator_session *rot,
 			   struct mdss_mdp_data *src_data,
 			   struct mdss_mdp_data *dst_data)
 {
 	struct mdss_mdp_pipe *rot_pipe = NULL;
-	struct mdss_mdp_ctl *ctl;
+	struct mdss_mdp_ctl *orig_ctl, *rot_ctl;
 	int ret;
 
 	if (!rot || !rot->ref_cnt)
@@ -218,51 +254,40 @@
 
 	pr_debug("queue rotator pnum=%d\n", rot_pipe->num);
 
-	ctl = rot_pipe->mixer->ctl;
-	if (ctl->shared_lock)
-		mutex_lock(ctl->shared_lock);
+	orig_ctl = rot_pipe->mixer->ctl;
+	if (orig_ctl->shared_lock)
+		mutex_lock(orig_ctl->shared_lock);
 
-	ctl = mdss_mdp_ctl_mixer_switch(ctl,
+	rot_ctl = mdss_mdp_ctl_mixer_switch(orig_ctl,
 			MDSS_MDP_WB_CTL_TYPE_BLOCK);
-	if (!ctl) {
+	if (!rot_ctl) {
 		ret = -EINVAL;
 		goto error;
 	} else {
-		rot->pipe->mixer = ctl->mixer_left;
+		rot->pipe->mixer = rot_ctl->mixer_left;
 	}
 
-	if (rot->params_changed || ctl->mdata->mixer_switched) {
-		rot->params_changed = 0;
-		rot_pipe->flags = rot->flags;
-		rot_pipe->src_fmt = mdss_mdp_get_format_params(rot->format);
-		rot_pipe->img_width = rot->img_width;
-		rot_pipe->img_height = rot->img_height;
-		rot_pipe->src = rot->src_rect;
-		rot_pipe->dst = rot->src_rect;
-		rot_pipe->dst.x = 0;
-		rot_pipe->dst.y = 0;
-		rot_pipe->params_changed++;
+	if (rot->params_changed || rot_ctl->mdata->mixer_switched) {
+		ret = __mdss_mdp_rotator_to_pipe(rot, rot_pipe);
+		if (ret) {
+			pr_err("rotator session=%x to pipe=%d failed %d\n",
+					rot->session_id, rot_pipe->num, ret);
+			goto error;
+		}
 	}
 
-	ret = mdss_mdp_smp_reserve(rot->pipe);
-	if (ret) {
-		pr_err("unable to mdss_mdp_smp_reserve rot data\n");
-		goto error;
-	}
-
-	ret = mdss_mdp_pipe_queue_data(rot->pipe, src_data);
+	ret = mdss_mdp_pipe_queue_data(rot_pipe, src_data);
 	if (ret) {
 		pr_err("unable to queue rot data\n");
-		mdss_mdp_smp_unreserve(rot->pipe);
 		goto error;
 	}
 
-	ret = mdss_mdp_rotator_kickoff(ctl, rot, dst_data);
+	ret = mdss_mdp_rotator_kickoff(rot_ctl, rot, dst_data);
 
 	return ret;
 error:
-	if (ctl->shared_lock)
-		mutex_unlock(ctl->shared_lock);
+	if (orig_ctl->shared_lock)
+		mutex_unlock(orig_ctl->shared_lock);
 	return ret;
 }
 
@@ -367,6 +392,45 @@
 	return ret;
 }
 
+/*
+ * Try to reserve hardware resources for rotator session if possible, if this
+ * is not possible we may still have a chance to reuse existing pipes used by
+ * other sessions at a later point.
+ */
+static int __mdss_mdp_rotator_pipe_reserve(struct mdss_mdp_rotator_session *rot)
+{
+	int ret;
+
+	if (!rot->pipe) {
+		rot->pipe = mdss_mdp_rotator_pipe_alloc();
+		if (rot->pipe) {
+			pr_debug("reserved rotator pipe=%d\n", rot->pipe->num);
+			list_add_tail(&rot->head, &rotator_queue);
+		} else {
+			/*
+			 * if rotator queue is not empty means that we'll be
+			 * able to reuse existing rotator pipes for this rotator
+			 * session, otherwise it means that there are no DMA
+			 * pipes available so we should abort now
+			 */
+			if (list_empty(&rotator_queue)) {
+				pr_err("unable to reserve rot pipe\n");
+				return -ENODEV;
+			}
+
+			pr_debug("unable to get rot pipe but some in queue\n");
+			return 0;
+		}
+	}
+
+	ret = __mdss_mdp_rotator_to_pipe(rot, rot->pipe);
+	if (ret)
+		pr_err("rotator session=%x to pipe=%d failed %d\n",
+				rot->session_id, rot->pipe->num, ret);
+
+	return ret;
+}
+
 int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
 			   struct mdp_overlay *req)
 {
@@ -391,14 +455,14 @@
 
 	if (req->id == MSMFB_NEW_REQUEST) {
 		rot = mdss_mdp_rotator_session_alloc();
-		rot->pid = current->tgid;
-		list_add(&rot->list, &mdp5_data->rot_proc_list);
-
 		if (!rot) {
 			pr_err("unable to allocate rotator session\n");
 			ret = -ENOMEM;
 			goto rot_err;
 		}
+
+		rot->pid = current->tgid;
+		list_add(&rot->list, &mdp5_data->rot_proc_list);
 	} else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
 		rot = mdss_mdp_rotator_session_get(req->id);
 
@@ -526,15 +590,22 @@
 
 	rot->params_changed++;
 
+	ret = __mdss_mdp_rotator_pipe_reserve(rot);
+	if (!ret && rot->next)
+		ret = __mdss_mdp_rotator_pipe_reserve(rot->next);
+
+	if (ret)
+		goto rot_err;
+
 	req->id = rot->session_id;
 
  rot_err:
-	mutex_unlock(&rotator_lock);
 	if (ret) {
 		pr_err("Unable to setup rotator session\n");
-		if (rot)
-			mdss_mdp_rotator_release(rot);
+		if (rot && (req->id == MSMFB_NEW_REQUEST))
+			mdss_mdp_rotator_finish(rot);
 	}
+	mutex_unlock(&rotator_lock);
 	return ret;
 }
 
@@ -560,6 +631,9 @@
 		list_del(&rot->head);
 	}
 
+	if (!list_empty(&rot->list))
+		list_del(&rot->list);
+
 	rot_sync_pt_data = rot->rot_sync_pt_data;
 	commit_work = rot->commit_work;
 	memset(rot, 0, sizeof(*rot));
@@ -616,6 +690,7 @@
 			    struct msmfb_overlay_data *req)
 {
 	struct mdss_mdp_rotator_session *rot;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	int ret;
 	u32 flgs;
 
@@ -635,6 +710,9 @@
 		goto dst_buf_fail;
 	}
 
+	if (!mfd->panel_info->cont_splash_enabled)
+		mdss_iommu_attach(mdp5_data->mdata);
+
 	mdss_mdp_overlay_free_buf(&rot->src_buf);
 	ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
 	if (ret) {
@@ -671,8 +749,6 @@
 		mdss_mdp_overlay_free_buf(&rot->dst_buf);
 
 		rot->pid = 0;
-		if (!list_empty(&rot->list))
-			list_del_init(&rot->list);
 		ret = mdss_mdp_rotator_finish(rot);
 	}
 	mutex_unlock(&rotator_lock);
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index c3e1916..69506d4 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -257,6 +257,27 @@
 	else
 		*res_rect = (struct mdss_mdp_img_rect){l, t, (r-l), (b-t)};
 }
+
+void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
+	struct mdss_mdp_img_rect *dst_rect,
+	const struct mdss_mdp_img_rect *sci_rect)
+{
+	struct mdss_mdp_img_rect res;
+	mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
+
+	if (res.w && res.h) {
+		if ((res.w != dst_rect->w) || (res.h != dst_rect->h)) {
+			src_rect->x = src_rect->x + (res.x - dst_rect->x);
+			src_rect->y = src_rect->y + (res.y - dst_rect->y);
+			src_rect->w = res.w;
+			src_rect->h = res.h;
+		}
+		*dst_rect = (struct mdss_mdp_img_rect)
+			{(res.x - sci_rect->x), (res.y - sci_rect->y),
+			res.w, res.h};
+	}
+}
+
 int mdss_mdp_get_rau_strides(u32 w, u32 h,
 			       struct mdss_mdp_format_params *fmt,
 			       struct mdss_mdp_plane_sizes *ps)
@@ -592,9 +613,9 @@
 
 int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase)
 {
-	u32 unit, residue;
+	u32 unit, residue, result;
 
-	if (dst == 0)
+	if (src == 0 || dst == 0)
 		return -EINVAL;
 
 	unit = 1 << PHASE_STEP_SHIFT;
@@ -602,8 +623,13 @@
 
 	/* check if overflow is possible */
 	if (src > dst) {
-		residue = *out_phase & (unit - 1);
-		if (residue && ((residue * dst) < (unit - residue)))
+		residue = *out_phase - unit;
+		result = (residue * dst) + residue;
+
+		while (result > (unit + (unit >> 1)))
+			result -= unit;
+
+		if ((result > residue) && (result < unit))
 			return -EOVERFLOW;
 	}
 
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index 5789341..6eb4d6e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -51,7 +51,8 @@
 	REGISTERED,
 	IN_FREE_QUEUE,
 	IN_BUSY_QUEUE,
-	WITH_CLIENT
+	WITH_CLIENT,
+	WB_BUFFER_READY,
 };
 
 struct mdss_mdp_wb_data {
@@ -60,11 +61,14 @@
 	struct msmfb_data buf_info;
 	struct mdss_mdp_data buf_data;
 	int state;
+	bool user_alloc;
 };
 
 static DEFINE_MUTEX(mdss_mdp_wb_buf_lock);
 static struct mdss_mdp_wb mdss_mdp_wb_info;
 
+static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node);
+
 #ifdef DEBUG_WRITEBACK
 /* for debugging: writeback output buffer to allocated memory */
 static inline
@@ -284,6 +288,7 @@
 		struct mdss_mdp_wb_data *node, *temp;
 		list_for_each_entry_safe(node, temp, &wb->register_queue,
 					 registered_entry) {
+			mdss_mdp_wb_free_node(node);
 			list_del(&node->registered_entry);
 			kfree(node);
 		}
@@ -400,12 +405,24 @@
 	struct mdss_mdp_img_data *buf;
 	int ret;
 
+	if (!list_empty(&wb->register_queue)) {
+		list_for_each_entry(node, &wb->register_queue, registered_entry)
+			if ((node->buf_info.memory_id == data->memory_id) &&
+				    (node->buf_info.offset == data->offset)) {
+				pr_debug("found node fd=%x off=%x addr=%x\n",
+						data->memory_id, data->offset,
+						node->buf_data.p[0].addr);
+				return node;
+			}
+	}
+
 	node = kzalloc(sizeof(struct mdss_mdp_wb_data), GFP_KERNEL);
 	if (node == NULL) {
 		pr_err("out of memory\n");
 		return NULL;
 	}
 
+	node->user_alloc = true;
 	node->buf_data.num_planes = 1;
 	buf = &node->buf_data.p[0];
 	if (wb->is_secure)
@@ -433,11 +450,28 @@
 	return NULL;
 }
 
+static void mdss_mdp_wb_free_node(struct mdss_mdp_wb_data *node)
+{
+	struct mdss_mdp_img_data *buf;
+
+	if (node->user_alloc) {
+		buf = &node->buf_data.p[0];
+		pr_debug("free user node mem_id=%d offset=%u addr=0x%x\n",
+				node->buf_info.memory_id,
+				node->buf_info.offset,
+				buf->addr);
+
+		mdss_mdp_put_img(&node->buf_data.p[0]);
+		node->user_alloc = false;
+	}
+}
+
 static int mdss_mdp_wb_queue(struct msm_fb_data_type *mfd,
 				struct msmfb_data *data, int local)
 {
 	struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
 	struct mdss_mdp_wb_data *node = NULL;
+	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	int ret = 0;
 
 	if (!wb) {
@@ -447,19 +481,46 @@
 
 	pr_debug("fb%d queue\n", wb->fb_ndx);
 
+	if (!mfd->panel_info->cont_splash_enabled)
+		mdss_iommu_attach(mdp5_data->mdata);
+
 	mutex_lock(&wb->lock);
 	if (local)
 		node = get_local_node(wb, data);
 	if (node == NULL)
 		node = get_user_node(mfd, data);
 
-	if (!node || node->state == IN_BUSY_QUEUE ||
-	    node->state == IN_FREE_QUEUE) {
-		pr_err("memory not registered or Buffer already with us\n");
-		ret = -EINVAL;
+	if (!node) {
+		pr_err("memory not registered\n");
+		ret = -ENOENT;
 	} else {
-		list_add_tail(&node->active_entry, &wb->free_queue);
-		node->state = IN_FREE_QUEUE;
+		struct mdss_mdp_img_data *buf = &node->buf_data.p[0];
+
+		switch (node->state) {
+		case IN_FREE_QUEUE:
+			pr_err("node 0x%pa was already queueued before\n",
+					&buf->addr);
+			ret = -EINVAL;
+			break;
+		case IN_BUSY_QUEUE:
+			pr_err("node 0x%pa still in busy state\n", &buf->addr);
+			ret = -EBUSY;
+			break;
+		case WB_BUFFER_READY:
+			pr_debug("node 0x%pa re-queueded without dequeue\n",
+				&buf->addr);
+			list_del(&node->active_entry);
+		case WITH_CLIENT:
+		case REGISTERED:
+			list_add_tail(&node->active_entry, &wb->free_queue);
+			node->state = IN_FREE_QUEUE;
+			break;
+		default:
+			pr_err("Invalid node 0x%pa state %d\n",
+				&buf->addr, node->state);
+			ret = -EINVAL;
+			break;
+		}
 	}
 	mutex_unlock(&wb->lock);
 
@@ -529,6 +590,8 @@
 	if (!ctl->power_on)
 		return 0;
 
+	memset(&wb_args, 0, sizeof(wb_args));
+
 	mutex_lock(&mdss_mdp_wb_buf_lock);
 	if (wb) {
 		mutex_lock(&wb->lock);
@@ -569,6 +632,7 @@
 	if (wb && node) {
 		mutex_lock(&wb->lock);
 		list_add_tail(&node->active_entry, &wb->busy_queue);
+		node->state = WB_BUFFER_READY;
 		mutex_unlock(&wb->lock);
 		wake_up(&wb->wait_q);
 	}
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index a42ff1e..274c523 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2014, 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
@@ -227,9 +227,14 @@
 	u32  init_delay;
 };
 
+struct edp_panel_info {
+	char frame_rate;	/* fps */
+};
+
 enum dynamic_fps_update {
 	DFPS_SUSPEND_RESUME_MODE,
 	DFPS_IMMEDIATE_CLK_UPDATE_MODE,
+	DFPS_IMMEDIATE_PORCH_UPDATE_MODE,
 };
 
 enum lvds_mode {
@@ -309,6 +314,7 @@
 	struct fbc_panel_info fbc;
 	struct mipi_panel_info mipi;
 	struct lvds_panel_info lvds;
+	struct edp_panel_info edp;
 };
 
 struct mdss_panel_data {
@@ -349,6 +355,9 @@
 	case MIPI_CMD_PANEL:
 		frame_rate = panel_info->mipi.frame_rate;
 		break;
+	case EDP_PANEL:
+		frame_rate = panel_info->edp.frame_rate;
+		break;
 	case WRITEBACK_PANEL:
 		frame_rate = DEFAULT_FRAME_RATE;
 		break;
diff --git a/drivers/video/msm/mdss/mdss_qpic.c b/drivers/video/msm/mdss/mdss_qpic.c
index fa6bd3d..54b837a 100644
--- a/drivers/video/msm/mdss/mdss_qpic.c
+++ b/drivers/video/msm/mdss/mdss_qpic.c
@@ -368,7 +368,7 @@
 		phys_addr += block_len;
 		len -= block_len;
 	}
-	ret = wait_for_completion_interruptible_timeout(
+	ret = wait_for_completion_timeout(
 		&qpic_res->qpic_endpt.completion,
 		msecs_to_jiffies(100 * 4));
 	if (ret <= 0)
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index ab01566..0f84b2d 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -193,6 +193,7 @@
 			enum mhl_st_type to_mode, bool hpd_off);
 static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl,
 				  bool mhl_disc_en);
+static int mhl_gpio_config(struct mhl_tx_ctrl *mhl_ctrl, int on);
 
 int mhl_i2c_reg_read(struct i2c_client *client,
 			    uint8_t slave_addr_index, uint8_t reg_offset)
@@ -359,12 +360,18 @@
 	int timeout;
 
 	pr_debug("%s:%u\n", __func__, __LINE__);
+
+	if (mhl_ctrl->mhl_mode) {
+		pr_debug("%s: already in mhl mode\n", __func__);
+		return 0;
+	}
+
 	INIT_COMPLETION(mhl_ctrl->rgnd_done);
 	/*
 	 * after toggling reset line and enabling disc
 	 * tx can take a while to generate intr
 	 */
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 		(&mhl_ctrl->rgnd_done, HZ * 3);
 	if (!timeout) {
 		/*
@@ -374,7 +381,8 @@
 		pr_warn("%s:%u timedout\n", __func__, __LINE__);
 		return -ENODEV;
 	}
-	return mhl_ctrl->mhl_mode ? 0 : 1;
+
+	return 0;
 }
 
 /*  USB_HANDSHAKING FUNCTIONS */
@@ -385,26 +393,7 @@
 	struct mhl_tx_ctrl *mhl_ctrl = data;
 	struct i2c_client *client = mhl_ctrl->i2c_handle;
 	unsigned long flags;
-
-	if (!mhl_ctrl->irq_req_done) {
-		rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
-					  &mhl_tx_isr,
-					  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-					  client->dev.driver->name, mhl_ctrl);
-		if (rc) {
-			pr_err("request_threaded_irq failed, status: %d\n",
-			       rc);
-			return -EINVAL;
-		} else {
-			pr_debug("request_threaded_irq succeeded\n");
-			mhl_ctrl->irq_req_done = true;
-		}
-	} else {
-		enable_irq(client->irq);
-	}
-
-	/* wait for i2c interrupt line to be activated */
-	msleep(100);
+	int discovery_retry = 5;
 
 	if (id) {
 		/* When MHL cable is disconnected we get a sii8334
@@ -424,6 +413,23 @@
 		mhl_ctrl->notify_usb_online = usb_notify_cb;
 		mhl_ctrl->notify_ctx = ctx;
 	}
+again:
+	if (!mhl_ctrl->irq_req_done) {
+		rc = request_threaded_irq(mhl_ctrl->i2c_handle->irq, NULL,
+			&mhl_tx_isr, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+			client->dev.driver->name, mhl_ctrl);
+		if (rc) {
+			pr_debug("request_threaded_irq failed, status: %d\n",
+			       rc);
+			return -EINVAL;
+		} else {
+			pr_debug("request_threaded_irq succeeded\n");
+			mhl_ctrl->irq_req_done = true;
+		}
+
+		/* wait for i2c interrupt line to be activated */
+		msleep(100);
+	}
 
 	if (!mhl_ctrl->disc_enabled) {
 		spin_lock_irqsave(&mhl_ctrl->lock, flags);
@@ -439,16 +445,38 @@
 		mhl_init_reg_settings(mhl_ctrl, true);
 		/* allow tx to enable dev disc after D3 state */
 		msleep(100);
-		rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
+		if (mhl_sii_wait_for_rgnd(mhl_ctrl)) {
+			pr_err("%s: discovery timeout\n", __func__);
+
+			free_irq(mhl_ctrl->i2c_handle->irq, mhl_ctrl);
+			mhl_gpio_config(mhl_ctrl, 0);
+			mhl_ctrl->irq_req_done = false;
+
+			msleep(100);
+
+			mhl_gpio_config(mhl_ctrl, 1);
+			if (discovery_retry--) {
+				pr_debug("%s: retrying discovery\n", __func__);
+				goto again;
+			} else {
+				pr_err("%s: discovery failed, ret to USB\n",
+					__func__);
+				if (mhl_ctrl->notify_usb_online)
+					mhl_ctrl->notify_usb_online(
+						mhl_ctrl->notify_ctx, 0);
+			}
+		}
 	} else {
 		if (mhl_ctrl->cur_state == POWER_STATE_D3) {
-			rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
+			mhl_sii_wait_for_rgnd(mhl_ctrl);
 		} else {
 			/* in MHL mode */
 			pr_debug("%s:%u\n", __func__, __LINE__);
-			rc = 0;
 		}
 	}
+
+	rc = mhl_ctrl->mhl_mode ? 0 : 1;
+
 	pr_debug("%s: ret result: %s\n", __func__, rc ? "usb" : " mhl");
 	return rc;
 }
@@ -796,6 +824,7 @@
 				 rc ? "failed" : "passed");
 		}
 		mhl_ctrl->cur_state = POWER_STATE_D3;
+		mhl_ctrl->mhl_mode = 0;
 		break;
 	default:
 		break;
@@ -1274,7 +1303,7 @@
 
 	INIT_COMPLETION(mhl_ctrl->msc_cmd_done);
 	MHL_SII_REG_NAME_WR(REG_CBUS_PRI_START, start_bit);
-	timeout = wait_for_completion_interruptible_timeout
+	timeout = wait_for_completion_timeout
 		(&mhl_ctrl->msc_cmd_done, msecs_to_jiffies(T_ABORT_NEXT));
 	if (!timeout) {
 		pr_err("%s: cbus_command_send timed out!\n", __func__);
@@ -1918,19 +1947,28 @@
 {
 	struct mhl_tx_ctrl *mhl_ctrl = i2c_get_clientdata(client);
 
-	if (mhl_ctrl->irq_req_done) {
-		enable_irq_wake(client->irq);
-		disable_irq(client->irq);
+	pr_debug("%s\n", __func__);
+
+	if (!mhl_ctrl)
+		return 0;
+
+	free_irq(mhl_ctrl->i2c_handle->irq, mhl_ctrl);
+	mhl_ctrl->irq_req_done = false;
+
+	if (mhl_ctrl->mhl_mode)	{
+		mhl_ctrl->mhl_mode = 0;
+		power_supply_changed(&mhl_ctrl->mhl_psy);
+		if (mhl_ctrl->notify_usb_online)
+			mhl_ctrl->notify_usb_online(mhl_ctrl->notify_ctx, 0);
 	}
+
 	return 0;
 }
 
 static int mhl_i2c_resume_sub(struct i2c_client *client)
 {
-	struct mhl_tx_ctrl *mhl_ctrl = i2c_get_clientdata(client);
+	pr_debug("%s\n", __func__);
 
-	if (mhl_ctrl->irq_req_done)
-		disable_irq_wake(client->irq);
 	return 0;
 }
 #endif /* defined(CONFIG_PM) || defined(CONFIG_PM_SLEEP) */
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index a63275b..5d4610c 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -675,6 +675,8 @@
 		clk_put(edp_drv->ahb_clk);
 	if (edp_drv->link_clk)
 		clk_put(edp_drv->link_clk);
+	if (edp_drv->mdp_core_clk)
+		clk_put(edp_drv->mdp_core_clk);
 }
 
 int mdss_edp_clk_init(struct mdss_edp_drv_pdata *edp_drv)
@@ -709,6 +711,14 @@
 		goto mdss_edp_clk_err;
 	}
 
+	/* need mdss clock to receive irq */
+	edp_drv->mdp_core_clk = clk_get(dev, "mdp_core_clk");
+	if (IS_ERR(edp_drv->mdp_core_clk)) {
+		pr_err("%s: Can't find mdp_core_clk", __func__);
+		edp_drv->mdp_core_clk = NULL;
+		goto mdss_edp_clk_err;
+	}
+
 	return 0;
 
 mdss_edp_clk_err:
@@ -736,7 +746,16 @@
 		goto c1;
 	}
 
+	/* need mdss clock to receive irq */
+	ret = clk_enable(edp_drv->mdp_core_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable mdp_core_clk\n", __func__);
+		goto c0;
+	}
+
 	return 0;
+c0:
+	clk_disable(edp_drv->ahb_clk);
 c1:
 	clk_disable(edp_drv->aux_clk);
 c2:
@@ -748,6 +767,7 @@
 {
 	clk_disable(edp_drv->aux_clk);
 	clk_disable(edp_drv->ahb_clk);
+	clk_disable(edp_drv->mdp_core_clk);
 }
 
 int mdss_edp_clk_enable(struct mdss_edp_drv_pdata *edp_drv)
@@ -791,11 +811,18 @@
 		pr_err("%s: Failed to enable link clk\n", __func__);
 		goto c1;
 	}
+	ret = clk_enable(edp_drv->mdp_core_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable mdp_core_clk\n", __func__);
+		goto c0;
+	}
 
 	edp_drv->clk_on = 1;
 
 	return 0;
 
+c0:
+	clk_disable(edp_drv->link_clk);
 c1:
 	clk_disable(edp_drv->ahb_clk);
 c2:
@@ -817,6 +844,7 @@
 	clk_disable(edp_drv->pixel_clk);
 	clk_disable(edp_drv->ahb_clk);
 	clk_disable(edp_drv->link_clk);
+	clk_disable(edp_drv->mdp_core_clk);
 
 	edp_drv->clk_on = 0;
 }
@@ -825,10 +853,11 @@
 {
 	int ret;
 
+	/* ahb clock should be prepared first */
 	ret = clk_prepare(edp_drv->ahb_clk);
 	if (ret) {
 		pr_err("%s: Failed to prepare ahb clk\n", __func__);
-		goto c1;
+		goto c3;
 	}
 	ret = clk_prepare(edp_drv->aux_clk);
 	if (ret) {
@@ -836,16 +865,26 @@
 		goto c2;
 	}
 
+	/* need mdss clock to receive irq */
+	ret = clk_prepare(edp_drv->mdp_core_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare mdp_core clk\n", __func__);
+		goto c1;
+	}
+
 	return 0;
 c1:
-	clk_unprepare(edp_drv->ahb_clk);
+	clk_unprepare(edp_drv->aux_clk);
 c2:
+	clk_unprepare(edp_drv->ahb_clk);
+c3:
 	return ret;
 
 }
 
 void mdss_edp_unprepare_aux_clocks(struct mdss_edp_drv_pdata *edp_drv)
 {
+	clk_unprepare(edp_drv->mdp_core_clk);
 	clk_unprepare(edp_drv->aux_clk);
 	clk_unprepare(edp_drv->ahb_clk);
 }
@@ -854,7 +893,7 @@
 {
 	int ret;
 
-	/* ahb clock should be first one to enable */
+	/* ahb clock should be prepared first */
 	ret = clk_prepare(edp_drv->ahb_clk);
 	if (ret) {
 		pr_err("%s: Failed to prepare ahb clk\n", __func__);
@@ -875,8 +914,15 @@
 		pr_err("%s: Failed to prepare link clk\n", __func__);
 		goto c1;
 	}
+	ret = clk_prepare(edp_drv->mdp_core_clk);
+	if (ret) {
+		pr_err("%s: Failed to prepare mdp_core clk\n", __func__);
+		goto c0;
+	}
 
 	return 0;
+c0:
+	clk_unprepare(edp_drv->link_clk);
 c1:
 	clk_unprepare(edp_drv->pixel_clk);
 c2:
@@ -889,6 +935,7 @@
 
 void mdss_edp_unprepare_clocks(struct mdss_edp_drv_pdata *edp_drv)
 {
+	clk_unprepare(edp_drv->mdp_core_clk);
 	clk_unprepare(edp_drv->aux_clk);
 	clk_unprepare(edp_drv->pixel_clk);
 	clk_unprepare(edp_drv->link_clk);
diff --git a/drivers/video/msm/mdss/splash.h b/drivers/video/msm/mdss/splash.h
new file mode 100644
index 0000000..dc8a473
--- /dev/null
+++ b/drivers/video/msm/mdss/splash.h
@@ -0,0 +1,5279 @@
+/* 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.
+ *
+ */
+#ifndef __SPLASH_H_
+#define __SPLASH_H_
+
+#define SPLASH_IMAGE_WIDTH	113
+#define SPLASH_IMAGE_HEIGHT	124
+#define SPLASH_IMAGE_FORMAT	MDP_BGR_888
+#define SPLASH_IMAGE_BPP	3
+
+char splash_bgr888_image[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
+	0x29, 0x19, 0x31, 0x31,
+	0x29, 0x31, 0x31, 0x29, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x31, 0x31,
+	0x29, 0x4a, 0x52, 0x4a, 0x6b, 0x5a, 0x73, 0x4a, 0x52, 0x4a, 0x10, 0x29,
+	0x19, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x31, 0x31, 0x29, 0x6b, 0x5a, 0x73, 0x6b, 0x7b, 0x73, 0x6b, 0x5a,
+	0x4a, 0x31, 0x31, 0x29,
+	0x3a, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x6b, 0x5a, 0x4a, 0x6b, 0x5a,
+	0x73, 0x3a, 0x31, 0x4a,
+	0x31, 0x31, 0x29, 0x10, 0x29, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x3a, 0x31,
+	0x4a, 0x31, 0x31, 0x29,
+	0x10, 0x29, 0x19, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x10, 0x21, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x08,
+	0x10, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x08, 0x08, 0x10,
+	0x08, 0x08, 0x10, 0x10,
+	0x29, 0x19, 0x10, 0x29, 0x19, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10,
+	0x4a, 0x52, 0x4a, 0x08,
+	0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x08,
+	0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10, 0x29, 0x19, 0x4a, 0x52, 0x4a, 0x3a, 0x31, 0x4a,
+	0x08, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x4a, 0x52, 0x4a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x4a,
+	0x52, 0x4a, 0x9c, 0xa5, 0x94, 0x9c, 0x7b, 0x94, 0x08, 0x08, 0x10, 0x08,
+	0x08, 0x10, 0x10, 0x29,
+	0x19, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+	0x10, 0x10, 0x21, 0x00,
+	0x08, 0x08, 0x10, 0x6b, 0x7b, 0x73, 0x9c, 0x7b, 0x94, 0x9c, 0xa5, 0x94,
+	0xce, 0xad, 0xad, 0xa5,
+	0xb5, 0xb5, 0x31, 0x31, 0x29, 0x08, 0x08, 0x10, 0x10, 0x29, 0x19, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x4a,
+	0x52, 0x4a, 0xa5, 0x9c, 0xad, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0x9c,
+	0x7b, 0x94, 0x10, 0x29,
+	0x19, 0x3a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x9c, 0x7b, 0x94, 0x9c, 0xa5, 0x94, 0xa5, 0xb5, 0xb5,
+	0xa5, 0xb5, 0xb5, 0xce,
+	0xde, 0xce, 0xc5, 0xad, 0xd6, 0x9c, 0xa5, 0x94, 0x3a, 0x10, 0x21, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x9c, 0x7b, 0x94, 0xce, 0xad, 0xad, 0xce, 0xe6, 0xef, 0xce,
+	0xe6, 0xef, 0xe6, 0xde,
+	0xde, 0xa5, 0x9c, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x6b, 0x5a, 0x73, 0xce, 0xde, 0xce, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0xde, 0xce, 0x6b,
+	0x7b, 0x73, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x10, 0x29, 0x19, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0x9c,
+	0xa5, 0x94, 0xce, 0xde,
+	0xce, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0xce, 0xde, 0xce, 0xff, 0xf7, 0xff,
+	0xff, 0xf7, 0xff, 0x9c,
+	0xa5, 0x94, 0x00, 0x00, 0x00, 0x31, 0x31, 0x29, 0xef, 0xf7, 0xe6, 0xff,
+	0xf7, 0xff, 0xef, 0xde,
+	0xef, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0xff, 0xf7, 0xff, 0x10,
+	0x29, 0x19, 0x08, 0x08,
+	0x10, 0x4a, 0x52, 0x4a, 0xce, 0xad, 0xad, 0xff, 0xff, 0xff, 0x4a, 0x52,
+	0x4a, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0xce, 0xad, 0xad,
+	0xef, 0xf7, 0xff, 0xce,
+	0xde, 0xce, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x9c, 0x7b, 0x94, 0x31,
+	0x31, 0x29, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0x4a, 0x52, 0x4a, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x5a, 0x73, 0xef,
+	0xf7, 0xe6, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x6b, 0x7b, 0x73, 0x08, 0x08, 0x10, 0xff, 0xff,
+	0xff, 0x6b, 0x7b, 0x73,
+	0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x4a, 0x52, 0x4a, 0x08, 0x08, 0x10,
+	0xce, 0xde, 0xce, 0xff,
+	0xff, 0xff, 0x10, 0x29, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31,
+	0x31, 0x29, 0x4a, 0x52,
+	0x4a, 0xa5, 0xb5, 0xb5, 0xff, 0xff, 0xff, 0x9c, 0x7b, 0x94, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x4a,
+	0x52, 0x4a, 0xe6, 0xde,
+	0xde, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x31, 0x31, 0x29, 0x08, 0x08,
+	0x10, 0xff, 0xff, 0xff,
+	0x4a, 0x52, 0x4a, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x9c,
+	0x7b, 0x94, 0xff, 0xff, 0xff, 0x3a, 0x10, 0x21, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x08, 0x08, 0x10, 0x6b, 0x5a, 0x73, 0xff, 0xff, 0xff, 0xa5, 0xb5,
+	0xb5, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x4a, 0x52,
+	0x4a, 0xef, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0xe6, 0xde, 0xde, 0x08, 0x31, 0x5a, 0x10, 0x7b, 0x9c, 0x10, 0x7b, 0x9c,
+	0x10, 0x7b, 0x9c, 0x10,
+	0x52, 0x7b, 0x31, 0x31, 0x29, 0xef, 0xf7, 0xff, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xa5, 0x94, 0xff, 0xff,
+	0xff, 0xa5, 0x9c, 0xad,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x21, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x08, 0x08, 0x10, 0xff, 0xf7, 0xff, 0x4a, 0x52, 0x4a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x31, 0x5a, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xd6, 0x00, 0xbd, 0xef,
+	0x00, 0xbd, 0xef, 0x00,
+	0x9c, 0xd6, 0x08, 0xa5, 0xad, 0x08, 0xad, 0xd6, 0x10, 0xce, 0xce, 0x6b,
+	0x7b, 0x9c, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0x6b, 0x5a, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xce, 0xde, 0xce, 0xff, 0xf7,
+	0xff, 0x10, 0x29, 0x19,
+	0x10, 0x5a, 0x9c, 0x00, 0x9c, 0xd6, 0x19, 0x94, 0xce, 0x00, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x08,
+	0xad, 0xd6, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xd6, 0x10,
+	0xc5, 0xef, 0x00, 0xbd,
+	0xef, 0x08, 0xa5, 0xad, 0x08, 0x31, 0x5a, 0x10, 0x29, 0x19, 0xff, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xe6, 0xde, 0xde, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x5a,
+	0x73, 0xef, 0xf7, 0xe6,
+	0x19, 0x7b, 0xbd, 0x19, 0x7b, 0xbd, 0x08, 0xad, 0xd6, 0x00, 0xbd, 0xef,
+	0x10, 0xc5, 0xef, 0x00,
+	0xbd, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x3a, 0xde, 0xef, 0x19,
+	0xbd, 0xf7, 0x3a, 0xde,
+	0xef, 0x3a, 0xde, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad,
+	0xd6, 0x19, 0x94, 0xce,
+	0xa5, 0xb5, 0xb5, 0x4a, 0x5a, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x08, 0x10,
+	0x10, 0x7b, 0x9c, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xd6,
+	0x08, 0xad, 0xef, 0x10,
+	0xc5, 0xef, 0x08, 0xad, 0xd6, 0x10, 0xc5, 0xef, 0x10, 0xe6, 0xef, 0x19,
+	0xbd, 0xf7, 0x3a, 0xde,
+	0xef, 0x3a, 0xde, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xe6, 0xef, 0x10, 0xe6,
+	0xef, 0x10, 0xc5, 0xef,
+	0x10, 0xe6, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xd6, 0x08, 0x31, 0x3a,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x08, 0x10,
+	0x10, 0x7b, 0x9c, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6,
+	0x10, 0xc5, 0xef, 0x08,
+	0xad, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x10,
+	0xc5, 0xef, 0x6b, 0xe6,
+	0xef, 0x3a, 0xde, 0xef, 0x10, 0xe6, 0xef, 0x10, 0xe6, 0xef, 0x10, 0xc5,
+	0xef, 0x10, 0xe6, 0xef,
+	0x10, 0xc5, 0xef, 0x10, 0xe6, 0xef, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7,
+	0x19, 0x7b, 0xbd, 0x00,
+	0x00, 0x00, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x31, 0x5a, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6,
+	0x08, 0xad, 0xef, 0x08,
+	0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xef, 0x10, 0xc5, 0xef, 0x10,
+	0xc5, 0xef, 0x10, 0xe6,
+	0xef, 0x3a, 0xde, 0xef, 0x19, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x10, 0xe6,
+	0xef, 0x10, 0xc5, 0xef,
+	0x10, 0xe6, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0x84, 0xbd, 0x10, 0x7b, 0x9c,
+	0x00, 0xbd, 0xef, 0x10,
+	0x73, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10, 0x52, 0x7b, 0x19, 0x7b, 0xbd, 0x00, 0x9c, 0xd6,
+	0x19, 0x94, 0xce, 0x08,
+	0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xd6, 0x10,
+	0xe6, 0xef, 0x19, 0xbd,
+	0xf7, 0x6b, 0xe6, 0xef, 0x19, 0xbd, 0xf7, 0x10, 0xe6, 0xef, 0x10, 0xe6,
+	0xef, 0x10, 0xe6, 0xef,
+	0x10, 0xc5, 0xef, 0x00, 0x9c, 0xd6, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6,
+	0x19, 0x94, 0xce, 0x00,
+	0x9c, 0xd6, 0x10, 0x52, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x31, 0x5a,
+	0x08, 0xa5, 0xad, 0x08,
+	0xad, 0xef, 0x00, 0xbd, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x10,
+	0xc5, 0xef, 0x10, 0xc5,
+	0xef, 0x10, 0xe6, 0xef, 0x19, 0xbd, 0xf7, 0x10, 0xe6, 0xef, 0x10, 0xc5,
+	0xef, 0x10, 0xc5, 0xef,
+	0x19, 0xbd, 0xf7, 0x10, 0x7b, 0x9c, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce,
+	0x08, 0xad, 0xd6, 0x00,
+	0x9c, 0xd6, 0x19, 0x94, 0xce, 0x08, 0x31, 0x3a, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x31, 0x31, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+	0x10, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x31, 0x3a, 0x10,
+	0x52, 0x7b, 0x10, 0x7b, 0x9c, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x10,
+	0xc5, 0xef, 0x10, 0xc5,
+	0xef, 0x3a, 0xde, 0xef, 0x10, 0xe6, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xe6,
+	0xef, 0x08, 0xad, 0xd6,
+	0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x00, 0x9c, 0xd6, 0x19, 0x94, 0xce,
+	0x00, 0x9c, 0xd6, 0x00,
+	0x9c, 0xd6, 0x19, 0x7b, 0xbd, 0x19, 0x7b, 0xbd, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x08, 0x10, 0x9c, 0x7b, 0x73, 0x6b, 0x5a, 0x73, 0x10, 0x29,
+	0x19, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x73, 0xa5, 0xad, 0x10, 0x52, 0x7b, 0x10, 0x52, 0x7b, 0x00,
+	0x84, 0xbd, 0x08, 0xa5,
+	0xad, 0x08, 0xad, 0xd6, 0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x10, 0x73,
+	0x7b, 0x10, 0x5a, 0x9c,
+	0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6, 0x00, 0x9c, 0xd6, 0x00, 0x9c, 0xd6,
+	0x00, 0x9c, 0xd6, 0x00,
+	0x84, 0xbd, 0x3a, 0xa5, 0xce, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0x6b,
+	0x5a, 0x73, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0x6b, 0x7b,
+	0x9c, 0x9c, 0x7b, 0x73,
+	0x31, 0x31, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x31, 0x31, 0x29, 0xc5, 0xad, 0xd6, 0x52, 0xa5, 0xa5, 0x10,
+	0x5a, 0x9c, 0x10, 0x7b,
+	0x9c, 0x19, 0x94, 0xce, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xd6, 0x19, 0x94,
+	0xce, 0x00, 0x9c, 0xd6,
+	0x00, 0x9c, 0xd6, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce,
+	0x00, 0x84, 0xbd, 0x19,
+	0x7b, 0xbd, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xce, 0xde, 0xce, 0xa5,
+	0xb5, 0xb5, 0xa5, 0xb5,
+	0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21,
+	0x00, 0x6b, 0x7b, 0x73,
+	0x9c, 0x7b, 0x94, 0x6b, 0x7b, 0x73, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x4a, 0x52, 0x4a, 0xa5, 0xd6, 0xad, 0xc5,
+	0xad, 0xd6, 0x4a, 0x7b,
+	0x9c, 0x10, 0x5a, 0x9c, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6, 0x00, 0x84,
+	0xbd, 0x00, 0x9c, 0xd6,
+	0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x00, 0x84, 0xbd,
+	0x19, 0x7b, 0xbd, 0x73,
+	0xa5, 0xad, 0xa5, 0xb5, 0xb5, 0xc5, 0xad, 0xd6, 0xa5, 0xb5, 0xb5, 0xe6,
+	0xde, 0xde, 0xce, 0xde,
+	0xce, 0xce, 0xad, 0xad, 0x10, 0x29, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x4a, 0x52, 0x4a, 0x6b, 0x7b, 0x73, 0x31, 0x31, 0x29, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x31, 0x4a, 0xce,
+	0xad, 0xad, 0xce, 0xde,
+	0xce, 0xa5, 0xb5, 0xb5, 0x73, 0xa5, 0xad, 0x10, 0x73, 0x7b, 0x10, 0x5a,
+	0x9c, 0x10, 0x7b, 0x9c,
+	0x10, 0x5a, 0xbd, 0x10, 0x7b, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c,
+	0x19, 0x7b, 0xbd, 0xa5,
+	0xb5, 0xb5, 0xa5, 0xb5, 0xb5, 0xc5, 0xad, 0xd6, 0xa5, 0xd6, 0xad, 0xef,
+	0xde, 0xef, 0xef, 0xf7,
+	0xe6, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xa5, 0x9c, 0xad, 0x08, 0x08,
+	0x10, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x4a,
+	0x52, 0x4a, 0xe6, 0xde,
+	0xde, 0xc5, 0xad, 0xd6, 0xa5, 0xb5, 0xb5, 0xce, 0xad, 0xad, 0x9c, 0xad,
+	0xce, 0x52, 0xa5, 0xa5,
+	0x10, 0x5a, 0x9c, 0x10, 0x7b, 0x9c, 0x10, 0x5a, 0x9c, 0x52, 0xa5, 0xa5,
+	0x73, 0xa5, 0xad, 0xc5,
+	0xad, 0xd6, 0xa5, 0xb5, 0xb5, 0xce, 0xde, 0xce, 0xce, 0xde, 0xce, 0xef,
+	0xde, 0xef, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xef, 0xf7,
+	0xe6, 0x08, 0x08, 0x10,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0xef, 0xf7,
+	0xe6, 0xef, 0xf7, 0xe6, 0xce, 0xde, 0xce, 0xce, 0xde, 0xce, 0xa5, 0xb5,
+	0xb5, 0xce, 0xde, 0xce,
+	0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xa5, 0xb5, 0xb5, 0xce, 0xde, 0xce,
+	0xce, 0xad, 0xad, 0xc5,
+	0xad, 0xd6, 0xa5, 0xd6, 0xad, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xe6,
+	0xde, 0xde, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xa5, 0xb5, 0xb5, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x10, 0x21, 0x00, 0x00,
+	0x00, 0x00, 0x9c, 0xa5,
+	0x94, 0xff, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xc5, 0xad,
+	0xd6, 0xa5, 0xb5, 0xb5,
+	0xce, 0xad, 0xad, 0xc5, 0xad, 0xd6, 0xa5, 0xb5, 0xb5, 0xce, 0xad, 0xad,
+	0xc5, 0xad, 0xd6, 0xa5,
+	0xd6, 0xad, 0xc5, 0xad, 0xd6, 0xce, 0xde, 0xce, 0xef, 0xde, 0xef, 0xef,
+	0xf7, 0xe6, 0xff, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0x31, 0x29, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0x08,
+	0x08, 0x10, 0x10, 0x29,
+	0x19, 0xef, 0xde, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xc5, 0xad, 0xd6, 0xa5, 0xd6, 0xad, 0xa5, 0xb5, 0xb5, 0xce, 0xde, 0xce,
+	0xa5, 0xb5, 0xb5, 0xce,
+	0xde, 0xce, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xef, 0xf7, 0xe6, 0xef,
+	0xf7, 0xff, 0xff, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xde, 0xde,
+	0x08, 0x08, 0x10, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x10, 0x21,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0xe6, 0xde, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xe6, 0xde, 0xde, 0xce, 0xad, 0xad, 0xc5, 0xad, 0xd6,
+	0xa5, 0xb5, 0xb5, 0xce,
+	0xad, 0xad, 0xce, 0xde, 0xce, 0xce, 0xe6, 0xef, 0xff, 0xf7, 0xff, 0xff,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x4a, 0x52, 0x4a, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xef, 0xf7, 0xe6,
+	0xe6, 0xde, 0xde, 0xef,
+	0xf7, 0xe6, 0xce, 0xe6, 0xef, 0xff, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xa5, 0x9c, 0xad, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xde, 0xde, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x08,
+	0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0xce, 0xde, 0xce, 0xef, 0xde,
+	0xef, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef,
+	0xf7, 0xff, 0x31, 0x31,
+	0x29, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0xce, 0xad,
+	0xad, 0xef, 0xf7, 0xe6,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xef,
+	0xde, 0xef, 0xef, 0xf7,
+	0xe6, 0x9c, 0xa5, 0x94, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31,
+	0x29, 0xa5, 0xb5, 0xb5,
+	0xce, 0xde, 0xce, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xe6, 0xef, 0xde, 0xef, 0xef,
+	0xf7, 0xe6, 0xe6, 0xde,
+	0xde, 0xce, 0xe6, 0xef, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0xef, 0xf7, 0xe6,
+	0xef, 0xf7, 0xe6, 0xef,
+	0xde, 0xef, 0xce, 0xe6, 0xef, 0xe6, 0xde, 0xde, 0xe6, 0xde, 0xde, 0xce,
+	0xde, 0xce, 0xce, 0xde,
+	0xce, 0xe6, 0xde, 0xde, 0xce, 0xad, 0xad, 0x08, 0x08, 0x10, 0x00, 0x00,
+	0x00, 0x10, 0x21, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
+	0x10, 0x6b, 0x5a, 0x4a,
+	0x73, 0xa5, 0xad, 0xce, 0xad, 0xad, 0xc5, 0xad, 0xd6, 0xe6, 0xde, 0xde,
+	0xe6, 0xde, 0xde, 0xff,
+	0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef,
+	0xde, 0xef, 0xce, 0xde,
+	0xce, 0xef, 0xde, 0xef, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xde, 0xef,
+	0xce, 0xde, 0xce, 0xc5,
+	0xad, 0xd6, 0xce, 0xde, 0xce, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xa5,
+	0xb5, 0xb5, 0xc5, 0xad,
+	0xd6, 0xa5, 0xb5, 0xb5, 0xc5, 0xad, 0xd6, 0xef, 0xf7, 0xff, 0x4a, 0x52,
+	0x4a, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00,
+	0x00, 0x10, 0x29, 0x19,
+	0x6b, 0x5a, 0x73, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xce, 0xde, 0xce,
+	0xef, 0xf7, 0xe6, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xef, 0xde, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xe6, 0xde, 0xde, 0xce, 0xde, 0xce, 0xc5,
+	0xad, 0xd6, 0xce, 0xde,
+	0xce, 0xce, 0xad, 0xad, 0xce, 0xde, 0xce, 0xa5, 0xb5, 0xb5, 0xce, 0xde,
+	0xce, 0xff, 0xf7, 0xff,
+	0x31, 0x31, 0x29, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x4a, 0x52, 0x4a,
+	0x31, 0x31, 0x29, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0xa5, 0x9c, 0xad, 0xce, 0xde, 0xce, 0xce, 0xe6, 0xef,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xce, 0xe6, 0xef, 0xe6, 0xde, 0xde, 0xce, 0xde, 0xce, 0xc5, 0xad,
+	0xd6, 0xce, 0xad, 0xad,
+	0xe6, 0xde, 0xde, 0xff, 0xf7, 0xff, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x31, 0x31, 0x29, 0x3a, 0x10, 0x21, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x31, 0x31,
+	0x29, 0x00, 0x00, 0x00,
+	0x10, 0x21, 0x00, 0x6b, 0x5a, 0x73, 0xce, 0xde, 0xce, 0xff, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xce, 0xde, 0xce,
+	0xce, 0xde, 0xce, 0x9c, 0xad, 0xce, 0xef, 0xf7, 0xe6, 0xa5, 0x9c, 0xad,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x3a, 0x31, 0x4a, 0x10,
+	0x29, 0x19, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x52,
+	0x4a, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0xe6, 0xde, 0xde, 0xef, 0xf7, 0xe6,
+	0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xf7, 0xff,
+	0xef, 0xf7, 0xff, 0xef, 0xde, 0xef, 0xce, 0xe6, 0xad, 0xc5, 0xad, 0xd6,
+	0xff, 0xff, 0xff, 0x10,
+	0x29, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x31, 0x31,
+	0x29, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x29,
+	0x19, 0x08, 0x08, 0x10,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x5a, 0x73, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xde, 0xef,
+	0xce, 0xde, 0xce, 0xce,
+	0xde, 0xce, 0xce, 0xad, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+	0x21, 0x00, 0x08, 0x08,
+	0x10, 0x08, 0x08, 0x10, 0x4a, 0x52, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x4a, 0x52, 0x4a,
+	0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xf7, 0xe6,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef,
+	0xde, 0xef, 0xce, 0xde, 0xce, 0xef, 0xf7, 0xff, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x3a, 0x10,
+	0x21, 0x31, 0x31, 0x29, 0x31, 0x31, 0x29, 0x08, 0x08, 0x10, 0x10, 0x29,
+	0x19, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x29, 0x19,
+	0x3a, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x7b, 0x94,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0x4a,
+	0x52, 0x4a, 0x00, 0x00,
+	0x00, 0x10, 0x29, 0x19, 0x4a, 0x52, 0x4a, 0x31, 0x31, 0x29, 0x08, 0x08,
+	0x10, 0x3a, 0x31, 0x4a,
+	0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x4a, 0x52, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xce, 0xde,
+	0xce, 0x3a, 0x10, 0x21, 0x10, 0x29, 0x19, 0x3a, 0x31, 0x4a, 0x3a, 0x10,
+	0x21, 0x10, 0x21, 0x00,
+	0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x3a, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x9c, 0x7b, 0x94, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xe6, 0xde, 0xde, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0xe6, 0xef, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0x3a, 0x10, 0x21, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x29,
+	0x08, 0x08, 0x10, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x31, 0x31, 0x29, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x4a,
+	0x52, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xe6, 0xde, 0xde,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x52,
+	0x4a, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x31,
+	0x31, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31, 0x29, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0xe6, 0xde, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6,
+	0xe6, 0xde, 0xde, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xf7, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0x9c, 0x7b, 0x94,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x10, 0x29, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x52, 0x4a,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x10, 0x29, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xce,
+	0xe6, 0xef, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xa5, 0xb5, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x3a, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x31, 0x31, 0x29, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xf7, 0xff, 0xef,
+	0xf7, 0xe6, 0xe6, 0xde, 0xde, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xce, 0xde, 0xce, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x29, 0x19, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x31,
+	0x31, 0x29, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0xce, 0xad, 0xad, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef, 0xde, 0xef, 0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x29, 0x19, 0x08,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10,
+	0x21, 0x00, 0x3a, 0x31, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce,
+	0xe6, 0xef, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xf7, 0xff, 0xce, 0xe6, 0xef, 0xe6, 0xde, 0xde, 0xef,
+	0xf7, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x3a,
+	0x31, 0x4a, 0x08, 0x08,
+	0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x4a, 0x52, 0x4a, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xe6, 0xde, 0xde, 0xe6,
+	0xde, 0xde, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x4a, 0x52,
+	0x4a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x10, 0x21, 0x4a, 0x52, 0x4a, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce,
+	0xe6, 0xef, 0xe6, 0xde,
+	0xde, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x10, 0x29, 0x19, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x3a, 0x31, 0x4a, 0x6b,
+	0x7b, 0x73, 0x08, 0x00,
+	0x00, 0x10, 0x29, 0x19, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xe6, 0xde,
+	0xde, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x29, 0x19, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
+	0x29, 0x19, 0x6b, 0x5a,
+	0x73, 0x08, 0x00, 0x00, 0x10, 0x29, 0x19, 0xff, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xe6, 0xde, 0xde, 0xe6, 0xde, 0xde, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x31, 0x31, 0x29, 0x08, 0x00, 0x00, 0x31, 0x31, 0x29, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xff, 0xe6, 0xde, 0xde, 0xef, 0xf7, 0xe6, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xe6, 0xde, 0xde, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x10, 0x29, 0x19, 0x08, 0x08,
+	0x10, 0x08, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x31, 0x4a, 0x31, 0x31,
+	0x29, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xde, 0xde, 0xce, 0xe6,
+	0xef, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff, 0xff, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa5,
+	0xb5, 0xb5, 0x00, 0x00,
+	0x00, 0x10, 0x21, 0x00, 0x3a, 0x31, 0x4a, 0x10, 0x29, 0x19, 0x3a, 0x08,
+	0x00, 0x08, 0x08, 0x10,
+	0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x31, 0x31, 0x29, 0x10, 0x29, 0x19,
+	0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x10,
+	0x7b, 0x9c, 0x10, 0xc5,
+	0xef, 0x10, 0xc5, 0xef, 0x10, 0x7b, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x4a, 0x52, 0x4a,
+	0xef, 0xf7, 0xe6, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xde,
+	0xde, 0xef, 0xf7, 0xe6,
+	0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0x6b, 0x5a,
+	0x4a, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08, 0x00,
+	0x00, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x3a, 0x10, 0x21, 0x6b,
+	0x5a, 0x73, 0x10, 0x29, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+	0x94, 0xce, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad,
+	0xd6, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x4a, 0x5a, 0x73, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xe6, 0xde, 0xde,
+	0xef, 0xde, 0xef, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0xe6, 0xef, 0xce,
+	0xe6, 0xef, 0xce, 0xe6,
+	0xef, 0x08, 0x10, 0x42, 0x10, 0x29, 0x19, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x31, 0x31, 0x29, 0x4a, 0x52, 0x4a, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19,
+	0x7b, 0xbd, 0x00, 0x9c,
+	0xd6, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0x9c, 0xd6, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x4a, 0x52, 0x4a,
+	0xef, 0xde, 0xef, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff,
+	0xe6, 0xde, 0xde, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0x08, 0xad, 0xd6, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x08, 0x08, 0x10, 0x08, 0x08,
+	0x10, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x31, 0x31, 0x29, 0x10, 0x29, 0x19, 0x3a,
+	0x10, 0x21, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x84,
+	0xbd, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0x7b, 0xbd, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x31,
+	0x31, 0x29, 0xe6, 0xde, 0xde, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xce, 0xe6, 0xef, 0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0xe6, 0xef, 0x08,
+	0xad, 0xef, 0x00, 0xbd,
+	0xf7, 0x10, 0xe6, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xe6, 0xef, 0x08, 0x08,
+	0x10, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x29, 0x19, 0x10, 0x29, 0x19, 0x00,
+	0x00, 0x00, 0x00, 0x84,
+	0xbd, 0x10, 0xe6, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x19, 0x7b,
+	0xbd, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x10, 0xc5, 0xef,
+	0x10, 0x5a, 0x9c, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x29, 0x19, 0xce, 0xde, 0xce, 0xff,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe6, 0xde, 0xde, 0xef, 0xde, 0xef,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xce,
+	0xe6, 0xef, 0x00, 0x9c,
+	0xd6, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad,
+	0xd6, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x08, 0x31,
+	0x3a, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x10, 0xc5, 0xef, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x84,
+	0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad,
+	0xef, 0x00, 0xbd, 0xef,
+	0x19, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x00,
+	0xbd, 0xef, 0x08, 0x31, 0x3a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x9c, 0xa5,
+	0x94, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xce, 0xe6,
+	0xef, 0x08, 0xad, 0xd6, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0x94, 0xce,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x19, 0x94, 0xce, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xef, 0x10, 0xc5,
+	0xef, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x84, 0xbd, 0x00,
+	0x84, 0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x00, 0x84, 0xbd, 0x19,
+	0x94, 0xce, 0x00, 0x84,
+	0xbd, 0x08, 0xad, 0xd6, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xd6, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x4a, 0x52, 0x4a, 0xff, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xef, 0xde,
+	0xef, 0x9c, 0xde, 0xd6, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef,
+	0x00, 0x84, 0xbd, 0x08, 0x31, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x10, 0x5a, 0x9c, 0x08, 0xad, 0xd6, 0x00, 0xbd, 0xef, 0x10, 0xc5,
+	0xef, 0x10, 0xc5, 0xef,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x19,
+	0x94, 0xce, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x08,
+	0xad, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19,
+	0x7b, 0xbd, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x31,
+	0x29, 0xce, 0xe6, 0xef,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xce, 0xe6,
+	0xef, 0xce, 0xad, 0xad, 0x9c, 0xad, 0xce, 0x19, 0x94, 0xce, 0x08, 0xad,
+	0xef, 0x00, 0xbd, 0xef,
+	0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x10, 0x5a, 0x9c, 0x08, 0x08, 0x10,
+	0x00, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x08,
+	0x10, 0x10, 0x73, 0x7b, 0x00, 0x9c, 0xd6, 0x00, 0xbd, 0xef, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef,
+	0x00, 0xbd, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x84, 0xbd, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08,
+	0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xef, 0x10, 0xce,
+	0xce, 0x08, 0x31, 0x3a, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x08, 0x10, 0xce, 0xde, 0xce, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xc5, 0xad, 0xd6, 0xce, 0xde, 0xce, 0x9c, 0xad, 0xce, 0x08, 0xad,
+	0xd6, 0x08, 0xad, 0xef,
+	0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x00, 0x9c, 0xd6, 0x19, 0x7b, 0xbd,
+	0x10, 0x7b, 0x9c, 0x08,
+	0x31, 0x5a, 0x08, 0x31, 0x3a, 0x08, 0x08, 0x10, 0x08, 0x31, 0x3a, 0x08,
+	0x31, 0x3a, 0x10, 0x5a,
+	0x9c, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6, 0x19, 0x94, 0xce, 0x00, 0xbd,
+	0xef, 0x08, 0xad, 0xef,
+	0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x19, 0x7b, 0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x08,
+	0xad, 0xef, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7, 0x19, 0x94, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0x7b, 0x94,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xa5, 0xb5, 0xb5, 0xce, 0xde, 0xce, 0x9c, 0xad,
+	0xce, 0x19, 0x94, 0xce,
+	0x08, 0xad, 0xd6, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xd6, 0x00, 0x9c, 0xd6,
+	0x00, 0x9c, 0xd6, 0x00,
+	0x84, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x19,
+	0x7b, 0xbd, 0x00, 0x84,
+	0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xef, 0x08, 0xad,
+	0xef, 0x10, 0xc5, 0xef,
+	0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xef, 0x08, 0xad, 0xef,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xd6, 0x08,
+	0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xef, 0x10, 0x52,
+	0x7b, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x6b,
+	0x7b, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xef, 0xf7,
+	0xe6, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xce, 0xad, 0xad, 0xce, 0xde,
+	0xce, 0xa5, 0xb5, 0xb5,
+	0x00, 0x9c, 0xd6, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef,
+	0x19, 0x94, 0xce, 0x00,
+	0x9c, 0xd6, 0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x00,
+	0x84, 0xbd, 0x00, 0x84,
+	0xbd, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x10, 0xc5, 0xef, 0x19,
+	0x94, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x7b, 0xbd, 0x19,
+	0x94, 0xce, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x08,
+	0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xd6,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0xde, 0xce, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xce, 0xde,
+	0xce, 0xc5, 0xad, 0xd6,
+	0xa5, 0xb5, 0xb5, 0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xd6,
+	0x08, 0xad, 0xef, 0x08,
+	0xad, 0xef, 0x08, 0xad, 0xef, 0x00, 0x9c, 0xd6, 0x00, 0x9c, 0xd6, 0x00,
+	0x9c, 0xd6, 0x00, 0x9c,
+	0xd6, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x08,
+	0xad, 0xef, 0x08, 0xad, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x84, 0xbd, 0x00, 0x9c,
+	0xd6, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xef,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0x7b, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x5a, 0x73, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xce, 0xde, 0xce,
+	0xa5, 0xb5, 0xb5, 0x9c, 0xad, 0xce, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6,
+	0x08, 0xad, 0xef, 0x10,
+	0xc5, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x19,
+	0x94, 0xce, 0x08, 0xad,
+	0xef, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x08, 0xad,
+	0xef, 0x00, 0xbd, 0xef,
+	0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x10, 0x7b, 0xe6, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x00, 0xbd,
+	0xef, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x08,
+	0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08,
+	0xad, 0xef, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x10, 0xe6, 0xef, 0x00, 0xbd, 0xef, 0x08, 0x31, 0x3a,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a,
+	0x52, 0x4a, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xf7, 0xff,
+	0xe6, 0xde, 0xde, 0xc5, 0xad, 0xd6, 0x29, 0x5a, 0x4a, 0x00, 0x84, 0xbd,
+	0x19, 0x94, 0xce, 0x08,
+	0xad, 0xd6, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef,
+	0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x00,
+	0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x19, 0x94, 0xce, 0x08, 0xad, 0xd6, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x08, 0xad, 0xd6, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x9c, 0xa5,
+	0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7,
+	0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xff, 0xf7, 0xff,
+	0xef, 0xf7, 0xff, 0xce, 0xde, 0xce, 0x4a, 0x52, 0x4a, 0x08, 0x31, 0x5a,
+	0x00, 0x84, 0xbd, 0x00,
+	0x9c, 0xd6, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x08, 0xad,
+	0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xef, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef,
+	0x00, 0xbd, 0xef, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xef, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9c, 0xd6, 0x19, 0x94,
+	0xce, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10,
+	0xc5, 0xef, 0x00, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x10,
+	0xc5, 0xef, 0x10, 0x5a, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x9c, 0x7b,
+	0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4a, 0x52, 0x4a, 0x08, 0x00, 0x00,
+	0x08, 0x31, 0x5a, 0x00,
+	0x84, 0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08,
+	0xad, 0xef, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x94,
+	0xce, 0x00, 0x9c, 0xd6,
+	0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xd6, 0x10, 0x73, 0x7b, 0xe6,
+	0xde, 0xde, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0x31, 0x31, 0x29, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10,
+	0x52, 0x7b, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x08,
+	0xad, 0xef, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x08, 0xad, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x84, 0xbd,
+	0x00, 0x9c, 0xd6, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x08, 0xad, 0xef,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xd6, 0x10, 0xc5, 0xef, 0x19,
+	0x94, 0xce, 0x9c, 0xad,
+	0xce, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xef, 0xf7, 0xff, 0xef, 0xde, 0xef, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x10, 0x52, 0x7b, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x08,
+	0xad, 0xef, 0x08, 0xad,
+	0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x08,
+	0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x00, 0xbd, 0xf7,
+	0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x84, 0xbd,
+	0x00, 0x84, 0xbd, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x08, 0xad,
+	0xd6, 0x10, 0x7b, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff,
+	0xff, 0xef, 0xf7, 0xff,
+	0xff, 0xff, 0xff, 0x9c, 0xa5, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x10, 0x52, 0x7b, 0x00, 0x84, 0xbd, 0x08,
+	0xad, 0xd6, 0x00, 0xbd,
+	0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x19, 0x94, 0xce, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef,
+	0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x00,
+	0xbd, 0xef, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xd6, 0x00, 0x84, 0xbd, 0x10, 0x52, 0x7b, 0xef, 0xf7,
+	0xe6, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xff, 0xff, 0xf7, 0xff, 0xef, 0xf7, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xf7, 0xff,
+	0xce, 0xde, 0xce, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x52, 0x7b, 0x00,
+	0x84, 0xbd, 0x19, 0x94,
+	0xce, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x00, 0x9c, 0xd6, 0x19, 0x7b, 0xbd,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef,
+	0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x19, 0xbd,
+	0xf7, 0x00, 0xbd, 0xef, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xd6, 0x10, 0x52,
+	0x7b, 0x3a, 0x31, 0x4a,
+	0xef, 0xf7, 0xe6, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6,
+	0xff, 0xff, 0xff, 0xef,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xef, 0xf7, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xce, 0xde, 0xce,
+	0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0x10,
+	0x52, 0x7b, 0x00, 0x84,
+	0xbd, 0x00, 0x9c, 0xd6, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x00, 0xbd, 0xf7,
+	0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x08, 0xad, 0xef,
+	0x08, 0xad, 0xef, 0x19, 0x94, 0xce, 0x19, 0x94, 0xce, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x19, 0x7b, 0xbd, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xef,
+	0x10, 0xc5, 0xef, 0x00,
+	0xbd, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x00, 0xbd,
+	0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x00, 0x9c,
+	0xd6, 0x10, 0x7b, 0x9c,
+	0x08, 0x31, 0x5a, 0x00, 0x00, 0x00, 0x4a, 0x5a, 0x73, 0xce, 0xde, 0xce,
+	0xef, 0xf7, 0xe6, 0xff,
+	0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xef, 0xf7,
+	0xe6, 0xef, 0xf7, 0xff, 0xef, 0xf7, 0xe6, 0xa5, 0xb5, 0xb5, 0x6b, 0x5a,
+	0x73, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x31, 0x3a, 0x10, 0x52,
+	0x7b, 0x19, 0x7b, 0xbd, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xef, 0x10, 0xc5,
+	0xef, 0x19, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x08, 0xad, 0xef, 0x10,
+	0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef,
+	0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x19, 0x7b, 0xbd, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6,
+	0x19, 0x94, 0xce, 0x08,
+	0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xf7, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x00, 0xbd,
+	0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x19,
+	0xbd, 0xf7, 0x08, 0xad,
+	0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x08, 0xad,
+	0xd6, 0x19, 0x94, 0xce,
+	0x00, 0x84, 0xbd, 0x10, 0x52, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x08, 0x10, 0x10, 0x29, 0x19, 0x31, 0x31, 0x29, 0x31,
+	0x31, 0x29, 0x08, 0x08,
+	0x10, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x31,
+	0x3a, 0x10, 0x52, 0x7b, 0x00, 0x84, 0xbd, 0x00, 0x9c, 0xd6, 0x08, 0xad,
+	0xef, 0x10, 0xc5, 0xef,
+	0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x08, 0xad,
+	0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad,
+	0xef, 0x00, 0x84, 0xbd,
+	0x19, 0x94, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0xbd,
+	0x19, 0x94, 0xce, 0x00,
+	0x9c, 0xd6, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xef, 0x08, 0xad, 0xd6, 0x08,
+	0xad, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef,
+	0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef,
+	0x00, 0x9c, 0xd6, 0x10, 0x5a, 0x9c, 0x10, 0x52, 0x7b, 0x08, 0x31, 0x3a,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x00, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x31, 0x5a, 0x10, 0x5a, 0x9c, 0x00, 0x84, 0xbd, 0x19, 0x94,
+	0xce, 0x08, 0xad, 0xef,
+	0x08, 0xad, 0xef, 0x00, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7,
+	0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x00, 0xbd, 0xf7, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x10,
+	0xc5, 0xef, 0x00, 0xbd,
+	0xef, 0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x19, 0x94, 0xce, 0x00, 0x9c,
+	0xd6, 0x00, 0x84, 0xbd,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x7b, 0x9c, 0x00,
+	0x84, 0xbd, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x19,
+	0x94, 0xce, 0x00, 0x9c,
+	0xd6, 0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x08, 0xad, 0xd6, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xd6,
+	0x08, 0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef,
+	0x10, 0xc5, 0xef, 0x08,
+	0xad, 0xef, 0x19, 0xbd, 0xf7, 0x00, 0xbd, 0xf7, 0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x10, 0xc5, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00, 0xbd,
+	0xf7, 0x08, 0xad, 0xd6,
+	0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x10, 0x7b, 0x9c, 0x10, 0x52, 0x7b,
+	0x08, 0x31, 0x5a, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x3a, 0x10, 0x52, 0x7b, 0x00, 0x84,
+	0xbd, 0x00, 0x84, 0xbd,
+	0x08, 0xad, 0xd6, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x10, 0xc5, 0xef,
+	0x00, 0xbd, 0xf7, 0x10,
+	0xc5, 0xef, 0x08, 0xad, 0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xf7, 0x08, 0xad,
+	0xef, 0x19, 0x94, 0xce, 0x08, 0xad, 0xd6, 0x00, 0x9c, 0xd6, 0x00, 0x9c,
+	0xd6, 0x10, 0x5a, 0x9c,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x10,
+	0x5a, 0x9c, 0x00, 0x84,
+	0xbd, 0x19, 0x7b, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x19, 0x94,
+	0xce, 0x00, 0x84, 0xbd,
+	0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef,
+	0x19, 0x94, 0xce, 0x08,
+	0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xef, 0x19,
+	0xbd, 0xf7, 0x00, 0xbd,
+	0xef, 0x19, 0xbd, 0xf7, 0x08, 0xad, 0xef, 0x00, 0xbd, 0xf7, 0x10, 0xc5,
+	0xef, 0x08, 0xad, 0xef,
+	0x08, 0xad, 0xef, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x10, 0x5a, 0x9c,
+	0x10, 0x52, 0x7b, 0x08,
+	0x31, 0x3a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x5a, 0x10, 0x52,
+	0x7b, 0x00, 0x84, 0xbd,
+	0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x08, 0xad, 0xd6, 0x08, 0xad, 0xef,
+	0x19, 0xbd, 0xf7, 0x08,
+	0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x00,
+	0xbd, 0xef, 0x08, 0xad,
+	0xef, 0x19, 0x94, 0xce, 0x08, 0xad, 0xef, 0x00, 0x84, 0xbd, 0x00, 0x84,
+	0xbd, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x7b, 0x10, 0x5a, 0x9c, 0x10, 0x7b,
+	0x9c, 0x10, 0x5a, 0xbd,
+	0x00, 0x84, 0xbd, 0x10, 0x7b, 0x9c, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd,
+	0x00, 0x84, 0xbd, 0x00,
+	0x84, 0xbd, 0x00, 0x84, 0xbd, 0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x08,
+	0xad, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xef,
+	0x08, 0xad, 0xd6, 0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x10, 0x5a, 0x9c,
+	0x10, 0x52, 0x7b, 0x10,
+	0x52, 0x7b, 0x08, 0x31, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x08, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x21, 0x00, 0x08,
+	0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31,
+	0x3a, 0x10, 0x52, 0x7b,
+	0x10, 0x5a, 0x9c, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x08, 0xad, 0xef,
+	0x08, 0xad, 0xd6, 0x08,
+	0xad, 0xef, 0x08, 0xad, 0xef, 0x10, 0xc5, 0xef, 0x08, 0xad, 0xef, 0x08,
+	0xad, 0xef, 0x19, 0x94,
+	0xce, 0x00, 0x9c, 0xd6, 0x00, 0x84, 0xbd, 0x19, 0x7b, 0xbd, 0x10, 0x5a,
+	0x9c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x10, 0x5a, 0x9c, 0x10, 0x52, 0x7b, 0x10, 0x5a, 0x9c,
+	0x10, 0x5a, 0x9c, 0x10,
+	0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x7b, 0x9c, 0x00, 0x84, 0xbd, 0x00,
+	0x84, 0xbd, 0x19, 0x94,
+	0xce, 0x00, 0x9c, 0xd6, 0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x08, 0xad,
+	0xef, 0x08, 0xad, 0xd6,
+	0x19, 0x94, 0xce, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x10, 0x5a, 0x9c,
+	0x10, 0x52, 0x7b, 0x10,
+	0x52, 0x7b, 0x08, 0x31, 0x5a, 0x08, 0x08, 0x10, 0x08, 0x08, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x31, 0x3a,
+	0x08, 0x31, 0x5a, 0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x19, 0x7b, 0xbd,
+	0x00, 0x84, 0xbd, 0x00,
+	0x9c, 0xd6, 0x08, 0xad, 0xd6, 0x19, 0x94, 0xce, 0x00, 0x9c, 0xd6, 0x19,
+	0x94, 0xce, 0x00, 0x9c,
+	0xd6, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x10, 0x5a,
+	0x9c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x10, 0x52, 0x7b, 0x10, 0x52, 0x7b, 0x10, 0x5a, 0x9c, 0x10,
+	0x5a, 0x9c, 0x10, 0x5a,
+	0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x7b, 0x9c, 0x00, 0x84, 0xbd, 0x19, 0x7b,
+	0xbd, 0x00, 0x84, 0xbd,
+	0x19, 0x7b, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x10, 0x5a, 0x9c,
+	0x10, 0x52, 0x7b, 0x10,
+	0x52, 0x7b, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x5a, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x08, 0x31, 0x5a, 0x10, 0x5a, 0x9c, 0x10, 0x7b, 0x9c,
+	0x00, 0x84, 0xbd, 0x00,
+	0x84, 0xbd, 0x19, 0x7b, 0xbd, 0x00, 0x84, 0xbd, 0x00, 0x84, 0xbd, 0x00,
+	0x84, 0xbd, 0x00, 0x84,
+	0xbd, 0x19, 0x7b, 0xbd, 0x10, 0x7b, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x52,
+	0x7b, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x08, 0x31, 0x5a, 0x10, 0x52, 0x7b, 0x10, 0x52, 0x7b, 0x10, 0x5a,
+	0x9c, 0x10, 0x73, 0x7b,
+	0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x52, 0x7b,
+	0x10, 0x52, 0x7b, 0x10,
+	0x52, 0x7b, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x3a, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x5a,
+	0x10, 0x52, 0x7b, 0x10,
+	0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x7b, 0x9c, 0x10, 0x5a, 0x9c, 0x00,
+	0x84, 0xbd, 0x00, 0x84,
+	0xbd, 0x10, 0x7b, 0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x08, 0x31,
+	0x5a, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31,
+	0x5a, 0x10, 0x52, 0x7b,
+	0x08, 0x31, 0x5a, 0x10, 0x52, 0x7b, 0x10, 0x52, 0x7b, 0x08, 0x31, 0x5a,
+	0x10, 0x52, 0x7b, 0x08,
+	0x31, 0x5a, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x3a, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x08, 0x31, 0x5a, 0x08,
+	0x31, 0x5a, 0x10, 0x52, 0x7b, 0x10, 0x5a, 0x9c, 0x10, 0x5a, 0x9c, 0x10,
+	0x5a, 0x9c, 0x10, 0x5a,
+	0x9c, 0x10, 0x5a, 0x9c, 0x10, 0x52, 0x7b, 0x10, 0x52, 0x7b, 0x08, 0x31,
+	0x5a, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x5a,
+	0x08, 0x31, 0x5a, 0x08,
+	0x31, 0x5a, 0x08, 0x31, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x31, 0x3a, 0x08, 0x31, 0x5a, 0x08,
+	0x31, 0x5a, 0x10, 0x52,
+	0x7b, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x5a, 0x08, 0x31, 0x3a, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,
+};
+
+#endif
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c
index aca1790..d0b8f98 100644
--- a/fs/ext4/ext4_jbd2.c
+++ b/fs/ext4/ext4_jbd2.c
@@ -109,10 +109,10 @@
 
 	if (ext4_handle_valid(handle)) {
 		err = jbd2_journal_dirty_metadata(handle, bh);
-		if (err) {
-			/* Errors can only happen if there is a bug */
-			handle->h_err = err;
-			__ext4_journal_stop(where, line, handle);
+		/* Errors can only happen if there is a bug */
+		if (WARN_ON_ONCE(err)) {
+			ext4_journal_abort_handle(where, line, __func__, bh,
+						  handle, err);
 		}
 	} else {
 		if (inode)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e1fb1d5..48609bc 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -4105,6 +4105,7 @@
 		ext4_commit_super(sb, 1);
 
 		jbd2_journal_clear_err(journal);
+		jbd2_journal_update_sb_errno(journal);
 	}
 }
 
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index e88748e..6c27436 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -1267,6 +1267,8 @@
 				    s_min_extra_isize) {
 					tried_min_extra_isize++;
 					new_extra_isize = s_min_extra_isize;
+					kfree(is); is = NULL;
+					kfree(bs); bs = NULL;
 					goto retry;
 				}
 				error = -1;
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 1cc7038..bab81ca 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -294,8 +294,9 @@
 	if (ret < 0)
 		return ret;
 	else if (ret == FAT_ENT_EOF) {
-		fat_fs_error(sb, "%s: request beyond EOF (i_pos %lld)",
-			     __func__, MSDOS_I(inode)->i_pos);
+		fat_fs_error_ratelimit(sb,
+				       "%s: request beyond EOF (i_pos %lld)",
+				       __func__, MSDOS_I(inode)->i_pos);
 		return -EIO;
 	}
 	return dclus;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 6b83222..837a6e3 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -692,6 +692,8 @@
 		lock_page(newpage);
 		put_page(newpage);
 
+		lru_cache_add_file(newpage);
+
 		/* finally release the old page and swap pointers */
 		unlock_page(oldpage);
 		page_cache_release(oldpage);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 1afb701..9956ac6 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1340,7 +1340,7 @@
  * Update a journal's errno.  Write updated superblock to disk waiting for IO
  * to complete.
  */
-static void jbd2_journal_update_sb_errno(journal_t *journal)
+void jbd2_journal_update_sb_errno(journal_t *journal)
 {
 	journal_superblock_t *sb = journal->j_superblock;
 
@@ -1352,6 +1352,7 @@
 
 	jbd2_write_superblock(journal, WRITE_SYNC);
 }
+EXPORT_SYMBOL(jbd2_journal_update_sb_errno);
 
 /*
  * Read the superblock for a given journal, performing initial
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 4640d3b..6d18d0f 100755
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -146,6 +146,7 @@
 header-y += genetlink.h
 header-y += gfs2_ondisk.h
 header-y += gigaset_dev.h
+header-y += hbtp_input.h
 header-y += hdlc.h
 header-y += hdlcdrv.h
 header-y += hdreg.h
diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
index 130d0fd..ac750ea 100644
--- a/include/linux/blk_types.h
+++ b/include/linux/blk_types.h
@@ -176,6 +176,8 @@
 	 REQ_SANITIZE)
 #define REQ_CLONE_MASK		REQ_COMMON_MASK
 
+#define MMC_REQ_NOREINSERT_MASK (REQ_URGENT | REQ_FUA | REQ_FLUSH)
+
 #define REQ_RAHEAD		(1 << __REQ_RAHEAD)
 #define REQ_THROTTLED		(1 << __REQ_THROTTLED)
 
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index d00847a..70b3eef 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -51,6 +51,7 @@
  * bound (greatest lower bound)
  */
 #define DEVFREQ_FLAG_LEAST_UPPER_BOUND		0x1
+#define DEVFREQ_FLAG_WAKEUP_MAXFREQ		0x2
 
 #define DEVFREQ_FLAG_FAST_HINT	0x2
 #define DEVFREQ_FLAG_SLOW_HINT	0x4
@@ -227,6 +228,9 @@
  *			the governor may consider slowing the frequency down.
  *			Specify 0 to use the default. Valid value = 0 to 100.
  *			downdifferential < upthreshold must hold.
+ * @simple_scaling:	Setting this flag will scale the clocks up only if the
+ *			load is above @upthreshold and will scale the clocks
+ *			down only if the load is below @downdifferential.
  *
  * If the fed devfreq_simple_ondemand_data pointer is NULL to the governor,
  * the governor uses the default values.
@@ -234,6 +238,7 @@
 struct devfreq_simple_ondemand_data {
 	unsigned int upthreshold;
 	unsigned int downdifferential;
+	unsigned int simple_scaling;
 };
 #endif
 
diff --git a/include/linux/hbtp_input.h b/include/linux/hbtp_input.h
new file mode 100644
index 0000000..2c3798e
--- /dev/null
+++ b/include/linux/hbtp_input.h
@@ -0,0 +1,46 @@
+#ifndef _HBTP_INPUT_H
+#define _HBTP_INPUT_H
+
+#include <linux/input.h>
+
+#define HBTP_MAX_FINGER		10
+
+struct hbtp_input_touch {
+	bool active;
+	__s32 tool;
+	__s32 x;
+	__s32 y;
+	__s32 pressure;
+	__s32 major;
+	__s32 minor;
+	__s32 orientation;
+};
+
+struct hbtp_input_mt {
+	__s32 num_touches;
+	struct hbtp_input_touch touches[HBTP_MAX_FINGER];
+};
+
+struct hbtp_input_absinfo {
+	bool  active;
+	__u16 code;
+	__s32 minimum;
+	__s32 maximum;
+};
+
+enum hbtp_afe_power_cmd {
+	HBTP_AFE_POWER_ON,
+	HBTP_AFE_POWER_OFF,
+};
+
+/* ioctl */
+#define HBTP_INPUT_IOCTL_BASE	'T'
+#define HBTP_SET_ABSPARAM	_IOW(HBTP_INPUT_IOCTL_BASE, 201, \
+					struct hbtp_input_absinfo *)
+#define HBTP_SET_TOUCHDATA	_IOW(HBTP_INPUT_IOCTL_BASE, 202, \
+					struct hbtp_input_mt)
+#define HBTP_SET_POWERSTATE	_IOW(HBTP_INPUT_IOCTL_BASE, 203, \
+					enum hbtp_afe_power_cmd)
+
+#endif	/* _HBTP_INPUT_H */
+
diff --git a/arch/arm/boot/dts/msm8926-qrd.dts b/include/linux/i2c/i2c-qup.h
similarity index 62%
copy from arch/arm/boot/dts/msm8926-qrd.dts
copy to include/linux/i2c/i2c-qup.h
index 8ee8828..a950864 100644
--- a/arch/arm/boot/dts/msm8926-qrd.dts
+++ b/include/linux/i2c/i2c-qup.h
@@ -1,4 +1,5 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2014, 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
@@ -10,12 +11,13 @@
  * GNU General Public License for more details.
  */
 
-/dts-v1/;
-/include/ "msm8926.dtsi"
-/include/ "msm8226-qrd.dtsi"
+#ifndef __I2C_QUP_H__
+#define __I2C_QUP_H__
 
-/ {
-	model = "Qualcomm MSM 8926 QRD";
-	compatible = "qcom,msm8926-qrd", "qcom,msm8926", "qcom,qrd";
-	qcom,board-id = <11 0>;
-};
+#ifdef CONFIG_I2C_QUP
+int __init qup_i2c_init_driver(void);
+#else
+static inline int __init qup_i2c_init_driver(void) { return 0; }
+#endif
+
+#endif /* __I2C_QUP_H__ */
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 912c30a..2ed66ef 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1091,6 +1091,7 @@
 extern int	   jbd2_journal_recover    (journal_t *journal);
 extern int	   jbd2_journal_wipe       (journal_t *, int);
 extern int	   jbd2_journal_skip_recovery	(journal_t *);
+extern void	   jbd2_journal_update_sb_errno(journal_t *);
 extern void	   jbd2_journal_update_sb_log_tail	(journal_t *, tid_t,
 				unsigned long, int);
 extern void	   __jbd2_journal_abort_hard	(journal_t *);
diff --git a/include/linux/mfd/wcd9xxx/core-resource.h b/include/linux/mfd/wcd9xxx/core-resource.h
index 442496e..b45cf6a 100644
--- a/include/linux/mfd/wcd9xxx/core-resource.h
+++ b/include/linux/mfd/wcd9xxx/core-resource.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -67,6 +67,8 @@
 				unsigned short, u8);
 	int (*codec_bulk_read) (struct wcd9xxx_core_resource *,
 				unsigned short, int, u8 *);
+	int (*codec_bulk_write) (struct wcd9xxx_core_resource *,
+				unsigned short, int, u8 *);
 
 	/* Pointer to parent container data structure */
 	void *parent;
@@ -80,6 +82,8 @@
 	int (*codec_read)(struct wcd9xxx_core_resource *, unsigned short),
 	int (*codec_write)(struct wcd9xxx_core_resource *, unsigned short, u8),
 	int (*codec_bulk_read) (struct wcd9xxx_core_resource *, unsigned short,
+							int, u8 *),
+	int (*codec_bulk_write) (struct wcd9xxx_core_resource *, unsigned short,
 							int, u8 *));
 
 extern void wcd9xxx_core_res_deinit(
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 43aebb5..1740576 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -352,6 +352,9 @@
 #define MMC_QUIRK_INAND_DATA_TIMEOUT  (1<<8)    /* For incorrect data timeout */
 /* To avoid eMMC device getting broken permanently due to HPI feature */
 #define MMC_QUIRK_BROKEN_HPI (1 << 11)
+ /* Skip data-timeout advertised by card */
+#define MMC_QUIRK_BROKEN_DATA_TIMEOUT	(1<<12)
+
 
 	unsigned int		erase_size;	/* erase size in sectors */
  	unsigned int		erase_shift;	/* if erase unit is power 2 */
diff --git a/include/linux/msm_hdmi.h b/include/linux/msm_hdmi.h
new file mode 100644
index 0000000..70fae94
--- /dev/null
+++ b/include/linux/msm_hdmi.h
@@ -0,0 +1,57 @@
+/* include/linux/msm_hdmi.h
+ *
+ * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _MSM_HDMI_H_
+#define _MSM_HDMI_H_
+
+/*
+ * HDMI cable notify handler sturcture.
+ * link A link for the linked list
+ * status Current status of HDMI cable connection
+ * hpd_notify Callback function to provide cable status
+ */
+struct hdmi_cable_notify {
+	struct list_head link;
+	int status;
+	void (*hpd_notify) (struct hdmi_cable_notify *h);
+};
+
+#ifdef CONFIG_FB_MSM_MDSS_HDMI_PANEL
+/*
+ * Register for HDMI cable connect or disconnect notification.
+ * @param handler callback handler for notification
+ * @return negative value as error otherwise current status of cable
+ */
+int register_hdmi_cable_notification(
+		struct hdmi_cable_notify *handler);
+
+/*
+ * Un-register for HDMI cable connect or disconnect notification.
+ * @param handler callback handler for notification
+ * @return negative value as error
+ */
+int unregister_hdmi_cable_notification(
+		struct hdmi_cable_notify *handler);
+#else
+int register_hdmi_cable_notification(
+		struct hdmi_cable_notify *handler) {
+	return 0;
+}
+
+int unregister_hdmi_cable_notification(
+		struct hdmi_cable_notify *handler) {
+	return 0;
+}
+#endif /* CONFIG_FB_MSM_MDSS_HDMI_PANEL */
+
+#endif /*_MSM_HDMI_H_*/
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index f74fcbe..17986b5 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -24,6 +24,7 @@
 
 #define KGSL_CONTEXT_NO_FAULT_TOLERANCE 0x00000200
 #define KGSL_CONTEXT_SYNC               0x00000400
+#define KGSL_CONTEXT_PWR_CONSTRAINT     0x00000800
 /* bits [12:15] are reserved for future use */
 #define KGSL_CONTEXT_TYPE_MASK          0x01F00000
 #define KGSL_CONTEXT_TYPE_SHIFT         20
@@ -197,6 +198,7 @@
 	KGSL_PROP_VERSION         = 0x00000008,
 	KGSL_PROP_GPU_RESET_STAT  = 0x00000009,
 	KGSL_PROP_PWRCTRL         = 0x0000000E,
+	KGSL_PROP_PWR_CONSTRAINT  = 0x00000012,
 };
 
 struct kgsl_shadowprop {
@@ -882,6 +884,34 @@
 #define IOCTL_KGSL_SUBMIT_COMMANDS \
 	_IOWR(KGSL_IOC_TYPE, 0x3D, struct kgsl_submit_commands)
 
+/**
+ * struct kgsl_device_constraint - device constraint argument
+ * @context_id: KGSL context ID
+ * @type: type of constraint i.e pwrlevel/none
+ * @data: constraint data
+ * @size: size of the constraint data
+ */
+struct kgsl_device_constraint {
+	unsigned int type;
+	unsigned int context_id;
+	void __user *data;
+	size_t size;
+};
+
+/* Constraint Type*/
+#define KGSL_CONSTRAINT_NONE 0
+#define KGSL_CONSTRAINT_PWRLEVEL 1
+
+/* PWRLEVEL constraint level*/
+/* set to min frequency */
+#define KGSL_CONSTRAINT_PWR_MIN    0
+/* set to max frequency */
+#define KGSL_CONSTRAINT_PWR_MAX    1
+
+struct kgsl_device_constraint_pwrlevel {
+	unsigned int level;
+};
+
 #ifdef __KERNEL__
 #ifdef CONFIG_MSM_KGSL_DRM
 int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 0791545..f36ee04 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -169,7 +169,7 @@
 #define MDP_BLUR 0x10
 #define MDP_BLEND_FG_PREMULT 0x20000
 #define MDP_IS_FG 0x40000
-#define MDP_SOLID_FILL 0x0000100
+#define MDP_SOLID_FILL 0x00000020
 #define MDP_DEINTERLACE 0x80000000
 #define MDP_SHARPENING  0x40000000
 #define MDP_NO_DMA_BARRIER_START	0x20000000
@@ -422,7 +422,7 @@
 	uint32_t val_region;
 };
 
-#define MDP_SIX_ZONE_TABLE_NUM		384
+#define MDP_SIX_ZONE_LUT_SIZE		384
 
 struct mdp_pa_v2_data {
 	/* Mask bits for PA features */
@@ -431,12 +431,13 @@
 	uint32_t global_sat_adj;
 	uint32_t global_val_adj;
 	uint32_t global_cont_adj;
-	uint32_t *six_zone_curve_p0;
-	uint32_t *six_zone_curve_p1;
-	uint32_t six_zone_thresh;
 	struct mdp_pa_mem_col_cfg skin_cfg;
 	struct mdp_pa_mem_col_cfg sky_cfg;
 	struct mdp_pa_mem_col_cfg fol_cfg;
+	uint32_t six_zone_len;
+	uint32_t six_zone_thresh;
+	uint32_t *six_zone_curve_p0;
+	uint32_t *six_zone_curve_p1;
 };
 
 struct mdp_igc_lut_data {
@@ -983,6 +984,7 @@
 
 #define MDP_MAX_FENCE_FD	32
 #define MDP_BUF_SYNC_FLAG_WAIT	1
+#define MDP_BUF_SYNC_FLAG_RETIRE_FENCE	0x10
 
 struct mdp_buf_sync {
 	uint32_t flags;
@@ -990,6 +992,7 @@
 	uint32_t session_id;
 	int *acq_fen_fd;
 	int *rel_fen_fd;
+	int *retire_fen_fd;
 };
 
 struct mdp_async_blit_req_list {
@@ -999,19 +1002,11 @@
 };
 
 #define MDP_DISPLAY_COMMIT_OVERLAY	1
-struct mdp_buf_fence {
-	uint32_t flags;
-	uint32_t acq_fen_fd_cnt;
-	int acq_fen_fd[MDP_MAX_FENCE_FD];
-	int rel_fen_fd[MDP_MAX_FENCE_FD];
-};
-
 
 struct mdp_display_commit {
 	uint32_t flags;
 	uint32_t wait_for_finish;
 	struct fb_var_screeninfo var;
-	struct mdp_buf_fence buf_fence;
 	struct mdp_rect roi;
 };
 
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index dcc2353..4ce3db1 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -59,6 +59,7 @@
 #define VEN_EXTRADATA_QCOMFILLER    0x002
 #define VEN_EXTRADATA_SLICEINFO     0x100
 #define VEN_EXTRADATA_LTRINFO       0x200
+#define VEN_EXTRADATA_MBINFO        0x400
 
 /*ENCODER CONFIGURATION CONSTANTS*/
 
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6a68b72..7be6cd2 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1380,6 +1380,28 @@
  *	allowed to be used with the first @NL80211_CMD_SET_STATION command to
  *	update a TDLS peer STA entry.
  *
+ * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information.
+ *
+ * @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's
+ *	until the channel switch event.
+ * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission
+ *	must be blocked on the current channel (before the channel switch
+ *	operation).
+ * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information
+ *	for the time while performing a channel switch.
+ * @NL80211_ATTR_CSA_C_OFF_BEACON: Offset of the channel switch counter
+ *	field in the beacons tail (%NL80211_ATTR_BEACON_TAIL).
+ * @NL80211_ATTR_CSA_C_OFF_PRESP: Offset of the channel switch counter
+ *	field in the probe response (%NL80211_ATTR_PROBE_RESP).
+ *
+ * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32.
+ *	As specified in the &enum nl80211_rxmgmt_flags.
+ *
+ * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels.
+ *
+ * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported
+ *      supported operating classes.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1680,6 +1702,19 @@
 
 	NL80211_ATTR_PEER_AID,
 
+	NL80211_ATTR_COALESCE_RULE,
+
+	NL80211_ATTR_CH_SWITCH_COUNT,
+	NL80211_ATTR_CH_SWITCH_BLOCK_TX,
+	NL80211_ATTR_CSA_IES,
+	NL80211_ATTR_CSA_C_OFF_BEACON,
+	NL80211_ATTR_CSA_C_OFF_PRESP,
+
+	NL80211_ATTR_RXMGMT_FLAGS,
+
+	NL80211_ATTR_STA_SUPPORTED_CHANNELS,
+
+	NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES,
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index ddbb6a9..289754e 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -254,8 +254,9 @@
 
 				exclude_host   :  1, /* don't count in host   */
 				exclude_guest  :  1, /* don't count in guest  */
+				constraint_duplicate : 1,
 
-				__reserved_1   : 43;
+				__reserved_1   : 42;
 
 	union {
 		__u32		wakeup_events;	  /* wakeup every n events */
@@ -740,6 +741,8 @@
 	int * __percpu			pmu_disable_count;
 	struct perf_cpu_context * __percpu pmu_cpu_context;
 	int				task_ctx_nr;
+	u32                             events_across_hotplug:1,
+					reserved:31;
 
 	/*
 	 * Fully disable/enable this PMU, can be used to protect from the PMI
diff --git a/include/linux/qpnp/power-on.h b/include/linux/qpnp/power-on.h
index 772bf62..ae4e731 100644
--- a/include/linux/qpnp/power-on.h
+++ b/include/linux/qpnp/power-on.h
@@ -52,6 +52,7 @@
 int qpnp_pon_system_pwr_off(enum pon_power_off_type type);
 int qpnp_pon_is_warm_reset(void);
 int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable);
+int qpnp_pon_wd_config(bool enable);
 #else
 static int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
 {
@@ -63,6 +64,10 @@
 {
 	return -ENODEV;
 }
+int qpnp_pon_wd_config(bool enable)
+{
+	return -ENODEV;
+}
 #endif
 
 #endif
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 6e711c2..2b47b88 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2014, 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
@@ -190,6 +190,7 @@
  * %CHAN_PATH_SCALING2: ratio of {1, 4}
  * %CHAN_PATH_SCALING3: ratio of {1, 6}
  * %CHAN_PATH_SCALING4: ratio of {1, 20}
+ * %CHAN_PATH_SCALING5: ratio of {1, 8}
  * %CHAN_PATH_NONE: Do not use this pre-scaling ratio type.
  *
  * The pre-scaling is applied for signals to be within the voltage range
@@ -201,6 +202,7 @@
 	PATH_SCALING2,
 	PATH_SCALING3,
 	PATH_SCALING4,
+	PATH_SCALING5,
 	PATH_SCALING_NONE,
 };
 
@@ -220,6 +222,8 @@
  *			btm parameters.
  * %SCALE_QRD_SKUAA_BATT_THERM: Conversion to temperature(decidegC) based on
  *          btm parametersi for SKUAA.
+ * %SCALE_QRD_SKUG_BATT_THERM: Conversion to temperature(decidegC) based on
+ * btm parametersi for SKUG.
  * %SCALE_NONE: Do not use this scaling type.
  */
 enum qpnp_adc_scale_fn_type {
@@ -231,6 +235,7 @@
 	SCALE_THERM_150K_PULLUP,
 	SCALE_QRD_BATT_THERM,
 	SCALE_QRD_SKUAA_BATT_THERM,
+	SCALE_QRD_SKUG_BATT_THERM = 9,
 	SCALE_NONE,
 };
 
@@ -890,7 +895,8 @@
 	{1, 3},
 	{1, 4},
 	{1, 6},
-	{1, 20}
+	{1, 20},
+	{1, 8}
 };
 
 /**
@@ -1135,6 +1141,23 @@
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
 /**
+ * qpnp_adc_scale_qrd_skug_batt_therm() - Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. Returns the temperature in decidegC.
+ * @dev:	Structure device for qpnp vadc
+ * @adc_code:	pre-calibrated digital ouput of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_qrd_skug_batt_therm(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
  * qpnp_adc_scale_batt_id() - Scales the pre-calibrated digital output
  *		of an ADC to the ADC reference and compensates for the
  *		gain and offset.
@@ -1388,6 +1411,12 @@
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
+static inline int32_t qpnp_adc_scale_qrd_skug_batt_therm(
+			struct qpnp_vadc_chip *vadc, int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
 static inline int32_t qpnp_adc_scale_batt_id(struct qpnp_vadc_chip *vadc,
 			int32_t adc_code,
 			const struct qpnp_adc_properties *adc_prop,
diff --git a/include/linux/qrng.h b/include/linux/qrng.h
index 35708e3..8c09627 100644
--- a/include/linux/qrng.h
+++ b/include/linux/qrng.h
@@ -1,5 +1,5 @@
-#ifndef __QRNG_H_
-#define __QRNG_H_
+#ifndef _QRNG_H_
+#define _QRNG_H_
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
@@ -9,4 +9,4 @@
 #define QRNG_IOCTL_RESET_BUS_BANDWIDTH\
 	_IO(QRNG_IOC_MAGIC, 1)
 
-#endif /* __QRNG_H_ */
+#endif /* _QRNG_H_ */
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index a45c34c..b7ba63a 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -127,6 +127,7 @@
 
 enum qseecom_key_management_usage_type {
 	QSEOS_KM_USAGE_DISK_ENCRYPTION = 0x01,
+	QSEOS_KM_USAGE_MAX
 };
 
 struct qseecom_create_key_req {
@@ -138,6 +139,12 @@
 	enum qseecom_key_management_usage_type usage;
 };
 
+struct qseecom_update_key_userinfo_req {
+	unsigned char current_hash32[QSEECOM_HASH_SIZE];
+	unsigned char new_hash32[QSEECOM_HASH_SIZE];
+	enum qseecom_key_management_usage_type usage;
+};
+
 #define SHA256_DIGEST_LENGTH	(256/8)
 /*
  * struct qseecom_save_partition_hash_req
@@ -157,11 +164,6 @@
 	int is_activated; /* out */
 };
 
-enum qseecom_buffer_protection {
-	QSEOS_UNPROTECTED_BUFFER,
-	QSEOS_PROTECT_BUFFER,
-	QSEOS_UNPROTECT_PROTECTED_BUFFER,
-};
 
 enum qseecom_bandwidth_request_mode {
 	INACTIVE = 0,
@@ -181,7 +183,6 @@
 	void *resp_buf_ptr; /* in */
 	unsigned int resp_len; /* in */
 	struct qseecom_ion_fd_info ifd_data[MAX_ION_FD]; /* in */
-	enum qseecom_buffer_protection protection_mode; /* in */
 };
 
 #define QSEECOM_IOC_MAGIC    0x97
@@ -250,10 +251,10 @@
 #define QSEECOM_IOCTL_SEND_MODFD_RESP \
 	_IOWR(QSEECOM_IOC_MAGIC, 21, struct qseecom_send_modfd_listener_resp)
 
-#define QSEECOM_IOCTL_UNPROTECT_BUF \
-	_IOWR(QSEECOM_IOC_MAGIC, 22, int)
-
 #define QSEECOM_IOCTL_SET_BUS_SCALING_REQ \
 	_IOWR(QSEECOM_IOC_MAGIC, 23, int)
 
+#define QSEECOM_IOCTL_UPDATE_KEY_USER_INFO_REQ \
+	_IOWR(QSEECOM_IOC_MAGIC, 24, struct qseecom_update_key_userinfo_req)
+
 #endif /* __QSEECOM_H_ */
diff --git a/include/linux/regulator/cpr-regulator.h b/include/linux/regulator/cpr-regulator.h
index 2e2d931..3b23d17 100644
--- a/include/linux/regulator/cpr-regulator.h
+++ b/include/linux/regulator/cpr-regulator.h
@@ -16,7 +16,7 @@
 
 #include <linux/regulator/machine.h>
 
-#define CPR_REGULATOR_DRIVER_NAME	"qti,cpr-regulator"
+#define CPR_REGULATOR_DRIVER_NAME	"qcom,cpr-regulator"
 
 #define CPR_PVS_EFUSE_BITS_MAX		5
 #define CPR_PVS_EFUSE_BINS_MAX		(1 << CPR_PVS_EFUSE_BITS_MAX)
diff --git a/include/linux/regulator/fan53555.h b/include/linux/regulator/fan53555.h
new file mode 100644
index 0000000..bb22419
--- /dev/null
+++ b/include/linux/regulator/fan53555.h
@@ -0,0 +1,66 @@
+/*
+ * fan53555.h - Fairchild Regulator FAN53555 Driver
+ *
+ * Copyright (C) 2012 Marvell Technology Ltd.
+ * Yunfan Zhang <yfzhang@marvell.com>
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __FAN53555_H__
+
+/* VSEL ID */
+enum {
+	FAN53555_VSEL_ID_0 = 0,
+	FAN53555_VSEL_ID_1,
+};
+
+/* Transition slew rate limiting from a low to high voltage.
+ * -----------------------
+ *   Bin |Slew Rate(mV/uS)
+ * ------|----------------
+ *   000 |    64.00
+ * ------|----------------
+ *   001 |    32.00
+ * ------|----------------
+ *   010 |    16.00
+ * ------|----------------
+ *   011 |     8.00
+ * ------|----------------
+ *   100 |     4.00
+ * ------|----------------
+ *   101 |     2.00
+ * ------|----------------
+ *   110 |     1.00
+ * ------|----------------
+ *   111 |     0.50
+ * -----------------------
+ */
+enum {
+	FAN53555_SLEW_RATE_64MV = 0,
+	FAN53555_SLEW_RATE_32MV,
+	FAN53555_SLEW_RATE_16MV,
+	FAN53555_SLEW_RATE_8MV,
+	FAN53555_SLEW_RATE_4MV,
+	FAN53555_SLEW_RATE_2MV,
+	FAN53555_SLEW_RATE_1MV,
+	FAN53555_SLEW_RATE_0_5MV,
+};
+
+struct fan53555_platform_data {
+	struct regulator_init_data *regulator;
+	unsigned int slew_rate;
+	/* Sleep VSEL ID */
+	unsigned int sleep_vsel_id;
+};
+
+#ifdef CONFIG_REGULATOR_FAN53555
+int __init fan53555_regulator_init(void);
+#else
+static inline int __init fan53555_regulator_init(void) { return 0; }
+#endif
+
+#endif /* __FAN53555_H__ */
diff --git a/include/linux/regulator/onsemi-ncp6335d.h b/include/linux/regulator/onsemi-ncp6335d.h
index 98a5fea..399742f 100644
--- a/include/linux/regulator/onsemi-ncp6335d.h
+++ b/include/linux/regulator/onsemi-ncp6335d.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -26,4 +26,10 @@
 	bool sleep_enable;
 };
 
+#ifdef CONFIG_REGULATOR_ONSEMI_NCP6335D
+int __init ncp6335d_regulator_init(void);
+#else
+static inline int __init ncp6335d_regulator_init(void) { return 0; }
+#endif
+
 #endif
diff --git a/include/linux/remote_spinlock.h b/include/linux/remote_spinlock.h
index e39846f..49d19ed 100644
--- a/include/linux/remote_spinlock.h
+++ b/include/linux/remote_spinlock.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, 2011, 2013 The Linux Foundation.
+/* Copyright (c) 2008-2009, 2011, 2013-2014 The Linux Foundation.
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -83,6 +83,11 @@
 				0; }) \
 		: 0; \
 	})
+#define remote_spin_lock_rlock_id(lock, tid) \
+	_remote_spin_lock_rlock_id(&((lock)->remote), tid)
+
+#define remote_spin_unlock_rlock(lock) \
+	_remote_spin_unlock_rlock(&((lock)->remote))
 
 #define remote_spin_release(lock, pid) \
 	_remote_spin_release(&((lock)->remote), pid)
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index c940091..67f4d8c 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -586,6 +586,9 @@
  * @device_down: This callback is called when device reports absent, or the
  *		bus goes down. Device will report present when bus is up and
  *		device_up callback will be called again when that happens
+ * @reset_device: This callback is called after framer is booted.
+ *		Driver should do the needful to reset the device,
+ *		so that device acquires sync and be operational.
  * @driver: Slimbus device drivers should initialize name and owner field of
  *	this structure
  * @id_table: List of slimbus devices supported by this driver
@@ -600,6 +603,8 @@
 	int				(*device_up)(struct slim_device *sldev);
 	int				(*device_down)
 						(struct slim_device *sldev);
+	int				(*reset_device)
+						(struct slim_device *sldev);
 
 	struct device_driver		driver;
 	const struct slim_device_id	*id_table;
@@ -1036,6 +1041,16 @@
 void slim_report_absent(struct slim_device *sbdev);
 
 /*
+ * slim_framer_booted: This function is called by controller after the active
+ * framer has booted (using Bus Reset sequence, or after it has shutdown and has
+ * come back up). Components, devices on the bus may be in undefined state,
+ * and this function triggers their drivers to do the needful
+ * to bring them back in Reset state so that they can acquire sync, report
+ * present and be operational again.
+ */
+void slim_framer_booted(struct slim_controller *ctrl);
+
+/*
  * slim_msg_response: Deliver Message response received from a device to the
  *	framework.
  * @ctrl: Controller handle
diff --git a/include/linux/usb/Kbuild b/include/linux/usb/Kbuild
index 087d163..fe4d6da 100644
--- a/include/linux/usb/Kbuild
+++ b/include/linux/usb/Kbuild
@@ -1,4 +1,5 @@
 header-y += audio.h
+header-y += ccid_bridge.h
 header-y += cdc.h
 header-y += ch9.h
 header-y += ch11.h
diff --git a/include/linux/usb/ccid_bridge.h b/include/linux/usb/ccid_bridge.h
new file mode 100644
index 0000000..1d1b895
--- /dev/null
+++ b/include/linux/usb/ccid_bridge.h
@@ -0,0 +1,64 @@
+#ifndef __UAPI_USB_CCID_BRIDGE_H
+#define __UAPI_USB_CCID_BRIDGE_H
+
+#include <linux/ioctl.h>
+
+/**
+ * struct usb_ccid_data - Used to receive the CCID class descriptor,
+ *        clock rates and data rates supported by the device.
+ * @length: The length of the buffer.
+ * @data: The buffer as it is returned by the device for GET_DESCRIPTOR,
+ *        GET_CLOCK_FREQUENCIES and GET_DATA_RATES requests.
+ */
+struct usb_ccid_data {
+	uint8_t length;
+	void *data;
+};
+
+/**
+ * struct usb_ccid_abort - Used to abort an already sent command.
+ * @seq: The sequence number of the command.
+ * @slot: The slot of the IC, on which the command is sent.
+ */
+struct usb_ccid_abort {
+	uint8_t seq;
+	uint8_t slot;
+};
+
+#define USB_CCID_NOTIFY_SLOT_CHANGE_EVENT 1
+#define USB_CCID_HARDWARE_ERROR_EVENT 2
+#define USB_CCID_RESUME_EVENT 3
+/**
+ * struct usb_ccid_event - Used to receive notify slot change or hardware
+ *        error event.
+ * @notify: If the event is USB_CCID_NOTIFY_SLOT_CHANGE_EVENT, slot_icc_state
+ *        has the information about the current slots state.
+ * @error: If the event is USB_CCID_HARDWARE_ERROR_EVENT, error has
+ *        information about the hardware error condition.
+ */
+struct usb_ccid_event {
+	uint8_t event;
+	union {
+		struct {
+			uint8_t slot_icc_state;
+		} notify;
+
+		struct {
+			uint8_t slot;
+			uint8_t seq;
+			uint8_t error_code;
+		} error;
+	} u;
+};
+
+#define USB_CCID_GET_CLASS_DESC _IOWR('C', 0, struct usb_ccid_data)
+
+#define USB_CCID_GET_CLOCK_FREQUENCIES _IOWR('C', 1, struct usb_ccid_data)
+
+#define USB_CCID_GET_DATA_RATES _IOWR('C', 2, struct usb_ccid_data)
+
+#define USB_CCID_ABORT _IOW('C', 3, struct usb_ccid_abort)
+
+#define USB_CCID_GET_EVENT _IOR('C', 4, struct usb_ccid_event)
+
+#endif /* __UAPI_USB_CCID_BRIDGE_H */
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index 4fb20f6..f9dec0b 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -212,7 +212,8 @@
 #define	HCD_MEMORY	0x0001		/* HC regs use memory (else I/O) */
 #define	HCD_LOCAL_MEM	0x0002		/* HC needs local memory */
 #define	HCD_SHARED	0x0004		/* Two (or more) usb_hcds share HW */
-#define	HCD_OLD_ENUM	0x0008		/* HC supports short enumeration */
+#define	HCD_RT_OLD_ENUM	0x0008		/* HC supports short enumeration
+					   on root port */
 #define	HCD_USB11	0x0010		/* USB 1.1 */
 #define	HCD_USB2	0x0020		/* USB 2.0 */
 #define	HCD_USB3	0x0040		/* USB 3.0 */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 045a58b..862a0cc 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -346,6 +346,7 @@
  * @chg_check_timer: The timer used to implement the workaround to detect
  *               very slow plug in of wall charger.
  * @ui_enabled: USB Intterupt is enabled or disabled.
+ * @pm_done: Indicates whether USB is PM resumed
  */
 struct msm_otg {
 	struct usb_phy phy;
@@ -462,6 +463,7 @@
 	bool ext_chg_active;
 	struct completion ext_chg_wait;
 	int ui_enabled;
+	bool pm_done;
 };
 
 struct ci13xxx_platform_data {
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index bfafe00..81d5b9c 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1841,7 +1841,11 @@
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_INPUT_CROP,
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_DIGITAL_ZOOM,
 	V4L2_MPEG_VIDC_INDEX_EXTRADATA_ASPECT_RATIO,
-	V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP
+	V4L2_MPEG_VIDC_EXTRADATA_MPEG2_SEQDISP,
+	V4L2_MPEG_VIDC_EXTRADATA_FRAME_QP,
+	V4L2_MPEG_VIDC_EXTRADATA_FRAME_BITS_INFO,
+	V4L2_MPEG_VIDC_EXTRADATA_LTR,
+	V4L2_MPEG_VIDC_EXTRADATA_METADATA_MBI,
 };
 
 #define V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL (V4L2_CID_MPEG_MSM_VIDC_BASE + 26)
@@ -1906,6 +1910,29 @@
 
 #define V4L2_CID_MPEG_VIDC_VIDEO_VP8_MIN_QP (V4L2_CID_MPEG_MSM_VIDC_BASE + 36)
 #define V4L2_CID_MPEG_VIDC_VIDEO_VP8_MAX_QP (V4L2_CID_MPEG_MSM_VIDC_BASE + 37)
+#define V4L2_CID_MPEG_VIDC_VIDEO_CONCEAL_COLOR \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 38)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 39)
+
+enum v4l2_mpeg_vidc_video_ltrmode {
+	V4L2_MPEG_VIDC_VIDEO_LTR_MODE_DISABLE = 0,
+	V4L2_MPEG_VIDC_VIDEO_LTR_MODE_MANUAL = 1,
+	V4L2_MPEG_VIDC_VIDEO_LTR_MODE_PERIODIC = 2
+};
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 40)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_USELTRFRAME \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 41)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_MARKLTRFRAME \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 42)
+
+#define V4L2_CID_MPEG_VIDC_VIDEO_HIER_P_NUM_LAYERS \
+		(V4L2_CID_MPEG_MSM_VIDC_BASE + 43)
 
 /*  Camera class control IDs */
 #define V4L2_CID_CAMERA_CLASS_BASE 	(V4L2_CTRL_CLASS_CAMERA | 0x900)
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 7675a5c..500421f 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -136,6 +136,12 @@
 extern __init void vm_area_add_early(struct vm_struct *vm);
 extern __init void vm_area_register_early(struct vm_struct *vm, size_t align);
 extern __init int vm_area_check_early(struct vm_struct *vm);
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+extern void mark_vmalloc_reserved_area(void *addr, unsigned long size);
+#else
+static inline void mark_vmalloc_reserved_area(void *addr, unsigned long size)
+{ };
+#endif
 
 #ifdef CONFIG_SMP
 # ifdef CONFIG_MMU
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 39357e0..9badfa3 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -41,6 +41,7 @@
 #define HAVE_WCNSS_RESET_INTR 1
 #define HAVE_WCNSS_CAL_DOWNLOAD 1
 #define HAVE_WCNSS_RX_BUFF_COUNT 1
+#define WLAN_MAC_ADDR_SIZE (6)
 
 struct device *wcnss_wlan_get_device(void);
 struct resource *wcnss_wlan_get_memory_map(struct device *dev);
@@ -64,6 +65,7 @@
 int wcnss_free_power_on_lock(char *driver_name);
 unsigned int wcnss_get_serial_number(void);
 void wcnss_flush_delayed_boot_votes(void);
+int wcnss_get_wlan_mac_address(char mac_addr[WLAN_MAC_ADDR_SIZE]);
 void wcnss_allow_suspend(void);
 void wcnss_prevent_suspend(void);
 int wcnss_hardware_type(void);
@@ -86,7 +88,11 @@
 {
 }
 #endif
-
+int wcnss_set_wlan_unsafe_channel(
+				u16 *unsafe_ch_list, u16 ch_count);
+int wcnss_get_wlan_unsafe_channel(
+				u16 *unsafe_ch_list, u16 buffer_size,
+				u16 *ch_count);
 #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
 #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
 /* WLAN driver uses these names */
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index a01dd9a..38d3aab 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -482,6 +482,7 @@
 	int8_t sign_dir;
 	int16_t dest_step_pos;
 	int32_t num_steps;
+	uint16_t curr_lens_pos;
 	struct damping_params_t *ringing_params;
 };
 
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index bc85ebb..9028b1a 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -7,8 +7,8 @@
 #include <linux/videodev2.h>
 
 enum core_id {
-	MSM_VIDC_CORE_0 = 0,
-	MSM_VIDC_CORE_1,      /* for Q6 core */
+	MSM_VIDC_CORE_VENUS = 0,
+	MSM_VIDC_CORE_Q6,
 	MSM_VIDC_CORES_MAX,
 };
 
@@ -60,6 +60,7 @@
 int msm_vidc_s_fmt(void *instance, struct v4l2_format *f);
 int msm_vidc_g_fmt(void *instance, struct v4l2_format *f);
 int msm_vidc_s_ctrl(void *instance, struct v4l2_control *a);
+int msm_vidc_s_ext_ctrl(void *instance, struct v4l2_ext_controls *a);
 int msm_vidc_g_ctrl(void *instance, struct v4l2_control *a);
 int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
 int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b);
@@ -95,6 +96,16 @@
 		int *domain_num, int *partition_num);
 void *msm_vidc_smem_get_client(void *instance);
 #endif
+
+struct msm_vidc_extradata_header {
+	unsigned int size;
+	unsigned int:32; /** Keeping binary compatibility */
+	unsigned int:32; /* with firmware and OpenMAX IL **/
+	unsigned int type; /* msm_vidc_extradata_type */
+	unsigned int data_size;
+	unsigned char data[1];
+};
+
 struct msm_vidc_interlace_payload {
 	unsigned int format;
 };
@@ -160,6 +171,13 @@
 	unsigned int fpa_repetition_period;
 	unsigned int fpa_extension_flag;
 };
+struct msm_vidc_frame_qp_payload {
+	unsigned int frame_qp;
+};
+struct msm_vidc_frame_bits_info_payload {
+	unsigned int frame_bits;
+	unsigned int header_bits;
+};
 
 enum msm_vidc_extradata_type {
 	EXTRADATA_NONE = 0x00000000,
@@ -173,11 +191,15 @@
 	EXTRADATA_PANSCAN_WINDOW = 0x00000008,
 	EXTRADATA_RECOVERY_POINT_SEI = 0x00000009,
 	EXTRADATA_MPEG2_SEQDISP = 0x0000000D,
+	EXTRADATA_FRAME_QP = 0x0000000F,
+	EXTRADATA_FRAME_BITS_INFO = 0x00000010,
 	EXTRADATA_MULTISLICE_INFO = 0x7F100000,
 	EXTRADATA_NUM_CONCEALED_MB = 0x7F100001,
 	EXTRADATA_INDEX = 0x7F100002,
 	EXTRADATA_ASPECT_RATIO = 0x7F100003,
 	EXTRADATA_METADATA_FILLER = 0x7FE00002,
+	MSM_VIDC_EXTRADATA_METADATA_LTR = 0x7F100004,
+	EXTRADATA_METADATA_MBI = 0x7F100005,
 };
 enum msm_vidc_interlace_type {
 	INTERLACE_FRAME_PROGRESSIVE = 0x01,
diff --git a/include/media/msmb_generic_buf_mgr.h b/include/media/msmb_generic_buf_mgr.h
index efcb425..237380f 100644
--- a/include/media/msmb_generic_buf_mgr.h
+++ b/include/media/msmb_generic_buf_mgr.h
@@ -20,4 +20,10 @@
 #define VIDIOC_MSM_BUF_MNGR_BUF_DONE \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 35, struct msm_buf_mngr_info)
 
+#define VIDIOC_MSM_BUF_MNGR_INIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 36, struct msm_buf_mngr_info)
+
+#define VIDIOC_MSM_BUF_MNGR_DEINIT \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 37, struct msm_buf_mngr_info)
+
 #endif
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 568a3fa..3ba0abe 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -228,6 +228,7 @@
 	VFE_READ_DMI_32BIT,
 	VFE_READ_DMI_64BIT,
 	GET_SOC_HW_VER,
+	GET_MAX_CLK_RATE,
 };
 
 struct msm_vfe_cfg_cmd2 {
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index d28a8c0..518dfb1 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -32,6 +32,50 @@
 #include <linux/mutex.h>
 #include <linux/atomic.h>
 #include "radio-iris-commands.h"
+const unsigned char MIN_TX_TONE_VAL = 0x00;
+const unsigned char MAX_TX_TONE_VAL = 0x07;
+const unsigned char MIN_HARD_MUTE_VAL = 0x00;
+const unsigned char MAX_HARD_MUTE_VAL = 0x03;
+const unsigned char MIN_SRCH_MODE = 0x00;
+const unsigned char MAX_SRCH_MODE = 0x09;
+const unsigned char MIN_SCAN_DWELL = 0x00;
+const unsigned char MAX_SCAN_DWELL = 0x0F;
+const unsigned char MIN_SIG_TH = 0x00;
+const unsigned char MAX_SIG_TH = 0x03;
+const unsigned char MIN_PTY = 0X00;
+const unsigned char MAX_PTY = 0x1F;
+const unsigned short MIN_PI = 0x0000;
+const unsigned short MAX_PI = 0xFFFF;
+const unsigned char MIN_SRCH_STATIONS_CNT = 0x00;
+const unsigned char MAX_SRCH_STATIONS_CNT = 0x14;
+const unsigned char MIN_CHAN_SPACING = 0x00;
+const unsigned char MAX_CHAN_SPACING = 0x02;
+const unsigned char MIN_EMPHASIS = 0x00;
+const unsigned char MAX_EMPHASIS = 0x01;
+const unsigned char MIN_RDS_STD = 0x00;
+const unsigned char MAX_RDS_STD = 0x02;
+const unsigned char MIN_ANTENNA_VAL = 0x00;
+const unsigned char MAX_ANTENNA_VAL = 0x01;
+const unsigned char MIN_TX_PS_REPEAT_CNT = 0x01;
+const unsigned char MAX_TX_PS_REPEAT_CNT = 0x0F;
+const unsigned char MIN_SOFT_MUTE = 0x00;
+const unsigned char MAX_SOFT_MUTE = 0x01;
+const unsigned char MIN_PEEK_ACCESS_LEN = 0x01;
+const unsigned char MAX_PEEK_ACCESS_LEN = 0xF9;
+const unsigned char MIN_RESET_CNTR = 0x00;
+const unsigned char MAX_RESET_CNTR = 0x01;
+const unsigned char MIN_HLSI = 0x00;
+const unsigned char MAX_HLSI = 0x02;
+const unsigned char MIN_NOTCH_FILTER = 0x00;
+const unsigned char MAX_NOTCH_FILTER = 0x02;
+const unsigned char MIN_INTF_DET_OUT_LW_TH = 0x00;
+const unsigned char MAX_INTF_DET_OUT_LW_TH = 0xFF;
+const unsigned char MIN_INTF_DET_OUT_HG_TH = 0x00;
+const unsigned char MAX_INTF_DET_OUT_HG_TH = 0xFF;
+const signed char MIN_SINR_TH = -128;
+const signed char MAX_SINR_TH = 127;
+const unsigned char MIN_SINR_SAMPLES = 0x01;
+const unsigned char MAX_SINR_SAMPLES = 0xFF;
 
 /* ---- HCI Packet structures ---- */
 #define RADIO_HCI_COMMAND_HDR_SIZE sizeof(struct radio_hci_command_hdr)
@@ -630,6 +674,7 @@
 	FM_TURNING_OFF,
 	FM_RECV_TURNING_ON,
 	FM_TRANS_TURNING_ON,
+	FM_MAX_NO_STATES,
 };
 
 enum emphasis_type {
@@ -828,4 +873,209 @@
 int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev);
 int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev);
 
+static inline int is_valid_tone(int tone)
+{
+	if ((tone >= MIN_TX_TONE_VAL) &&
+		(tone <= MAX_TX_TONE_VAL))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_hard_mute(int hard_mute)
+{
+	if ((hard_mute >= MIN_HARD_MUTE_VAL) &&
+		(hard_mute <= MAX_HARD_MUTE_VAL))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_srch_mode(int srch_mode)
+{
+	if ((srch_mode >= MIN_SRCH_MODE) &&
+		(srch_mode <= MAX_SRCH_MODE))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_scan_dwell_prd(int scan_dwell_prd)
+{
+	if ((scan_dwell_prd >= MIN_SCAN_DWELL) &&
+		(scan_dwell_prd <= MAX_SCAN_DWELL))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_sig_th(int sig_th)
+{
+	if ((sig_th >= MIN_SIG_TH) &&
+		(sig_th <= MAX_SIG_TH))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_pty(int pty)
+{
+	if ((pty >= MIN_PTY) &&
+		(pty <= MAX_PTY))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_pi(int pi)
+{
+	if ((pi >= MIN_PI) &&
+		(pi <= MAX_PI))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_srch_station_cnt(int cnt)
+{
+	if ((cnt >= MIN_SRCH_STATIONS_CNT) &&
+		(cnt <= MAX_SRCH_STATIONS_CNT))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_chan_spacing(int spacing)
+{
+	if ((spacing >= MIN_CHAN_SPACING) &&
+		(spacing <= MAX_CHAN_SPACING))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_emphasis(int emphasis)
+{
+	if ((emphasis >= MIN_EMPHASIS) &&
+		(emphasis <= MAX_EMPHASIS))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_rds_std(int rds_std)
+{
+	if ((rds_std >= MIN_RDS_STD) &&
+		(rds_std <= MAX_RDS_STD))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_antenna(int antenna_type)
+{
+	if ((antenna_type >= MIN_ANTENNA_VAL) &&
+		(antenna_type <= MAX_ANTENNA_VAL))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_ps_repeat_cnt(int cnt)
+{
+	if ((cnt >= MIN_TX_PS_REPEAT_CNT) &&
+		(cnt <= MAX_TX_PS_REPEAT_CNT))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_soft_mute(int soft_mute)
+{
+	if ((soft_mute >= MIN_SOFT_MUTE) &&
+		(soft_mute <= MAX_SOFT_MUTE))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_peek_len(int len)
+{
+	if ((len >= MIN_PEEK_ACCESS_LEN) &&
+		(len <= MAX_PEEK_ACCESS_LEN))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_reset_cntr(int cntr)
+{
+	if ((cntr >= MIN_RESET_CNTR) &&
+		(cntr <= MAX_RESET_CNTR))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_hlsi(int hlsi)
+{
+	if ((hlsi >= MIN_HLSI) &&
+		(hlsi <= MAX_HLSI))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_notch_filter(int filter)
+{
+	if ((filter >= MIN_NOTCH_FILTER) &&
+		(filter <= MAX_NOTCH_FILTER))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_intf_det_low_th(int th)
+{
+	if ((th >= MIN_INTF_DET_OUT_LW_TH) &&
+		(th <= MAX_INTF_DET_OUT_LW_TH))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_intf_det_hgh_th(int th)
+{
+	if ((th >= MIN_INTF_DET_OUT_HG_TH) &&
+		(th <= MAX_INTF_DET_OUT_HG_TH))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_sinr_th(int th)
+{
+	if ((th >= MIN_SINR_TH) &&
+		(th <= MAX_SINR_TH))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_sinr_samples(int samples_cnt)
+{
+	if ((samples_cnt >= MIN_SINR_SAMPLES) &&
+		(samples_cnt <= MAX_SINR_SAMPLES))
+		return 1;
+	else
+		return 0;
+}
+
+static inline int is_valid_fm_state(int state)
+{
+	if ((state >= 0) && (state < FM_MAX_NO_STATES))
+		return 1;
+	else
+		return 0;
+}
 #endif /* __RADIO_HCI_CORE_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7932ba1..77084ed 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -524,6 +524,10 @@
  * @capability: station capability
  * @ext_capab: extended capabilities of the station
  * @ext_capab_len: number of extended capabilities
+ * @supported_channels: supported channels in IEEE 802.11 format
+ * @supported_channels_len: number of supported channels
+ * @supported_oper_classes: supported oper classes in IEEE 802.11 format
+ * @supported_oper_classes_len: number of supported operating classes
  */
 struct station_parameters {
 	u8 *supported_rates;
@@ -542,6 +546,10 @@
 	u16 capability;
 	u8 *ext_capab;
 	u8 ext_capab_len;
+	const u8 *supported_channels;
+	u8 supported_channels_len;
+	const u8 *supported_oper_classes;
+	u8 supported_oper_classes_len;
 };
 
 /**
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 7c6a558..6a54bb4 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -152,7 +152,10 @@
 	unsigned no_read_disc_info:1;	/* Avoid READ_DISC_INFO cmds */
 	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
 	unsigned is_visible:1;	/* is the device visible in sysfs */
+	unsigned use_rpm_auto:1; /* Enable runtime PM auto suspend */
 
+#define SCSI_DEFAULT_AUTOSUSPEND_DELAY  -1
+	int autosuspend_delay;
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
 	struct list_head event_list;	/* asserted events */
 	struct work_struct event_work;
diff --git a/kernel/events/core.c b/kernel/events/core.c
index aafa4c1..7dd822b 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1194,6 +1194,28 @@
 	return 0;
 }
 
+#ifdef CONFIG_SMP
+static void perf_retry_remove(struct perf_event *event)
+{
+	int up_ret;
+	/*
+	 * CPU was offline. Bring it online so we can
+	 * gracefully exit a perf context.
+	 */
+	up_ret = cpu_up(event->cpu);
+	if (!up_ret)
+		/* Try the remove call once again. */
+		cpu_function_call(event->cpu, __perf_remove_from_context,
+				  event);
+	else
+		pr_err("Failed to bring up CPU: %d, ret: %d\n",
+		       event->cpu, up_ret);
+}
+#else
+static void perf_retry_remove(struct perf_event *event)
+{
+}
+#endif
 
 /*
  * Remove the event from a task's (or a CPU's) list of events.
@@ -1208,19 +1230,22 @@
  * When called from perf_event_exit_task, it's OK because the
  * context has been detached from its task.
  */
-static void perf_remove_from_context(struct perf_event *event)
+static void __ref perf_remove_from_context(struct perf_event *event)
 {
 	struct perf_event_context *ctx = event->ctx;
 	struct task_struct *task = ctx->task;
+	int ret;
 
 	lockdep_assert_held(&ctx->mutex);
 
 	if (!task) {
 		/*
-		 * Per cpu events are removed via an smp call and
-		 * the removal is always successful.
+		 * Per cpu events are removed via an smp call
 		 */
-		cpu_function_call(event->cpu, __perf_remove_from_context, event);
+		ret = cpu_function_call(event->cpu, __perf_remove_from_context,
+					event);
+		if (ret == -ENXIO)
+			perf_retry_remove(event);
 		return;
 	}
 
@@ -2934,6 +2959,14 @@
 	struct perf_event *event = file->private_data;
 	struct task_struct *owner;
 
+	/*
+	 * Event can be in state OFF because of a constraint check.
+	 * Change to ACTIVE so that it gets cleaned up correctly.
+	 */
+	if ((event->state == PERF_EVENT_STATE_OFF) &&
+	    event->attr.constraint_duplicate)
+		event->state = PERF_EVENT_STATE_ACTIVE;
+
 	file->private_data = NULL;
 
 	rcu_read_lock();
@@ -5171,6 +5204,7 @@
 	.read		= perf_swevent_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 #ifdef CONFIG_EVENT_TRACING
@@ -5265,6 +5299,7 @@
 	.read		= perf_swevent_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 static inline void perf_tp_register(void)
@@ -5492,6 +5527,7 @@
 	.read		= cpu_clock_event_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 /*
@@ -5572,6 +5608,7 @@
 	.read		= task_clock_event_read,
 
 	.event_idx	= perf_swevent_event_idx,
+	.events_across_hotplug = 1,
 };
 
 static void perf_pmu_nop_void(struct pmu *pmu)
@@ -7029,11 +7066,20 @@
 
 	idx = srcu_read_lock(&pmus_srcu);
 	list_for_each_entry_rcu(pmu, &pmus, entry) {
-		ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
+		/*
+		 * If keeping events across hotplugging is supported, do not
+		 * remove the event list, but keep it alive across CPU hotplug.
+		 * The context is exited via an fd close path when userspace
+		 * is done and the target CPU is online.
+		 */
+		if (!pmu->events_across_hotplug) {
+			ctx = &per_cpu_ptr(pmu->pmu_cpu_context, cpu)->ctx;
 
-		mutex_lock(&ctx->mutex);
-		smp_call_function_single(cpu, __perf_event_exit_context, ctx, 1);
-		mutex_unlock(&ctx->mutex);
+			mutex_lock(&ctx->mutex);
+			smp_call_function_single(cpu, __perf_event_exit_context,
+						 ctx, 1);
+			mutex_unlock(&ctx->mutex);
+		}
 	}
 	srcu_read_unlock(&pmus_srcu, idx);
 }
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index bb38c4d..98e6903 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -635,6 +635,7 @@
 	.read		= hw_breakpoint_pmu_read,
 
 	.event_idx	= hw_breakpoint_event_idx,
+	.events_across_hotplug = 1,
 };
 
 int __init init_hw_breakpoint(void)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 954a8c4..d9e1f1d 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1682,9 +1682,12 @@
 {
 	struct rq *rq = task_rq(p);
 
-	if (WARN_ON(rq != this_rq()) ||
-	    WARN_ON(p == current))
+	if (rq != this_rq() || p == current) {
+		printk_sched("%s: Failed to wakeup task %d (%s), rq = %p, this_rq = %p, p = %p, current = %p\n",
+			__func__, task_pid_nr(p), p->comm, rq,
+			this_rq(), p, current);
 		return;
+	}
 
 	lockdep_assert_held(&rq->lock);
 
@@ -6947,6 +6950,7 @@
 
 #ifdef CONFIG_CGROUP_SCHED
 struct task_group root_task_group;
+LIST_HEAD(task_groups);
 #endif
 
 DECLARE_PER_CPU(cpumask_var_t, load_balance_tmpmask);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index c0288a6..34fe64f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -80,7 +80,7 @@
 struct cfs_rq;
 struct rt_rq;
 
-static LIST_HEAD(task_groups);
+extern struct list_head task_groups;
 
 struct cfs_bandwidth {
 #ifdef CONFIG_CFS_BANDWIDTH
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index aa27d39..a2a28a0 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -98,6 +98,8 @@
 
 static inline void alarmtimer_rtc_timer_init(void)
 {
+	mutex_init(&power_on_alarm_lock);
+
 	rtc_timer_init(&rtctimer, NULL, NULL);
 }
 
@@ -123,6 +125,7 @@
 static inline int alarmtimer_rtc_interface_setup(void) { return 0; }
 static inline void alarmtimer_rtc_interface_remove(void) { }
 static inline void alarmtimer_rtc_timer_init(void) { }
+void set_power_on_alarm(long secs, bool enable) { }
 #endif
 
 /**
diff --git a/lib/Kconfig b/lib/Kconfig
index 8437e36..09f0d8a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -379,7 +379,7 @@
 	  Implementation is done using GnuPG MPI library
 
 config QMI_ENCDEC
-	bool
+	bool "QMI Encode/Decode Library"
 	help
 	  Library to encode & decode QMI messages from within
 	  the kernel. The kernel drivers encode the C structure into
@@ -388,7 +388,7 @@
 	  and then decode it into a C structure.
 
 config QMI_ENCDEC_DEBUG
-	bool
+	bool "QMI Encode/Decode Library Debug"
 	help
 	  Kernel config option to enable debugging QMI Encode/Decode
 	  library. This will log the information regarding the element
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index e174693..2e074aa 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -184,36 +184,6 @@
 	return ret;
 }
 
-#ifdef ENABLE_VMALLOC_SAVING
-int is_vmalloc_addr(const void *x)
-{
-	struct rb_node *n;
-	struct vmap_area *va;
-	int ret = 0;
-
-	spin_lock(&vmap_area_lock);
-
-	for (n = rb_first(vmap_area_root); n; rb_next(n)) {
-		va = rb_entry(n, struct vmap_area, rb_node);
-		if (x >= va->va_start && x < va->va_end) {
-			ret = 1;
-			break;
-		}
-	}
-
-	spin_unlock(&vmap_area_lock);
-	return ret;
-}
-#else
-int is_vmalloc_addr(const void *x)
-{
-	unsigned long addr = (unsigned long)x;
-
-	return addr >= VMALLOC_START && addr < VMALLOC_END;
-}
-#endif
-EXPORT_SYMBOL(is_vmalloc_addr);
-
 int is_vmalloc_or_module_addr(const void *x)
 {
 	/*
@@ -302,6 +272,47 @@
 
 static unsigned long vmap_area_pcpu_hole;
 
+#ifdef CONFIG_ENABLE_VMALLOC_SAVING
+#define POSSIBLE_VMALLOC_START	PAGE_OFFSET
+
+#define VMALLOC_BITMAP_SIZE	((VMALLOC_END - PAGE_OFFSET) >> \
+					PAGE_SHIFT)
+#define VMALLOC_TO_BIT(addr)	((addr - PAGE_OFFSET) >> PAGE_SHIFT)
+#define BIT_TO_VMALLOC(i)	(PAGE_OFFSET + i * PAGE_SIZE)
+
+DECLARE_BITMAP(possible_areas, VMALLOC_BITMAP_SIZE);
+
+void mark_vmalloc_reserved_area(void *x, unsigned long size)
+{
+	unsigned long addr = (unsigned long)x;
+
+	bitmap_set(possible_areas, VMALLOC_TO_BIT(addr), size >> PAGE_SHIFT);
+}
+
+int is_vmalloc_addr(const void *x)
+{
+	unsigned long addr = (unsigned long)x;
+
+	if (addr < POSSIBLE_VMALLOC_START || addr >= VMALLOC_END)
+		return 0;
+
+	if (test_bit(VMALLOC_TO_BIT(addr), possible_areas))
+		return 0;
+
+	return 1;
+}
+#else
+int is_vmalloc_addr(const void *x)
+{
+	unsigned long addr = (unsigned long)x;
+
+	return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+EXPORT_SYMBOL(is_vmalloc_addr);
+
+
+
 static struct vmap_area *__find_vmap_area(unsigned long addr)
 {
 	struct rb_node *n = vmap_area_root.rb_node;
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index a225089..f378b38 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -35,7 +35,7 @@
 		struct iphdr _iph;
 ip:
 		iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
-		if (!iph)
+		if (!iph || iph->ihl < 5)
 			return false;
 
 		if (ip_is_fragment(iph))
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index fd7a3f6..cfaaf13 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -271,6 +271,11 @@
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
 	private = table->private;
+	/*
+	 * Ensure we load private-> members after we've fetched the base
+	 * pointer.
+	 */
+	smp_read_barrier_depends();
 	table_base = private->entries[smp_processor_id()];
 
 	e = get_entry(table_base, private->hook_entry[hook]);
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 24e556e..ed1468a 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -327,6 +327,11 @@
 	addend = xt_write_recseq_begin();
 	private = table->private;
 	cpu        = smp_processor_id();
+	/*
+	 * Ensure we load private-> members after we've fetched the base
+	 * pointer.
+	 */
+	smp_read_barrier_depends();
 	table_base = private->entries[cpu];
 	jumpstack  = (struct ipt_entry **)private->jumpstack[cpu];
 	stackptr   = per_cpu_ptr(private->stackptr, cpu);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b2b0e99..74a286c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -485,14 +485,12 @@
 			 !tp->urg_data ||
 			 before(tp->urg_seq, tp->copied_seq) ||
 			 !before(tp->urg_seq, tp->rcv_nxt)) {
-			struct sk_buff *skb;
 
 			answ = tp->rcv_nxt - tp->copied_seq;
 
-			/* Subtract 1, if FIN is in queue. */
-			skb = skb_peek_tail(&sk->sk_receive_queue);
-			if (answ && skb)
-				answ -= tcp_hdr(skb)->fin;
+			/* Subtract 1, if FIN was received */
+			if (answ && sock_flag(sk, SOCK_DONE))
+				answ--;
 		} else
 			answ = tp->urg_seq - tp->copied_seq;
 		release_sock(sk);
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index e641f8f..c30a20c 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -349,6 +349,11 @@
 	local_bh_disable();
 	addend = xt_write_recseq_begin();
 	private = table->private;
+	/*
+	 * Ensure we load private-> members after we've fetched the base
+	 * pointer.
+	 */
+	smp_read_barrier_depends();
 	cpu        = smp_processor_id();
 	table_base = private->entries[cpu];
 	jumpstack  = (struct ip6t_entry **)private->jumpstack[cpu];
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8d987c3..5888e00 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -832,8 +832,13 @@
 		return NULL;
 	}
 
-	table->private = newinfo;
 	newinfo->initial_entries = private->initial_entries;
+	/*
+	 * Ensure contents of newinfo are visible before assigning to
+	 * private.
+	 */
+	smp_wmb();
+	table->private = newinfo;
 
 	/*
 	 * Even though table entries have now been swapped, other CPU's
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index b1efe57..0e44fa8 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -14,14 +14,6 @@
 	(57240 - 63720 @ 2160), (N/A, 0)
 
 
-country AD:
-	(2402 - 2482 @ 40), (N/A, 20)
-	(5170 - 5250 @ 80), (N/A, 20)
-	(5250 - 5330 @ 80), (N/A, 20), DFS
-	(5490 - 5710 @ 80), (N/A, 27), DFS
-	# 60 gHz band channels 1-4, ref: Etsi En 302 567
-	(57240 - 65880 @ 2160), (N/A, 40), NO-OUTDOOR
-
 country AE:
 	(2402 - 2482 @ 40), (N/A, 20)
 	(5170 - 5250 @ 80), (3, 17)
@@ -126,11 +118,6 @@
 	(5250 - 5330 @ 20), (N/A, 20), DFS
 	(5735 - 5835 @ 20), (N/A, 20)
 
-country BL:
-	(2402 - 2482 @ 40), (N/A, 20)
-	(5170 - 5250 @ 40), (N/A, 18)
-	(5250 - 5330 @ 40), (N/A, 18), DFS
-
 country BM:
 	(2402 - 2472 @ 40), (N/A, 30)
 	(5150 - 5250 @ 80), (6, 17)
@@ -849,7 +836,7 @@
 
 country TW:
 	(2402 - 2472 @ 40), (3, 27)
-	(5270 - 5330 @ 80), (6, 17), DFS
+	(5270 - 5330 @ 40), (6, 17), DFS
 	(5490 - 5710 @ 80), (6, 30), DFS
 	(5735 - 5815 @ 80), (6, 30)
 
@@ -909,7 +896,7 @@
 	(5250 - 5330 @ 80), (3, 24), DFS
 	(5490 - 5600 @ 80), (3, 24), DFS
 	(5650 - 5710 @ 40), (3, 24), DFS
-	(5735 - 5835 @ 80), (3, 30)
+	(5710 - 5835 @ 80), (3, 30)
 	# 60g band
 	# reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255
 	# channels 1,2,3, EIRP=40dBm(43dBm peak)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7db02f3..a251231 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -223,6 +223,8 @@
 	[NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
 				  .len = IEEE80211_MAX_DATA_LEN },
 	[NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },
+	[NL80211_ATTR_STA_SUPPORTED_CHANNELS] = { .type = NLA_BINARY },
+	[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES] = { .type = NLA_BINARY },
 };
 
 /* policy for the key attributes */
@@ -2774,6 +2776,41 @@
 	return ERR_PTR(ret);
 }
 
+static int nl80211_parse_sta_channel_info(struct genl_info *info,
+				      struct station_parameters *params)
+{
+	if (info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]) {
+		params->supported_channels =
+		     nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
+		params->supported_channels_len =
+		     nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_CHANNELS]);
+		/*
+		 * Need to include at least one (first channel, number of
+		 * channels) tuple for each subband, and must have proper
+		 * tuples for the rest of the data as well.
+		 */
+		if (params->supported_channels_len < 2)
+			return -EINVAL;
+		if (params->supported_channels_len % 2)
+			return -EINVAL;
+	}
+
+	if (info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]) {
+		params->supported_oper_classes =
+		 nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
+		params->supported_oper_classes_len =
+		  nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES]);
+		/*
+		 * The value of the Length field of the Supported Operating
+		 * Classes element is between 2 and 253.
+		 */
+		if (params->supported_oper_classes_len < 2 ||
+		    params->supported_oper_classes_len > 253)
+			return -EINVAL;
+	}
+	return 0;
+}
+
 static struct nla_policy
 nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = {
 	[NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 },
@@ -2797,6 +2834,10 @@
 		params->vht_capa =
 			nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]);
 
+	err = nl80211_parse_sta_channel_info(info, params);
+	if (err)
+		return err;
+
 	/* parse WME attributes if present */
 	if (!info->attrs[NL80211_ATTR_STA_WME])
 		return 0;
@@ -3063,6 +3104,10 @@
 		params.plink_action =
 		    nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);
 
+	err = nl80211_parse_sta_channel_info(info, &params);
+	if (err)
+		return err;
+
 	if (!rdev->ops->add_station)
 		return -EOPNOTSUPP;
 
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 3adfe7f..e40104f 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1014,8 +1014,6 @@
 		if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE)
 			creq->n_ssids = 0;
 	}
-	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
-		creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;
 
 	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
 		if (wiphy->bands[i])
diff --git a/sound/compress_offload/core.c b/sound/compress_offload/core.c
deleted file mode 100644
index 987594a..0000000
--- a/sound/compress_offload/core.c
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- *  core.c - compress offload core
- *
- *  Copyright (C) 2011 Intel Corporation
- *  Authors:	Vinod Koul <vinod.koul@linux.intel.com>
- *		Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
- *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; version 2 of the License.
- *
- *  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.
- *
- *  You should have received a copy of the GNU General Public License along
- *  with this program; if not, write to the Free Software Foundation, Inc.,
- *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- */
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/uio.h>
-#include <linux/uaccess.h>
-#include <sound/snd_compress_params.h>
-#include <sound/compress_offload.h>
-#include <sound/compress_driver.h>
-
-/* TODO:
- * - Integrate with alsa, compressed devices should register as alsa devices
- *	as /dev/snd_compr_xxx
- * - Integrate with ASoC:
- *	Opening compressed path should also start the codec dai
- *   TBD how the cpu dai will be viewed and started.
- *	ASoC should always be optional part
- *	(we should be able to use this framework in non asoc systems
- * - Multiple node representation
- *	driver should be able to register multiple nodes
- * - Version numbering for API
- */
-
-static DEFINE_MUTEX(device_mutex);
-static LIST_HEAD(device_list);
-static LIST_HEAD(misc_list);
-
-/*
- * currently we are using misc device for registration and exposing ioctls
- * this is temporary and will be moved to snd
- * the device should be registered as /dev/snd_compr.....
- */
-
-struct snd_compr_misc {
-	struct miscdevice misc;
-	struct list_head list;
-	struct snd_compr *compr;
-};
-
-struct snd_ioctl_data {
-	struct snd_compr_misc *misc;
-	unsigned long caps;
-	unsigned int minor;
-	struct snd_compr_stream stream;
-};
-
-static struct snd_compr_misc *snd_compr_get_device(unsigned int minor)
-{
-	struct snd_compr_misc *misc;
-
-	list_for_each_entry(misc, &misc_list, list) {
-		if (minor == misc->misc.minor)
-			return misc;
-	}
-	return NULL;
-}
-
-static int snd_compr_open(struct inode *inode, struct file *f)
-{
-	unsigned int minor = iminor(inode);
-	struct snd_compr_misc *misc = snd_compr_get_device(minor);
-	struct snd_ioctl_data *data;
-	struct snd_compr_runtime *runtime;
-	unsigned int direction;
-	int ret;
-
-	mutex_lock(&device_mutex);
-	if (f->f_flags & O_WRONLY)
-		direction = SNDRV_PCM_STREAM_PLAYBACK;
-	else {
-		ret = -ENXIO;
-		goto out;
-	}
-	/* curently only encoded playback is supported, above needs to be
-	 * removed once we have recording support */
-
-	data = kzalloc(sizeof(*data), GFP_KERNEL);
-	if (!data) {
-		ret = -ENOMEM;
-		goto out;
-	}
-	data->misc = misc;
-	data->minor = minor;
-	data->stream.ops = misc->compr->ops;
-	data->stream.direction = direction;
-	data->stream.private_data = misc->compr->private_data;
-	data->stream.device = misc->compr;
-	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
-	if (!runtime) {
-		ret = -ENOMEM;
-		kfree(data);
-		goto out;
-	}
-	runtime->state = SNDRV_PCM_STATE_OPEN;
-	init_waitqueue_head(&runtime->sleep);
-	data->stream.runtime = runtime;
-	f->private_data = (void *)data;
-	ret = misc->compr->ops->open(&data->stream);
-	if (ret) {
-		kfree(runtime);
-		kfree(data);
-		goto out;
-	}
-out:
-	mutex_unlock(&device_mutex);
-	return ret;
-}
-
-static int snd_compr_free(struct inode *inode, struct file *f)
-{
-	struct snd_ioctl_data *data = f->private_data;
-	mutex_lock(&device_mutex);
-	data->stream.ops->free(&data->stream);
-	kfree(data->stream.runtime->buffer);
-	kfree(data->stream.runtime);
-	kfree(data);
-	mutex_unlock(&device_mutex);
-	return 0;
-}
-
-static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
-		struct snd_compr_tstamp *tstamp)
-{
-	stream->ops->pointer(stream, tstamp);
-	stream->runtime->hw_pointer = tstamp->copied_bytes;
-}
-
-static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
-		struct snd_compr_avail *avail)
-{
-	size_t avail_calc;
-
-	snd_compr_update_tstamp(stream, &avail->tstamp);
-	avail_calc = stream->runtime->app_pointer - stream->runtime->hw_pointer;
-	if (avail_calc < 0)
-		avail_calc = stream->runtime->buffer_size + avail_calc;
-	avail->avail = avail_calc;
-	return avail_calc;
-}
-
-static size_t snd_compr_get_avail(struct snd_compr_stream *stream)
-{
-	struct snd_compr_avail avail;
-
-	return snd_compr_calc_avail(stream, &avail);
-}
-
-static int
-snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
-{
-	struct snd_compr_avail ioctl_avail;
-
-	snd_compr_calc_avail(stream, &ioctl_avail);
-
-	if (copy_to_user((unsigned long __user *)arg, &ioctl_avail, sizeof(ioctl_avail)))
-		return -EFAULT;
-	return 0;
-}
-
-static int snd_compr_write_data(struct snd_compr_stream *stream,
-	       const char __user *buf, size_t count)
-{
-	void *dstn;
-	size_t copy;
-
-	dstn = stream->runtime->buffer + stream->runtime->app_pointer;
-	if (count < stream->runtime->buffer_size - stream->runtime->app_pointer) {
-		if (copy_from_user(dstn, buf, count))
-			return -EFAULT;
-		stream->runtime->app_pointer += count;
-	} else {
-		copy = stream->runtime->buffer_size - stream->runtime->app_pointer;
-		if (copy_from_user(dstn, buf, copy))
-			return -EFAULT;
-		if (copy_from_user(stream->runtime->buffer, buf + copy, count - copy))
-			return -EFAULT;
-		stream->runtime->app_pointer = count - copy;
-	}
-	/* if DSP cares, let it know data has been written */
-	if (stream->ops->ack)
-		stream->ops->ack(stream);
-	return count;
-}
-
-static ssize_t snd_compr_write(struct file *f, const char __user *buf,
-		size_t count, loff_t *offset)
-{
-	struct snd_ioctl_data *data = f->private_data;
-	struct snd_compr_stream *stream;
-	size_t avail;
-	int retval;
-
-	BUG_ON(!data);
-	stream = &data->stream;
-	mutex_lock(&stream->device->lock);
-	/* write is allowed when stream is running or has been steup */
-	if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
-			stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
-		mutex_unlock(&stream->device->lock);
-		return -EPERM;
-	}
-
-	avail = snd_compr_get_avail(stream);
-	/* calculate how much we can write to buffer */
-	if (avail > count)
-		avail = count;
-
-	if (stream->ops->copy)
-		retval = stream->ops->copy(stream, buf, avail);
-	else
-		retval = snd_compr_write_data(stream, buf, avail);
-
-	/* while initiating the stream, write should be called before START
-	 * call, so in setup move state */
-	if (stream->runtime->state == SNDRV_PCM_STATE_SETUP)
-		stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
-
-	mutex_unlock(&stream->device->lock);
-	return retval;
-}
-
-
-static ssize_t snd_compr_read(struct file *f, char __user *buf,
-		size_t count, loff_t *offset)
-{
-	return -ENXIO;
-}
-
-static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
-{
-	return -ENXIO;
-}
-
-unsigned int snd_compr_poll(struct file *f, poll_table *wait)
-{
-	struct snd_ioctl_data *data = f->private_data;
-	struct snd_compr_stream *stream;
-	int retval = 0;
-
-	BUG_ON(!data);
-	stream = &data->stream;
-
-	mutex_lock(&stream->device->lock);
-	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
-		retval = -ENXIO;
-		goto out;
-	}
-	poll_wait(f, &stream->runtime->sleep, wait);
-
-	/* this would change after read is implemented, we would need to
-	 * check for direction here */
-	if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
-		retval = POLLOUT | POLLWRNORM;
-out:
-	mutex_unlock(&stream->device->lock);
-	return retval;
-}
-
-void snd_compr_fragment_elapsed(struct snd_compr_stream *stream)
-{
-	size_t avail;
-
-	if (stream->direction !=  SNDRV_PCM_STREAM_PLAYBACK)
-		return;
-	avail = snd_compr_get_avail(stream);
-	if (avail >= stream->runtime->fragment_size)
-		wake_up(&stream->runtime->sleep);
-}
-EXPORT_SYMBOL_GPL(snd_compr_fragment_elapsed);
-
-void snd_compr_frame_elapsed(struct snd_compr_stream *stream)
-{
-	size_t avail;
-
-	if (stream->direction !=  SNDRV_PCM_STREAM_CAPTURE)
-		return;
-	avail = snd_compr_get_avail(stream);
-	if (avail)
-		wake_up(&stream->runtime->sleep);
-}
-EXPORT_SYMBOL_GPL(snd_compr_frame_elapsed);
-
-static int snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
-{
-	int retval;
-	struct snd_compr_caps caps;
-
-	if (!stream->ops->get_caps)
-		return -ENXIO;
-
-	retval = stream->ops->get_caps(stream, &caps);
-	if (retval)
-		goto out;
-	if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
-		retval = -EFAULT;
-out:
-	return retval;
-}
-
-static int snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
-{
-	int retval;
-	struct snd_compr_codec_caps *caps;
-
-	if (!stream->ops->get_codec_caps)
-		return -ENXIO;
-
-	caps = kmalloc(sizeof(*caps), GFP_KERNEL);
-	if (!caps)
-		return -ENOMEM;
-
-	retval = stream->ops->get_codec_caps(stream, caps);
-	if (retval)
-		goto out;
-	if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
-		retval = -EFAULT;
-
-out:
-	kfree(caps);
-	return retval;
-}
-
-/* revisit this with snd_pcm_preallocate_xxx */
-static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
-		struct snd_compr_params *params)
-{
-	unsigned int buffer_size;
-	void *buffer;
-
-	buffer_size = params->buffer.fragment_size * params->buffer.fragments;
-	if (stream->ops->copy) {
-		buffer = NULL;
-		/* if copy is defined the driver will be required to copy
-		 * the data from core
-		 */
-	} else {
-		buffer = kmalloc(buffer_size, GFP_KERNEL);
-		if (!buffer)
-			return -ENOMEM;
-	}
-	stream->runtime->fragment_size = params->buffer.fragment_size;
-	stream->runtime->fragments = params->buffer.fragments;
-	stream->runtime->buffer = buffer;
-	stream->runtime->buffer_size = buffer_size;
-	return 0;
-}
-
-static int snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
-{
-	struct snd_compr_params *params;
-	int retval;
-
-	if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
-		/*
-		 * we should allow parameter change only when stream has been
-		 * opened not in other cases
-		 */
-		params = kmalloc(sizeof(*params), GFP_KERNEL);
-		if (!params)
-			return -ENOMEM;
-		if (copy_from_user(params, (void __user *)arg, sizeof(*params)))
-			return -EFAULT;
-		retval = snd_compr_allocate_buffer(stream, params);
-		if (retval) {
-			kfree(params);
-			return -ENOMEM;
-		}
-		retval = stream->ops->set_params(stream, params);
-		if (retval)
-			goto out;
-		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-	} else
-		return -EPERM;
-out:
-	kfree(params);
-	return retval;
-}
-
-static int snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
-{
-	struct snd_compr_params *params;
-	int retval;
-
-	if (!stream->ops->get_params)
-		return -ENXIO;
-
-	params = kmalloc(sizeof(*params), GFP_KERNEL);
-	if (!params)
-		return -ENOMEM;
-	retval = stream->ops->get_params(stream, params);
-	if (retval)
-		goto out;
-	if (copy_to_user((char __user *)arg, params, sizeof(*params)))
-		retval = -EFAULT;
-
-out:
-	kfree(params);
-	return retval;
-}
-
-static int snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
-{
-	struct snd_compr_tstamp tstamp;
-
-	snd_compr_update_tstamp(stream, &tstamp);
-	if (copy_to_user((struct snd_compr_tstamp __user *)arg, &tstamp, sizeof(tstamp)))
-		return -EFAULT;
-	return 0;
-}
-
-static int snd_compr_pause(struct snd_compr_stream *stream)
-{
-	int retval;
-
-	if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED)
-		return 0;
-	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
-	if (!retval) {
-		stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
-		wake_up(&stream->runtime->sleep);
-	}
-	return retval;
-}
-
-static int snd_compr_resume(struct snd_compr_stream *stream)
-{
-	int retval;
-
-	if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
-		return -EPERM;
-	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
-	if (!retval)
-		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
-	return retval;
-}
-
-static int snd_compr_start(struct snd_compr_stream *stream)
-{
-	int retval;
-
-	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
-		return -EPERM;
-	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
-	if (!retval)
-		stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
-	return retval;
-}
-
-static int snd_compr_stop(struct snd_compr_stream *stream)
-{
-	int retval;
-
-	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
-		return -EPERM;
-	retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
-	if (!retval) {
-		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-		wake_up(&stream->runtime->sleep);
-	}
-	return retval;
-}
-
-static int snd_compr_drain(struct snd_compr_stream *stream)
-{
-	int retval;
-
-	if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED ||
-			stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
-		return -EPERM;
-	retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
-	if (!retval) {
-		stream->runtime->state = SNDRV_PCM_STATE_SETUP;
-		wake_up(&stream->runtime->sleep);
-	}
-	return retval;
-}
-
-static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
-{
-	struct snd_ioctl_data *data = f->private_data;
-	struct snd_compr_stream *stream;
-	int retval = -ENOTTY;
-
-	BUG_ON(!data);
-	stream = &data->stream;
-	mutex_lock(&stream->device->lock);
-	switch (_IOC_NR(cmd)) {
-	case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
-		retval = snd_compr_get_caps(stream, arg);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
-		retval = snd_compr_get_codec_caps(stream, arg);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
-		retval = snd_compr_set_params(stream, arg);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
-		retval = snd_compr_get_params(stream, arg);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
-		retval = snd_compr_tstamp(stream, arg);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_AVAIL):
-		retval = snd_compr_ioctl_avail(stream, arg);
-	case _IOC_NR(SNDRV_COMPRESS_PAUSE):
-		retval = snd_compr_pause(stream);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_RESUME):
-		retval = snd_compr_resume(stream);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_START):
-		retval = snd_compr_start(stream);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_STOP):
-		retval = snd_compr_stop(stream);
-		break;
-	case _IOC_NR(SNDRV_COMPRESS_DRAIN):
-		cmd = SND_COMPR_TRIGGER_DRAIN;
-		retval = snd_compr_drain(stream);
-		break;
-	}
-	mutex_unlock(&stream->device->lock);
-	return retval;
-}
-
-static const struct file_operations snd_comp_file = {
-	.owner =	THIS_MODULE,
-	.open =		snd_compr_open,
-	.release =	snd_compr_free,
-	.read =		snd_compr_read,
-	.write =	snd_compr_write,
-	.unlocked_ioctl = snd_compr_ioctl,
-	.mmap =		snd_compr_mmap,
-	.poll =		snd_compr_poll,
-};
-
-static int snd_compress_add_device(struct snd_compr *device)
-{
-	int ret;
-
-	struct snd_compr_misc *misc = kzalloc(sizeof(*misc), GFP_KERNEL);
-
-	misc->misc.name = device->name;
-	misc->misc.fops = &snd_comp_file;
-	misc->misc.minor = MISC_DYNAMIC_MINOR;
-	misc->compr = device;
-	ret = misc_register(&misc->misc);
-	if (ret) {
-		pr_err("couldn't register misc device\n");
-		kfree(misc);
-	} else {
-		pr_debug("Got minor %d\n", misc->misc.minor);
-		list_add_tail(&misc->list, &misc_list);
-	}
-	return ret;
-}
-
-static int snd_compress_remove_device(struct snd_compr *device)
-{
-	struct snd_compr_misc *misc, *__misc;
-
-	list_for_each_entry_safe(misc, __misc, &misc_list, list) {
-		if (device == misc->compr) {
-			misc_deregister(&misc->misc);
-			list_del(&device->list);
-			kfree(misc);
-		}
-	}
-	return 0;
-}
-/**
- * snd_compress_register - register compressed device
- *
- * @device: compressed device to register
- */
-int snd_compress_register(struct snd_compr *device)
-{
-	int retval;
-
-	if (device->name == NULL || device->dev == NULL || device->ops == NULL)
-		return -EINVAL;
-	BUG_ON(!device->ops->open);
-	BUG_ON(!device->ops->free);
-	BUG_ON(!device->ops->set_params);
-	BUG_ON(!device->ops->get_params);
-	BUG_ON(!device->ops->trigger);
-	BUG_ON(!device->ops->pointer);
-	BUG_ON(!device->ops->get_caps);
-	BUG_ON(!device->ops->get_codec_caps);
-
-	INIT_LIST_HEAD(&device->list);
-	/* todo register the compressed streams */
-	/* todo integrate with asoc */
-
-	/* register a compressed card  TBD if this needs change */
-
-	pr_debug("Registering compressed device %s\n", device->name);
-	mutex_lock(&device_mutex);
-	/*  register a msic device for now */
-	retval = snd_compress_add_device(device);
-	if (!retval)
-		list_add_tail(&device->list, &device_list);
-	mutex_unlock(&device_mutex);
-	return retval;
-}
-EXPORT_SYMBOL_GPL(snd_compress_register);
-
-int snd_compress_deregister(struct snd_compr *device)
-{
-	pr_debug("Removing compressed device %s\n", device->name);
-	mutex_lock(&device_mutex);
-	snd_compress_remove_device(device);
-	list_del(&device->list);
-	mutex_unlock(&device_mutex);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(snd_compress_deregister);
-
-static int __init snd_compress_init(void)
-{
-	return 0;
-}
-
-static void __exit snd_compress_exit(void)
-{
-}
-
-module_init(snd_compress_init);
-module_exit(snd_compress_exit);
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 1962ff0..7706e3e 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -50,6 +50,8 @@
 #define BITS_PER_REG		8
 #define MSM8X10_WCD_TX_PORT_NUMBER	4
 
+#define DAPM_MICBIAS_EXTERNAL_STANDALONE "MIC BIAS External Standalone"
+
 #define MSM8X10_WCD_I2S_MASTER_MODE_MASK	0x08
 #define MSM8X10_DINO_CODEC_BASE_ADDR		0xFE043000
 #define MSM8X10_DINO_CODEC_REG_SIZE		0x200
@@ -395,6 +397,32 @@
 	return temp;
 }
 
+static int __msm8x10_wcd_bulk_write(struct msm8x10_wcd *msm8x10_wcd,
+		unsigned short reg, int count, u8 *buf)
+{
+	int ret = -EINVAL;
+	mutex_lock(&msm8x10_wcd->io_lock);
+	if (MSM8X10_WCD_IS_HELICON_REG(reg))
+		ret = msm8x10_wcd_i2c_write(reg, count, buf);
+	else if (MSM8X10_WCD_IS_DINO_REG(reg))
+		ret = msm8x10_wcd_abh_write_device(msm8x10_wcd, reg,
+						buf, count);
+	if (ret < 0)
+		dev_err(msm8x10_wcd->dev,
+				"%s: codec bulk write failed\n", __func__);
+	mutex_unlock(&msm8x10_wcd->io_lock);
+	return ret;
+}
+
+int msm8x10_wcd_bulk_write(struct wcd9xxx_core_resource *core_res,
+			unsigned short reg, int count, u8 *buf)
+{
+	struct msm8x10_wcd *msm8x10_wcd =
+				(struct msm8x10_wcd *) core_res->parent;
+	return __msm8x10_wcd_bulk_write(msm8x10_wcd, reg, count, buf);
+}
+EXPORT_SYMBOL(msm8x10_wcd_bulk_write);
+
 int msm8x10_wcd_reg_read(struct wcd9xxx_core_resource *core_res,
 				unsigned short reg)
 {
@@ -1271,6 +1299,10 @@
 	"ZERO", "RX3", "RX2"
 };
 
+static const char * const rx_rdac3_text[] = {
+	"RX1", "RX2"
+};
+
 static const struct soc_enum rx_mix1_inp1_chain_enum =
 	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_RX1_B1_CTL, 0, 6, rx_mix1_text);
 
@@ -1312,6 +1344,10 @@
 	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_LO_DAC_CTL, 0, 3,
 	rx_rdac4_text);
 
+static const struct soc_enum rx_rdac3_enum  =
+	SOC_ENUM_SINGLE(MSM8X10_WCD_A_CDC_CONN_HPHR_DAC_CTL, 0, 2,
+	rx_rdac3_text);
+
 static const struct soc_enum adc2_enum =
 	SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(adc2_mux_text), adc2_mux_text);
 
@@ -1345,6 +1381,9 @@
 static const struct snd_kcontrol_new rx_dac4_mux =
 	SOC_DAPM_ENUM("RDAC4 MUX Mux", rx_rdac4_enum);
 
+static const struct snd_kcontrol_new rx_dac3_mux =
+	SOC_DAPM_ENUM("RDAC3 MUX Mux", rx_rdac3_enum);
+
 static const struct snd_kcontrol_new tx_adc2_mux =
 	SOC_DAPM_ENUM("ADC2 MUX Mux", adc2_enum);
 
@@ -1635,6 +1674,8 @@
 
 		/* Always pull up TxFe for TX2 to Micbias */
 		snd_soc_update_bits(codec, micb_int_reg, 0x04, 0x04);
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_MICB_1_CTL,
+					0x80, 0x80);
 		break;
 	case SND_SOC_DAPM_POST_PMU:
 		usleep_range(20000, 20100);
@@ -1642,6 +1683,8 @@
 		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_on);
 		break;
 	case SND_SOC_DAPM_POST_PMD:
+		snd_soc_update_bits(codec, MSM8X10_WCD_A_MICB_1_CTL,
+					0x80, 0x00);
 		/* Let MBHC module know so micbias switch to be off */
 		wcd9xxx_resmgr_notifier_call(&msm8x10_wcd->resmgr, e_post_off);
 
@@ -1972,7 +2015,10 @@
 
 	{"DAC1", "Switch", "RX1 CHAIN"},
 	{"HPHL DAC", "Switch", "RX1 CHAIN"},
-	{"HPHR DAC", NULL, "RX2 CHAIN"},
+	{"HPHR DAC", NULL, "RDAC3 MUX"},
+
+	{"RDAC3 MUX", "RX1", "RX1 CHAIN"},
+	{"RDAC3 MUX", "RX2", "RX2 CHAIN"},
 
 	{"LINEOUT", NULL, "LINEOUT PA"},
 	{"SPK_OUT", NULL, "SPK PA"},
@@ -2300,7 +2346,8 @@
 	SND_SOC_DAPM_OUTPUT("EAR"),
 
 	SND_SOC_DAPM_PGA_E("EAR PA", MSM8X10_WCD_A_RX_EAR_EN, 4, 0, NULL, 0,
-			msm8x10_wcd_codec_enable_ear_pa, SND_SOC_DAPM_POST_PMU),
+			msm8x10_wcd_codec_enable_ear_pa,
+			SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_MIXER("DAC1", MSM8X10_WCD_A_RX_EAR_EN, 6, 0, dac1_switch,
 		ARRAY_SIZE(dac1_switch)),
@@ -2414,6 +2461,8 @@
 		&rx2_mix2_inp1_mux),
 	SND_SOC_DAPM_MUX("RDAC4 MUX", SND_SOC_NOPM, 0, 0,
 		&rx_dac4_mux),
+	SND_SOC_DAPM_MUX("RDAC3 MUX", SND_SOC_NOPM, 0, 0,
+		&rx_dac3_mux),
 
 	SND_SOC_DAPM_SUPPLY("MICBIAS_REGULATOR", SND_SOC_NOPM,
 		ON_DEMAND_MICBIAS, 0,
@@ -2458,6 +2507,11 @@
 		MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
 		msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+	SND_SOC_DAPM_MICBIAS_E(DAPM_MICBIAS_EXTERNAL_STANDALONE,
+		MSM8X10_WCD_A_MICB_1_CTL,
+		7, 0, msm8x10_wcd_codec_enable_micbias,
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+		SND_SOC_DAPM_POST_PMD),
 
 	SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
 		msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
@@ -2709,6 +2763,30 @@
 	return ret;
 }
 
+static int msm8x10_wcd_enable_mbhc_micbias(struct snd_soc_codec *codec,
+	 bool enable)
+{
+	int rc;
+
+	if (enable)
+		rc = snd_soc_dapm_force_enable_pin(&codec->dapm,
+			DAPM_MICBIAS_EXTERNAL_STANDALONE);
+	else
+		rc = snd_soc_dapm_disable_pin(&codec->dapm,
+			DAPM_MICBIAS_EXTERNAL_STANDALONE);
+	snd_soc_dapm_sync(&codec->dapm);
+
+	snd_soc_update_bits(codec, WCD9XXX_A_MICB_1_CTL,
+		0x80, enable ? 0x80 : 0x00);
+	if (rc)
+		pr_debug("%s: Failed to force %s micbias", __func__,
+			enable ? "enable" : "disable");
+	else
+		pr_debug("%s: Trying force %s micbias", __func__,
+			enable ? "enable" : "disable");
+	return rc;
+}
+
 static void msm8x10_wcd_micb_internal(struct snd_soc_codec *codec, bool on)
 {
 	snd_soc_update_bits(codec, MSM8X10_WCD_A_MICB_1_INT_RBIAS,
@@ -3191,7 +3269,8 @@
 
 	ret = wcd9xxx_mbhc_init(&msm8x10_wcd_priv->mbhc,
 				&msm8x10_wcd_priv->resmgr,
-				codec, NULL, &mbhc_cb, &cdc_intr_ids,
+				codec, msm8x10_wcd_enable_mbhc_micbias,
+				&mbhc_cb, &cdc_intr_ids,
 				HELICON_MCLK_CLK_9P6MHZ, true);
 	if (ret) {
 		dev_err(msm8x10_wcd->dev, "%s: Failed to initialize mbhc\n",
@@ -3565,7 +3644,8 @@
 					MSM8X10_WCD_NUM_IRQ_REGS,
 					msm8x10_wcd_reg_read,
 					msm8x10_wcd_reg_write,
-					msm8x10_wcd_bulk_read);
+					msm8x10_wcd_bulk_read,
+					msm8x10_wcd_bulk_write);
 	if (wcd9xxx_core_irq_init(core_res)) {
 		dev_err(msm8x10->dev,
 				"%s: irq initialization failed\n", __func__);
diff --git a/sound/soc/codecs/msm_hdmi_codec_rx.c b/sound/soc/codecs/msm_hdmi_codec_rx.c
index 73c9547e..9cf37b4 100644
--- a/sound/soc/codecs/msm_hdmi_codec_rx.c
+++ b/sound/soc/codecs/msm_hdmi_codec_rx.c
@@ -21,8 +21,6 @@
 
 #define MSM_HDMI_PCM_RATES	SNDRV_PCM_RATE_48000
 
-static int msm_hdmi_audio_codec_return_value;
-
 struct msm_hdmi_audio_codec_rx_data {
 	struct platform_device *hdmi_core_pdev;
 	struct msm_hdmi_audio_codec_ops hdmi_ops;
@@ -86,18 +84,18 @@
 		struct snd_pcm_substream *substream,
 		struct snd_soc_dai *dai)
 {
+	int rv;
 	struct msm_hdmi_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->codec->dev);
 
-	msm_hdmi_audio_codec_return_value =
-		codec_data->hdmi_ops.hdmi_cable_status(
+	rv = codec_data->hdmi_ops.hdmi_cable_status(
 		codec_data->hdmi_core_pdev, 1);
-	if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) {
+	if (IS_ERR_VALUE(rv)) {
 		dev_err(dai->dev,
 			"%s() HDMI core is not ready\n", __func__);
 	}
 
-	return msm_hdmi_audio_codec_return_value;
+	return rv;
 }
 
 static int msm_hdmi_audio_codec_rx_dai_hw_params(
@@ -109,16 +107,17 @@
 	u32 level_shift  = 0; /* 0dB */
 	bool down_mix = 0;
 	u32 num_channels = params_channels(params);
-	int rc = 0;
+	int rv = 0;
 
 	struct msm_hdmi_audio_codec_rx_data *codec_data =
 			dev_get_drvdata(dai->codec->dev);
 
-	/*refer to HDMI spec CEA-861-E: Table 28 Audio InfoFrame Data Byte 4*/
-	if (IS_ERR_VALUE(msm_hdmi_audio_codec_return_value)) {
+	rv = codec_data->hdmi_ops.hdmi_cable_status(
+		codec_data->hdmi_core_pdev, 1);
+	if (IS_ERR_VALUE(rv)) {
 		dev_err(dai->dev,
 			"%s() HDMI core is not ready\n", __func__);
-		return msm_hdmi_audio_codec_return_value;
+		return rv;
 	}
 
 	switch (num_channels) {
@@ -153,16 +152,16 @@
 		__func__, num_channels, params_rate(params),
 		channel_allocation);
 
-	rc = codec_data->hdmi_ops.audio_info_setup(
+	rv = codec_data->hdmi_ops.audio_info_setup(
 			codec_data->hdmi_core_pdev,
 			params_rate(params), num_channels,
 			channel_allocation, level_shift, down_mix);
-	if (IS_ERR_VALUE(rc)) {
+	if (IS_ERR_VALUE(rv)) {
 		dev_err(dai->dev,
 			"%s() HDMI core is not ready\n", __func__);
 	}
 
-	return rc;
+	return rv;
 }
 
 static void msm_hdmi_audio_codec_rx_dai_shutdown(
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 4912cf04a..07f4a5b 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -514,31 +514,41 @@
 				struct snd_ctl_elem_value *ucontrol)
 {
 	u8 ear_pa_gain;
+	int rc = 0;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 
 	ear_pa_gain = snd_soc_read(codec, TAPAN_A_RX_EAR_GAIN);
-
 	ear_pa_gain = ear_pa_gain >> 5;
 
-	if (ear_pa_gain == 0x00) {
-		ucontrol->value.integer.value[0] = 0;
-	} else if (ear_pa_gain == 0x04) {
-		ucontrol->value.integer.value[0] = 1;
-	} else  {
+	switch (ear_pa_gain) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		ucontrol->value.integer.value[0] = ear_pa_gain;
+		break;
+	case 7:
+		ucontrol->value.integer.value[0] = (ear_pa_gain - 1);
+		break;
+	default:
+		rc = -EINVAL;
 		pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
-				__func__, ear_pa_gain);
-		return -EINVAL;
+		       __func__, ear_pa_gain);
+		break;
 	}
 
 	dev_dbg(codec->dev, "%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
 
-	return 0;
+	return rc;
 }
 
 static int tapan_pa_gain_put(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
 	u8 ear_pa_gain;
+	int rc = 0;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 
 	dev_dbg(codec->dev, "%s: ucontrol->value.integer.value[0]  = %ld\n",
@@ -546,17 +556,24 @@
 
 	switch (ucontrol->value.integer.value[0]) {
 	case 0:
-		ear_pa_gain = 0x00;
-		break;
 	case 1:
-		ear_pa_gain = 0x80;
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+		ear_pa_gain = ucontrol->value.integer.value[0];
+		break;
+	case 6:
+		ear_pa_gain = 0x07;
 		break;
 	default:
-		return -EINVAL;
+		rc = -EINVAL;
+		break;
 	}
-
-	snd_soc_update_bits(codec, TAPAN_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
-	return 0;
+	if (!rc)
+		snd_soc_update_bits(codec, TAPAN_A_RX_EAR_GAIN,
+				    0xE0, ear_pa_gain << 5);
+	return rc;
 }
 
 static int tapan_get_iir_enable_audio_mixer(
@@ -1017,9 +1034,13 @@
 	return 0;
 }
 
-static const char * const tapan_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const char * const tapan_ear_pa_gain_text[] = {"POS_6_DB", "POS_4P5_DB",
+						      "POS_3_DB", "POS_1P5_DB",
+						      "POS_0_DB", "NEG_2P5_DB",
+						      "NEG_12_DB"};
 static const struct soc_enum tapan_ear_pa_gain_enum[] = {
-		SOC_ENUM_SINGLE_EXT(2, tapan_ear_pa_gain_text),
+		SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tapan_ear_pa_gain_text),
+				    tapan_ear_pa_gain_text),
 };
 
 static const char *const tapan_anc_func_text[] = {"OFF", "ON"};
@@ -1099,7 +1120,7 @@
 	SOC_SINGLE_TLV("LINEOUT2 Volume", TAPAN_A_RX_LINE_2_GAIN, 0, 14, 1,
 		line_gain),
 
-	SOC_SINGLE_TLV("SPK DRV Volume", TAPAN_A_SPKR_DRV_GAIN, 3, 7, 1,
+	SOC_SINGLE_TLV("SPK DRV Volume", TAPAN_A_SPKR_DRV_GAIN, 3, 8, 1,
 		line_gain),
 
 	SOC_SINGLE_TLV("ADC1 Volume", TAPAN_A_TX_1_EN, 2, 19, 0, analog_gain),
@@ -1867,9 +1888,10 @@
 
 	switch (event) {
 	case SND_SOC_DAPM_PRE_PMU:
-		if (w->reg == TAPAN_A_TX_3_EN)
+		if (w->reg == TAPAN_A_TX_3_EN ||
+		    w->reg == TAPAN_A_TX_1_EN)
 			wcd9xxx_resmgr_notifier_call(&tapan->resmgr,
-						WCD9XXX_EVENT_PRE_TX_3_ON);
+						WCD9XXX_EVENT_PRE_TX_1_3_ON);
 		snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
 				1 << init_bit_shift);
 		break;
@@ -1879,9 +1901,10 @@
 
 		break;
 	case SND_SOC_DAPM_POST_PMD:
-		if (w->reg == TAPAN_A_TX_3_EN)
+		if (w->reg == TAPAN_A_TX_3_EN ||
+		    w->reg == TAPAN_A_TX_1_EN)
 			wcd9xxx_resmgr_notifier_call(&tapan->resmgr,
-						WCD9XXX_EVENT_POST_TX_3_OFF);
+						WCD9XXX_EVENT_POST_TX_1_3_OFF);
 		break;
 	}
 	return 0;
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 14218d8..32ca0c6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -98,7 +98,7 @@
  * Invalid voltage range for the detection
  * of plug type with current source
  */
-#define WCD9XXX_CS_MEAS_INVALD_RANGE_LOW_MV 110
+#define WCD9XXX_CS_MEAS_INVALD_RANGE_LOW_MV 160
 #define WCD9XXX_CS_MEAS_INVALD_RANGE_HIGH_MV 265
 
 /*
@@ -121,7 +121,7 @@
 #define WCD9XXX_V_CS_HS_MAX 500
 #define WCD9XXX_V_CS_NO_MIC 5
 #define WCD9XXX_MB_MEAS_DELTA_MAX_MV 80
-#define WCD9XXX_CS_MEAS_DELTA_MAX_MV 10
+#define WCD9XXX_CS_MEAS_DELTA_MAX_MV 12
 
 static int impedance_detect_en;
 module_param(impedance_detect_en, int,
@@ -1352,7 +1352,6 @@
 
 		vdce = __wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce,
 						 dce_z, (u32)mb_mv);
-
 		d->_vdces = vdce;
 		if (d->_vdces < no_mic)
 			d->_type = PLUG_TYPE_HEADPHONE;
@@ -1386,14 +1385,6 @@
 		}
 	}
 
-	if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
-		pr_debug("%s: HPHL PA was ON\n", __func__);
-	} else if (ch != sz && ch > 0) {
-		pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
-		type = PLUG_TYPE_INVALID;
-		goto exit;
-	}
-
 	delta_thr = ((highhph_cnt == sz) || highhph) ?
 			      WCD9XXX_MB_MEAS_DELTA_MAX_MV :
 			      WCD9XXX_CS_MEAS_DELTA_MAX_MV;
@@ -1445,6 +1436,30 @@
 		}
 	}
 
+	if (type == PLUG_TYPE_HEADSET && dgnd && !dgnd->mic_bias) {
+		/* if plug type is Headphone report as GND_MIC_SWAP */
+		if (dgnd->_type == PLUG_TYPE_HEADPHONE) {
+			pr_debug("%s: GND_MIC_SWAP\n", __func__);
+			type = PLUG_TYPE_GND_MIC_SWAP;
+			/*
+			 * if type is GND_MIC_SWAP we should not check
+			 * HPHL status hence goto exit
+			 */
+			goto exit;
+		} else if (dgnd->_type != PLUG_TYPE_HEADSET && !dmicbias) {
+			pr_debug("%s: Invalid, inconsistent types\n", __func__);
+			type = PLUG_TYPE_INVALID;
+		}
+	}
+
+	if (event_state & (1 << MBHC_EVENT_PA_HPHL)) {
+		pr_debug("%s: HPHL PA was ON\n", __func__);
+	} else if (ch != sz && ch > 0) {
+		pr_debug("%s: Invalid, inconsistent HPHL..\n", __func__);
+		type = PLUG_TYPE_INVALID;
+		goto exit;
+	}
+
 	if (!(event_state & (1UL << MBHC_EVENT_PA_HPHL))) {
 		if (((type == PLUG_TYPE_HEADSET ||
 		      type == PLUG_TYPE_HEADPHONE) && ch != sz)) {
@@ -1453,17 +1468,12 @@
 			type = PLUG_TYPE_INVALID;
 		}
 	}
-	if (type == PLUG_TYPE_HEADSET && dgnd && !dgnd->mic_bias) {
-		if ((dgnd->_vdces + WCD9XXX_CS_GM_SWAP_THRES_MIN_MV <
-		     minv) &&
-		    (dgnd->_vdces + WCD9XXX_CS_GM_SWAP_THRES_MAX_MV >
-		     maxv))
-			type = PLUG_TYPE_GND_MIC_SWAP;
-		else if (dgnd->_type != PLUG_TYPE_HEADSET && !dmicbias) {
-			pr_debug("%s: Invalid, inconsistent types\n", __func__);
-			type = PLUG_TYPE_INVALID;
-		}
-	}
+
+	if (type == PLUG_TYPE_HEADSET &&
+	    (mbhc->mbhc_cfg->micbias_enable_flags &
+	    (1 << MBHC_MICBIAS_ENABLE_REGULAR_HEADSET)))
+		mbhc->micbias_enable = true;
+
 exit:
 	pr_debug("%s: Plug type %d detected\n", __func__, type);
 	return type;
@@ -2034,7 +2044,8 @@
 
 		/* if PA is already on, switch micbias source to VDDIO */
 		if (mbhc->event_state &
-		    (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR))
+		    (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR |
+		     1 << MBHC_EVENT_PRE_TX_1_3_ON))
 			__wcd9xxx_switch_micbias(mbhc, 1, false, false);
 		wcd9xxx_start_hs_polling(mbhc);
 	} else if (plug_type == PLUG_TYPE_HIGH_HPH) {
@@ -4265,6 +4276,14 @@
 			if (!mbhc->polling_active)
 				wcd9xxx_enable_mbhc_txfe(mbhc, false);
 		}
+		if (mbhc->micbias_enable && mbhc->polling_active &&
+		    !(snd_soc_read(mbhc->codec, mbhc->mbhc_bias_regs.ctl_reg)
+	            & 0x80)) {
+			pr_debug("%s:Micbias turned off by recording, set up again",
+				 __func__);
+			snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg,
+					    0x80, 0x80);
+		}
 		break;
 	/* PA usage change */
 	case WCD9XXX_EVENT_PRE_HPHL_PA_ON:
@@ -4285,7 +4304,7 @@
 			hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
 		if (!(mbhc->event_state &
 		      (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR |
-		       1 << MBHC_EVENT_PRE_TX_3_ON)))
+		       1 << MBHC_EVENT_PRE_TX_1_3_ON)))
 			wcd9xxx_switch_micbias(mbhc, 0);
 		break;
 	case WCD9XXX_EVENT_POST_HPHR_PA_OFF:
@@ -4297,7 +4316,7 @@
 			hphrocp_off_report(mbhc, SND_JACK_OC_HPHL);
 		if (!(mbhc->event_state &
 		      (1 << MBHC_EVENT_PA_HPHL | 1 << MBHC_EVENT_PA_HPHR |
-		       1 << MBHC_EVENT_PRE_TX_3_ON)))
+		       1 << MBHC_EVENT_PRE_TX_1_3_ON)))
 			wcd9xxx_switch_micbias(mbhc, 0);
 		break;
 	/* Clock usage change */
@@ -4379,23 +4398,23 @@
 	case WCD9XXX_EVENT_POST_BG_MBHC_ON:
 		/* Not used for now */
 		break;
-	case WCD9XXX_EVENT_PRE_TX_3_ON:
+	case WCD9XXX_EVENT_PRE_TX_1_3_ON:
 		/*
 		 * if polling is ON, mbhc micbias not enabled
 		 *  switch micbias source to VDDIO
 		 */
-		set_bit(MBHC_EVENT_PRE_TX_3_ON, &mbhc->event_state);
+		set_bit(MBHC_EVENT_PRE_TX_1_3_ON, &mbhc->event_state);
 		if (!(snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg)
 		      & 0x80) &&
 		    mbhc->polling_active && !mbhc->mbhc_micbias_switched)
 			wcd9xxx_switch_micbias(mbhc, 1);
 		break;
-	case WCD9XXX_EVENT_POST_TX_3_OFF:
+	case WCD9XXX_EVENT_POST_TX_1_3_OFF:
 		/*
 		 * Switch back to micbias if HPH PA or TX3 path
 		 * is disabled
 		 */
-		clear_bit(MBHC_EVENT_PRE_TX_3_ON, &mbhc->event_state);
+		clear_bit(MBHC_EVENT_PRE_TX_1_3_ON, &mbhc->event_state);
 		if (mbhc->polling_active && mbhc->mbhc_micbias_switched &&
 		    !(mbhc->event_state & (1 << MBHC_EVENT_PA_HPHL |
 		      1 << MBHC_EVENT_PA_HPHR)))
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 98f73fc..b5031a6 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -123,8 +123,8 @@
 enum wcd9xxx_mbhc_event_state {
 	MBHC_EVENT_PA_HPHL,
 	MBHC_EVENT_PA_HPHR,
-	MBHC_EVENT_PRE_TX_3_ON,
-	MBHC_EVENT_POST_TX_3_OFF,
+	MBHC_EVENT_PRE_TX_1_3_ON,
+	MBHC_EVENT_POST_TX_1_3_OFF,
 };
 
 struct wcd9xxx_mbhc_general_cfg {
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index e56b182..4843b51 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -92,8 +92,8 @@
 
 	"WCD9XXX_EVENT_POST_RESUME",
 
-	"WCD9XXX_EVENT_PRE_TX_3_ON",
-	"WCD9XXX_EVENT_POST_TX_3_OFF",
+	"WCD9XXX_EVENT_PRE_TX_1_3_ON",
+	"WCD9XXX_EVENT_POST_TX_1_3_OFF",
 
 	"WCD9XXX_EVENT_LAST",
 };
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.h b/sound/soc/codecs/wcd9xxx-resmgr.h
index 9f383b6..29896fc 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.h
+++ b/sound/soc/codecs/wcd9xxx-resmgr.h
@@ -105,8 +105,8 @@
 
 	WCD9XXX_EVENT_POST_RESUME,
 
-	WCD9XXX_EVENT_PRE_TX_3_ON,
-	WCD9XXX_EVENT_POST_TX_3_OFF,
+	WCD9XXX_EVENT_PRE_TX_1_3_ON,
+	WCD9XXX_EVENT_POST_TX_1_3_OFF,
 
 	WCD9XXX_EVENT_LAST,
 };
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 373090e..635f125 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -1179,7 +1179,13 @@
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
 				compr->info.codec_param.codec.dts;
-			int modelIdLength = opt_dts.modelIdLength;
+			unsigned int modelIdLength = opt_dts.modelIdLength;
+			if (modelIdLength >= sizeof(modelId)) {
+				rc = -EINVAL;
+				pr_err("%s: ERROR: modelIdLength is"
+						"invalid\n", __func__);
+				return rc;
+			}
 			if (copy_from_user(modelId, (void *)opt_dts.modelId,
 				modelIdLength))
 				pr_err("%s: ERROR: copy modelId\n", __func__);
@@ -1222,8 +1228,14 @@
 			char modelId[128];
 			struct snd_dec_dts opt_dts =
 				compr->info.codec_param.codec.dts;
-			int modelIdLength = opt_dts.modelIdLength;
+			unsigned int modelIdLength = opt_dts.modelIdLength;
 			pr_debug("SND_AUDIOCODEC_DTS\n");
+			if (modelIdLength >= sizeof(modelId)) {
+				rc = -EINVAL;
+				pr_err("%s: ERROR: modelIdLength is"
+						"invalid\n", __func__);
+				return rc;
+			}
 			if (copy_from_user(modelId, (void *)opt_dts.modelId,
 				modelIdLength))
 				pr_err("%s: ERROR: copy modelId\n", __func__);
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 4c3a72e..9c00e95 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -1313,6 +1313,8 @@
 			SNDRV_PCM_HW_PARAM_CHANNELS);
 
 	pr_debug("%s()\n", __func__);
+	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+				   slim0_rx_bit_format);
 	rate->min = rate->max = 48000;
 	channels->min = channels->max = msm_slim_0_tx_ch;
 
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index c1ba26a..4eab965 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2012-2014, 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
@@ -99,6 +99,8 @@
 	.insert_detect = true,
 	.swap_gnd_mic = NULL,
 	.use_int_rbias = false,
+	.micbias_enable_flags = 1 << MBHC_MICBIAS_ENABLE_THRESHOLD_HEADSET |
+				1 << MBHC_MICBIAS_ENABLE_REGULAR_HEADSET,
 	.cs_enable_flags = (1 << MBHC_CS_ENABLE_POLLING |
 			    1 << MBHC_CS_ENABLE_INSERTION |
 			    1 << MBHC_CS_ENABLE_REMOVAL),
@@ -284,6 +286,8 @@
 					SNDRV_PCM_HW_PARAM_CHANNELS);
 
 	pr_debug("%s(), channel:%d\n", __func__, msm_pri_mi2s_tx_ch);
+	param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+					msm_sec_mi2s_rx_bit_format);
 	rate->min = rate->max = 48000;
 	channels->min = channels->max = msm_pri_mi2s_tx_ch;
 
@@ -607,21 +611,21 @@
 	btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
 					       MBHC_BTN_DET_V_BTN_HIGH);
 	btn_low[0] = -50;
-	btn_high[0] = 10;
-	btn_low[1] = 11;
-	btn_high[1] = 52;
-	btn_low[2] = 53;
-	btn_high[2] = 94;
-	btn_low[3] = 95;
-	btn_high[3] = 133;
-	btn_low[4] = 134;
-	btn_high[4] = 171;
-	btn_low[5] = 172;
-	btn_high[5] = 208;
-	btn_low[6] = 209;
-	btn_high[6] = 244;
-	btn_low[7] = 245;
-	btn_high[7] = 330;
+	btn_high[0] = 20;
+	btn_low[1] = 21;
+	btn_high[1] = 61;
+	btn_low[2] = 62;
+	btn_high[2] = 104;
+	btn_low[3] = 105;
+	btn_high[3] = 148;
+	btn_low[4] = 149;
+	btn_high[4] = 189;
+	btn_low[5] = 190;
+	btn_high[5] = 228;
+	btn_low[6] = 229;
+	btn_high[6] = 269;
+	btn_low[7] = 270;
+	btn_high[7] = 500;
 	n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
 	n_ready[0] = 80;
 	n_ready[1] = 68;
diff --git a/sound/soc/msm/qdsp6v2/audio_ocmem.c b/sound/soc/msm/qdsp6v2/audio_ocmem.c
index 4a25606..5be880d 100644
--- a/sound/soc/msm/qdsp6v2/audio_ocmem.c
+++ b/sound/soc/msm/qdsp6v2/audio_ocmem.c
@@ -536,6 +536,7 @@
 	mutex_unlock(&audio_ocmem_lcl.state_process_lock);
 fail_cmd:
 	pr_debug("%s: exit\n", __func__);
+	audio_ocmem_lcl.buf = NULL;
 	audio_ocmem_lcl.audio_ocmem_running = false;
 	return ret;
 }
@@ -834,6 +835,7 @@
 	ret = ocmem_free(OCMEM_LP_AUDIO, audio_ocmem_lcl.buf);
 	if (ret)
 		pr_err("%s: ocmem_free failed\n", __func__);
+	audio_ocmem_lcl.buf = NULL;
 }
 
 static int lpass_notifier_cb(struct notifier_block *this, unsigned long code,
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 7935100..d2352ff 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -49,8 +49,13 @@
 #define PARTIAL_DRAIN_ACK_EARLY_BY_MSEC	150
 #define MP3_OUTPUT_FRAME_SZ		1152
 #define AAC_OUTPUT_FRAME_SZ		1024
+#define AC3_OUTPUT_FRAME_SZ		1536
+#define EAC3_OUTPUT_FRAME_SZ		1536
 #define DSP_NUM_OUTPUT_FRAME_BUFFERED	2
 
+/* decoder parameter length */
+#define DDP_DEC_MAX_NUM_PARAM		18
+
 /* Default values used if user space does not set */
 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
@@ -66,6 +71,8 @@
 	int32_t stream_opened[2];
 	uint32_t initial_samples_drop;
 	uint32_t trailing_samples_drop;
+	uint32_t gapless_transition;
+	bool use_dsp_gapless_mode;
 };
 
 struct msm_compr_pdata {
@@ -73,6 +80,8 @@
 	struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
 	uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */
 	struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX];
+	bool use_dsp_gapless_mode;
+	struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX];
 };
 
 struct msm_compr_audio {
@@ -102,6 +111,8 @@
 	uint32_t cmd_ack;
 	uint32_t cmd_interrupt;
 	uint32_t drain_ready;
+	uint32_t stream_available;
+	uint32_t next_stream;
 
 	struct msm_compr_gapless_state gapless_state;
 
@@ -117,6 +128,7 @@
 	wait_queue_head_t drain_wait;
 	wait_queue_head_t flush_wait;
 	wait_queue_head_t close_wait;
+	wait_queue_head_t wait_for_stream_avail;
 
 	spinlock_t lock;
 };
@@ -128,6 +140,10 @@
 	struct eq_params equalizer;
 };
 
+struct msm_compr_dec_params {
+	struct snd_dec_ddp ddp_params;
+};
+
 static int msm_compr_set_volume(struct snd_compr_stream *cstream,
 				uint32_t volume_l, uint32_t volume_r)
 {
@@ -155,6 +171,23 @@
 	return rc;
 }
 
+static int msm_compr_send_ddp_cfg(struct audio_client *ac,
+				  struct snd_dec_ddp *ddp)
+{
+	int i, rc;
+	pr_debug("%s\n", __func__);
+	for (i = 0; i < ddp->params_length; i++) {
+		rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
+						ddp->params_value[i]);
+		if (rc) {
+			pr_err("sending params_id: %d failed\n",
+				ddp->params_id[i]);
+			return rc;
+		}
+	}
+	return 0;
+}
+
 static int msm_compr_send_buffer(struct msm_compr_audio *prtd)
 {
 	int buffer_length;
@@ -174,7 +207,7 @@
 
 	pr_debug("%s: bytes_received = %d copied_total = %d\n",
 		__func__, prtd->bytes_received, prtd->copied_total);
-	if (prtd->first_buffer)
+	if (prtd->first_buffer &&  prtd->gapless_state.use_dsp_gapless_mode)
 		q6asm_send_meta_data(prtd->audio_client,
 				prtd->gapless_state.initial_samples_drop,
 				prtd->gapless_state.trailing_samples_drop);
@@ -299,6 +332,8 @@
 			prtd->gapless_state.stream_opened[stream_id] = 0;
 			prtd->gapless_state.set_next_stream_id = false;
 		}
+		if (prtd->gapless_state.gapless_transition)
+			prtd->gapless_state.gapless_transition = 0;
 		spin_unlock(&prtd->lock);
 		break;
 	case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
@@ -343,6 +378,17 @@
 			break;
 		case ASM_STREAM_CMD_CLOSE:
 			pr_debug("ASM_DATA_CMD_CLOSE\n");
+			/*
+			 * wakeup wait for stream avail on stream 3
+			 * after stream 1 ends.
+			 */
+			if (prtd->next_stream) {
+				pr_debug("%s:CLOSE:wakeup wait for stream\n",
+								   __func__);
+				prtd->stream_available = 1;
+				wake_up(&prtd->wait_for_stream_avail);
+				prtd->next_stream = 0;
+			}
 			if (atomic_read(&prtd->close) &&
 			    atomic_read(&prtd->wait_on_close)) {
 				prtd->cmd_ack = 1;
@@ -406,7 +452,11 @@
 	case FORMAT_MPEG4_AAC:
 		memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
 		aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
-		aac_cfg.format = 0x03;
+		if (prtd->codec_param.codec.format ==
+					SND_AUDIOSTREAMFORMAT_MP4ADTS)
+			aac_cfg.format = 0x0;
+		else
+			aac_cfg.format = 0x03;
 		aac_cfg.ch_cfg = prtd->num_channels;
 		aac_cfg.sample_rate = prtd->sample_rate;
 		ret = q6asm_stream_media_format_block_aac(prtd->audio_client,
@@ -448,7 +498,8 @@
 	pr_debug("%s\n", __func__);
 	ret = q6asm_stream_open_write_v2(ac,
 				prtd->codec, bits_per_sample,
-				ac->stream_id, true/*gapless*/);
+				ac->stream_id,
+				prtd->gapless_state.use_dsp_gapless_mode);
 	if (ret < 0) {
 		pr_err("%s: Session out open failed\n", __func__);
 		 return -ENOMEM;
@@ -533,11 +584,20 @@
 		kfree(prtd);
 		return -ENOMEM;
 	}
+	pdata->dec_params[rtd->dai_link->be_id] =
+		 kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL);
+	if (!pdata->dec_params[rtd->dai_link->be_id]) {
+		pr_err("%s: Could not allocate memory for dec params\n",
+			__func__);
+		kfree(prtd);
+		return -ENOMEM;
+	}
 	prtd->audio_client = q6asm_audio_client_alloc(
 				(app_cb)compr_event_handler, prtd);
 	if (!prtd->audio_client) {
 		pr_err("%s: Could not allocate memory for client\n", __func__);
 		kfree(pdata->audio_effects[rtd->dai_link->be_id]);
+		kfree(pdata->dec_params[rtd->dai_link->be_id]);
 		kfree(prtd);
 		return -ENOMEM;
 	}
@@ -555,7 +615,15 @@
 	prtd->last_buffer = 0;
 	prtd->first_buffer = 1;
 	prtd->partial_drain_delay = 0;
+	prtd->next_stream = 0;
 	memset(&prtd->gapless_state, 0, sizeof(struct msm_compr_gapless_state));
+	/*
+	 * Update the use_dsp_gapless_mode from gapless struture with the value
+	 * part of platform data.
+	 */
+	prtd->gapless_state.use_dsp_gapless_mode = pdata->use_dsp_gapless_mode;
+
+	pr_debug("%s: gapless mode %d", __func__, pdata->use_dsp_gapless_mode);
 
 	spin_lock_init(&prtd->lock);
 
@@ -571,6 +639,7 @@
 	init_waitqueue_head(&prtd->drain_wait);
 	init_waitqueue_head(&prtd->flush_wait);
 	init_waitqueue_head(&prtd->close_wait);
+	init_waitqueue_head(&prtd->wait_for_stream_avail);
 
 	runtime->private_data = prtd;
 	populate_codec_list(prtd);
@@ -601,19 +670,6 @@
 	unsigned long flags;
 
 	pr_debug("%s\n", __func__);
-	pdata->cstream[soc_prtd->dai_link->be_id] = NULL;
-	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
-		if (atomic_read(&pdata->audio_ocmem_req) > 1)
-			atomic_dec(&pdata->audio_ocmem_req);
-		else if (atomic_cmpxchg(&pdata->audio_ocmem_req, 1, 0))
-			audio_ocmem_process_req(AUDIO, false);
-
-		msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
-						SNDRV_PCM_STREAM_PLAYBACK);
-	}
-
-	pr_debug("%s: ocmem_req: %d\n", __func__,
-		atomic_read(&pdata->audio_ocmem_req));
 
 	if (atomic_read(&prtd->eos)) {
 		ret = wait_event_timeout(prtd->eos_wait,
@@ -634,16 +690,30 @@
 	stream_id = ac->stream_id;
 	if (prtd->gapless_state.stream_opened[stream_id^1]) {
 		spin_unlock_irqrestore(&prtd->lock, flags);
+		pr_debug(" close stream %d", stream_id^1);
 		q6asm_stream_cmd(ac, CMD_CLOSE, stream_id^1);
 		spin_lock_irqsave(&prtd->lock, flags);
 	}
 	if (prtd->gapless_state.stream_opened[stream_id]) {
 		spin_unlock_irqrestore(&prtd->lock, flags);
+		pr_debug("close stream %d", stream_id);
 		q6asm_stream_cmd(ac, CMD_CLOSE, stream_id);
 		spin_lock_irqsave(&prtd->lock, flags);
 	}
 	spin_unlock_irqrestore(&prtd->lock, flags);
 
+	pdata->cstream[soc_prtd->dai_link->be_id] = NULL;
+	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
+		if (atomic_read(&pdata->audio_ocmem_req) > 1)
+			atomic_dec(&pdata->audio_ocmem_req);
+		else if (atomic_cmpxchg(&pdata->audio_ocmem_req, 1, 0))
+			audio_ocmem_process_req(AUDIO, false);
+		msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+						SNDRV_PCM_STREAM_PLAYBACK);
+	}
+
+	pr_debug("%s: ocmem_req: %d\n", __func__,
+		atomic_read(&pdata->audio_ocmem_req));
 	/* client buf alloc was with stream id 0, so free with the same */
 	ac->stream_id = 0;
 	q6asm_audio_client_buf_free_contiguous(dir, ac);
@@ -651,6 +721,7 @@
 	q6asm_audio_client_free(ac);
 
 	kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]);
+	kfree(pdata->dec_params[soc_prtd->dai_link->be_id]);
 	kfree(prtd);
 
 	return 0;
@@ -715,11 +786,13 @@
 
 	case SND_AUDIOCODEC_AC3: {
 		prtd->codec = FORMAT_AC3;
+		frame_sz = AC3_OUTPUT_FRAME_SZ;
 		break;
 	}
 
 	case SND_AUDIOCODEC_EAC3: {
 		prtd->codec = FORMAT_EAC3;
+		frame_sz = EAC3_OUTPUT_FRAME_SZ;
 		break;
 	}
 
@@ -762,6 +835,45 @@
 	return rc;
 }
 
+static int msm_compr_wait_for_stream_avail(struct msm_compr_audio *prtd,
+				    unsigned long *flags)
+{
+	int rc = 0;
+	pr_debug("next session is already in opened state\n");
+	prtd->next_stream = 1;
+	prtd->cmd_interrupt = 0;
+	spin_unlock_irqrestore(&prtd->lock, *flags);
+	/*
+	 * Wait for stream to be available, or the wait to be interrupted by
+	 * commands like flush or till a timeout of one second.
+	 */
+	rc = wait_event_timeout(prtd->wait_for_stream_avail,
+		prtd->stream_available || prtd->cmd_interrupt, 1 * HZ);
+	pr_err("%s:prtd->stream_available %d, prtd->cmd_interrupt %d rc %d\n",
+		   __func__, prtd->stream_available, prtd->cmd_interrupt, rc);
+
+	spin_lock_irqsave(&prtd->lock, *flags);
+	if (rc == 0) {
+		pr_err("%s: wait_for_stream_avail timed out\n",
+						__func__);
+		rc =  -ETIMEDOUT;
+	} else if (prtd->cmd_interrupt == 1) {
+		/*
+		 * This scenario might not happen as we do not allow
+		 * flush in transition state.
+		 */
+		pr_debug("%s: wait_for_stream_avail interrupted\n", __func__);
+		prtd->cmd_interrupt = 0;
+		prtd->stream_available = 0;
+		rc = -EINTR;
+	} else {
+		prtd->stream_available = 0;
+		rc = 0;
+	}
+	pr_debug("%s : rc = %d",  __func__, rc);
+	return rc;
+}
+
 static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd)
 {
 	struct snd_compr_runtime *runtime = cstream->runtime;
@@ -801,22 +913,18 @@
 				__func__, rc);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		pr_debug("%s: SNDRV_PCM_TRIGGER_STOP\n", __func__);
 		spin_lock_irqsave(&prtd->lock, flags);
-
+		pr_debug("%s: SNDRV_PCM_TRIGGER_STOP transition %d\n", __func__,
+					prtd->gapless_state.gapless_transition);
 		stream_id = ac->stream_id;
-		if (prtd->gapless_state.set_next_stream_id &&
-		    prtd->first_buffer) {
-			/*
-			 * Stream just switched for gapless, no buffers sent.
-			 * So seek needs to be applied to previous stream
-			 */
-			pr_debug("Seek previous stream as next stream hasn't started\n");
-			stream_id = stream_id^1;
-			ac->stream_id = stream_id;
-			prtd->first_buffer = 0;
-		}
 		atomic_set(&prtd->start, 0);
+		if (prtd->next_stream) {
+			pr_debug("%s: interrupt next track wait queues\n",
+								__func__);
+			prtd->cmd_interrupt = 1;
+			wake_up(&prtd->wait_for_stream_avail);
+			prtd->next_stream = 0;
+		}
 		if (atomic_read(&prtd->eos)) {
 			pr_debug("%s: interrupt eos wait queues", __func__);
 			prtd->cmd_interrupt = 1;
@@ -833,22 +941,27 @@
 		prtd->last_buffer = 0;
 		pr_debug("issue CMD_FLUSH\n");
 		prtd->cmd_ack = 0;
-		spin_unlock_irqrestore(&prtd->lock, flags);
-		rc = q6asm_stream_cmd(prtd->audio_client, CMD_FLUSH, stream_id);
-		if (rc < 0) {
-			pr_err("%s: flush cmd failed rc=%d\n",
-			       __func__, rc);
-			return rc;
-		}
-		rc = wait_event_timeout(prtd->flush_wait,
+		if (!prtd->gapless_state.gapless_transition) {
+			spin_unlock_irqrestore(&prtd->lock, flags);
+			rc = q6asm_stream_cmd(
+				prtd->audio_client, CMD_FLUSH, stream_id);
+			if (rc < 0) {
+				pr_err("%s: flush cmd failed rc=%d\n",
+							__func__, rc);
+				return rc;
+			}
+			rc = wait_event_timeout(prtd->flush_wait,
 					prtd->cmd_ack, 1 * HZ);
-		if (!rc) {
-			rc = -ETIMEDOUT;
-			pr_err("Flush cmd timeout\n");
-		} else
-			rc = 0; /* prtd->cmd_status == OK? 0 : -EPERM */
-
-		spin_lock_irqsave(&prtd->lock, flags);
+			if (!rc) {
+				rc = -ETIMEDOUT;
+				pr_err("Flush cmd timeout\n");
+			} else {
+				rc = 0; /* prtd->cmd_status == OK? 0 : -EPERM*/
+			}
+			spin_lock_irqsave(&prtd->lock, flags);
+		} else {
+			prtd->first_buffer = 0;
+		}
 		/* FIXME. only reset if flush was successful */
 		prtd->byte_offset  = 0;
 		prtd->copied_total = 0;
@@ -858,17 +971,27 @@
 		spin_unlock_irqrestore(&prtd->lock, flags);
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		pr_debug("SNDRV_PCM_TRIGGER_PAUSE_PUSH\n");
-		q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
-		atomic_set(&prtd->start, 0);
+		pr_debug("SNDRV_PCM_TRIGGER_PAUSE_PUSH transition %d\n",
+				prtd->gapless_state.gapless_transition);
+		if (!prtd->gapless_state.gapless_transition) {
+			q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+			atomic_set(&prtd->start, 0);
+		}
 		break;
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		pr_debug("SNDRV_PCM_TRIGGER_PAUSE_RELEASE\n");
-		atomic_set(&prtd->start, 1);
-		q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+		pr_debug("SNDRV_PCM_TRIGGER_PAUSE_RELEASE transition %d\n",
+				   prtd->gapless_state.gapless_transition);
+		if (!prtd->gapless_state.gapless_transition) {
+			atomic_set(&prtd->start, 1);
+			q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+		}
 		break;
 	case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
 		pr_debug("%s: SND_COMPR_TRIGGER_PARTIAL_DRAIN\n", __func__);
+		if (!prtd->gapless_state.use_dsp_gapless_mode) {
+			pr_debug("%s: set partial drain as drain\n", __func__);
+			cmd = SND_COMPR_TRIGGER_DRAIN;
+		}
 	case SND_COMPR_TRIGGER_DRAIN:
 		pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
 		/* Make sure all the data is sent to DSP before sending EOS */
@@ -915,6 +1038,7 @@
 		if ((cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN) &&
 		    (prtd->gapless_state.set_next_stream_id)) {
 			/* wait for the last buffer to be returned */
+
 			if (prtd->last_buffer) {
 				pr_debug("%s: last buffer drain\n", __func__);
 				rc = msm_compr_drain_buffer(prtd, &flags);
@@ -926,7 +1050,6 @@
 
 			/* send EOS */
 			prtd->cmd_ack = 0;
-			atomic_set(&prtd->eos, 1);
 			q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
 			pr_info("PARTIAL DRAIN, do not wait for EOS ack\n");
 
@@ -970,6 +1093,7 @@
 			prtd->app_pointer  = 0;
 			prtd->first_buffer = 1;
 			prtd->last_buffer = 0;
+			prtd->gapless_state.gapless_transition = 1;
 			/*
 			Don't reset these as these vars map to
 			total_bytes_transferred and total_bytes_available
@@ -1013,7 +1137,7 @@
 			rc = -EINTR;
 
 		/*FIXME : what if a flush comes while PC is here */
-		if (rc == 0 && (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN)) {
+		if (rc == 0) {
 			/*
 			 * Failed to open second stream in DSP for gapless
 			 * so prepare the current stream in session for gapless playback
@@ -1049,20 +1173,56 @@
 		prtd->cmd_interrupt = 0;
 		break;
 	case SND_COMPR_TRIGGER_NEXT_TRACK:
+		if (!prtd->gapless_state.use_dsp_gapless_mode) {
+			pr_debug("%s: ignore trigger next track\n", __func__);
+			rc = 0;
+			break;
+		}
 		pr_debug("%s: SND_COMPR_TRIGGER_NEXT_TRACK\n", __func__);
 		spin_lock_irqsave(&prtd->lock, flags);
 		rc = 0;
 		stream_id = ac->stream_id^1; /*next stream in gapless*/
+		/*
+		 * Wait if stream 1 has not completed before honoring next
+		 * track for stream 3. Scenario happens if second clip is
+		 * small and fills in one buffer so next track will be
+		 * called immediately.
+		 */
 		if (prtd->gapless_state.stream_opened[stream_id]) {
-			pr_debug("next session is already in opened state\n");
-			spin_unlock_irqrestore(&prtd->lock, flags);
-			break;
+			if (prtd->gapless_state.gapless_transition) {
+				rc = msm_compr_wait_for_stream_avail(prtd,
+								    &flags);
+			} else {
+				/*
+				 * If session is already opened break out if
+				 * the state is not gapless transition. This
+				 * is when seek happens after the last buffer
+				 * is sent to the driver. Next track would be
+				 * called again after last buffer is sent.
+				 */
+				pr_debug("next session is in opened state\n");
+				spin_unlock_irqrestore(&prtd->lock, flags);
+				break;
+			}
 		}
 		spin_unlock_irqrestore(&prtd->lock, flags);
+		if (rc < 0) {
+			/*
+			 * if return type EINTR  then reset to zero. Tiny
+			 * compress treats EINTR as error and prevents PARTIAL
+			 * DRAIN. EINTR is not an error. wait for stream avail
+			 * is interrupted by some other command like FLUSH.
+			 */
+			if (rc == -EINTR) {
+				pr_debug("%s: EINTR reset rc to 0\n", __func__);
+				rc = 0;
+			}
+			break;
+		}
 		rc = q6asm_stream_open_write_v2(prtd->audio_client,
-						prtd->codec, 16,
-						stream_id,
-						true /*gapless*/);
+				prtd->codec, 16,
+				stream_id,
+				prtd->gapless_state.use_dsp_gapless_mode);
 		if (rc < 0) {
 			pr_err("%s: Session out open failed for gapless\n",
 				 __func__);
@@ -1226,7 +1386,6 @@
 	 * since the available bytes fits fragment_size, copy the data right away
 	 */
 	spin_lock_irqsave(&prtd->lock, flags);
-
 	prtd->bytes_received += count;
 	if (atomic_read(&prtd->start)) {
 		if (atomic_read(&prtd->xrun)) {
@@ -1315,7 +1474,6 @@
 	prtd = cstream->runtime->private_data;
 	if (!prtd && !prtd->audio_client)
 		return -EINVAL;
-
 	ac = prtd->audio_client;
 	if (metadata->key == SNDRV_COMPRESS_ENCODER_PADDING) {
 		pr_debug("%s, got encoder padding %u", __func__, metadata->value[0]);
@@ -1449,6 +1607,74 @@
 	return 0;
 }
 
+static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	unsigned long fe_id = kcontrol->private_value;
+	struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+			snd_soc_platform_get_drvdata(platform);
+	struct msm_compr_dec_params *dec_params = NULL;
+	struct snd_compr_stream *cstream = NULL;
+	struct msm_compr_audio *prtd = NULL;
+	long *values = &(ucontrol->value.integer.value[0]);
+
+	pr_debug("%s\n", __func__);
+	if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+		pr_err("%s Received out of bounds fe_id %lu\n",
+			__func__, fe_id);
+		return -EINVAL;
+	}
+
+	cstream = pdata->cstream[fe_id];
+	dec_params = pdata->dec_params[fe_id];
+
+	if (!cstream || !dec_params) {
+		pr_err("%s: stream or dec_params inactive\n", __func__);
+		return -EINVAL;
+	}
+	prtd = cstream->runtime->private_data;
+	if (!prtd) {
+		pr_err("%s: cannot set dec_params\n", __func__);
+		return -EINVAL;
+	}
+	switch (prtd->codec) {
+	case FORMAT_MP3:
+	case FORMAT_MPEG4_AAC:
+		pr_debug("%s: no runtime parameters for codec: %d\n", __func__,
+			 prtd->codec);
+		break;
+	case FORMAT_AC3:
+	case FORMAT_EAC3: {
+		struct snd_dec_ddp *ddp = &dec_params->ddp_params;
+		int cnt;
+		ddp->params_length = (*values++);
+		if (ddp->params_length > DDP_DEC_MAX_NUM_PARAM) {
+			pr_err("%s: invalid num of params:: %d\n", __func__,
+				ddp->params_length);
+			return -EINVAL;
+		}
+		for (cnt = 0; cnt < ddp->params_length; cnt++) {
+			ddp->params_id[cnt] = *values++;
+			ddp->params_value[cnt] = *values++;
+		}
+		if (msm_compr_send_ddp_cfg(prtd->audio_client, ddp) < 0)
+			pr_err("%s: DDP CMD CFG failed\n", __func__);
+		break;
+	}
+	default:
+		break;
+	}
+	return 0;
+}
+
+static int msm_compr_dec_params_get(struct snd_kcontrol *kcontrol,
+				    struct snd_ctl_elem_value *ucontrol)
+{
+	/* dummy function */
+	return 0;
+}
+
 static int msm_compr_probe(struct snd_soc_platform *platform)
 {
 	struct msm_compr_pdata *pdata;
@@ -1468,9 +1694,17 @@
 		pdata->volume[i][0] = COMPRESSED_LR_VOL_MAX_STEPS;
 		pdata->volume[i][1] = COMPRESSED_LR_VOL_MAX_STEPS;
 		pdata->audio_effects[i] = NULL;
+		pdata->dec_params[i] = NULL;
 		pdata->cstream[i] = NULL;
 	}
 
+	/*
+	 * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL
+	 * through a mixer control before compress driver is opened. The mixer
+	 * control is used to decide if dsp gapless mode needs to be enabled.
+	 * Gapless is disabled by default.
+	 */
+	pdata->use_dsp_gapless_mode = false;
 	return 0;
 }
 
@@ -1494,6 +1728,16 @@
 	return 0;
 }
 
+static int msm_compr_dec_params_info(struct snd_kcontrol *kcontrol,
+				     struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 128;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xFFFFFFFF;
+	return 0;
+}
+
 static int msm_compr_add_volume_control(struct snd_soc_pcm_runtime *rtd)
 {
 	const char *mixer_ctl_name = "Compress Playback";
@@ -1580,7 +1824,7 @@
 
 	fe_audio_effects_config_control[0].name = mixer_str;
 	fe_audio_effects_config_control[0].private_value = rtd->dai_link->be_id;
-	pr_debug("Registering new mixer ctl %s", mixer_str);
+	pr_debug("Registering new mixer ctl %s\n", mixer_str);
 	snd_soc_add_platform_controls(rtd->platform,
 				fe_audio_effects_config_control,
 				ARRAY_SIZE(fe_audio_effects_config_control));
@@ -1588,6 +1832,89 @@
 	return 0;
 }
 
+static int msm_compr_gapless_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+		snd_soc_platform_get_drvdata(platform);
+	pdata->use_dsp_gapless_mode =  ucontrol->value.integer.value[0];
+	pr_debug("%s: value: %ld\n", __func__,
+		ucontrol->value.integer.value[0]);
+
+	return 0;
+}
+
+static int msm_compr_gapless_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct snd_soc_platform *platform = snd_kcontrol_chip(kcontrol);
+	struct msm_compr_pdata *pdata =
+		snd_soc_platform_get_drvdata(platform);
+	pr_debug("%s:gapless mode %d\n", __func__, pdata->use_dsp_gapless_mode);
+	ucontrol->value.integer.value[0] = pdata->use_dsp_gapless_mode;
+
+	return 0;
+}
+
+static const struct snd_kcontrol_new msm_compr_gapless_controls[] = {
+	SOC_SINGLE_EXT("Compress Gapless Playback",
+			0, 0, 1, 0,
+			msm_compr_gapless_get,
+			msm_compr_gapless_put),
+};
+
+static int msm_compr_add_dec_runtime_params_control(
+						struct snd_soc_pcm_runtime *rtd)
+{
+	const char *mixer_ctl_name	= "Audio Stream";
+	const char *deviceNo		= "NN";
+	const char *suffix		= "Dec Params";
+	char *mixer_str = NULL;
+	int ctl_len;
+	struct snd_kcontrol_new fe_dec_params_control[1] = {
+		{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "?",
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = msm_compr_dec_params_info,
+		.get = msm_compr_dec_params_get,
+		.put = msm_compr_dec_params_put,
+		.private_value = 0,
+		}
+	};
+
+	if (!rtd) {
+		pr_err("%s NULL rtd\n", __func__);
+		return 0;
+	}
+
+	pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n",
+		 __func__, rtd->dai_link->name, rtd->dai_link->be_id,
+		 rtd->dai_link->cpu_dai_name, rtd->pcm->device);
+
+	ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
+		  strlen(suffix) + 1;
+	mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+
+	if (!mixer_str) {
+		pr_err("failed to allocate mixer ctrl str of len %d", ctl_len);
+		return 0;
+	}
+
+	snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name,
+		 rtd->pcm->device, suffix);
+
+	fe_dec_params_control[0].name = mixer_str;
+	fe_dec_params_control[0].private_value = rtd->dai_link->be_id;
+	pr_debug("Registering new mixer ctl %s", mixer_str);
+	snd_soc_add_platform_controls(rtd->platform,
+				      fe_dec_params_control,
+				      ARRAY_SIZE(fe_dec_params_control));
+	kfree(mixer_str);
+	return 0;
+}
+
 static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
 {
 	int rc;
@@ -1599,6 +1926,10 @@
 	if (rc)
 		pr_err("%s: Could not add Compr Audio Effects Control\n",
 			__func__);
+	rc = msm_compr_add_dec_runtime_params_control(rtd);
+	if (rc)
+		pr_err("%s: Could not add Compr Dec runtime params Control\n",
+			__func__);
 	return 0;
 }
 
@@ -1618,7 +1949,10 @@
 static struct snd_soc_platform_driver msm_soc_platform = {
 	.probe		= msm_compr_probe,
 	.compr_ops	= &msm_compr_ops,
-	.pcm_new = msm_compr_new,
+	.pcm_new	= msm_compr_new,
+	.controls       = msm_compr_gapless_controls,
+	.num_controls   = ARRAY_SIZE(msm_compr_gapless_controls),
+
 };
 
 static __devinit int msm_compr_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 3f57078..ff82299 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -170,6 +170,9 @@
 				 */
 				rc = -EFAULT;
 			} else {
+				if (!access_ok(VERIFY_READ, user,
+					sizeof(struct snd_lsm_event_status)))
+					rc = -EFAULT;
 				if (user->payload_size <
 				    event_status->payload_size) {
 					pr_debug("%s: provided %dbytes isn't enough, needs %dbytes\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 3ddc3e0..32eaebf 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -188,6 +188,7 @@
 		} else {
 			pr_debug("%s: reclaim flushed buf in_count %x\n",
 				__func__, atomic_read(&prtd->in_count));
+			prtd->pcm_irq_pos += prtd->pcm_count;
 			atomic_inc(&prtd->in_count);
 			if (atomic_read(&prtd->in_count) == prtd->periods) {
 				pr_info("%s: reclaimed all bufs\n", __func__);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 91c0744..2c001fa 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2784,6 +2784,7 @@
 int msm_routing_get_rms_value_control(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol) {
 	int rc = 0;
+	int be_idx = 0;
 	char *param_value;
 	int *update_param_value;
 	uint32_t param_length = sizeof(uint32_t);
@@ -2793,21 +2794,26 @@
 		pr_err("%s, param memory alloc failed\n", __func__);
 		return -ENOMEM;
 	}
-	rc = adm_get_params(SLIMBUS_0_TX,
-			RMS_MODULEID_APPI_PASSTHRU,
-			RMS_PARAM_FIRST_SAMPLE,
-			param_length + param_payload_len,
-			param_value);
-	if (rc) {
-		pr_err("%s: get parameters failed\n", __func__);
-		kfree(param_value);
-		return -EINVAL;
-	}
-	update_param_value = (int *)param_value;
-	ucontrol->value.integer.value[0] = update_param_value[0];
+	for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++)
+		if (msm_bedais[be_idx].port_id == SLIMBUS_0_TX)
+			break;
+	if ((be_idx < MSM_BACKEND_DAI_MAX) && msm_bedais[be_idx].active) {
+		rc = adm_get_params(SLIMBUS_0_TX,
+				RMS_MODULEID_APPI_PASSTHRU,
+				RMS_PARAM_FIRST_SAMPLE,
+				param_length + param_payload_len,
+				param_value);
+		if (rc) {
+			pr_err("%s: get parameters failed\n", __func__);
+			kfree(param_value);
+			return -EINVAL;
+		}
+		update_param_value = (int *)param_value;
+		ucontrol->value.integer.value[0] = update_param_value[0];
 
-	pr_debug("%s: FROM DSP value[0] 0x%x\n",
-		__func__, update_param_value[0]);
+		pr_debug("%s: FROM DSP value[0] 0x%x\n",
+			  __func__, update_param_value[0]);
+	}
 	kfree(param_value);
 	return 0;
 }
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 97c7b5d..e3c8944 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -86,6 +86,10 @@
 struct voip_frame_hdr {
 	uint32_t timestamp;
 	union {
+		/*
+		 * Bits 0-15: Frame type
+		 * Bits 16-31: Frame rate
+		 */
 		uint32_t frame_type;
 		uint32_t packet_rate;
 	};
@@ -162,8 +166,6 @@
 				    struct snd_ctl_elem_value *ucontrol);
 static int msm_voip_rate_config_put(struct snd_kcontrol *kcontrol,
 				    struct snd_ctl_elem_value *ucontrol);
-static int msm_voip_rate_config_get(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol);
 static int msm_voip_evrc_min_max_rate_config_put(struct snd_kcontrol *kcontrol,
 					 struct snd_ctl_elem_value *ucontrol);
 static int msm_voip_evrc_min_max_rate_config_get(struct snd_kcontrol *kcontrol,
@@ -277,7 +279,7 @@
 	SOC_SINGLE_EXT("Voip Mode Config", SND_SOC_NOPM, 0, VOIP_MODE_MAX, 0,
 		       msm_voip_mode_config_get, msm_voip_mode_config_put),
 	SOC_SINGLE_EXT("Voip Rate Config", SND_SOC_NOPM, 0, VOIP_RATE_MAX, 0,
-		       msm_voip_rate_config_get, msm_voip_rate_config_put),
+		       NULL, msm_voip_rate_config_put),
 	SOC_SINGLE_MULTI_EXT("Voip Evrc Min Max Rate Config", SND_SOC_NOPM,
 			     0, VOC_1_RATE, 0, 2, msm_voip_evrc_min_max_rate_config_get,
 			     msm_voip_evrc_min_max_rate_config_put),
@@ -385,6 +387,8 @@
 	struct voip_buf_node *buf_node = NULL;
 	struct voip_drv_info *prtd = private_data;
 	unsigned long dsp_flags;
+	uint32_t rate_type;
+	uint32_t frame_rate;
 
 	if (prtd->playback_substream == NULL)
 		return;
@@ -408,7 +412,19 @@
 			 * Bits 4-7: Frame type
 			 */
 			*voc_pkt = ((buf_node->frame.frm_hdr.frame_type &
-					0x0F) << 4) | (prtd->rate_type & 0x0F);
+				   0x0F) << 4);
+			frame_rate = (buf_node->frame.frm_hdr.frame_type &
+				     0xFFFF0000) >> 16;
+			if (frame_rate) {
+				if (voip_get_rate_type(prtd->mode, frame_rate,
+						       &rate_type)) {
+					pr_err("%s(): fail at getting rate_type \n",
+						__func__);
+				} else
+					prtd->rate_type = rate_type;
+			}
+			*voc_pkt |= prtd->rate_type & 0x0F;
+
 			voc_pkt = voc_pkt + DSP_FRAME_HDR_LEN;
 			memcpy(voc_pkt,
 				&buf_node->frame.voc_pkt[0],
@@ -1087,30 +1103,43 @@
 	return 0;
 }
 
-static int msm_voip_rate_config_get(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	mutex_lock(&voip_info.lock);
-
-	ucontrol->value.integer.value[0] = voip_info.rate;
-
-	mutex_unlock(&voip_info.lock);
-
-	return 0;
-}
-
 static int msm_voip_rate_config_put(struct snd_kcontrol *kcontrol,
 				    struct snd_ctl_elem_value *ucontrol)
 {
+	int ret = 0;
+	int rate = ucontrol->value.integer.value[0];
+
 	mutex_lock(&voip_info.lock);
 
-	voip_info.rate = ucontrol->value.integer.value[0];
+	if (voip_info.rate != rate) {
+		voip_info.rate = rate;
+		pr_debug("%s: rate=%d\n", __func__, voip_info.rate);
 
-	pr_debug("%s: rate=%d\n", __func__, voip_info.rate);
+		if (voip_info.state == VOIP_STARTED &&
+		   (voip_info.mode == MODE_AMR ||
+		    voip_info.mode == MODE_AMR_WB)) {
+			ret = voip_config_vocoder(
+					voip_info.capture_substream);
+			if (ret) {
+				pr_err("%s:Failed to configure vocoder, ret=%d\n",
+					__func__, ret);
 
+				goto done;
+			}
+
+			ret = voc_update_amr_vocoder_rate(
+					voc_get_session_id(VOIP_SESSION_NAME));
+			if (ret) {
+				pr_err("%s:Failed to update AMR rate, ret=%d\n",
+					__func__, ret);
+			}
+		}
+	}
+
+done:
 	mutex_unlock(&voip_info.lock);
 
-	return 0;
+	return ret;
 }
 
 static int msm_voip_evrc_min_max_rate_config_get(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 54b1263..3e30290 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -93,6 +93,11 @@
 		sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
 			sizeof(struct srs_trumedia_params_GLOBAL);
 		adm_params = kzalloc(sz, GFP_KERNEL);
+		if (!adm_params) {
+			pr_err("%s, adm params memory alloc failed\n",
+				__func__);
+			return -ENOMEM;
+		}
 		adm_params->payload_size =
 			sizeof(struct srs_trumedia_params_GLOBAL) +
 			sizeof(struct adm_param_data_v5);
@@ -117,6 +122,11 @@
 		sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
 			sizeof(struct srs_trumedia_params_WOWHD);
 		adm_params = kzalloc(sz, GFP_KERNEL);
+		if (!adm_params) {
+			pr_err("%s, adm params memory alloc failed\n",
+				__func__);
+			return -ENOMEM;
+		}
 		adm_params->payload_size =
 			sizeof(struct srs_trumedia_params_WOWHD) +
 			sizeof(struct adm_param_data_v5);
@@ -142,6 +152,11 @@
 		sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
 			sizeof(struct srs_trumedia_params_CSHP);
 		adm_params = kzalloc(sz, GFP_KERNEL);
+		if (!adm_params) {
+			pr_err("%s, adm params memory alloc failed\n",
+				__func__);
+			return -ENOMEM;
+		}
 		adm_params->payload_size =
 			sizeof(struct srs_trumedia_params_CSHP) +
 			sizeof(struct adm_param_data_v5);
@@ -166,6 +181,11 @@
 		sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
 			sizeof(struct srs_trumedia_params_HPF);
 		adm_params = kzalloc(sz, GFP_KERNEL);
+		if (!adm_params) {
+			pr_err("%s, adm params memory alloc failed\n",
+				__func__);
+			return -ENOMEM;
+		}
 		adm_params->payload_size =
 			sizeof(struct srs_trumedia_params_HPF) +
 			sizeof(struct adm_param_data_v5);
@@ -186,6 +206,11 @@
 		sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
 			sizeof(struct srs_trumedia_params_PEQ);
 		adm_params = kzalloc(sz, GFP_KERNEL);
+		if (!adm_params) {
+			pr_err("%s, adm params memory alloc failed\n",
+				__func__);
+			return -ENOMEM;
+		}
 		adm_params->payload_size =
 				sizeof(struct srs_trumedia_params_PEQ) +
 				sizeof(struct adm_param_data_v5);
@@ -208,6 +233,11 @@
 		sz = sizeof(struct adm_cmd_set_pp_params_inband_v5) +
 			sizeof(struct srs_trumedia_params_HL);
 		adm_params = kzalloc(sz, GFP_KERNEL);
+		if (!adm_params) {
+			pr_err("%s, adm params memory alloc failed\n",
+				__func__);
+			return -ENOMEM;
+		}
 		adm_params->payload_size =
 			sizeof(struct srs_trumedia_params_HL) +
 			sizeof(struct adm_param_data_v5);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 24f5f3b..ee26f2e 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -335,15 +335,12 @@
 static int q6asm_session_alloc(struct audio_client *ac)
 {
 	int n;
-	mutex_lock(&session_lock);
 	for (n = 1; n <= SESSION_MAX; n++) {
 		if (!session[n]) {
 			session[n] = ac;
-			mutex_unlock(&session_lock);
 			return n;
 		}
 	}
-	mutex_unlock(&session_lock);
 	return -ENOMEM;
 }
 
@@ -351,9 +348,7 @@
 {
 	pr_debug("%s: sessionid[%d]\n", __func__, ac->session);
 	rtac_remove_popp_from_adm_devices(ac->session);
-	mutex_lock(&session_lock);
 	session[ac->session] = 0;
-	mutex_unlock(&session_lock);
 	ac->session = 0;
 	ac->perf_mode = LEGACY_PCM_MODE;
 	ac->fptr_cache_ops = NULL;
@@ -724,6 +719,9 @@
 	struct audio_port_data *port;
 	if (!ac || !ac->session)
 		return;
+
+	mutex_lock(&session_lock);
+
 	pr_debug("%s: Session id %d\n", __func__, ac->session);
 	if (ac->io_mode & SYNC_IO_MODE) {
 		for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
@@ -748,6 +746,8 @@
 /*done:*/
 	kfree(ac);
 	ac = NULL;
+	mutex_unlock(&session_lock);
+
 	return;
 }
 
@@ -804,9 +804,13 @@
 	ac = kzalloc(sizeof(struct audio_client), GFP_KERNEL);
 	if (!ac)
 		return NULL;
+
+	mutex_lock(&session_lock);
 	n = q6asm_session_alloc(ac);
-	if (n <= 0)
+	if (n <= 0) {
+		mutex_unlock(&session_lock);
 		goto fail_session;
+	}
 	ac->session = n;
 	ac->cb = cb;
 	ac->priv = priv;
@@ -820,7 +824,8 @@
 
 	if (ac->apr == NULL) {
 		pr_err("%s Registration with APR failed\n", __func__);
-			goto fail;
+		mutex_unlock(&session_lock);
+		goto fail;
 	}
 	ac->apr2 = apr_register("ADSP", "ASM", \
 				(apr_fn)q6asm_callback,\
@@ -829,14 +834,17 @@
 
 	if (ac->apr2 == NULL) {
 		pr_err("%s Registration with APR-2 failed\n", __func__);
-			goto fail;
+		mutex_unlock(&session_lock);
+		goto fail;
 	}
 	rtac_set_asm_handle(n, ac->apr);
 
 	pr_debug("%s Registering the common port with APR\n", __func__);
 	ac->mmap_apr = q6asm_mmap_apr_reg();
-	if (ac->mmap_apr == NULL)
+	if (ac->mmap_apr == NULL) {
+		mutex_unlock(&session_lock);
 		goto fail;
+        }
 
 	init_waitqueue_head(&ac->cmd_wait);
 	init_waitqueue_head(&ac->time_wait);
@@ -856,6 +864,8 @@
 
 	pr_debug("%s: session[%d]\n", __func__, ac->session);
 
+	mutex_unlock(&session_lock);
+
 	return ac;
 fail:
 	q6asm_audio_client_free(ac);
@@ -1056,8 +1066,11 @@
 {
 	uint32_t sid = 0;
 	uint32_t dir = 0;
+	uint32_t i = IN;
 	uint32_t *payload;
 	unsigned long dsp_flags;
+	struct asm_buffer_node *buf_node = NULL;
+	struct list_head *ptr, *next;
 
 	struct audio_client *ac = NULL;
 	struct audio_port_data *port;
@@ -1076,6 +1089,20 @@
 				data->reset_proc,
 				this_mmap.apr);
 		apr_reset(this_mmap.apr);
+		for (; i <= OUT; i++) {
+			list_for_each_safe(ptr, next,
+				&common_client.port[i].mem_map_handle) {
+				buf_node = list_entry(ptr,
+						struct asm_buffer_node,
+						list);
+				if (buf_node->buf_addr_lsw ==
+				common_client.port[i].buf->phys) {
+					list_del(&buf_node->list);
+					kfree(buf_node);
+				}
+			}
+			pr_debug("%s:Clearing custom topology\n", __func__);
+		}
 		this_mmap.apr = NULL;
 		reset_custom_topology_flags();
 		set_custom_topology = 1;
@@ -1209,6 +1236,9 @@
 	}
 
 	if (data->opcode == RESET_EVENTS) {
+		if(ac->apr == NULL) {
+		    ac->apr = ac->apr2;
+		}
 		pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",
 				data->reset_event, data->reset_proc, ac->apr);
 			if (ac->cb)
@@ -3073,6 +3103,9 @@
 		rc = -EINVAL;
 		goto fail_cmd;
 	}
+
+	rc = 0;
+fail_cmd:
 	list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
 		buf_node = list_entry(ptr, struct asm_buffer_node,
 						list);
@@ -3082,9 +3115,6 @@
 			break;
 		}
 	}
-
-	rc = 0;
-fail_cmd:
 	return rc;
 }
 
@@ -3252,6 +3282,9 @@
 		pr_err("timeout. waited for memory_unmap\n");
 		goto fail_cmd;
 	}
+	rc = 0;
+
+fail_cmd:
 	list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
 		buf_node = list_entry(ptr, struct asm_buffer_node,
 						list);
@@ -3261,9 +3294,6 @@
 			break;
 		}
 	}
-	rc = 0;
-
-fail_cmd:
 	return rc;
 }
 
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index c4395c2..06ee692 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1,4 +1,4 @@
-/*  Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/*  Copyright (c) 2012-2014, 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
@@ -29,7 +29,7 @@
 #include "q6voice.h"
 
 
-#define TIMEOUT_MS 200
+#define TIMEOUT_MS 300
 
 
 #define CMD_STATUS_SUCCESS 0
@@ -943,6 +943,7 @@
 
 	if (is_voip_session(v->session_id) ||
 	    is_qchat_session(v->session_id) ||
+	    is_volte_session(v->session_id) ||
 	    v->voc_state == VOC_ERROR) {
 		/* Destroy CVS. */
 		pr_debug("%s: CVS destroy session\n", __func__);
@@ -1493,6 +1494,77 @@
 	return ret;
 }
 
+static int voice_config_cvs_vocoder_amr_rate(struct voice_data *v)
+{
+	int ret = 0;
+	void *apr_cvs;
+	u16 cvs_handle;
+	struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate;
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL\n", __func__);
+
+		ret = -EINVAL;
+		goto done;
+	}
+	apr_cvs = common.apr_q6_cvs;
+
+	if (!apr_cvs) {
+		pr_err("%s: apr_cvs is NULL.\n", __func__);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	cvs_handle = voice_get_cvs_handle(v);
+
+	pr_debug("%s: Setting AMR rate. Media Type: %d\n", __func__,
+		 common.mvs_info.media_type);
+
+	cvs_set_amr_rate.hdr.hdr_field =
+			APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+			APR_HDR_LEN(APR_HDR_SIZE),
+			APR_PKT_VER);
+	cvs_set_amr_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+			       sizeof(cvs_set_amr_rate) - APR_HDR_SIZE);
+	cvs_set_amr_rate.hdr.src_port =
+			voice_get_idx_for_session(v->session_id);
+	cvs_set_amr_rate.hdr.dest_port = cvs_handle;
+	cvs_set_amr_rate.hdr.token = 0;
+
+	if (common.mvs_info.media_type == VSS_MEDIA_ID_AMR_NB_MODEM)
+		cvs_set_amr_rate.hdr.opcode =
+				VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE;
+	else if (common.mvs_info.media_type == VSS_MEDIA_ID_AMR_WB_MODEM)
+		cvs_set_amr_rate.hdr.opcode =
+				VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE;
+
+	cvs_set_amr_rate.amr_rate.mode = common.mvs_info.rate;
+
+	v->cvs_state = CMD_STATUS_FAIL;
+
+	ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_amr_rate);
+	if (ret < 0) {
+		pr_err("%s: Error %d sending SET_AMR_RATE\n",
+		       __func__, ret);
+
+		goto done;
+	}
+	ret = wait_event_timeout(v->cvs_wait,
+				 (v->cvs_state == CMD_STATUS_SUCCESS),
+				 msecs_to_jiffies(TIMEOUT_MS));
+	if (!ret) {
+		pr_err("%s: wait_event timeout\n", __func__);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	return 0;
+done:
+	return ret;
+}
+
 static int voice_config_cvs_vocoder(struct voice_data *v)
 {
 	int ret = 0;
@@ -1597,80 +1669,13 @@
 
 		break;
 	}
-	case VSS_MEDIA_ID_AMR_NB_MODEM: {
-		struct cvs_set_amr_enc_rate_cmd cvs_set_amr_rate;
-
-		pr_debug("Setting AMR rate\n");
-
-		cvs_set_amr_rate.hdr.hdr_field =
-				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-				APR_HDR_LEN(APR_HDR_SIZE),
-				APR_PKT_VER);
-		cvs_set_amr_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-				       sizeof(cvs_set_amr_rate) - APR_HDR_SIZE);
-		cvs_set_amr_rate.hdr.src_port =
-				voice_get_idx_for_session(v->session_id);
-		cvs_set_amr_rate.hdr.dest_port = cvs_handle;
-		cvs_set_amr_rate.hdr.token = 0;
-		cvs_set_amr_rate.hdr.opcode =
-					VSS_ISTREAM_CMD_VOC_AMR_SET_ENC_RATE;
-		cvs_set_amr_rate.amr_rate.mode = common.mvs_info.rate;
-
-		v->cvs_state = CMD_STATUS_FAIL;
-
-		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_amr_rate);
-		if (ret < 0) {
-			pr_err("%s: Error %d sending SET_AMR_RATE\n",
-			       __func__, ret);
-			goto fail;
-		}
-		ret = wait_event_timeout(v->cvs_wait,
-					 (v->cvs_state == CMD_STATUS_SUCCESS),
-					 msecs_to_jiffies(TIMEOUT_MS));
-		if (!ret) {
-			pr_err("%s: wait_event timeout\n", __func__);
-			goto fail;
-		}
-
-		ret = voice_set_dtx(v);
-		if (ret < 0)
-			goto fail;
-
-		break;
-	}
+	case VSS_MEDIA_ID_AMR_NB_MODEM:
 	case VSS_MEDIA_ID_AMR_WB_MODEM: {
-		struct cvs_set_amrwb_enc_rate_cmd cvs_set_amrwb_rate;
-
-		pr_debug("Setting AMR WB rate\n");
-
-		cvs_set_amrwb_rate.hdr.hdr_field =
-				APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
-				APR_HDR_LEN(APR_HDR_SIZE),
-				APR_PKT_VER);
-		cvs_set_amrwb_rate.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
-						sizeof(cvs_set_amrwb_rate) -
-						APR_HDR_SIZE);
-		cvs_set_amrwb_rate.hdr.src_port =
-				voice_get_idx_for_session(v->session_id);
-		cvs_set_amrwb_rate.hdr.dest_port = cvs_handle;
-		cvs_set_amrwb_rate.hdr.token = 0;
-		cvs_set_amrwb_rate.hdr.opcode =
-					VSS_ISTREAM_CMD_VOC_AMRWB_SET_ENC_RATE;
-		cvs_set_amrwb_rate.amrwb_rate.mode = common.mvs_info.rate;
-
-		v->cvs_state = CMD_STATUS_FAIL;
-
-		ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_amrwb_rate);
-		if (ret < 0) {
-			pr_err("%s: Error %d sending SET_AMRWB_RATE\n",
+		ret = voice_config_cvs_vocoder_amr_rate(v);
+		if (ret) {
+			pr_err("%s: Failed to update vocoder rate. %d\n",
 			       __func__, ret);
-			goto fail;
-		}
-		ret = wait_event_timeout(v->cvs_wait,
-					 (v->cvs_state == CMD_STATUS_SUCCESS),
-					 msecs_to_jiffies(TIMEOUT_MS));
-		if (!ret) {
-			pr_err("%s: wait_event timeout\n", __func__);
+
 			goto fail;
 		}
 
@@ -1697,6 +1702,31 @@
 	return -EINVAL;
 }
 
+int voc_update_amr_vocoder_rate(uint32_t session_id)
+{
+	int ret = 0;
+	struct voice_data *v;
+
+	pr_debug("%s: session_id:%d", __func__, session_id);
+
+	v = voice_get_session(session_id);
+
+	if (v == NULL) {
+		pr_err("%s: v is NULL, session_id:%d\n", __func__,
+		       session_id);
+
+		ret = -EINVAL;
+		goto done;
+	}
+
+	mutex_lock(&v->lock);
+	ret = voice_config_cvs_vocoder_amr_rate(v);
+	mutex_unlock(&v->lock);
+
+done:
+	return ret;
+}
+
 static int voice_send_start_voice_cmd(struct voice_data *v)
 {
 	struct apr_hdr mvm_start_voice_cmd;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 5c0cf21..9efc9fc 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, 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
@@ -1465,5 +1465,6 @@
 int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id);
 int voice_get_idx_for_session(u32 session_id);
 int voc_set_ext_ec_ref(uint16_t port_id, bool state);
+int voc_update_amr_vocoder_rate(uint32_t session_id);
 
 #endif
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index b9af9b6..0970a83 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -95,7 +95,7 @@
 	else
 		stream = SNDRV_PCM_STREAM_CAPTURE;
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
+	mutex_lock(&fe->card->dpcm_mutex);
 
 	if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
 		ret = platform->driver->compr_ops->open(cstream);
@@ -154,7 +154,7 @@
 	codec_dai->active++;
 	fe->codec->active++;
 
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 
 	return 0;
 
@@ -166,7 +166,7 @@
 		platform->driver->compr_ops->free(cstream);
 out:
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return ret;
 }
 
@@ -273,8 +273,7 @@
 	else
 		stream = SNDRV_PCM_STREAM_CAPTURE;
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-
+	mutex_lock(&fe->card->dpcm_mutex);
 	if (cstream->direction == SND_COMPRESS_PLAYBACK) {
 		cpu_dai->playback_active--;
 		codec_dai->playback_active--;
@@ -323,7 +322,7 @@
 		platform->driver->compr_ops->free(cstream);
 	//cpu_dai->runtime = NULL;
 
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return 0;
 }
 
@@ -393,8 +392,7 @@
 		stream = SNDRV_PCM_STREAM_CAPTURE;
 
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-
+	mutex_lock(&fe->card->dpcm_mutex);
 	if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
 		ret = platform->driver->compr_ops->trigger(cstream, cmd);
 		if (ret < 0)
@@ -422,7 +420,7 @@
 
 out:
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return ret;
 }
 
@@ -489,8 +487,7 @@
 	if (hw_params == NULL)
 		return -ENOMEM;
 
-	mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME);
-
+	mutex_lock(&fe->card->dpcm_mutex);
 	/* first we call set_params for the platform driver
 	 * this should configure the soc side
 	 * if the machine has compressed ops then we call that as well
@@ -535,7 +532,7 @@
 
 out:
 	fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO;
-	mutex_unlock(&fe->card->mutex);
+	mutex_unlock(&fe->card->dpcm_mutex);
 	return ret;
 }
 
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 63bbbdd..2f9e319 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1904,16 +1904,12 @@
 	}
 
 	if (found) {
-		if (widget->platform) {
-			soc_dpcm_runtime_update(widget);
-		} else {
-	  		dapm_mark_dirty(widget, "mux change");
-			dapm_power_widgets(widget->dapm,
-					   SND_SOC_DAPM_STREAM_NOP);
-		}
+		dapm_mark_dirty(widget, "mux change");
+		dapm_power_widgets(widget->dapm,
+			   SND_SOC_DAPM_STREAM_NOP);
 	}
 
-	return 0;
+	return found;
 }
 
 int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
@@ -1925,6 +1921,8 @@
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	ret = soc_dapm_mux_update_power(widget, kcontrol, change, mux, e);
 	mutex_unlock(&card->dapm_mutex);
+	if (ret > 0)
+		soc_dpcm_runtime_update(widget);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
@@ -1953,16 +1951,11 @@
 	}
 
 	if (found) {
-	  if (widget->platform) {
-		soc_dpcm_runtime_update(widget);
-	  } else {
 		dapm_mark_dirty(widget, "mixer update");
 		dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
-	  }
-
 	}
 
-	return 0;
+	return found;
 }
 
 int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
@@ -1973,6 +1966,8 @@
 	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	ret = soc_dapm_mixer_update_power(widget, kcontrol, connect);
 	mutex_unlock(&card->dapm_mutex);
+	if (ret > 0)
+		soc_dpcm_runtime_update(widget);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
@@ -3100,9 +3095,11 @@
 {
 	struct snd_soc_dapm_context *pdapm = &rtd->platform->dapm;
 	struct snd_soc_dapm_context *cdapm = &rtd->codec->dapm;
+	struct snd_soc_card *card = rtd->card;
 
 	dev_dbg(rtd->dev, "rtd stream %d event %d\n", stream, event);
 
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 	if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
 		widget_stream_event(pdapm, rtd->cpu_dai->playback_aif, event);
 		widget_stream_event(cdapm, rtd->codec_dai->playback_aif, event);
@@ -3110,6 +3107,7 @@
 		widget_stream_event(pdapm, rtd->cpu_dai->capture_aif, event);
 		widget_stream_event(cdapm, rtd->codec_dai->capture_aif, event);
 	}
+	mutex_unlock(&card->dapm_mutex);
 
 	/* do we need to notify any clients that DAPM stream is complete */
 	if (pdapm->stream_event)
@@ -3133,14 +3131,14 @@
 int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
 	const char *stream, int event)
 {
+	struct snd_soc_card *card = rtd->card;
 	struct snd_soc_codec *codec = rtd->codec;
 
 	if (stream == NULL)
 		return 0;
-
-	mutex_lock(&codec->mutex);
+	mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_PCM);
 	soc_dapm_stream_event(&codec->dapm, stream, event);
-	mutex_unlock(&codec->mutex);
+	mutex_unlock(&card->dapm_mutex);
 	return 0;
 }