Merge "msm: Kconfig: Select MSM_SCM unconditionally"
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index a9528c5..7ed873f 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -56,9 +56,9 @@
 - qcom,enable-gpio:			Specifies the panel lcd/display enable gpio.
 - qcom,rst-gpio:			Specifies the panel reset gpio.
 - qcom,te-gpio:				Specifies the gpio used for TE.
-- qcom,dsi-lpg-channel :		LPG channel for backlight.
-- qcom,dsi-pwm-period :			PWM period in microseconds.
-- qcom,dsi-pwm-gpio :			PWM gpio.
+- qcom,pwm-lpg-channel:			LPG channel for backlight.
+- qcom,pwm-period:			PWM period in microseconds.
+- qcom,pwm-pmic-gpio:			PMIC gpio binding to backlight.
 - qcom,mdss-pan-broadcast-mode:		Boolean used to enable broadcast mode.
 - qcom,cont-splash-enabled:		Boolean used to enable continuous splash mode.
 - qcom,fbc-enabled:			Boolean used to enable frame buffer compression mode.
@@ -174,6 +174,19 @@
 - qcom,off-cmds-dsi-state:		A string that Specifies the ctrl state for sending ON commands.
 					Supported modes are "DSI_LP_MODE" and "DSI_HS_MODE".
 
+
+- qcom,panel-on-cmds: 			A byte stream formed by multiple dcs packets base on
+					qcom dsi controller protocol.
+					byte 0 : dcs data type
+					byte 1 : set to indicate this is an individual packet
+						(no chain).
+					byte 2 : virtual channel number
+					byte 3 : expect ack from client (dcs read command)
+					byte 4 : wait number of specified ms after dcs command
+						transmitted
+					byte 5, 6: 16 bits length in network byte order
+					byte 7 and beyond: number byte of payload
+
 Note, if a given optional qcom,* binding is not present, then the driver will configure
 the default values specified.
 
@@ -204,7 +217,7 @@
 		qcom,mdss-pan-dsi-mdp-tr = <0x04>;
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
 		qcom,mdss-pan-frame-rate = <60>;
-		qcom,panel-on-cmds = [32 01 00 00 00 02 00 00];
+		qcom,panel-on-cmds = [32 01 00 00 00 00 02 00 00];
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
 		qcom,panel-off-cmds = [22 01 00 00 00 00 00];
 		qcom,off-cmds-dsi-state = "DSI LP MODE";
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index 9a7fa90..7616505 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -91,6 +91,7 @@
 - gpios : should contain phandle to gpio controller node and array of
     #gpio-cells specifying specific gpio (controller specific)
 - qcom,gpio-reset : should contain index to gpio used by sensors reset_n
+- qcom,gpio-standby : should contain index to gpio used by sensors standby_n
 - qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
 - qcom,gpio-req-tbl-flags : should contain direction of gpios present in
     qcom,gpio-req-tbl-num property (in the same order)
@@ -201,11 +202,15 @@
                qcom,cam-vreg-op-mode = <105000 80000 0 100000>;
                qcom,gpio-no-mux = <0>;
                gpios = <&msmgpio 15 0>,
+                       <&msmgpio 90 0>,
+                       <&msmgpio 89 0>;
                qcom,gpio-reset = <1>;
-               qcom,gpio-req-tbl-num = <0 1>;
-               qcom,gpio-req-tbl-flags = <1 0>;
+               qcom,gpio-standby = <2>;
+               qcom,gpio-req-tbl-num = <0 1 2>;
+               qcom,gpio-req-tbl-flags = <1 0 0>;
                qcom,gpio-req-tbl-label = "CAMIF_MCLK",
-                                         "CAM_RESET1";
+                                         "CAM_RESET1",
+                                         "CAM_STANDBY";
                qcom,gpio-set-tbl-num = <1 1>;
                qcom,gpio-set-tbl-flags = <0 2>;
                qcom,gpio-set-tbl-delay = <1000 4000>;
diff --git a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
index 10ca8a8..7bc748d 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -51,474 +51,474 @@
 					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
 					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
 					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [29 01 00 00 00 02 FF EE
-					29 01 00 00 00 02 26 08
-					29 01 00 00 00 02 26 00
-					29 01 00 00 10 02 FF 00
-					29 01 00 00 00 02 BA 03
-					29 01 00 00 00 02 C2 03
-					29 01 00 00 00 02 FF 01
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 00 4A
-					29 01 00 00 00 02 01 33
-					29 01 00 00 00 02 02 53
-					29 01 00 00 00 02 03 55
-					29 01 00 00 00 02 04 55
-					29 01 00 00 00 02 05 33
-					29 01 00 00 00 02 06 22
-					29 01 00 00 00 02 08 56
-					29 01 00 00 00 02 09 8F
-					29 01 00 00 00 02 36 73
-					29 01 00 00 00 02 0B 9F
-					29 01 00 00 00 02 0C 9F
-					29 01 00 00 00 02 0D 2F
-					29 01 00 00 00 02 0E 24
-					29 01 00 00 00 02 11 83
-					29 01 00 00 00 02 12 03
-					29 01 00 00 00 02 71 2C
-					29 01 00 00 00 02 6F 03
-					29 01 00 00 00 02 0F 0A
-					29 01 00 00 00 02 FF 05
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 01 00
-					29 01 00 00 00 02 02 8B
-					29 01 00 00 00 02 03 82
-					29 01 00 00 00 02 04 82
-					29 01 00 00 00 02 05 30
-					29 01 00 00 00 02 06 33
-					29 01 00 00 00 02 07 01
-					29 01 00 00 00 02 08 00
-					29 01 00 00 00 02 09 46
-					29 01 00 00 00 02 0A 46
-					29 01 00 00 00 02 0D 0B
-					29 01 00 00 00 02 0E 1D
-					29 01 00 00 00 02 0F 08
-					29 01 00 00 00 02 10 53
-					29 01 00 00 00 02 11 00
-					29 01 00 00 00 02 12 00
-					29 01 00 00 00 02 14 01
-					29 01 00 00 00 02 15 00
-					29 01 00 00 00 02 16 05
-					29 01 00 00 00 02 17 00
-					29 01 00 00 00 02 19 7F
-					29 01 00 00 00 02 1A FF
-					29 01 00 00 00 02 1B 0F
-					29 01 00 00 00 02 1C 00
-					29 01 00 00 00 02 1D 00
-					29 01 00 00 00 02 1E 00
-					29 01 00 00 00 02 1F 07
-					29 01 00 00 00 02 20 00
-					29 01 00 00 00 02 21 06
-					29 01 00 00 00 02 22 55
-					29 01 00 00 00 02 23 4D
-					29 01 00 00 00 02 2D 02
-					29 01 00 00 00 02 28 01
-					29 01 00 00 00 02 2F 02
-					29 01 00 00 00 02 83 01
-					29 01 00 00 00 02 9E 58
-					29 01 00 00 00 02 9F 6A
-					29 01 00 00 00 02 A0 01
-					29 01 00 00 00 02 A2 10
-					29 01 00 00 00 02 BB 0A
-					29 01 00 00 00 02 BC 0A
-					29 01 00 00 00 02 32 08
-					29 01 00 00 00 02 33 B8
-					29 01 00 00 00 02 36 01
-					29 01 00 00 00 02 37 00
-					29 01 00 00 00 02 43 00
-					29 01 00 00 00 02 4B 21
-					29 01 00 00 00 02 4C 03
-					29 01 00 00 00 02 50 21
-					29 01 00 00 00 02 51 03
-					29 01 00 00 00 02 58 21
-					29 01 00 00 00 02 59 03
-					29 01 00 00 00 02 5D 21
-					29 01 00 00 00 02 5E 03
-					29 01 00 00 00 02 6C 00
-					29 01 00 00 00 02 6D 00
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 FF 01
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 75 00
-					29 01 00 00 00 02 76 7D
-					29 01 00 00 00 02 77 00
-					29 01 00 00 00 02 78 8A
-					29 01 00 00 00 02 79 00
-					29 01 00 00 00 02 7A 9C
-					29 01 00 00 00 02 7B 00
-					29 01 00 00 00 02 7C B1
-					29 01 00 00 00 02 7D 00
-					29 01 00 00 00 02 7E BF
-					29 01 00 00 00 02 7F 00
-					29 01 00 00 00 02 80 CF
-					29 01 00 00 00 02 81 00
-					29 01 00 00 00 02 82 DD
-					29 01 00 00 00 02 83 00
-					29 01 00 00 00 02 84 E8
-					29 01 00 00 00 02 85 00
-					29 01 00 00 00 02 86 F2
-					29 01 00 00 00 02 87 01
-					29 01 00 00 00 02 88 1F
-					29 01 00 00 00 02 89 01
-					29 01 00 00 00 02 8A 41
-					29 01 00 00 00 02 8B 01
-					29 01 00 00 00 02 8C 78
-					29 01 00 00 00 02 8D 01
-					29 01 00 00 00 02 8E A5
-					29 01 00 00 00 02 8F 01
-					29 01 00 00 00 02 90 EE
-					29 01 00 00 00 02 91 02
-					29 01 00 00 00 02 92 29
-					29 01 00 00 00 02 93 02
-					29 01 00 00 00 02 94 2A
-					29 01 00 00 00 02 95 02
-					29 01 00 00 00 02 96 5D
-					29 01 00 00 00 02 97 02
-					29 01 00 00 00 02 98 93
-					29 01 00 00 00 02 99 02
-					29 01 00 00 00 02 9A B8
-					29 01 00 00 00 02 9B 02
-					29 01 00 00 00 02 9C E7
-					29 01 00 00 00 02 9D 03
-					29 01 00 00 00 02 9E 07
-					29 01 00 00 00 02 9F 03
-					29 01 00 00 00 02 A0 37
-					29 01 00 00 00 02 A2 03
-					29 01 00 00 00 02 A3 46
-					29 01 00 00 00 02 A4 03
-					29 01 00 00 00 02 A5 56
-					29 01 00 00 00 02 A6 03
-					29 01 00 00 00 02 A7 66
-					29 01 00 00 00 02 A9 03
-					29 01 00 00 00 02 AA 7A
-					29 01 00 00 00 02 AB 03
-					29 01 00 00 00 02 AC 93
-					29 01 00 00 00 02 AD 03
-					29 01 00 00 00 02 AE A3
-					29 01 00 00 00 02 AF 03
-					29 01 00 00 00 02 B0 B4
-					29 01 00 00 00 02 B1 03
-					29 01 00 00 00 02 B2 CB
-					29 01 00 00 00 02 B3 00
-					29 01 00 00 00 02 B4 7D
-					29 01 00 00 00 02 B5 00
-					29 01 00 00 00 02 B6 8A
-					29 01 00 00 00 02 B7 00
-					29 01 00 00 00 02 B8 9C
-					29 01 00 00 00 02 B9 00
-					29 01 00 00 00 02 BA B1
-					29 01 00 00 00 02 BB 00
-					29 01 00 00 00 02 BC BF
-					29 01 00 00 00 02 BD 00
-					29 01 00 00 00 02 BE CF
-					29 01 00 00 00 02 BF 00
-					29 01 00 00 00 02 C0 DD
-					29 01 00 00 00 02 C1 00
-					29 01 00 00 00 02 C2 E8
-					29 01 00 00 00 02 C3 00
-					29 01 00 00 00 02 C4 F2
-					29 01 00 00 00 02 C5 01
-					29 01 00 00 00 02 C6 1F
-					29 01 00 00 00 02 C7 01
-					29 01 00 00 00 02 C8 41
-					29 01 00 00 00 02 C9 01
-					29 01 00 00 00 02 CA 78
-					29 01 00 00 00 02 CB 01
-					29 01 00 00 00 02 CC A5
-					29 01 00 00 00 02 CD 01
-					29 01 00 00 00 02 CE EE
-					29 01 00 00 00 02 CF 02
-					29 01 00 00 00 02 D0 29
-					29 01 00 00 00 02 D1 02
-					29 01 00 00 00 02 D2 2A
-					29 01 00 00 00 02 D3 02
-					29 01 00 00 00 02 D4 5D
-					29 01 00 00 00 02 D5 02
-					29 01 00 00 00 02 D6 93
-					29 01 00 00 00 02 D7 02
-					29 01 00 00 00 02 D8 B8
-					29 01 00 00 00 02 D9 02
-					29 01 00 00 00 02 DA E7
-					29 01 00 00 00 02 DB 03
-					29 01 00 00 00 02 DC 07
-					29 01 00 00 00 02 DD 03
-					29 01 00 00 00 02 DE 37
-					29 01 00 00 00 02 DF 03
-					29 01 00 00 00 02 E0 46
-					29 01 00 00 00 02 E1 03
-					29 01 00 00 00 02 E2 56
-					29 01 00 00 00 02 E3 03
-					29 01 00 00 00 02 E4 66
-					29 01 00 00 00 02 E5 03
-					29 01 00 00 00 02 E6 7A
-					29 01 00 00 00 02 E7 03
-					29 01 00 00 00 02 E8 93
-					29 01 00 00 00 02 E9 03
-					29 01 00 00 00 02 EA A3
-					29 01 00 00 00 02 EB 03
-					29 01 00 00 00 02 EC B4
-					29 01 00 00 00 02 ED 03
-					29 01 00 00 00 02 EE CB
-					29 01 00 00 00 02 EF 00
-					29 01 00 00 00 02 F0 ED
-					29 01 00 00 00 02 F1 00
-					29 01 00 00 00 02 F2 F3
-					29 01 00 00 00 02 F3 00
-					29 01 00 00 00 02 F4 FE
-					29 01 00 00 00 02 F5 01
-					29 01 00 00 00 02 F6 09
-					29 01 00 00 00 02 F7 01
-					29 01 00 00 00 02 F8 13
-					29 01 00 00 00 02 F9 01
-					29 01 00 00 00 02 FA 1D
-					29 01 00 00 00 02 FF 02
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 00 01
-					29 01 00 00 00 02 01 26
-					29 01 00 00 00 02 02 01
-					29 01 00 00 00 02 03 2F
-					29 01 00 00 00 02 04 01
-					29 01 00 00 00 02 05 37
-					29 01 00 00 00 02 06 01
-					29 01 00 00 00 02 07 56
-					29 01 00 00 00 02 08 01
-					29 01 00 00 00 02 09 70
-					29 01 00 00 00 02 0A 01
-					29 01 00 00 00 02 0B 9D
-					29 01 00 00 00 02 0C 01
-					29 01 00 00 00 02 0D C2
-					29 01 00 00 00 02 0E 01
-					29 01 00 00 00 02 0F FF
-					29 01 00 00 00 02 10 02
-					29 01 00 00 00 02 11 31
-					29 01 00 00 00 02 12 02
-					29 01 00 00 00 02 13 32
-					29 01 00 00 00 02 14 02
-					29 01 00 00 00 02 15 60
-					29 01 00 00 00 02 16 02
-					29 01 00 00 00 02 17 94
-					29 01 00 00 00 02 18 02
-					29 01 00 00 00 02 19 B5
-					29 01 00 00 00 02 1A 02
-					29 01 00 00 00 02 1B E3
-					29 01 00 00 00 02 1C 03
-					29 01 00 00 00 02 1D 03
-					29 01 00 00 00 02 1E 03
-					29 01 00 00 00 02 1F 2D
-					29 01 00 00 00 02 20 03
-					29 01 00 00 00 02 21 3A
-					29 01 00 00 00 02 22 03
-					29 01 00 00 00 02 23 48
-					29 01 00 00 00 02 24 03
-					29 01 00 00 00 02 25 57
-					29 01 00 00 00 02 26 03
-					29 01 00 00 00 02 27 68
-					29 01 00 00 00 02 28 03
-					29 01 00 00 00 02 29 7B
-					29 01 00 00 00 02 2A 03
-					29 01 00 00 00 02 2B 90
-					29 01 00 00 00 02 2D 03
-					29 01 00 00 00 02 2F A0
-					29 01 00 00 00 02 30 03
-					29 01 00 00 00 02 31 CB
-					29 01 00 00 00 02 32 00
-					29 01 00 00 00 02 33 ED
-					29 01 00 00 00 02 34 00
-					29 01 00 00 00 02 35 F3
-					29 01 00 00 00 02 36 00
-					29 01 00 00 00 02 37 FE
-					29 01 00 00 00 02 38 01
-					29 01 00 00 00 02 39 09
-					29 01 00 00 00 02 3A 01
-					29 01 00 00 00 02 3B 13
-					29 01 00 00 00 02 3D 01
-					29 01 00 00 00 02 3F 1D
-					29 01 00 00 00 02 40 01
-					29 01 00 00 00 02 41 26
-					29 01 00 00 00 02 42 01
-					29 01 00 00 00 02 43 2F
-					29 01 00 00 00 02 44 01
-					29 01 00 00 00 02 45 37
-					29 01 00 00 00 02 46 01
-					29 01 00 00 00 02 47 56
-					29 01 00 00 00 02 48 01
-					29 01 00 00 00 02 49 70
-					29 01 00 00 00 02 4A 01
-					29 01 00 00 00 02 4B 9D
-					29 01 00 00 00 02 4C 01
-					29 01 00 00 00 02 4D C2
-					29 01 00 00 00 02 4E 01
-					29 01 00 00 00 02 4F FF
-					29 01 00 00 00 02 50 02
-					29 01 00 00 00 02 51 31
-					29 01 00 00 00 02 52 02
-					29 01 00 00 00 02 53 32
-					29 01 00 00 00 02 54 02
-					29 01 00 00 00 02 55 60
-					29 01 00 00 00 02 56 02
-					29 01 00 00 00 02 58 94
-					29 01 00 00 00 02 59 02
-					29 01 00 00 00 02 5A B5
-					29 01 00 00 00 02 5B 02
-					29 01 00 00 00 02 5C E3
-					29 01 00 00 00 02 5D 03
-					29 01 00 00 00 02 5E 03
-					29 01 00 00 00 02 5F 03
-					29 01 00 00 00 02 60 2D
-					29 01 00 00 00 02 61 03
-					29 01 00 00 00 02 62 3A
-					29 01 00 00 00 02 63 03
-					29 01 00 00 00 02 64 48
-					29 01 00 00 00 02 65 03
-					29 01 00 00 00 02 66 57
-					29 01 00 00 00 02 67 03
-					29 01 00 00 00 02 68 68
-					29 01 00 00 00 02 69 03
-					29 01 00 00 00 02 6A 7B
-					29 01 00 00 00 02 6B 03
-					29 01 00 00 00 02 6C 90
-					29 01 00 00 00 02 6D 03
-					29 01 00 00 00 02 6E A0
-					29 01 00 00 00 02 6F 03
-					29 01 00 00 00 02 70 CB
-					29 01 00 00 00 02 71 00
-					29 01 00 00 00 02 72 19
-					29 01 00 00 00 02 73 00
-					29 01 00 00 00 02 74 36
-					29 01 00 00 00 02 75 00
-					29 01 00 00 00 02 76 55
-					29 01 00 00 00 02 77 00
-					29 01 00 00 00 02 78 70
-					29 01 00 00 00 02 79 00
-					29 01 00 00 00 02 7A 83
-					29 01 00 00 00 02 7B 00
-					29 01 00 00 00 02 7C 99
-					29 01 00 00 00 02 7D 00
-					29 01 00 00 00 02 7E A8
-					29 01 00 00 00 02 7F 00
-					29 01 00 00 00 02 80 B7
-					29 01 00 00 00 02 81 00
-					29 01 00 00 00 02 82 C5
-					29 01 00 00 00 02 83 00
-					29 01 00 00 00 02 84 F7
-					29 01 00 00 00 02 85 01
-					29 01 00 00 00 02 86 1E
-					29 01 00 00 00 02 87 01
-					29 01 00 00 00 02 88 60
-					29 01 00 00 00 02 89 01
-					29 01 00 00 00 02 8A 95
-					29 01 00 00 00 02 8B 01
-					29 01 00 00 00 02 8C E1
-					29 01 00 00 00 02 8D 02
-					29 01 00 00 00 02 8E 20
-					29 01 00 00 00 02 8F 02
-					29 01 00 00 00 02 90 23
-					29 01 00 00 00 02 91 02
-					29 01 00 00 00 02 92 59
-					29 01 00 00 00 02 93 02
-					29 01 00 00 00 02 94 94
-					29 01 00 00 00 02 95 02
-					29 01 00 00 00 02 96 B4
-					29 01 00 00 00 02 97 02
-					29 01 00 00 00 02 98 E1
-					29 01 00 00 00 02 99 03
-					29 01 00 00 00 02 9A 01
-					29 01 00 00 00 02 9B 03
-					29 01 00 00 00 02 9C 28
-					29 01 00 00 00 02 9D 03
-					29 01 00 00 00 02 9E 30
-					29 01 00 00 00 02 9F 03
-					29 01 00 00 00 02 A0 37
-					29 01 00 00 00 02 A2 03
-					29 01 00 00 00 02 A3 3B
-					29 01 00 00 00 02 A4 03
-					29 01 00 00 00 02 A5 40
-					29 01 00 00 00 02 A6 03
-					29 01 00 00 00 02 A7 50
-					29 01 00 00 00 02 A9 03
-					29 01 00 00 00 02 AA 6D
-					29 01 00 00 00 02 AB 03
-					29 01 00 00 00 02 AC 80
-					29 01 00 00 00 02 AD 03
-					29 01 00 00 00 02 AE CB
-					29 01 00 00 00 02 AF 00
-					29 01 00 00 00 02 B0 19
-					29 01 00 00 00 02 B1 00
-					29 01 00 00 00 02 B2 36
-					29 01 00 00 00 02 B3 00
-					29 01 00 00 00 02 B4 55
-					29 01 00 00 00 02 B5 00
-					29 01 00 00 00 02 B6 70
-					29 01 00 00 00 02 B7 00
-					29 01 00 00 00 02 B8 83
-					29 01 00 00 00 02 B9 00
-					29 01 00 00 00 02 BA 99
-					29 01 00 00 00 02 BB 00
-					29 01 00 00 00 02 BC A8
-					29 01 00 00 00 02 BD 00
-					29 01 00 00 00 02 BE B7
-					29 01 00 00 00 02 BF 00
-					29 01 00 00 00 02 C0 C5
-					29 01 00 00 00 02 C1 00
-					29 01 00 00 00 02 C2 F7
-					29 01 00 00 00 02 C3 01
-					29 01 00 00 00 02 C4 1E
-					29 01 00 00 00 02 C5 01
-					29 01 00 00 00 02 C6 60
-					29 01 00 00 00 02 C7 01
-					29 01 00 00 00 02 C8 95
-					29 01 00 00 00 02 C9 01
-					29 01 00 00 00 02 CA E1
-					29 01 00 00 00 02 CB 02
-					29 01 00 00 00 02 CC 20
-					29 01 00 00 00 02 CD 02
-					29 01 00 00 00 02 CE 23
-					29 01 00 00 00 02 CF 02
-					29 01 00 00 00 02 D0 59
-					29 01 00 00 00 02 D1 02
-					29 01 00 00 00 02 D2 94
-					29 01 00 00 00 02 D3 02
-					29 01 00 00 00 02 D4 B4
-					29 01 00 00 00 02 D5 02
-					29 01 00 00 00 02 D6 E1
-					29 01 00 00 00 02 D7 03
-					29 01 00 00 00 02 D8 01
-					29 01 00 00 00 02 D9 03
-					29 01 00 00 00 02 DA 28
-					29 01 00 00 00 02 DB 03
-					29 01 00 00 00 02 DC 30
-					29 01 00 00 00 02 DD 03
-					29 01 00 00 00 02 DE 37
-					29 01 00 00 00 02 DF 03
-					29 01 00 00 00 02 E0 3B
-					29 01 00 00 00 02 E1 03
-					29 01 00 00 00 02 E2 40
-					29 01 00 00 00 02 E3 03
-					29 01 00 00 00 02 E4 50
-					29 01 00 00 00 02 E5 03
-					29 01 00 00 00 02 E6 6D
-					29 01 00 00 00 02 E7 03
-					29 01 00 00 00 02 E8 80
-					29 01 00 00 00 02 E9 03
-					29 01 00 00 00 02 EA CB
-					29 01 00 00 00 02 FF 01
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 FF 02
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 FF 04
-					29 01 00 00 00 02 FB 01
-					29 01 00 00 00 02 FF 00
-					29 01 00 00 64 02 11 00
-					29 01 00 00 00 02 FF EE
-					29 01 00 00 00 02 12 50
-					29 01 00 00 00 02 13 02
-					29 01 00 00 00 02 6A 60
-					29 01 00 00 00 02 FF 00
-					29 01 00 00 78 02 29 00];
+		qcom,panel-on-cmds = [29 01 00 00 00 00 02 FF EE
+					29 01 00 00 00 00 02 26 08
+					29 01 00 00 00 00 02 26 00
+					29 01 00 00 10 00 02 FF 00
+					29 01 00 00 00 00 02 BA 03
+					29 01 00 00 00 00 02 C2 03
+					29 01 00 00 00 00 02 FF 01
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 00 4A
+					29 01 00 00 00 00 02 01 33
+					29 01 00 00 00 00 02 02 53
+					29 01 00 00 00 00 02 03 55
+					29 01 00 00 00 00 02 04 55
+					29 01 00 00 00 00 02 05 33
+					29 01 00 00 00 00 02 06 22
+					29 01 00 00 00 00 02 08 56
+					29 01 00 00 00 00 02 09 8F
+					29 01 00 00 00 00 02 36 73
+					29 01 00 00 00 00 02 0B 9F
+					29 01 00 00 00 00 02 0C 9F
+					29 01 00 00 00 00 02 0D 2F
+					29 01 00 00 00 00 02 0E 24
+					29 01 00 00 00 00 02 11 83
+					29 01 00 00 00 00 02 12 03
+					29 01 00 00 00 00 02 71 2C
+					29 01 00 00 00 00 02 6F 03
+					29 01 00 00 00 00 02 0F 0A
+					29 01 00 00 00 00 02 FF 05
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 01 00
+					29 01 00 00 00 00 02 02 8B
+					29 01 00 00 00 00 02 03 82
+					29 01 00 00 00 00 02 04 82
+					29 01 00 00 00 00 02 05 30
+					29 01 00 00 00 00 02 06 33
+					29 01 00 00 00 00 02 07 01
+					29 01 00 00 00 00 02 08 00
+					29 01 00 00 00 00 02 09 46
+					29 01 00 00 00 00 02 0A 46
+					29 01 00 00 00 00 02 0D 0B
+					29 01 00 00 00 00 02 0E 1D
+					29 01 00 00 00 00 02 0F 08
+					29 01 00 00 00 00 02 10 53
+					29 01 00 00 00 00 02 11 00
+					29 01 00 00 00 00 02 12 00
+					29 01 00 00 00 00 02 14 01
+					29 01 00 00 00 00 02 15 00
+					29 01 00 00 00 00 02 16 05
+					29 01 00 00 00 00 02 17 00
+					29 01 00 00 00 00 02 19 7F
+					29 01 00 00 00 00 02 1A FF
+					29 01 00 00 00 00 02 1B 0F
+					29 01 00 00 00 00 02 1C 00
+					29 01 00 00 00 00 02 1D 00
+					29 01 00 00 00 00 02 1E 00
+					29 01 00 00 00 00 02 1F 07
+					29 01 00 00 00 00 02 20 00
+					29 01 00 00 00 00 02 21 06
+					29 01 00 00 00 00 02 22 55
+					29 01 00 00 00 00 02 23 4D
+					29 01 00 00 00 00 02 2D 02
+					29 01 00 00 00 00 02 28 01
+					29 01 00 00 00 00 02 2F 02
+					29 01 00 00 00 00 02 83 01
+					29 01 00 00 00 00 02 9E 58
+					29 01 00 00 00 00 02 9F 6A
+					29 01 00 00 00 00 02 A0 01
+					29 01 00 00 00 00 02 A2 10
+					29 01 00 00 00 00 02 BB 0A
+					29 01 00 00 00 00 02 BC 0A
+					29 01 00 00 00 00 02 32 08
+					29 01 00 00 00 00 02 33 B8
+					29 01 00 00 00 00 02 36 01
+					29 01 00 00 00 00 02 37 00
+					29 01 00 00 00 00 02 43 00
+					29 01 00 00 00 00 02 4B 21
+					29 01 00 00 00 00 02 4C 03
+					29 01 00 00 00 00 02 50 21
+					29 01 00 00 00 00 02 51 03
+					29 01 00 00 00 00 02 58 21
+					29 01 00 00 00 00 02 59 03
+					29 01 00 00 00 00 02 5D 21
+					29 01 00 00 00 00 02 5E 03
+					29 01 00 00 00 00 02 6C 00
+					29 01 00 00 00 00 02 6D 00
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 FF 01
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 75 00
+					29 01 00 00 00 00 02 76 7D
+					29 01 00 00 00 00 02 77 00
+					29 01 00 00 00 00 02 78 8A
+					29 01 00 00 00 00 02 79 00
+					29 01 00 00 00 00 02 7A 9C
+					29 01 00 00 00 00 02 7B 00
+					29 01 00 00 00 00 02 7C B1
+					29 01 00 00 00 00 02 7D 00
+					29 01 00 00 00 00 02 7E BF
+					29 01 00 00 00 00 02 7F 00
+					29 01 00 00 00 00 02 80 CF
+					29 01 00 00 00 00 02 81 00
+					29 01 00 00 00 00 02 82 DD
+					29 01 00 00 00 00 02 83 00
+					29 01 00 00 00 00 02 84 E8
+					29 01 00 00 00 00 02 85 00
+					29 01 00 00 00 00 02 86 F2
+					29 01 00 00 00 00 02 87 01
+					29 01 00 00 00 00 02 88 1F
+					29 01 00 00 00 00 02 89 01
+					29 01 00 00 00 00 02 8A 41
+					29 01 00 00 00 00 02 8B 01
+					29 01 00 00 00 00 02 8C 78
+					29 01 00 00 00 00 02 8D 01
+					29 01 00 00 00 00 02 8E A5
+					29 01 00 00 00 00 02 8F 01
+					29 01 00 00 00 00 02 90 EE
+					29 01 00 00 00 00 02 91 02
+					29 01 00 00 00 00 02 92 29
+					29 01 00 00 00 00 02 93 02
+					29 01 00 00 00 00 02 94 2A
+					29 01 00 00 00 00 02 95 02
+					29 01 00 00 00 00 02 96 5D
+					29 01 00 00 00 00 02 97 02
+					29 01 00 00 00 00 02 98 93
+					29 01 00 00 00 00 02 99 02
+					29 01 00 00 00 00 02 9A B8
+					29 01 00 00 00 00 02 9B 02
+					29 01 00 00 00 00 02 9C E7
+					29 01 00 00 00 00 02 9D 03
+					29 01 00 00 00 00 02 9E 07
+					29 01 00 00 00 00 02 9F 03
+					29 01 00 00 00 00 02 A0 37
+					29 01 00 00 00 00 02 A2 03
+					29 01 00 00 00 00 02 A3 46
+					29 01 00 00 00 00 02 A4 03
+					29 01 00 00 00 00 02 A5 56
+					29 01 00 00 00 00 02 A6 03
+					29 01 00 00 00 00 02 A7 66
+					29 01 00 00 00 00 02 A9 03
+					29 01 00 00 00 00 02 AA 7A
+					29 01 00 00 00 00 02 AB 03
+					29 01 00 00 00 00 02 AC 93
+					29 01 00 00 00 00 02 AD 03
+					29 01 00 00 00 00 02 AE A3
+					29 01 00 00 00 00 02 AF 03
+					29 01 00 00 00 00 02 B0 B4
+					29 01 00 00 00 00 02 B1 03
+					29 01 00 00 00 00 02 B2 CB
+					29 01 00 00 00 00 02 B3 00
+					29 01 00 00 00 00 02 B4 7D
+					29 01 00 00 00 00 02 B5 00
+					29 01 00 00 00 00 02 B6 8A
+					29 01 00 00 00 00 02 B7 00
+					29 01 00 00 00 00 02 B8 9C
+					29 01 00 00 00 00 02 B9 00
+					29 01 00 00 00 00 02 BA B1
+					29 01 00 00 00 00 02 BB 00
+					29 01 00 00 00 00 02 BC BF
+					29 01 00 00 00 00 02 BD 00
+					29 01 00 00 00 00 02 BE CF
+					29 01 00 00 00 00 02 BF 00
+					29 01 00 00 00 00 02 C0 DD
+					29 01 00 00 00 00 02 C1 00
+					29 01 00 00 00 00 02 C2 E8
+					29 01 00 00 00 00 02 C3 00
+					29 01 00 00 00 00 02 C4 F2
+					29 01 00 00 00 00 02 C5 01
+					29 01 00 00 00 00 02 C6 1F
+					29 01 00 00 00 00 02 C7 01
+					29 01 00 00 00 00 02 C8 41
+					29 01 00 00 00 00 02 C9 01
+					29 01 00 00 00 00 02 CA 78
+					29 01 00 00 00 00 02 CB 01
+					29 01 00 00 00 00 02 CC A5
+					29 01 00 00 00 00 02 CD 01
+					29 01 00 00 00 00 02 CE EE
+					29 01 00 00 00 00 02 CF 02
+					29 01 00 00 00 00 02 D0 29
+					29 01 00 00 00 00 02 D1 02
+					29 01 00 00 00 00 02 D2 2A
+					29 01 00 00 00 00 02 D3 02
+					29 01 00 00 00 00 02 D4 5D
+					29 01 00 00 00 00 02 D5 02
+					29 01 00 00 00 00 02 D6 93
+					29 01 00 00 00 00 02 D7 02
+					29 01 00 00 00 00 02 D8 B8
+					29 01 00 00 00 00 02 D9 02
+					29 01 00 00 00 00 02 DA E7
+					29 01 00 00 00 00 02 DB 03
+					29 01 00 00 00 00 02 DC 07
+					29 01 00 00 00 00 02 DD 03
+					29 01 00 00 00 00 02 DE 37
+					29 01 00 00 00 00 02 DF 03
+					29 01 00 00 00 00 02 E0 46
+					29 01 00 00 00 00 02 E1 03
+					29 01 00 00 00 00 02 E2 56
+					29 01 00 00 00 00 02 E3 03
+					29 01 00 00 00 00 02 E4 66
+					29 01 00 00 00 00 02 E5 03
+					29 01 00 00 00 00 02 E6 7A
+					29 01 00 00 00 00 02 E7 03
+					29 01 00 00 00 00 02 E8 93
+					29 01 00 00 00 00 02 E9 03
+					29 01 00 00 00 00 02 EA A3
+					29 01 00 00 00 00 02 EB 03
+					29 01 00 00 00 00 02 EC B4
+					29 01 00 00 00 00 02 ED 03
+					29 01 00 00 00 00 02 EE CB
+					29 01 00 00 00 00 02 EF 00
+					29 01 00 00 00 00 02 F0 ED
+					29 01 00 00 00 00 02 F1 00
+					29 01 00 00 00 00 02 F2 F3
+					29 01 00 00 00 00 02 F3 00
+					29 01 00 00 00 00 02 F4 FE
+					29 01 00 00 00 00 02 F5 01
+					29 01 00 00 00 00 02 F6 09
+					29 01 00 00 00 00 02 F7 01
+					29 01 00 00 00 00 02 F8 13
+					29 01 00 00 00 00 02 F9 01
+					29 01 00 00 00 00 02 FA 1D
+					29 01 00 00 00 00 02 FF 02
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 00 01
+					29 01 00 00 00 00 02 01 26
+					29 01 00 00 00 00 02 02 01
+					29 01 00 00 00 00 02 03 2F
+					29 01 00 00 00 00 02 04 01
+					29 01 00 00 00 00 02 05 37
+					29 01 00 00 00 00 02 06 01
+					29 01 00 00 00 00 02 07 56
+					29 01 00 00 00 00 02 08 01
+					29 01 00 00 00 00 02 09 70
+					29 01 00 00 00 00 02 0A 01
+					29 01 00 00 00 00 02 0B 9D
+					29 01 00 00 00 00 02 0C 01
+					29 01 00 00 00 00 02 0D C2
+					29 01 00 00 00 00 02 0E 01
+					29 01 00 00 00 00 02 0F FF
+					29 01 00 00 00 00 02 10 02
+					29 01 00 00 00 00 02 11 31
+					29 01 00 00 00 00 02 12 02
+					29 01 00 00 00 00 02 13 32
+					29 01 00 00 00 00 02 14 02
+					29 01 00 00 00 00 02 15 60
+					29 01 00 00 00 00 02 16 02
+					29 01 00 00 00 00 02 17 94
+					29 01 00 00 00 00 02 18 02
+					29 01 00 00 00 00 02 19 B5
+					29 01 00 00 00 00 02 1A 02
+					29 01 00 00 00 00 02 1B E3
+					29 01 00 00 00 00 02 1C 03
+					29 01 00 00 00 00 02 1D 03
+					29 01 00 00 00 00 02 1E 03
+					29 01 00 00 00 00 02 1F 2D
+					29 01 00 00 00 00 02 20 03
+					29 01 00 00 00 00 02 21 3A
+					29 01 00 00 00 00 02 22 03
+					29 01 00 00 00 00 02 23 48
+					29 01 00 00 00 00 02 24 03
+					29 01 00 00 00 00 02 25 57
+					29 01 00 00 00 00 02 26 03
+					29 01 00 00 00 00 02 27 68
+					29 01 00 00 00 00 02 28 03
+					29 01 00 00 00 00 02 29 7B
+					29 01 00 00 00 00 02 2A 03
+					29 01 00 00 00 00 02 2B 90
+					29 01 00 00 00 00 02 2D 03
+					29 01 00 00 00 00 02 2F A0
+					29 01 00 00 00 00 02 30 03
+					29 01 00 00 00 00 02 31 CB
+					29 01 00 00 00 00 02 32 00
+					29 01 00 00 00 00 02 33 ED
+					29 01 00 00 00 00 02 34 00
+					29 01 00 00 00 00 02 35 F3
+					29 01 00 00 00 00 02 36 00
+					29 01 00 00 00 00 02 37 FE
+					29 01 00 00 00 00 02 38 01
+					29 01 00 00 00 00 02 39 09
+					29 01 00 00 00 00 02 3A 01
+					29 01 00 00 00 00 02 3B 13
+					29 01 00 00 00 00 02 3D 01
+					29 01 00 00 00 00 02 3F 1D
+					29 01 00 00 00 00 02 40 01
+					29 01 00 00 00 00 02 41 26
+					29 01 00 00 00 00 02 42 01
+					29 01 00 00 00 00 02 43 2F
+					29 01 00 00 00 00 02 44 01
+					29 01 00 00 00 00 02 45 37
+					29 01 00 00 00 00 02 46 01
+					29 01 00 00 00 00 02 47 56
+					29 01 00 00 00 00 02 48 01
+					29 01 00 00 00 00 02 49 70
+					29 01 00 00 00 00 02 4A 01
+					29 01 00 00 00 00 02 4B 9D
+					29 01 00 00 00 00 02 4C 01
+					29 01 00 00 00 00 02 4D C2
+					29 01 00 00 00 00 02 4E 01
+					29 01 00 00 00 00 02 4F FF
+					29 01 00 00 00 00 02 50 02
+					29 01 00 00 00 00 02 51 31
+					29 01 00 00 00 00 02 52 02
+					29 01 00 00 00 00 02 53 32
+					29 01 00 00 00 00 02 54 02
+					29 01 00 00 00 00 02 55 60
+					29 01 00 00 00 00 02 56 02
+					29 01 00 00 00 00 02 58 94
+					29 01 00 00 00 00 02 59 02
+					29 01 00 00 00 00 02 5A B5
+					29 01 00 00 00 00 02 5B 02
+					29 01 00 00 00 00 02 5C E3
+					29 01 00 00 00 00 02 5D 03
+					29 01 00 00 00 00 02 5E 03
+					29 01 00 00 00 00 02 5F 03
+					29 01 00 00 00 00 02 60 2D
+					29 01 00 00 00 00 02 61 03
+					29 01 00 00 00 00 02 62 3A
+					29 01 00 00 00 00 02 63 03
+					29 01 00 00 00 00 02 64 48
+					29 01 00 00 00 00 02 65 03
+					29 01 00 00 00 00 02 66 57
+					29 01 00 00 00 00 02 67 03
+					29 01 00 00 00 00 02 68 68
+					29 01 00 00 00 00 02 69 03
+					29 01 00 00 00 00 02 6A 7B
+					29 01 00 00 00 00 02 6B 03
+					29 01 00 00 00 00 02 6C 90
+					29 01 00 00 00 00 02 6D 03
+					29 01 00 00 00 00 02 6E A0
+					29 01 00 00 00 00 02 6F 03
+					29 01 00 00 00 00 02 70 CB
+					29 01 00 00 00 00 02 71 00
+					29 01 00 00 00 00 02 72 19
+					29 01 00 00 00 00 02 73 00
+					29 01 00 00 00 00 02 74 36
+					29 01 00 00 00 00 02 75 00
+					29 01 00 00 00 00 02 76 55
+					29 01 00 00 00 00 02 77 00
+					29 01 00 00 00 00 02 78 70
+					29 01 00 00 00 00 02 79 00
+					29 01 00 00 00 00 02 7A 83
+					29 01 00 00 00 00 02 7B 00
+					29 01 00 00 00 00 02 7C 99
+					29 01 00 00 00 00 02 7D 00
+					29 01 00 00 00 00 02 7E A8
+					29 01 00 00 00 00 02 7F 00
+					29 01 00 00 00 00 02 80 B7
+					29 01 00 00 00 00 02 81 00
+					29 01 00 00 00 00 02 82 C5
+					29 01 00 00 00 00 02 83 00
+					29 01 00 00 00 00 02 84 F7
+					29 01 00 00 00 00 02 85 01
+					29 01 00 00 00 00 02 86 1E
+					29 01 00 00 00 00 02 87 01
+					29 01 00 00 00 00 02 88 60
+					29 01 00 00 00 00 02 89 01
+					29 01 00 00 00 00 02 8A 95
+					29 01 00 00 00 00 02 8B 01
+					29 01 00 00 00 00 02 8C E1
+					29 01 00 00 00 00 02 8D 02
+					29 01 00 00 00 00 02 8E 20
+					29 01 00 00 00 00 02 8F 02
+					29 01 00 00 00 00 02 90 23
+					29 01 00 00 00 00 02 91 02
+					29 01 00 00 00 00 02 92 59
+					29 01 00 00 00 00 02 93 02
+					29 01 00 00 00 00 02 94 94
+					29 01 00 00 00 00 02 95 02
+					29 01 00 00 00 00 02 96 B4
+					29 01 00 00 00 00 02 97 02
+					29 01 00 00 00 00 02 98 E1
+					29 01 00 00 00 00 02 99 03
+					29 01 00 00 00 00 02 9A 01
+					29 01 00 00 00 00 02 9B 03
+					29 01 00 00 00 00 02 9C 28
+					29 01 00 00 00 00 02 9D 03
+					29 01 00 00 00 00 02 9E 30
+					29 01 00 00 00 00 02 9F 03
+					29 01 00 00 00 00 02 A0 37
+					29 01 00 00 00 00 02 A2 03
+					29 01 00 00 00 00 02 A3 3B
+					29 01 00 00 00 00 02 A4 03
+					29 01 00 00 00 00 02 A5 40
+					29 01 00 00 00 00 02 A6 03
+					29 01 00 00 00 00 02 A7 50
+					29 01 00 00 00 00 02 A9 03
+					29 01 00 00 00 00 02 AA 6D
+					29 01 00 00 00 00 02 AB 03
+					29 01 00 00 00 00 02 AC 80
+					29 01 00 00 00 00 02 AD 03
+					29 01 00 00 00 00 02 AE CB
+					29 01 00 00 00 00 02 AF 00
+					29 01 00 00 00 00 02 B0 19
+					29 01 00 00 00 00 02 B1 00
+					29 01 00 00 00 00 02 B2 36
+					29 01 00 00 00 00 02 B3 00
+					29 01 00 00 00 00 02 B4 55
+					29 01 00 00 00 00 02 B5 00
+					29 01 00 00 00 00 02 B6 70
+					29 01 00 00 00 00 02 B7 00
+					29 01 00 00 00 00 02 B8 83
+					29 01 00 00 00 00 02 B9 00
+					29 01 00 00 00 00 02 BA 99
+					29 01 00 00 00 00 02 BB 00
+					29 01 00 00 00 00 02 BC A8
+					29 01 00 00 00 00 02 BD 00
+					29 01 00 00 00 00 02 BE B7
+					29 01 00 00 00 00 02 BF 00
+					29 01 00 00 00 00 02 C0 C5
+					29 01 00 00 00 00 02 C1 00
+					29 01 00 00 00 00 02 C2 F7
+					29 01 00 00 00 00 02 C3 01
+					29 01 00 00 00 00 02 C4 1E
+					29 01 00 00 00 00 02 C5 01
+					29 01 00 00 00 00 02 C6 60
+					29 01 00 00 00 00 02 C7 01
+					29 01 00 00 00 00 02 C8 95
+					29 01 00 00 00 00 02 C9 01
+					29 01 00 00 00 00 02 CA E1
+					29 01 00 00 00 00 02 CB 02
+					29 01 00 00 00 00 02 CC 20
+					29 01 00 00 00 00 02 CD 02
+					29 01 00 00 00 00 02 CE 23
+					29 01 00 00 00 00 02 CF 02
+					29 01 00 00 00 00 02 D0 59
+					29 01 00 00 00 00 02 D1 02
+					29 01 00 00 00 00 02 D2 94
+					29 01 00 00 00 00 02 D3 02
+					29 01 00 00 00 00 02 D4 B4
+					29 01 00 00 00 00 02 D5 02
+					29 01 00 00 00 00 02 D6 E1
+					29 01 00 00 00 00 02 D7 03
+					29 01 00 00 00 00 02 D8 01
+					29 01 00 00 00 00 02 D9 03
+					29 01 00 00 00 00 02 DA 28
+					29 01 00 00 00 00 02 DB 03
+					29 01 00 00 00 00 02 DC 30
+					29 01 00 00 00 00 02 DD 03
+					29 01 00 00 00 00 02 DE 37
+					29 01 00 00 00 00 02 DF 03
+					29 01 00 00 00 00 02 E0 3B
+					29 01 00 00 00 00 02 E1 03
+					29 01 00 00 00 00 02 E2 40
+					29 01 00 00 00 00 02 E3 03
+					29 01 00 00 00 00 02 E4 50
+					29 01 00 00 00 00 02 E5 03
+					29 01 00 00 00 00 02 E6 6D
+					29 01 00 00 00 00 02 E7 03
+					29 01 00 00 00 00 02 E8 80
+					29 01 00 00 00 00 02 E9 03
+					29 01 00 00 00 00 02 EA CB
+					29 01 00 00 00 00 02 FF 01
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 FF 02
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 FF 04
+					29 01 00 00 00 00 02 FB 01
+					29 01 00 00 00 00 02 FF 00
+					29 01 00 00 64 00 02 11 00
+					29 01 00 00 00 00 02 FF EE
+					29 01 00 00 00 00 02 12 50
+					29 01 00 00 00 00 02 13 02
+					29 01 00 00 00 00 02 6A 60
+					29 01 00 00 00 00 02 FF 00
+					29 01 00 00 78 00 02 29 00];
 
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
-					05 01 00 00 78 02 10 00];
+		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
 		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
index a27a88a..478541f 100644
--- a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -50,11 +50,11 @@
 					     00 c2 45 00 00 00 00 01 75 /* lane3 config */
 					     00 02 45 00 00 00 00 01 97]; /* Clk ln config */
 
-		qcom,panel-on-cmds = [05 01 00 00 78 02 11 00
-					05 01 00 00 78 02 29 00];
+		qcom,panel-on-cmds = [05 01 00 00 78 00 02 11 00
+					05 01 00 00 78 00 02 29 00];
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
-					05 01 00 00 78 02 10 00];
+		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
 		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
index d182bac..45d396c 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -52,16 +52,16 @@
 					     00 00 00 00 0a 00 00 01 97 /* lane2 config */
 					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
 					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
-		qcom,panel-on-cmds = [05 01 00 00 32 02 01 00 /* sw reset */
-					05 01 00 00 0a 02 11 00 /* exit sleep */
-					15 01 00 00 0a 02 53 2c /* backlight on */
-					15 01 00 00 0a 02 51 ff /* brightness max */
-					05 01 00 00 0a 02 29 00 /* display on */
-					15 01 00 00 0a 02 ae 03 /* set num of lanes */
-					15 01 00 00 0a 02 3a 77 /* rgb_888 */];
+		qcom,panel-on-cmds = [05 01 00 00 32 00 02 01 00 /* sw reset */
+					05 01 00 00 0a 00 02 11 00 /* exit sleep */
+					15 01 00 00 0a 00 02 53 2c /* backlight on */
+					15 01 00 00 0a 00 02 51 ff /* brightness max */
+					05 01 00 00 0a 00 02 29 00 /* display on */
+					15 01 00 00 0a 00 02 ae 03 /* set num of lanes */
+					15 01 00 00 0a 00 02 3a 77 /* rgb_888 */];
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 0a 02 28 00 /* display off */
-					05 01 00 00 78 02 10 00 /* enter sleep */];
+		qcom,panel-off-cmds = [05 01 00 00 0a 00 02 28 00 /* display off */
+					05 01 00 00 78 00 02 10 00 /* enter sleep */];
 		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index 3b39dea..271e373 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -38,9 +38,9 @@
 		qcom,mdss-pan-dsi-mdp-tr = <0x04>;
 		qcom,mdss-pan-dsi-dma-tr = <0x04>;
 		qcom,mdss-pan-dsi-frame-rate = <60>;
-		qcom,panel-on-cmds = [32 01 00 00 00 02 00 00];
+		qcom,panel-on-cmds = [32 01 00 00 00 00 02 00 00];
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [22 01 00 00 00 02 00 00];
+		qcom,panel-off-cmds = [22 01 00 00 00 00 02 00 00];
 		qcom,off-cmds-dsi-state = "DSI_LP_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
index 82b57cd..5c37cf8 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -54,71 +54,71 @@
 					     00 00 00 00 0f 00 00 01 97 /* lane3 config */
 					     00 c0 00 00 00 00 00 01 bb]; /* Clk ln config */
 
-		qcom,panel-on-cmds = [23 01 00 00 0a 02 b0 00
-					23 01 00 00 0a 02 b2 00
-					23 01 00 00 0a 02 b3 0c
-					23 01 00 00 0a 02 b4 02
-					29 01 00 00 00 06
+		qcom,panel-on-cmds = [23 01 00 00 0a 00 02 b0 00
+					23 01 00 00 0a 00 02 b2 00
+					23 01 00 00 0a 00 02 b3 0c
+					23 01 00 00 0a 00 02 b4 02
+					29 01 00 00 00 00 06
 						c0 40 02 7f c8 08
-					29 01 00 00 00 10
+					29 01 00 00 00 00 10
 						c1 00 a8 00 00 00
 						00 00 9d 08 27 00
 						00 00 00 00
-					29 01 00 00 00 06
+					29 01 00 00 00 00 06
 						c2 00 00 09 00 00
-					23 01 00 00 0a 02 c3 04
-					29 01 00 00 00 04
+					23 01 00 00 0a 00 02 c3 04
+					29 01 00 00 00 00 04
 						c4 4d 83 00
-					29 01 00 00 00 0b
+					29 01 00 00 00 00 0b
 						c6 12 00 08 71 00
 						00 00 80 00 04
-					23 01 00 00 0a 02 c7 22
-					29 01 00 00 00 05
+					23 01 00 00 0a 00 02 c7 22
+					29 01 00 00 00 00 05
 						c8 4c 0c 0c 0c
-					29 01 00 00 00 0e
+					29 01 00 00 00 00 0e
 						c9 00 40 00 16 32
 						2e 3a 43 3e 3c 45
 						79 3f
-					29 01 00 00 00 0e
+					29 01 00 00 00 00 0e
 						ca 00 46 1a 23 21
 						1c 25 31 2d 49 5f
 						7f 3f
-					29 01 00 00 00 0e
+					29 01 00 00 00 00 0e
 						cb 00 4c 20 3a 42
 						40 47 4b 42 3e 46
 						7e 3f
-					29 01 00 00 00 0e
+					29 01 00 00 00 00 0e
 						cc 00 41 19 21 1d
 						14 18 1f 1d 25 3f
 						73 3f
-					29 01 00 00 00 0e
+					29 01 00 00 00 00 0e
 						cd 23 79 5a 5f 57
 						4c 51 51 45 3f 4b
 						7f 3f
-					29 01 00 00 00 0e
+					29 01 00 00 00 00 0e
 						ce 00 40 14 20 1a
 						0e 0e 13 08 00 05
 						46 1c
-					29 01 00 00 00 04
+					29 01 00 00 00 00 04
 						d0 6a 64 01
-					29 01 00 00 00 03 d1 77 d4
-					23 01 00 00 0a 02 d3 33
-					29 01 00 00 00 03 d5 0f 0f
-					29 01 00 00 00 07
+					29 01 00 00 00 00 03 d1 77 d4
+					23 01 00 00 0a 00 02 d3 33
+					29 01 00 00 00 00 03 d5 0f 0f
+					29 01 00 00 00 00 07
 						d8 34 64 23 25 62
 						32
-					29 01 00 00 00 0c
+					29 01 00 00 00 00 0c
 						de 10 7b 11 0a 00
 						00 00 00 00 00 00
-					29 01 00 00 00 09
+					29 01 00 00 00 00 09
 						fd 04 55 53 00 70
 						ff 10 73
-					23 01 00 00 0a 02 e2 00
-					05 01 00 00 78 02 11 00
-					05 01 00 00 32 02 29 00];
+					23 01 00 00 0a 00 02 e2 00
+					05 01 00 00 78 00 02 11 00
+					05 01 00 00 32 00 02 29 00];
 		qcom,on-cmds-dsi-state = "DSI_LP_MODE";
-		qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
-					05 01 00 00 78 02 10 00];
+		qcom,panel-off-cmds = [05 01 00 00 32 00 02 28 00
+					05 01 00 00 78 00 02 10 00];
 		qcom,off-cmds-dsi-state = "DSI_HS_MODE";
 	};
 };
diff --git a/arch/arm/boot/dts/mpq8092-ion.dtsi b/arch/arm/boot/dts/mpq8092-ion.dtsi
index ee3fbc4..f9f5985 100644
--- a/arch/arm/boot/dts/mpq8092-ion.dtsi
+++ b/arch/arm/boot/dts/mpq8092-ion.dtsi
@@ -20,58 +20,14 @@
 			reg = <30>;
 		};
 
-		qcom,ion-heap@8 { /* CP_MM HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <8>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x7800000>;
-		};
-
-		qcom,ion-heap@29 { /* FIRMWARE HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <29>;
-			qcom,heap-align = <0x20000>;
-			qcom,heap-adjacent = <8>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0xA00000>;
-		};
-
-		qcom,ion-heap@12 { /* MFC HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <12>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x2000>;
-		};
-
-		qcom,ion-heap@24 { /* SF HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <24>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x2800000>;
+		qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+			reg = <21>;
 		};
 
 		qcom,ion-heap@25 { /* IOMMU HEAP */
 			reg = <25>;
 		};
 
-		qcom,ion-heap@27 { /* QSECOM HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <27>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x600000>;
-		};
-
-		qcom,ion-heap@28 { /* AUDIO HEAP */
-			compatible = "qcom,msm-ion-reserve";
-			reg = <28>;
-			qcom,heap-align = <0x1000>;
-			qcom,memory-reservation-type = "EBI1"; /* reserve EBI memory */
-			qcom,memory-reservation-size = <0x2B4000>;
-		};
 	};
 };
 
diff --git a/arch/arm/boot/dts/mpq8092-sim.dts b/arch/arm/boot/dts/mpq8092-sim.dts
index ce97d4d..676ef3b 100644
--- a/arch/arm/boot/dts/mpq8092-sim.dts
+++ b/arch/arm/boot/dts/mpq8092-sim.dts
@@ -16,7 +16,7 @@
 
 / {
 	model = "Qualcomm MPQ8092 Simulator";
-	compatible = "qcom,mpq8092-sim", "qcom,mpq8092";
+	compatible = "qcom,mpq8092-sim", "qcom,mpq8092", "qcom,sim";
 	qcom,msm-id = <126 16 0>;
 };
 
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
index 07f16b9..41d6b7e 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-cdp.dtsi
@@ -73,7 +73,7 @@
 		reg = <0x6d>;
 		qcom,slave-id = <0x20 0x0 0x9724>;
 		qcom,csiphy-sd-index = <1>;
-		qcom,csid-sd-index = <0>;
+		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <0>;
 		qcom,sensor-name = "ov9724";
 		cam_vdig-supply = <&pm8226_l5>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
index f06033e..53860ac 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
@@ -73,8 +73,8 @@
 		reg = <0x6d>;
 		qcom,slave-id = <0x20 0x0 0x9724>;
 		qcom,csiphy-sd-index = <1>;
-		qcom,csid-sd-index = <0>;
-		qcom,mount-angle = <90>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <270>;
 		qcom,sensor-name = "ov9724";
 		cam_vdig-supply = <&pm8226_l5>;
 		cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
index 47f4049..3935dbb 100644
--- a/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-qrd.dtsi
@@ -73,8 +73,8 @@
 		reg = <0x6d>;
 		qcom,slave-id = <0x20 0x0 0x9724>;
 		qcom,csiphy-sd-index = <1>;
-		qcom,csid-sd-index = <0>;
-		qcom,mount-angle = <90>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <270>;
 		qcom,sensor-name = "ov9724";
 		cam_vdig-supply = <&pm8226_l5>;
 		cam_vana-supply = <&pm8226_l19>;
diff --git a/arch/arm/boot/dts/msm8226-camera.dtsi b/arch/arm/boot/dts/msm8226-camera.dtsi
index 0dae162..ec0092d 100644
--- a/arch/arm/boot/dts/msm8226-camera.dtsi
+++ b/arch/arm/boot/dts/msm8226-camera.dtsi
@@ -21,8 +21,9 @@
 	qcom,csiphy@fda0ac00 {
 		cell-index = <0>;
 		compatible = "qcom,csiphy";
-		reg = <0xfda0ac00 0x200>;
-		reg-names = "csiphy";
+		reg = <0xfda0ac00 0x200>,
+			<0xfda00030 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
 		interrupts = <0 78 0>;
 		interrupt-names = "csiphy";
 	};
@@ -30,8 +31,9 @@
 	qcom,csiphy@fda0b000 {
 		cell-index = <1>;
 		compatible = "qcom,csiphy";
-		reg = <0xfda0b000 0x200>;
-		reg-names = "csiphy";
+		reg = <0xfda0b000 0x200>,
+			<0xfda00038 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
 		interrupts = <0 79 0>;
 		interrupt-names = "csiphy";
 	};
@@ -61,8 +63,9 @@
 	qcom,ispif@fda0a000 {
 		cell-index = <0>;
 		compatible = "qcom,ispif";
-		reg = <0xfda0a000 0x500>;
-		reg-names = "ispif";
+		reg = <0xfda0a000 0x500>,
+			<0xfda00020 0x10>;
+		reg-names = "ispif", "csi_clk_mux";
 		interrupts = <0 55 0>;
 		interrupt-names = "ispif";
 	};
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index b574a31..efd9c32 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -89,11 +89,15 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 90 0>;
+			<&msmgpio 90 0>,
+			<&msmgpio 89 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-req-tbl-num = <0 1>;
-		qcom,gpio-req-tbl-flags = <1 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1",
+					  "CAM_STANDBY";
 		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index 748d5f7..9cbd45c 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -90,11 +90,15 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 90 0>;
+			<&msmgpio 90 0>,
+			<&msmgpio 89 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-req-tbl-num = <0 1>;
-		qcom,gpio-req-tbl-flags = <1 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1",
+					  "CAM_STANDBY";
 		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index 5a97a11..e9d3d75 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -86,11 +86,15 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 90 0>;
+			<&msmgpio 90 0>,
+			<&msmgpio 89 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-req-tbl-num = <0 1>;
-		qcom,gpio-req-tbl-flags = <1 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1",
+					  "CAM_STANDBY";
 		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 53f6e9e..68af4a6 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -90,11 +90,15 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		gpios = <&msmgpio 15 0>,
-			<&msmgpio 90 0>;
+			<&msmgpio 90 0>,
+			<&msmgpio 89 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-req-tbl-num = <0 1>;
-		qcom,gpio-req-tbl-flags = <1 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+					  "CAM_RESET1",
+					  "CAM_STANDBY";
 		qcom,gpio-set-tbl-num = <1 1>;
 		qcom,gpio-set-tbl-flags = <0 2>;
 		qcom,gpio-set-tbl-delay = <1000 30000>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index 5fa7c08..3e65b8a 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -247,7 +247,7 @@
 				<85 512 40000 160000>,
 				<85 512 40000 320000>,
 				<85 512 40000 480000>,
-				<85 512 40000 640000>;
+				<85 512 40000 800000>;
 	};
 };
 
diff --git a/arch/arm/configs/mpq8092_defconfig b/arch/arm/configs/mpq8092_defconfig
index 713691d..c06161d 100644
--- a/arch/arm/configs/mpq8092_defconfig
+++ b/arch/arm/configs/mpq8092_defconfig
@@ -54,6 +54,7 @@
 CONFIG_MSM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM_V2=y
 CONFIG_MSM_L2_SPM=y
+CONFIG_MSM_MULTIMEDIA_USE_ION=y
 CONFIG_MSM_OCMEM=y
 CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
 CONFIG_MSM_OCMEM_DEBUG=y
@@ -268,6 +269,8 @@
 CONFIG_REGULATOR_QPNP=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
 CONFIG_MSM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
@@ -329,6 +332,7 @@
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
 CONFIG_MSM_IOMMU=y
+CONFIG_IOMMU_PGTABLES_L2=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index aea092e..ba36df1 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -370,6 +370,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_SHIRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index dda9bd3..5885c6e 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -428,6 +428,7 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index f90e5f3..6c18a97 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -510,6 +510,7 @@
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index bae4ee9..72032dc 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -459,6 +459,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_TIMER_STATS=y
+CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MEMORY_INIT=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 0d51251..be0daf3 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -317,6 +317,25 @@
 	select SPARSE_IRQ
 	select MSM_NOPM
 
+config ARCH_FSM9900
+	bool "FSM9900"
+	select ARCH_MSM_KRAITMP
+	select GPIO_MSM_V3
+	select ARM_GIC
+	select CPU_V7
+	select MSM_SCM
+	select MSM_GPIOMUX
+	select MULTI_IRQ_HANDLER
+	select MSM_PIL
+	select MSM_NATIVE_RESTART
+	select MSM_RESTART_V2
+	select MAY_HAVE_SPARSE_IRQ
+	select SPARSE_IRQ
+	select REGULATOR
+	select ARM_HAS_SG_CHAIN
+	select MSM_RUN_QUEUE_STATS
+	select MSM_NOPM
+
 config ARCH_FSM9XXX
 	bool "FSM9XXX"
 	select ARCH_MSM_SCORPION
@@ -1093,6 +1112,7 @@
 	default "0x00000000" if ARCH_MSM8226
 	default "0x00000000" if ARCH_MSM8610
 	default "0x10000000" if ARCH_FSM9XXX
+	default "0x00000000" if ARCH_FSM9900
 	default "0x00200000" if ARCH_MSM9625
 	default "0x00000000" if ARCH_MSMKRYPTON
 	default "0x00200000" if !MSM_STACKED_MEMORY
@@ -1256,6 +1276,14 @@
                 help
                   Say Y here if you want the debug print routines to direct
                   their output to the serial port on MSM9625 devices.
+
+	config DEBUG_FSM9900_UART
+		bool "Kernel low-level debugging messages via FSM9900 UART"
+		depends on ARCH_FSM9900
+		select MSM_HAS_DEBUG_UART_HS_V14
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the serial port on FSM9900 devices.
 endchoice
 
 choice
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 400f859..f53b7fe 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -121,6 +121,7 @@
 ifndef CONFIG_ARCH_MSM8610
 ifndef CONFIG_ARCH_APQ8084
 ifndef CONFIG_ARCH_MSMKRYPTON
+ifndef CONFIG_ARCH_FSM9900
 	obj-y += nand_partitions.o
 endif
 endif
@@ -132,6 +133,7 @@
 endif
 endif
 endif
+endif
 obj-$(CONFIG_MSM_SDIO_TTY) += sdio_tty.o
 obj-$(CONFIG_MSM_SMD_TTY) += smd_tty.o
 obj-$(CONFIG_MSM_SMD_QMI) += smd_qmi.o
@@ -230,6 +232,7 @@
 obj-$(CONFIG_ARCH_FSM9XXX) += clock-fsm9xxx.o clock-local.o acpuclock-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += dfe-fsm9xxx.o rfic-fsm9xxx.o
 obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o xo-fsm9xxx.o
+obj-$(CONFIG_ARCH_FSM9900) += board-fsm9900.o board-fsm9900-gpiomux.o
 
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
 obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog_asm.o
@@ -377,6 +380,7 @@
 obj-$(CONFIG_ARCH_MSM8226) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += gpiomux-v2.o gpiomux.o
 obj-$(CONFIG_ARCH_APQ8084) += gpiomux-v2.o gpiomux.o
+obj-$(CONFIG_ARCH_FSM9900) += gpiomux-v2.o gpiomux.o
 
 obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o
 obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 2827e65..07969e0 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -93,6 +93,11 @@
 params_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x10000100
 initrd_phys-$(CONFIG_ARCH_FSM9XXX)	:= 0x12000000
 
+# FSM9900
+   zreladdr-$(CONFIG_ARCH_FSM9900)	:= 0x00008000
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-rumi.dtb
+        dtb-$(CONFIG_ARCH_FSM9900)	:= fsm9900-sim.dtb
+
 # MPQ8092
    zreladdr-$(CONFIG_ARCH_MPQ8092)	:= 0x00008000
 
diff --git a/arch/arm/mach-msm/board-fsm9900-gpiomux.c b/arch/arm/mach-msm/board-fsm9900-gpiomux.c
new file mode 100644
index 0000000..dede706
--- /dev/null
+++ b/arch/arm/mach-msm/board-fsm9900-gpiomux.c
@@ -0,0 +1,29 @@
+/* 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/gpio.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+
+void __init fsm9900_init_gpiomux(void)
+{
+	int rc;
+
+	rc = msm_gpiomux_init_dt();
+	if (rc) {
+		pr_err("%s failed %d\n", __func__, rc);
+		return;
+	}
+}
diff --git a/arch/arm/mach-msm/board-fsm9900.c b/arch/arm/mach-msm/board-fsm9900.c
new file mode 100644
index 0000000..7177355
--- /dev/null
+++ b/arch/arm/mach-msm/board-fsm9900.c
@@ -0,0 +1,102 @@
+/* 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/err.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/memory.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include <mach/board.h>
+#include <mach/gpiomux.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_smd.h>
+#include <mach/restart.h>
+#include <mach/socinfo.h>
+#include <mach/clk-provider.h>
+#include "board-dt.h"
+#include "clock.h"
+#include "devices.h"
+#include "platsmp.h"
+
+void __init fsm9900_reserve(void)
+{
+}
+
+static void __init fsm9900_early_memory(void)
+{
+}
+
+static struct clk_lookup msm_clocks_dummy[] = {
+	CLK_DUMMY("core_clk",   BLSP2_UART_CLK, "f9960000.serial", OFF),
+	CLK_DUMMY("iface_clk",  BLSP2_UART_CLK, "f9960000.serial", OFF),
+	CLK_DUMMY("core_clk",   BLSP1_UART_CLK, "f991f000.serial", OFF),
+	CLK_DUMMY("iface_clk",  BLSP1_UART_CLK, "f991f000.serial", OFF),
+};
+
+static struct clock_init_data msm_dummy_clock_init_data __initdata = {
+	.table = msm_clocks_dummy,
+	.size = ARRAY_SIZE(msm_clocks_dummy),
+};
+
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init fsm9900_add_drivers(void)
+{
+	msm_smd_init();
+	msm_clock_init(&msm_dummy_clock_init_data);
+}
+
+static void __init fsm9900_map_io(void)
+{
+	msm_map_fsm9900_io();
+}
+
+void __init fsm9900_init(void)
+{
+	if (socinfo_init() < 0)
+		pr_err("%s: socinfo_init() failed\n", __func__);
+
+	fsm9900_init_gpiomux();
+	board_dt_populate(NULL);
+	fsm9900_add_drivers();
+}
+
+void __init fsm9900_init_very_early(void)
+{
+	fsm9900_early_memory();
+}
+
+static const char *fsm9900_dt_match[] __initconst = {
+	"qcom,fsm9900",
+	NULL
+};
+
+DT_MACHINE_START(FSM9900_DT, "Qualcomm FSM 9900 (Flattened Device Tree)")
+	.map_io = fsm9900_map_io,
+	.init_irq = msm_dt_init_irq,
+	.init_machine = fsm9900_init,
+	.handle_irq = gic_handle_irq,
+	.timer = &msm_dt_timer,
+	.dt_compat = fsm9900_dt_match,
+	.reserve = fsm9900_reserve,
+	.init_very_early = fsm9900_init_very_early,
+	.restart = msm_restart,
+	.smp = &msm8974_smp_ops,
+MACHINE_END
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index ac5efc1..7fe3f97 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3327,31 +3327,40 @@
 		"fda0b000.qcom,csiphy"),
 
 	/* CSID clocks */
-	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
-		"fda08000.qcom,csid"),
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
-		"fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c,       "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c,  "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_clk", camss_csi0_clk.c,         "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c,  "fda08000.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c,  "fda08000.qcom,csid"),
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", camss_csi0_ahb_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_src_clk", csi0_clk_src.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_phy_clk", camss_csi0phy_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_clk", camss_csi0_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_pix_clk", camss_csi0pix_clk.c,
+					"fda08000.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_clk", camss_csi0rdi_clk.c,
+					"fda08000.qcom,csid"),
 
-	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
-		"fda08400.qcom,csid"),
+
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
-		"fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_ahb_clk", camss_csi0_ahb_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_ahb_clk", camss_csi1_ahb_clk.c, "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c,       "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_src_clk", csi1_clk_src.c,       "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_phy_clk", camss_csi0phy_clk.c,  "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_phy_clk", camss_csi1phy_clk.c,  "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c,  "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_pix_clk", camss_csi1pix_clk.c,  "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c,  "fda08400.qcom,csid"),
-	CLK_LOOKUP("csi1_rdi_clk", camss_csi1rdi_clk.c,  "fda08400.qcom,csid"),
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_ahb_clk", camss_csi1_ahb_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_src_clk", csi1_clk_src.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_phy_clk", camss_csi1phy_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_clk", camss_csi1_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_pix_clk", camss_csi1pix_clk.c,
+					"fda08400.qcom,csid"),
+	CLK_LOOKUP("csi_rdi_clk", camss_csi1rdi_clk.c,
+					"fda08400.qcom,csid"),
 
 	/* ISPIF clocks */
 	CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index f83aa93..690e52a 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -600,6 +600,7 @@
 void msm_map_msm7x30_io(void);
 void msm_map_fsm9xxx_io(void);
 void msm_map_fsm9900_io(void);
+void fsm9900_init_gpiomux(void);
 void msm_map_8974_io(void);
 void msm_map_8084_io(void);
 void msm_map_msmkrypton_io(void);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 30168b8..098cbd5 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -330,12 +330,13 @@
 
 	drv->crash = true;
 
+	disable_irq_nosync(drv->irq);
+
 	if (drv->restart_inprogress) {
 		pr_err("Ignoring wcnss bite irq, restart in progress\n");
 		return IRQ_HANDLED;
 	}
 
-	disable_irq_nosync(drv->irq);
 	drv->restart_inprogress = true;
 	restart_wcnss(drv);
 
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 9a5883f..19b5671 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -410,12 +410,6 @@
 	drv->err_fatal_irq = ret;
 
 	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
-					    "qcom,gpio-err-ready", 0));
-	if (ret < 0)
-		return ret;
-	drv->subsys_desc.err_ready_irq = ret;
-
-	ret = gpio_to_irq(of_get_named_gpio(pdev->dev.of_node,
 					    "qcom,gpio-proxy-unvote", 0));
 	if (ret < 0)
 		return ret;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 1945651..a177593 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3939,12 +3939,11 @@
 	}
 
 	registered = true;
-	rc = remote_spin_lock_init(&remote_spinlock, SMEM_SPINLOCK_SMEM_ALLOC);
+	rc = init_smem_remote_spinlock();
 	if (rc) {
 		pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
 		return rc;
 	}
-	spinlocks_initialized = 1;
 
 	rc = platform_driver_register(&msm_smd_driver);
 	if (rc) {
diff --git a/arch/arm/mach-msm/smem.c b/arch/arm/mach-msm/smem.c
index c00f96f..2204609 100644
--- a/arch/arm/mach-msm/smem.c
+++ b/arch/arm/mach-msm/smem.c
@@ -56,6 +56,7 @@
 struct ramdump_segment *smem_ramdump_segments;
 
 static void *smem_ramdump_dev;
+static DEFINE_MUTEX(spinlock_init_lock);
 
 struct restart_notifier_block {
 	unsigned processor;
@@ -215,6 +216,7 @@
 	struct smem_heap_entry *toc = shared->heap_toc;
 	unsigned long flags;
 	void *ret = NULL;
+	int rc;
 
 	if (!shared->heap_info.initialized) {
 		pr_err("%s: smem heap info not initialized\n", __func__);
@@ -224,6 +226,15 @@
 	if (id >= SMEM_NUM_ITEMS)
 		return NULL;
 
+	if (unlikely(!spinlocks_initialized)) {
+		rc = init_smem_remote_spinlock();
+		if (unlikely(rc)) {
+			pr_err("%s: remote spinlock init failed %d\n",
+								__func__, rc);
+			return NULL;
+		}
+	}
+
 	size_in = ALIGN(size_in, 8);
 	remote_spin_lock_irqsave(&remote_spinlock, flags);
 	if (toc[id].allocated) {
@@ -301,6 +312,35 @@
 }
 EXPORT_SYMBOL(smem_get_remote_spinlock);
 
+/**
+ * init_smem_remote_spinlock - Reentrant remote spinlock initialization
+ *
+ * @returns: sucess or error code for failure
+ */
+int init_smem_remote_spinlock(void)
+{
+	int rc = 0;
+
+	/*
+	 * Optimistic locking.  Init only needs to be done once by the first
+	 * caller.  After that, serializing inits between different callers
+	 * is unnecessary.  The second check after the lock ensures init
+	 * wasn't previously completed by someone else before the lock could
+	 * be grabbed.
+	 */
+	if (!spinlocks_initialized) {
+		mutex_lock(&spinlock_init_lock);
+		if (!spinlocks_initialized) {
+			rc = remote_spin_lock_init(&remote_spinlock,
+						SMEM_SPINLOCK_SMEM_ALLOC);
+			if (!rc)
+				spinlocks_initialized = 1;
+		}
+		mutex_unlock(&spinlock_init_lock);
+	}
+	return rc;
+}
+
 static int restart_notifier_cb(struct notifier_block *this,
 				unsigned long code,
 				void *data)
diff --git a/arch/arm/mach-msm/smem_private.h b/arch/arm/mach-msm/smem_private.h
index 89b2b7b..b631e7c 100644
--- a/arch/arm/mach-msm/smem_private.h
+++ b/arch/arm/mach-msm/smem_private.h
@@ -19,7 +19,7 @@
 
 #define SMEM_SPINLOCK_SMEM_ALLOC       "S:3"
 extern remote_spinlock_t remote_spinlock;
-extern int spinlocks_initialized;
+extern int spinlocks_initialized; /* only modify in init_smem_remote_spinlock */
 
 #define SMD_HEAP_SIZE 512
 
@@ -65,4 +65,10 @@
 
 /* used for unit testing spinlocks */
 remote_spinlock_t *smem_get_remote_spinlock(void);
+
+/*
+ * used to ensure the remote spinlock is only inited once since local
+ * spinlock init code appears non-reentrant
+ */
+int init_smem_remote_spinlock(void);
 #endif /* _ARCH_ARM_MACH_MSM_SMEM_PRIVATE_H_ */
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 0e2e2d9..2b14f86 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -2,7 +2,6 @@
 # Makefile for CoreSight drivers.
 #
 obj-$(CONFIG_CORESIGHT) += coresight.o
-obj-$(CONFIG_OF) += of_coresight.o
 obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
 obj-$(CONFIG_CORESIGHT_CSR) += coresight-csr.o
 obj-$(CONFIG_CORESIGHT_TMC) += coresight-tmc.o
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index bf022ac..a506aa8 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -878,9 +878,10 @@
 				freq_next = dbs_tuners_ins.sync_freq;
 
 			if (max_load_freq >
-				 (dbs_tuners_ins.up_threshold_multi_core -
+				 ((dbs_tuners_ins.up_threshold_multi_core -
 				  dbs_tuners_ins.down_differential_multi_core) *
-				  policy->cur)
+				  policy->cur) &&
+				freq_next < dbs_tuners_ins.optimal_freq)
 				freq_next = dbs_tuners_ins.optimal_freq;
 
 		}
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 58fa5c9..2b70d3f 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -717,6 +717,9 @@
 	bool sha1 = false;
 	uint32_t auth_cfg = 0;
 
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
 							CRYPTO_CONFIG_REG));
 	/*
@@ -896,6 +899,9 @@
 	uint32_t ivsize = creq->ivsize;
 	int i;
 
+	/* clear status */
+	writel_relaxed(0, pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	writel_relaxed(pce_dev->reg.crypto_cfg_be, (pce_dev->iobase +
 							CRYPTO_CONFIG_REG));
 	/*
@@ -1213,6 +1219,7 @@
 {
 	struct aead_request *areq;
 	unsigned char mac[SHA256_DIGEST_SIZE];
+	uint32_t status;
 
 	areq = (struct aead_request *) pce_dev->areq;
 	if (areq->src != areq->dst) {
@@ -1227,16 +1234,55 @@
 	/* check MAC */
 	memcpy(mac, (char *)(&pce_dev->ce_sps.result->auth_iv[0]),
 						SHA256_DIGEST_SIZE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
 	if (pce_dev->mode == QCE_MODE_CCM) {
-		uint32_t result_status;
+		int32_t result_status;
+
+		/*
+		 * Don't use result dump status. The operation may not
+		 * be complete.
+		 * Instead, use the status we just read of device.
+		 * In case, we need to use result_status from result
+		 * dump the result_status needs to be byte swapped,
+		 * since we set the device to little endian.
+		 */
+
 		result_status = pce_dev->ce_sps.result->status;
-		result_status &= (1 << CRYPTO_MAC_FAILED);
-		result_status |= (pce_dev->ce_sps.consumer_status |
-					pce_dev->ce_sps.producer_status);
+		pce_dev->ce_sps.result->status = 0;
+
+		if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+
+			pr_err("aead 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("aead 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("aead 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 if (status & (1 << CRYPTO_MAC_FAILED)) {
+			result_status = -EBADMSG;
+		} else {
+			result_status = 0;
+		}
+
 		pce_dev->qce_cb(areq, mac, NULL, result_status);
+
 	} else {
 		uint32_t ivsize = 0;
 		struct crypto_aead *aead;
@@ -1260,6 +1306,8 @@
 	struct ahash_request *areq;
 	unsigned char digest[SHA256_DIGEST_SIZE];
 	uint32_t bytecount32[2];
+	int32_t result_status = pce_dev->ce_sps.result->status;
+	uint32_t status;
 
 	areq = (struct ahash_request *) pce_dev->areq;
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
@@ -1269,10 +1317,39 @@
 	_byte_stream_to_net_words(bytecount32,
 		(unsigned char *)pce_dev->ce_sps.result->auth_byte_count,
 					2 * CRYPTO_REG_SIZE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
+
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+
+		pr_err("sha operation error. Status %x\n", status);
+		result_status = -ENXIO;
+	} else if (pce_dev->ce_sps.consumer_status) {
+		pr_err("sha sps operation error. sps status %x\n",
+			pce_dev->ce_sps.consumer_status);
+		result_status = -ENXIO;
+	} else if ((status & (1 << CRYPTO_OPERATION_DONE)) == 0) {
+		pr_err("sha operation not done? Status %x, sps status %x\n",
+			status, pce_dev->ce_sps.consumer_status);
+		result_status = -ENXIO;
+	} else {
+		result_status = 0;
+	}
 	pce_dev->qce_cb(areq, digest, (char *)bytecount32,
-				pce_dev->ce_sps.consumer_status);
+				result_status);
 	return 0;
 };
 
@@ -1280,6 +1357,8 @@
 {
 	struct ablkcipher_request *areq;
 	unsigned char iv[NUM_OF_CRYPTO_CNTR_IV_REG * CRYPTO_REG_SIZE];
+	uint32_t status;
+	int32_t result_status;
 
 	areq = (struct ablkcipher_request *) pce_dev->areq;
 
@@ -1290,13 +1369,46 @@
 	qce_dma_unmap_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 		(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 						DMA_TO_DEVICE);
+
+	/* read status before unlock */
+	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
+
 	if (_qce_unlock_other_pipes(pce_dev))
 		return -EINVAL;
 
+	/*
+	 * Don't use result dump status. The operation may not be complete.
+	 * Instead, use the status we just read of device.
+	 * In case, we need to use result_status from result
+	 * dump the result_status needs to be byte swapped,
+	 * since we set the device to little endian.
+	 */
+	if (status & ((1 << CRYPTO_SW_ERR) | (1 << CRYPTO_AXI_ERR)
+			| (1 <<  CRYPTO_HSD_ERR))) {
+		pr_err("ablk_cipher 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("ablk_cipher 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("ablk_cipher 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;
+	}
+
 	if (pce_dev->mode == QCE_MODE_ECB) {
 		pce_dev->qce_cb(areq, NULL, NULL,
 					pce_dev->ce_sps.consumer_status |
-					pce_dev->ce_sps.producer_status);
+					result_status);
 	} else {
 		if (pce_dev->ce_sps.minor_version == 0) {
 			if (pce_dev->mode == QCE_MODE_CBC) {
@@ -1342,9 +1454,7 @@
 				(char *)(pce_dev->ce_sps.result->encr_cntr_iv),
 				sizeof(iv));
 		}
-		pce_dev->qce_cb(areq, NULL, iv,
-			pce_dev->ce_sps.consumer_status |
-			pce_dev->ce_sps.producer_status);
+		pce_dev->qce_cb(areq, NULL, iv, result_status);
 	}
 	return 0;
 };
@@ -1993,6 +2103,9 @@
 	break;
 	}
 
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
@@ -2037,13 +2150,9 @@
 	if (mode == QCE_MODE_XTS) {
 		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_CFG_REG,
-						0, &pcl_info->auth_seg_size);
 	} else {
 		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_CFG_REG,
-						0, &pcl_info->auth_seg_size);
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_START_REG,
 						0, &pcl_info->auth_seg_size);
 	}
@@ -2130,6 +2239,9 @@
 	break;
 	}
 
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 
@@ -2156,13 +2268,7 @@
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CNTR1_IV1_REG, 0,
 								NULL);
 	}
-	/* Add dummy to  align size to burst-size multiple */
-	if (!mode_cbc) {
-		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_CFG_REG,
-						0, &pcl_info->auth_seg_size);
-	}
+
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_le, NULL);
 
@@ -2206,10 +2312,13 @@
 
 		auth_cfg = pdev->reg.auth_cfg_sha1;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		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_AUTH_SEG_CFG_REG,
-							0, NULL);
 
 	break;
 	case QCE_HASH_SHA256:
@@ -2218,13 +2327,16 @@
 
 		auth_cfg = pdev->reg.auth_cfg_sha256;
 		iv_reg = 8;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	case QCE_HASH_SHA1_HMAC:
 		cmdlistptr->auth_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2233,10 +2345,13 @@
 		auth_cfg = pdev->reg.auth_cfg_hmac_sha1;
 		key_reg = 16;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		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_AUTH_SEG_CFG_REG,
-							0, NULL);
 	break;
 	case QCE_AEAD_SHA1_HMAC:
 		cmdlistptr->aead_sha1_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2245,13 +2360,16 @@
 		auth_cfg = pdev->reg.auth_cfg_aead_sha1_hmac;
 		key_reg = 16;
 		iv_reg = 5;
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG,
+					0, NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-							0, NULL);
 	break;
 	case QCE_HASH_SHA256_HMAC:
 		cmdlistptr->auth_sha256_hmac.cmdlist = (uint32_t)ce_vaddr;
@@ -2261,13 +2379,15 @@
 		key_reg = 16;
 		iv_reg = 8;
 
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
+					NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	case QCE_HASH_AES_CMAC:
 		if (key_128 == true) {
@@ -2285,13 +2405,16 @@
 			auth_cfg = pdev->reg.auth_cfg_cmac_256;
 			key_reg = 8;
 		}
+
+		/* clear status register */
+		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0,
+					NULL);
+
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_CONFIG_REG,
 			pdev->reg.crypto_cfg_be, &pcl_info->crypto_cfg);
 		/* 1 dummy write */
 		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_SIZE_REG,
 								0, NULL);
-		qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_AUTH_SEG_CFG_REG,
-								0, NULL);
 	break;
 	default:
 		pr_err("Unknown algorithms %d received, exiting now\n", alg);
@@ -2395,10 +2518,13 @@
 
 		key_reg = 8;
 	}
+
+	/* clear status register */
+	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_STATUS_REG, 0, NULL);
+
 	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_ENCR_SEG_SIZE_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_CFG_REG, 0, NULL);
 	qce_add_cmd_element(pdev, &ce_vaddr, CRYPTO_ENCR_SEG_START_REG, 0,
 									NULL);
diff --git a/drivers/crypto/msm/qcryptohw_50.h b/drivers/crypto/msm/qcryptohw_50.h
index 1be2702..e93e25c 100644
--- a/drivers/crypto/msm/qcryptohw_50.h
+++ b/drivers/crypto/msm/qcryptohw_50.h
@@ -297,6 +297,7 @@
 #define CRYPTO_DOUT_SIZE_AVAIL_MASK		(0x1F << CRYPTO_DOUT_SIZE_AVAIL)
 #define CRYPTO_DIN_SIZE_AVAIL			21 /* bit 21-25 */
 #define CRYPTO_DIN_SIZE_AVAIL_MASK		(0x1F << CRYPTO_DIN_SIZE_AVAIL)
+#define CRYPTO_HSD_ERR				20
 #define CRYPTO_ACCESS_VIOL			19
 #define CRYPTO_PIPE_ACTIVE_ERR			18
 #define CRYPTO_CFG_CHNG_ERR			17
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index e071650..52340cc 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -1454,6 +1454,8 @@
 	}
 	if (ret == 0)
 		device->active_cnt++;
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	return ret;
 }
 EXPORT_SYMBOL(kgsl_active_count_get);
@@ -1482,6 +1484,8 @@
 	}
 
 	device->active_cnt++;
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	return 0;
 }
 EXPORT_SYMBOL(kgsl_active_count_get_light);
@@ -1504,6 +1508,8 @@
 	kgsl_pwrscale_idle(device);
 	if (device->active_cnt > 1) {
 		device->active_cnt--;
+		trace_kgsl_active_count(device,
+			(unsigned long) __builtin_return_address(0));
 		return;
 	}
 
@@ -1520,6 +1526,8 @@
 	}
 	device->active_cnt--;
 
+	trace_kgsl_active_count(device,
+		(unsigned long) __builtin_return_address(0));
 	if (device->active_cnt == 0)
 		complete(&device->suspend_gate);
 }
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 5f7ee3c..08677ef 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -739,6 +739,30 @@
 			__entry->id, __entry->ts, __entry->age)
 );
 
+TRACE_EVENT(kgsl_active_count,
+
+	TP_PROTO(struct kgsl_device *device, unsigned long ip),
+
+	TP_ARGS(device, ip),
+
+	TP_STRUCT__entry(
+		__string(device_name, device->name)
+		__field(unsigned int, count)
+		__field(unsigned long, ip)
+	),
+
+	TP_fast_assign(
+		__assign_str(device_name, device->name);
+		__entry->count = device->active_cnt;
+		__entry->ip = ip;
+	),
+
+	TP_printk(
+		"d_name=%s active_cnt=%x func=%pf",
+		__get_str(device_name), __entry->count, (void *) __entry->ip
+	)
+);
+
 #endif /* _KGSL_TRACE_H */
 
 /* This part must be outside protection */
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index b3b3b5e..4306b1d 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -83,6 +83,14 @@
 #define QPNP_VADC_M1_LOW_THR_MSB					0x6a
 #define QPNP_VADC_M1_HIGH_THR_LSB				0x6b
 #define QPNP_VADC_M1_HIGH_THR_MSB				0x6c
+#define QPNP_VADC_ACCESS					0xd0
+#define QPNP_VADC_ACCESS_DATA					0xa5
+#define QPNP_VADC_PERH_RESET_CTL3				0xda
+#define QPNP_FOLLOW_OTST2_RB					BIT(3)
+#define QPNP_FOLLOW_WARM_RB					BIT(2)
+#define QPNP_FOLLOW_SHUTDOWN1_RB				BIT(1)
+#define QPNP_FOLLOW_SHUTDOWN2_RB				BIT(0)
+
 #define QPNP_INT_TEST_VAL					0xE1
 
 #define QPNP_VADC_DATA0						0x60
@@ -150,6 +158,40 @@
 	return 0;
 }
 
+static int32_t qpnp_vadc_warm_rst_configure(void)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_PERH_RESET_CTL3, &data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 read failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	data |= QPNP_FOLLOW_WARM_RB;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_PERH_RESET_CTL3, data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 write failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_vadc_enable(bool state)
 {
 	int rc = 0;
@@ -1126,6 +1168,12 @@
 	}
 	vadc->id = fab_id;
 
+	rc = qpnp_vadc_warm_rst_configure();
+	if (rc < 0) {
+		pr_err("Setting perp reset on warm reset failed %d\n", rc);
+		return rc;
+	}
+
 	vadc->vadc_initialized = true;
 	vadc->vadc_iadc_sync_lock = false;
 
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index fcade49..2c2b339 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -75,7 +75,8 @@
 	DMX_FIFO_ERROR, /* Receiver FIFO overrun */
 	DMX_MISSED_ERROR, /* Receiver missed packet */
 	DMX_OK_DECODER_BUF, /* Received OK, new ES data in decoder buffer */
-	DMX_OK_IDX /* Received OK, new index event */
+	DMX_OK_IDX, /* Received OK, new index event */
+	DMX_OK_SCRAMBLING_STATUS, /* Received OK, new scrambling status */
 } ;
 
 
@@ -135,6 +136,7 @@
 		} marker;
 
 		struct dmx_index_event_info idx_event;
+		struct dmx_scrambling_status_event_info scrambling_bits;
 	};
 };
 
@@ -250,6 +252,7 @@
 	int (*ts_insertion_terminate)(struct dmx_ts_feed *feed);
 	int (*ts_insertion_insert_buffer)(struct dmx_ts_feed *feed,
 			char *data, size_t size);
+	int (*get_scrambling_bits)(struct dmx_ts_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
@@ -300,6 +303,7 @@
 				struct dmx_secure_mode *sec_mode);
 	int (*oob_command) (struct dmx_section_feed *feed,
 				struct dmx_oob_command *cmd);
+	int (*get_scrambling_bits)(struct dmx_section_feed *feed, u8 *value);
 };
 
 /*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 2a750a6..6734da8 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -1796,6 +1796,35 @@
 	return 0;
 }
 
+static int dvb_dmxdev_get_scrambling_bits(struct dmxdev_filter *filter,
+	struct dmx_scrambling_bits *scrambling_bits)
+{
+	struct dmxdev_feed *feed;
+
+	if (!scrambling_bits ||
+		(filter->state != DMXDEV_STATE_GO))
+		return -EINVAL;
+
+	if (filter->type == DMXDEV_TYPE_SEC) {
+		if (filter->feed.sec.feed->get_scrambling_bits)
+			return filter->feed.sec.feed->get_scrambling_bits(
+						filter->feed.sec.feed,
+						&scrambling_bits->value);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(feed, &filter->feed.ts, next) {
+		if (feed->pid == scrambling_bits->pid) {
+			if (feed->ts->get_scrambling_bits)
+				return feed->ts->get_scrambling_bits(feed->ts,
+						&scrambling_bits->value);
+			return -EINVAL;
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void dvb_dmxdev_ts_insertion_work(struct work_struct *worker)
 {
 	struct ts_insertion_buffer *ts_buffer =
@@ -2519,6 +2548,13 @@
 			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
 			spin_unlock(&dmxdevfilter->dev->lock);
 			wake_up_all(&dmxdevfilter->buffer.queue);
+		} else if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+			event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+			event.params.scrambling_status =
+				dmx_data_ready->scrambling_bits;
+			dvb_dmxdev_add_event(&dmxdevfilter->events, &event);
+			spin_unlock(&dmxdevfilter->dev->lock);
+			wake_up_all(&dmxdevfilter->buffer.queue);
 		} else {
 			spin_unlock(&dmxdevfilter->dev->lock);
 		}
@@ -2635,6 +2671,16 @@
 		return 0;
 	}
 
+	if (dmx_data_ready->status == DMX_OK_SCRAMBLING_STATUS) {
+		event.type = DMX_EVENT_SCRAMBLING_STATUS_CHANGE;
+		event.params.scrambling_status =
+			dmx_data_ready->scrambling_bits;
+		dvb_dmxdev_add_event(events, &event);
+		spin_unlock(&dmxdevfilter->dev->lock);
+		wake_up_all(&buffer->queue);
+		return 0;
+	}
+
 	if (dmx_data_ready->status == DMX_OK_DECODER_BUF) {
 		event.type = DMX_EVENT_NEW_ES_DATA;
 		event.params.es_data.buf_handle = dmx_data_ready->buf.handle;
@@ -3938,6 +3984,15 @@
 		mutex_unlock(&dmxdevfilter->mutex);
 		break;
 
+	case DMX_GET_SCRAMBLING_BITS:
+		if (mutex_lock_interruptible(&dmxdevfilter->mutex)) {
+			mutex_unlock(&dmxdev->mutex);
+			return -ERESTARTSYS;
+		}
+		ret = dvb_dmxdev_get_scrambling_bits(dmxdevfilter, parg);
+		mutex_unlock(&dmxdevfilter->mutex);
+		break;
+
 	default:
 		ret = -EINVAL;
 		break;
@@ -4193,6 +4248,7 @@
 	struct dmxdev_filter *filter;
 	int active_count = 0;
 	struct dmx_buffer_status buffer_status;
+	struct dmx_scrambling_bits scrambling_bits;
 	const char *pes_feeds[] = {"DEC", "PES", "DVR", "REC"};
 
 	if (!dmxdev)
@@ -4209,23 +4265,32 @@
 				seq_printf(s, "type: SEC, ");
 				seq_printf(s, "PID %04d ",
 						filter->params.sec.pid);
+				scrambling_bits.pid = filter->params.sec.pid;
 			} else {
 				seq_printf(s, "type: %s, ",
 					pes_feeds[filter->params.pes.output]);
 				seq_printf(s, "PID: %04d ",
 						filter->params.pes.pid);
+				scrambling_bits.pid = filter->params.pes.pid;
 			}
 
+			dvb_dmxdev_get_scrambling_bits(filter,
+				&scrambling_bits);
+
 			if (0 == dvb_dmxdev_get_buffer_status(
 						filter, &buffer_status)) {
 				seq_printf(s, "size: %08d, ",
 					buffer_status.size);
 				seq_printf(s, "fullness: %08d, ",
 					buffer_status.fullness);
-				seq_printf(s, "error: %d\n",
+				seq_printf(s, "error: %d, ",
 					buffer_status.error);
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
+
 			} else {
-				seq_printf(s, "\n");
+				seq_printf(s, "scramble: %d\n",
+					scrambling_bits.value);
 			}
 		}
 	}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 9844c64..8caa9dd 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -164,6 +164,11 @@
 	return ((buf[1] & 0x1f) << 8) + buf[2];
 }
 
+static inline u16 ts_scrambling_ctrl(const u8 *buf)
+{
+	return (buf[3] >> 6) & 0x3;
+}
+
 static inline u8 payload(const u8 *tsp)
 {
 	if (!(tsp[3] & 0x10))	// no payload?
@@ -1287,6 +1292,32 @@
 static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed,
 			const u8 *buf, const u8 timestamp[TIMESTAMP_LEN])
 {
+	u16 pid = ts_pid(buf);
+	u8 scrambling_bits = ts_scrambling_ctrl(buf);
+	struct dmx_data_ready dmx_data_ready;
+
+	/*
+	 * Notify on scrambling status change only when we move
+	 * from clear (0) to non-clear and vise-versa
+	 */
+	if ((scrambling_bits && !feed->scrambling_bits) ||
+		(!scrambling_bits && feed->scrambling_bits)) {
+		dmx_data_ready.status = DMX_OK_SCRAMBLING_STATUS;
+		dmx_data_ready.data_length = 0;
+		dmx_data_ready.scrambling_bits.pid = pid;
+		dmx_data_ready.scrambling_bits.old_value =
+			feed->scrambling_bits;
+		dmx_data_ready.scrambling_bits.new_value = scrambling_bits;
+
+		if (feed->type == DMX_TYPE_SEC)
+			feed->data_ready_cb.sec(&feed->filter->filter,
+					&dmx_data_ready);
+		else
+			feed->data_ready_cb.ts(&feed->feed.ts, &dmx_data_ready);
+	}
+
+	feed->scrambling_bits = scrambling_bits;
+
 	switch (feed->type) {
 	case DMX_TYPE_TS:
 		if (!feed->feed.ts.is_filtering)
@@ -2047,6 +2078,7 @@
 	}
 
 	feed->first_cc = 1;
+	feed->scrambling_bits = 0;
 
 	if ((feed->ts_type & TS_PACKET) &&
 		!(feed->ts_type & TS_PAYLOAD_ONLY)) {
@@ -2302,6 +2334,25 @@
 	return ret;
 }
 
+static int dvbdmx_ts_get_scrambling_bits(struct dmx_ts_feed *ts_feed,
+			u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)ts_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!ts_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_ts_insertion_insert_buffer(struct dmx_ts_feed *ts_feed,
 			char *data, size_t size)
 {
@@ -2391,6 +2442,7 @@
 	(*ts_feed)->notify_data_read = NULL;
 	(*ts_feed)->set_secure_mode = dmx_ts_set_secure_mode;
 	(*ts_feed)->oob_command = dvbdmx_ts_feed_oob_cmd;
+	(*ts_feed)->get_scrambling_bits = dvbdmx_ts_get_scrambling_bits;
 	(*ts_feed)->ts_insertion_init = NULL;
 	(*ts_feed)->ts_insertion_terminate = NULL;
 	(*ts_feed)->ts_insertion_insert_buffer =
@@ -2557,6 +2609,7 @@
 	dvbdmxfeed->feed.sec.secbufp = 0;
 	dvbdmxfeed->feed.sec.seclen = 0;
 	dvbdmxfeed->first_cc = 1;
+	dvbdmxfeed->scrambling_bits = 0;
 
 	if (!dvbdmx->start_feed) {
 		mutex_unlock(&dvbdmx->mutex);
@@ -2723,6 +2776,25 @@
 	return ret;
 }
 
+static int dvbdmx_section_get_scrambling_bits(
+	struct dmx_section_feed *section_feed, u8 *value)
+{
+	struct dvb_demux_feed *feed = (struct dvb_demux_feed *)section_feed;
+	struct dvb_demux *demux = feed->demux;
+
+	spin_lock(&demux->lock);
+
+	if (!section_feed->is_filtering) {
+		spin_unlock(&demux->lock);
+		return -EINVAL;
+	}
+
+	*value = feed->scrambling_bits;
+	spin_unlock(&demux->lock);
+
+	return 0;
+}
+
 static int dvbdmx_allocate_section_feed(struct dmx_demux *demux,
 					struct dmx_section_feed **feed,
 					dmx_section_cb callback)
@@ -2763,6 +2835,7 @@
 	(*feed)->notify_data_read = NULL;
 	(*feed)->set_secure_mode = dmx_section_set_secure_mode;
 	(*feed)->oob_command = dvbdmx_section_feed_oob_cmd;
+	(*feed)->get_scrambling_bits = dvbdmx_section_get_scrambling_bits;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index 879aad2..9fb1a12 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -187,6 +187,8 @@
 	int first_cc;
 	int pusi_seen;		/* prevents feeding of garbage from previous section */
 
+	u8 scrambling_bits;
+
 	struct dvb_demux_rec_info *rec_info;
 	u64 prev_tsp_num;
 	u64 prev_stc;
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 59858b5..88f2f08 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
@@ -80,13 +80,20 @@
 }
 
 static uint32_t msm_isp_get_buf_handle(
-	struct msm_isp_buf_mgr *buf_mgr)
+	struct msm_isp_buf_mgr *buf_mgr,
+	uint32_t session_id, uint32_t stream_id)
 {
 	int i;
 	if ((buf_mgr->buf_handle_cnt << 8) == 0)
 		buf_mgr->buf_handle_cnt++;
 
 	for (i = 0; i < buf_mgr->num_buf_q; i++) {
+		if (buf_mgr->bufq[i].session_id == session_id &&
+			buf_mgr->bufq[i].stream_id == stream_id)
+			return 0;
+	}
+
+	for (i = 0; i < buf_mgr->num_buf_q; i++) {
 		if (buf_mgr->bufq[i].bufq_handle == 0) {
 			memset(&buf_mgr->bufq[i],
 				0, sizeof(struct msm_isp_bufq));
@@ -604,7 +611,8 @@
 		return rc;
 	}
 
-	buf_request->handle = msm_isp_get_buf_handle(buf_mgr);
+	buf_request->handle = msm_isp_get_buf_handle(buf_mgr,
+		buf_request->session_id, buf_request->stream_id);
 	if (!buf_request->handle) {
 		pr_err("Invalid buffer handle\n");
 		return rc;
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 7bc2b7d..4e3818c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -38,6 +38,8 @@
 #define VFE_PING_FLAG 0xFFFFFFFF
 #define VFE_PONG_FLAG 0x0
 
+#define VFE_MAX_CFG_TIMEOUT 3000
+
 struct vfe_device;
 struct msm_vfe_axi_stream;
 struct msm_vfe_stats_stream;
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 13160ee..cc534fc 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
@@ -384,7 +384,7 @@
 		break;
 	}
 
-	sof_event.frame_id = vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id;
+	sof_event.frame_id = vfe_dev->axi_data.src_info[frame_src].frame_id;
 	sof_event.timestamp = ts->event_time;
 	msm_isp_send_event(vfe_dev, ISP_EVENT_SOF, &sof_event);
 }
@@ -852,7 +852,7 @@
 	spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stream_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
@@ -976,18 +976,33 @@
 			enum msm_isp_camif_update_state camif_update)
 {
 	int i, rc = 0;
+	uint8_t wait_for_complete = 0;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		stream_info = &axi_data->stream_info[
 			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+
 		stream_info->state = STOP_PENDING;
+		if (stream_info->stream_type == BURST_STREAM &&
+			stream_info->runtime_num_burst_capture == 0) {
+			/*Configure AXI writemasters to stop immediately
+			 *since for burst case, write masters already skip
+			 *all frames.
+			 */
+			msm_isp_axi_stream_enable_cfg(vfe_dev, stream_info);
+			stream_info->state = INACTIVE;
+		} else {
+			wait_for_complete = 1;
+		}
 	}
 
-	rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
-	if (rc < 0) {
-		pr_err("%s: wait for config done failed\n", __func__);
-		return rc;
+	if (wait_for_complete) {
+		rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
+		if (rc < 0) {
+			pr_err("%s: wait for config done failed\n", __func__);
+			return rc;
+		}
 	}
 	msm_isp_update_stream_bandwidth(vfe_dev);
 	if (camif_update == DISABLE_CAMIF)
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index ce71235..d857a14 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -343,7 +343,7 @@
 	atomic_set(&vfe_dev->stats_data.stats_update, 2);
 	rc = wait_for_completion_interruptible_timeout(
 		&vfe_dev->stats_config_complete,
-		msecs_to_jiffies(500));
+		msecs_to_jiffies(VFE_MAX_CFG_TIMEOUT));
 	if (rc == 0) {
 		pr_err("%s: wait timeout\n", __func__);
 		rc = -1;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/Makefile b/drivers/media/platform/msm/camera_v2/pproc/Makefile
index 854e4e7..4193adc 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/Makefile
+++ b/drivers/media/platform/msm/camera_v2/pproc/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_MSMB_CAMERA) += cpp/
+obj-$(CONFIG_MSMB_CAMERA) += vpe/
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/Makefile b/drivers/media/platform/msm/camera_v2/pproc/vpe/Makefile
new file mode 100644
index 0000000..65a7e34
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/Makefile
@@ -0,0 +1,3 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+obj-$(CONFIG_MSMB_CAMERA) += msm_vpe.o
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
new file mode 100644
index 0000000..d53d766
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.c
@@ -0,0 +1,1643 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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) "MSM-VPE %s:%d " fmt, __func__, __LINE__
+
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <linux/msm_ion.h>
+#include <linux/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/iommu.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-subdev.h>
+#include <media/media-entity.h>
+#include <media/msmb_pproc.h>
+#include <media/msmb_generic_buf_mgr.h>
+#include "msm_vpe.h"
+#include "msm_camera_io_util.h"
+
+#define MSM_VPE_IDENT_TO_SESSION_ID(identity) ((identity >> 16) & 0xFFFF)
+#define MSM_VPE_IDENT_TO_STREAM_ID(identity) (identity & 0xFFFF)
+
+#define MSM_VPE_DRV_NAME "msm_vpe"
+
+#define MSM_VPE_MAX_BUFF_QUEUE 16
+
+#define CONFIG_MSM_VPE_DBG 0
+
+#if CONFIG_MSM_VPE_DBG
+#define VPE_DBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define VPE_DBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+static void vpe_mem_dump(const char * const name, const void * const addr,
+			int size)
+{
+	char line_str[128], *p_str;
+	int i;
+	u32 *p = (u32 *) addr;
+	u32 data;
+	VPE_DBG("%s: (%s) %p %d\n", __func__, name, addr, size);
+	line_str[0] = '\0';
+	p_str = line_str;
+	for (i = 0; i < size/4; i++) {
+		if (i % 4 == 0) {
+			snprintf(p_str, 12, "%08x: ", (u32) p);
+			p_str += 10;
+		}
+		data = *p++;
+		snprintf(p_str, 12, "%08x ", data);
+		p_str += 9;
+		if ((i + 1) % 4 == 0) {
+			VPE_DBG("%s\n", line_str);
+			line_str[0] = '\0';
+			p_str = line_str;
+		}
+	}
+	if (line_str[0] != '\0')
+		VPE_DBG("%s\n", line_str);
+}
+
+static inline long long vpe_do_div(long long num, long long den)
+{
+	do_div(num, den);
+	return num;
+}
+
+#define msm_dequeue(queue, member) ({					\
+			unsigned long flags;				\
+			struct msm_device_queue *__q = (queue);		\
+			struct msm_queue_cmd *qcmd = 0;			\
+			spin_lock_irqsave(&__q->lock, flags);		\
+			if (!list_empty(&__q->list)) {			\
+				__q->len--;				\
+				qcmd = list_first_entry(&__q->list,	\
+							struct msm_queue_cmd, \
+							member);	\
+				list_del_init(&qcmd->member);		\
+			}						\
+			spin_unlock_irqrestore(&__q->lock, flags);	\
+			qcmd;						\
+		})
+
+static void msm_queue_init(struct msm_device_queue *queue, const char *name)
+{
+	spin_lock_init(&queue->lock);
+	queue->len = 0;
+	queue->max = 0;
+	queue->name = name;
+	INIT_LIST_HEAD(&queue->list);
+	init_waitqueue_head(&queue->wait);
+}
+
+static struct msm_cam_clk_info vpe_clk_info[] = {
+	{"vpe_clk", 160000000},
+	{"vpe_pclk", -1},
+};
+
+static int msm_vpe_notify_frame_done(struct vpe_device *vpe_dev);
+
+static void msm_enqueue(struct msm_device_queue *queue,
+			struct list_head *entry)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&queue->lock, flags);
+	queue->len++;
+	if (queue->len > queue->max) {
+		queue->max = queue->len;
+		pr_debug("queue %s new max is %d\n", queue->name, queue->max);
+	}
+	list_add_tail(entry, &queue->list);
+	wake_up(&queue->wait);
+	VPE_DBG("woke up %s\n", queue->name);
+	spin_unlock_irqrestore(&queue->lock, flags);
+}
+
+static struct msm_vpe_buff_queue_info_t *msm_vpe_get_buff_queue_entry(
+	struct vpe_device *vpe_dev, uint32_t session_id, uint32_t stream_id)
+{
+	uint32_t i = 0;
+	struct msm_vpe_buff_queue_info_t *buff_queue_info = NULL;
+
+	for (i = 0; i < vpe_dev->num_buffq; i++) {
+		if ((vpe_dev->buff_queue[i].used == 1) &&
+			(vpe_dev->buff_queue[i].session_id == session_id) &&
+			(vpe_dev->buff_queue[i].stream_id == stream_id)) {
+			buff_queue_info = &vpe_dev->buff_queue[i];
+			break;
+		}
+	}
+
+	if (buff_queue_info == NULL) {
+		pr_err("error buffer queue entry for sess:%d strm:%d not found\n",
+			session_id, stream_id);
+	}
+	return buff_queue_info;
+}
+
+static unsigned long msm_vpe_get_phy_addr(struct vpe_device *vpe_dev,
+	struct msm_vpe_buff_queue_info_t *buff_queue_info, uint32_t buff_index,
+	uint8_t native_buff)
+{
+	unsigned long phy_add = 0;
+	struct list_head *buff_head;
+	struct msm_vpe_buffer_map_list_t *buff, *save;
+
+	if (native_buff)
+		buff_head = &buff_queue_info->native_buff_head;
+	else
+		buff_head = &buff_queue_info->vb2_buff_head;
+
+	list_for_each_entry_safe(buff, save, buff_head, entry) {
+		if (buff->map_info.buff_info.index == buff_index) {
+			phy_add = buff->map_info.phy_addr;
+			break;
+		}
+	}
+
+	return phy_add;
+}
+
+static unsigned long msm_vpe_queue_buffer_info(struct vpe_device *vpe_dev,
+	struct msm_vpe_buff_queue_info_t *buff_queue,
+	struct msm_vpe_buffer_info_t *buffer_info)
+{
+	struct list_head *buff_head;
+	struct msm_vpe_buffer_map_list_t *buff, *save;
+	int rc = 0;
+
+	if (buffer_info->native_buff)
+		buff_head = &buff_queue->native_buff_head;
+	else
+		buff_head = &buff_queue->vb2_buff_head;
+
+	list_for_each_entry_safe(buff, save, buff_head, entry) {
+		if (buff->map_info.buff_info.index == buffer_info->index) {
+			pr_err("error buffer index already queued\n");
+			return -EINVAL;
+		}
+	}
+
+	buff = kzalloc(
+		sizeof(struct msm_vpe_buffer_map_list_t), GFP_KERNEL);
+	if (!buff) {
+		pr_err("error allocating memory\n");
+		return -EINVAL;
+	}
+
+	buff->map_info.buff_info = *buffer_info;
+	buff->map_info.ion_handle = ion_import_dma_buf(vpe_dev->client,
+		buffer_info->fd);
+	if (IS_ERR_OR_NULL(buff->map_info.ion_handle)) {
+		pr_err("ION import failed\n");
+		goto queue_buff_error1;
+	}
+
+	rc = ion_map_iommu(vpe_dev->client, buff->map_info.ion_handle,
+		vpe_dev->domain_num, 0, SZ_4K, 0,
+		(unsigned long *)&buff->map_info.phy_addr,
+		&buff->map_info.len, 0, 0);
+	if (rc < 0) {
+		pr_err("ION mmap failed\n");
+		goto queue_buff_error2;
+	}
+
+	INIT_LIST_HEAD(&buff->entry);
+	list_add_tail(&buff->entry, buff_head);
+
+	return buff->map_info.phy_addr;
+
+queue_buff_error2:
+	ion_unmap_iommu(vpe_dev->client, buff->map_info.ion_handle,
+		vpe_dev->domain_num, 0);
+queue_buff_error1:
+	ion_free(vpe_dev->client, buff->map_info.ion_handle);
+	buff->map_info.ion_handle = NULL;
+	kzfree(buff);
+
+	return 0;
+}
+
+static void msm_vpe_dequeue_buffer_info(struct vpe_device *vpe_dev,
+	struct msm_vpe_buffer_map_list_t *buff)
+{
+	ion_unmap_iommu(vpe_dev->client, buff->map_info.ion_handle,
+		vpe_dev->domain_num, 0);
+	ion_free(vpe_dev->client, buff->map_info.ion_handle);
+	buff->map_info.ion_handle = NULL;
+
+	list_del_init(&buff->entry);
+	kzfree(buff);
+
+	return;
+}
+
+static unsigned long msm_vpe_fetch_buffer_info(struct vpe_device *vpe_dev,
+	struct msm_vpe_buffer_info_t *buffer_info, uint32_t session_id,
+	uint32_t stream_id)
+{
+	unsigned long phy_addr = 0;
+	struct msm_vpe_buff_queue_info_t *buff_queue_info;
+	uint8_t native_buff = buffer_info->native_buff;
+
+	buff_queue_info = msm_vpe_get_buff_queue_entry(vpe_dev, session_id,
+		stream_id);
+	if (buff_queue_info == NULL) {
+		pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+			session_id, stream_id);
+		return phy_addr;
+	}
+
+	phy_addr = msm_vpe_get_phy_addr(vpe_dev, buff_queue_info,
+		buffer_info->index, native_buff);
+	if ((phy_addr == 0) && (native_buff)) {
+		phy_addr = msm_vpe_queue_buffer_info(vpe_dev, buff_queue_info,
+			buffer_info);
+	}
+	return phy_addr;
+}
+
+static int32_t msm_vpe_enqueue_buff_info_list(struct vpe_device *vpe_dev,
+	struct msm_vpe_stream_buff_info_t *stream_buff_info)
+{
+	uint32_t j;
+	struct msm_vpe_buff_queue_info_t *buff_queue_info;
+
+	buff_queue_info = msm_vpe_get_buff_queue_entry(vpe_dev,
+			(stream_buff_info->identity >> 16) & 0xFFFF,
+			stream_buff_info->identity & 0xFFFF);
+	if (buff_queue_info == NULL) {
+		pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+			(stream_buff_info->identity >> 16) & 0xFFFF,
+			stream_buff_info->identity & 0xFFFF);
+		return -EINVAL;
+	}
+
+	for (j = 0; j < stream_buff_info->num_buffs; j++) {
+		msm_vpe_queue_buffer_info(vpe_dev, buff_queue_info,
+		&stream_buff_info->buffer_info[j]);
+	}
+	return 0;
+}
+
+static int32_t msm_vpe_dequeue_buff_info_list(struct vpe_device *vpe_dev,
+	struct msm_vpe_buff_queue_info_t *buff_queue_info)
+{
+	struct msm_vpe_buffer_map_list_t *buff, *save;
+	struct list_head *buff_head;
+
+	buff_head = &buff_queue_info->native_buff_head;
+	list_for_each_entry_safe(buff, save, buff_head, entry) {
+		msm_vpe_dequeue_buffer_info(vpe_dev, buff);
+	}
+
+	buff_head = &buff_queue_info->vb2_buff_head;
+	list_for_each_entry_safe(buff, save, buff_head, entry) {
+		msm_vpe_dequeue_buffer_info(vpe_dev, buff);
+	}
+
+	return 0;
+}
+
+static int32_t msm_vpe_add_buff_queue_entry(struct vpe_device *vpe_dev,
+	uint16_t session_id, uint16_t stream_id)
+{
+	uint32_t i;
+	struct msm_vpe_buff_queue_info_t *buff_queue_info;
+
+	for (i = 0; i < vpe_dev->num_buffq; i++) {
+		if (vpe_dev->buff_queue[i].used == 0) {
+			buff_queue_info = &vpe_dev->buff_queue[i];
+			buff_queue_info->used = 1;
+			buff_queue_info->session_id = session_id;
+			buff_queue_info->stream_id = stream_id;
+			INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
+			INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
+			return 0;
+		}
+	}
+	pr_err("buffer queue full. error for sessionid: %d streamid: %d\n",
+		session_id, stream_id);
+	return -EINVAL;
+}
+
+static int32_t msm_vpe_free_buff_queue_entry(struct vpe_device *vpe_dev,
+					uint32_t session_id, uint32_t stream_id)
+{
+	struct msm_vpe_buff_queue_info_t *buff_queue_info;
+
+	buff_queue_info = msm_vpe_get_buff_queue_entry(vpe_dev, session_id,
+		stream_id);
+	if (buff_queue_info == NULL) {
+		pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+			session_id, stream_id);
+		return -EINVAL;
+	}
+
+	buff_queue_info->used = 0;
+	buff_queue_info->session_id = 0;
+	buff_queue_info->stream_id = 0;
+	INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
+	INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
+	return 0;
+}
+
+static int32_t msm_vpe_create_buff_queue(struct vpe_device *vpe_dev,
+					uint32_t num_buffq)
+{
+	struct msm_vpe_buff_queue_info_t *buff_queue;
+	buff_queue = kzalloc(
+		sizeof(struct msm_vpe_buff_queue_info_t) * num_buffq,
+		GFP_KERNEL);
+	if (!buff_queue) {
+		pr_err("Buff queue allocation failure\n");
+		return -ENOMEM;
+	}
+
+	if (vpe_dev->buff_queue) {
+		pr_err("Buff queue not empty\n");
+		kzfree(buff_queue);
+		return -EINVAL;
+	} else {
+		vpe_dev->buff_queue = buff_queue;
+		vpe_dev->num_buffq = num_buffq;
+	}
+	return 0;
+}
+
+static void msm_vpe_delete_buff_queue(struct vpe_device *vpe_dev)
+{
+	uint32_t i;
+
+	for (i = 0; i < vpe_dev->num_buffq; i++) {
+		if (vpe_dev->buff_queue[i].used == 1) {
+			pr_err("Queue not free sessionid: %d, streamid: %d\n",
+				vpe_dev->buff_queue[i].session_id,
+				vpe_dev->buff_queue[i].stream_id);
+			msm_vpe_free_buff_queue_entry(vpe_dev,
+				vpe_dev->buff_queue[i].session_id,
+				vpe_dev->buff_queue[i].stream_id);
+		}
+	}
+	kzfree(vpe_dev->buff_queue);
+	vpe_dev->buff_queue = NULL;
+	vpe_dev->num_buffq = 0;
+	return;
+}
+
+void vpe_release_ion_client(struct kref *ref)
+{
+	struct vpe_device *vpe_dev = container_of(ref,
+		struct vpe_device, refcount);
+	ion_client_destroy(vpe_dev->client);
+}
+
+static int vpe_init_mem(struct vpe_device *vpe_dev)
+{
+	kref_init(&vpe_dev->refcount);
+	kref_get(&vpe_dev->refcount);
+	vpe_dev->client = msm_ion_client_create(-1, "vpe");
+
+	if (!vpe_dev->client) {
+		pr_err("couldn't create ion client\n");
+		return  -ENODEV;
+	}
+
+	return 0;
+}
+
+static void vpe_deinit_mem(struct vpe_device *vpe_dev)
+{
+	kref_put(&vpe_dev->refcount, vpe_release_ion_client);
+}
+
+static irqreturn_t msm_vpe_irq(int irq_num, void *data)
+{
+	unsigned long flags;
+	uint32_t irq_status;
+	struct msm_vpe_tasklet_queue_cmd *queue_cmd;
+	struct vpe_device *vpe_dev = (struct vpe_device *) data;
+
+	irq_status = msm_camera_io_r_mb(vpe_dev->base +
+					VPE_INTR_STATUS_OFFSET);
+
+	spin_lock_irqsave(&vpe_dev->tasklet_lock, flags);
+	queue_cmd = &vpe_dev->tasklet_queue_cmd[vpe_dev->taskletq_idx];
+	if (queue_cmd->cmd_used) {
+		VPE_DBG("%s: vpe tasklet queue overflow\n", __func__);
+		list_del(&queue_cmd->list);
+	} else {
+		atomic_add(1, &vpe_dev->irq_cnt);
+	}
+	queue_cmd->irq_status = irq_status;
+
+	queue_cmd->cmd_used = 1;
+	vpe_dev->taskletq_idx =
+		(vpe_dev->taskletq_idx + 1) % MSM_VPE_TASKLETQ_SIZE;
+	list_add_tail(&queue_cmd->list, &vpe_dev->tasklet_q);
+	spin_unlock_irqrestore(&vpe_dev->tasklet_lock, flags);
+
+	tasklet_schedule(&vpe_dev->vpe_tasklet);
+
+	msm_camera_io_w_mb(irq_status, vpe_dev->base + VPE_INTR_CLEAR_OFFSET);
+	msm_camera_io_w(0, vpe_dev->base + VPE_INTR_ENABLE_OFFSET);
+	VPE_DBG("%s: irq_status=0x%x.\n", __func__, irq_status);
+
+	return IRQ_HANDLED;
+}
+
+static void msm_vpe_do_tasklet(unsigned long data)
+{
+	unsigned long flags;
+	struct vpe_device *vpe_dev = (struct vpe_device *)data;
+	struct msm_vpe_tasklet_queue_cmd *queue_cmd;
+
+	while (atomic_read(&vpe_dev->irq_cnt)) {
+		spin_lock_irqsave(&vpe_dev->tasklet_lock, flags);
+		queue_cmd = list_first_entry(&vpe_dev->tasklet_q,
+					struct msm_vpe_tasklet_queue_cmd, list);
+		if (!queue_cmd) {
+			atomic_set(&vpe_dev->irq_cnt, 0);
+			spin_unlock_irqrestore(&vpe_dev->tasklet_lock, flags);
+			return;
+		}
+		atomic_sub(1, &vpe_dev->irq_cnt);
+		list_del(&queue_cmd->list);
+		queue_cmd->cmd_used = 0;
+
+		spin_unlock_irqrestore(&vpe_dev->tasklet_lock, flags);
+
+		VPE_DBG("Frame done!!\n");
+		msm_vpe_notify_frame_done(vpe_dev);
+	}
+}
+
+static int vpe_init_hardware(struct vpe_device *vpe_dev)
+{
+	int rc = 0;
+
+	if (vpe_dev->fs_vpe == NULL) {
+		vpe_dev->fs_vpe =
+			regulator_get(&vpe_dev->pdev->dev, "vdd");
+		if (IS_ERR(vpe_dev->fs_vpe)) {
+			pr_err("Regulator vpe vdd get failed %ld\n",
+				PTR_ERR(vpe_dev->fs_vpe));
+			vpe_dev->fs_vpe = NULL;
+			rc = -ENODEV;
+			goto fail;
+		} else if (regulator_enable(vpe_dev->fs_vpe)) {
+			pr_err("Regulator vpe vdd enable failed\n");
+			regulator_put(vpe_dev->fs_vpe);
+			vpe_dev->fs_vpe = NULL;
+			rc = -ENODEV;
+			goto fail;
+		}
+	}
+
+	rc = msm_cam_clk_enable(&vpe_dev->pdev->dev, vpe_clk_info,
+				vpe_dev->vpe_clk, ARRAY_SIZE(vpe_clk_info), 1);
+	if (rc < 0) {
+		rc = -ENODEV;
+		pr_err("clk enable failed\n");
+		goto disable_and_put_regulator;
+	}
+
+	vpe_dev->base = ioremap(vpe_dev->mem->start,
+		resource_size(vpe_dev->mem));
+	if (!vpe_dev->base) {
+		rc = -ENOMEM;
+		pr_err("ioremap failed\n");
+		goto disable_and_put_regulator;
+	}
+
+	if (vpe_dev->state != VPE_STATE_BOOT) {
+		rc = request_irq(vpe_dev->irq->start, msm_vpe_irq,
+				IRQF_TRIGGER_RISING,
+				"vpe", vpe_dev);
+		if (rc < 0) {
+			pr_err("irq request fail! start=%u\n",
+				vpe_dev->irq->start);
+			rc = -EBUSY;
+			goto unmap_base;
+		} else {
+			VPE_DBG("Got irq! %d\n", vpe_dev->irq->start);
+		}
+	} else {
+		VPE_DBG("Skip requesting the irq since device is booting\n");
+	}
+	vpe_dev->buf_mgr_subdev = msm_buf_mngr_get_subdev();
+
+	msm_vpe_create_buff_queue(vpe_dev, MSM_VPE_MAX_BUFF_QUEUE);
+	return rc;
+
+unmap_base:
+	iounmap(vpe_dev->base);
+disable_and_put_regulator:
+	regulator_disable(vpe_dev->fs_vpe);
+	regulator_put(vpe_dev->fs_vpe);
+fail:
+	return rc;
+}
+
+static int vpe_release_hardware(struct vpe_device *vpe_dev)
+{
+	if (vpe_dev->state != VPE_STATE_BOOT) {
+		free_irq(vpe_dev->irq->start, vpe_dev);
+		tasklet_kill(&vpe_dev->vpe_tasklet);
+		atomic_set(&vpe_dev->irq_cnt, 0);
+	}
+
+	msm_vpe_delete_buff_queue(vpe_dev);
+	iounmap(vpe_dev->base);
+	msm_cam_clk_enable(&vpe_dev->pdev->dev, vpe_clk_info,
+			vpe_dev->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
+	return 0;
+}
+
+static int vpe_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	int rc = 0;
+	uint32_t i;
+	struct vpe_device *vpe_dev = v4l2_get_subdevdata(sd);
+
+	mutex_lock(&vpe_dev->mutex);
+	if (vpe_dev->vpe_open_cnt == MAX_ACTIVE_VPE_INSTANCE) {
+		pr_err("No free VPE instance\n");
+		rc = -ENODEV;
+		goto err_mutex_unlock;
+	}
+
+	for (i = 0; i < MAX_ACTIVE_VPE_INSTANCE; i++) {
+		if (vpe_dev->vpe_subscribe_list[i].active == 0) {
+			vpe_dev->vpe_subscribe_list[i].active = 1;
+			vpe_dev->vpe_subscribe_list[i].vfh = &fh->vfh;
+			break;
+		}
+	}
+	if (i == MAX_ACTIVE_VPE_INSTANCE) {
+		pr_err("No free instance\n");
+		rc = -ENODEV;
+		goto err_mutex_unlock;
+	}
+
+	VPE_DBG("open %d %p\n", i, &fh->vfh);
+	vpe_dev->vpe_open_cnt++;
+	if (vpe_dev->vpe_open_cnt == 1) {
+		rc = vpe_init_hardware(vpe_dev);
+		if (rc < 0) {
+			pr_err("%s: Couldn't init vpe hardware\n", __func__);
+			vpe_dev->vpe_open_cnt--;
+			rc = -ENODEV;
+			goto err_fixup_sub_list;
+		}
+		rc = vpe_init_mem(vpe_dev);
+		if (rc < 0) {
+			pr_err("%s: Couldn't init mem\n", __func__);
+			vpe_dev->vpe_open_cnt--;
+			rc = -ENODEV;
+			goto err_release_hardware;
+		}
+		vpe_dev->state = VPE_STATE_IDLE;
+	}
+	mutex_unlock(&vpe_dev->mutex);
+
+	return rc;
+
+err_release_hardware:
+	vpe_release_hardware(vpe_dev);
+err_fixup_sub_list:
+	for (i = 0; i < MAX_ACTIVE_VPE_INSTANCE; i++) {
+		if (vpe_dev->vpe_subscribe_list[i].vfh == &fh->vfh) {
+			vpe_dev->vpe_subscribe_list[i].active = 0;
+			vpe_dev->vpe_subscribe_list[i].vfh = NULL;
+			break;
+		}
+	}
+err_mutex_unlock:
+	mutex_unlock(&vpe_dev->mutex);
+	return rc;
+}
+
+static int vpe_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	uint32_t i;
+	struct vpe_device *vpe_dev = v4l2_get_subdevdata(sd);
+	mutex_lock(&vpe_dev->mutex);
+	for (i = 0; i < MAX_ACTIVE_VPE_INSTANCE; i++) {
+		if (vpe_dev->vpe_subscribe_list[i].vfh == &fh->vfh) {
+			vpe_dev->vpe_subscribe_list[i].active = 0;
+			vpe_dev->vpe_subscribe_list[i].vfh = NULL;
+			break;
+		}
+	}
+	if (i == MAX_ACTIVE_VPE_INSTANCE) {
+		pr_err("Invalid close\n");
+		mutex_unlock(&vpe_dev->mutex);
+		return -ENODEV;
+	}
+
+	VPE_DBG("close %d %p\n", i, &fh->vfh);
+	vpe_dev->vpe_open_cnt--;
+	if (vpe_dev->vpe_open_cnt == 0) {
+		vpe_deinit_mem(vpe_dev);
+		vpe_release_hardware(vpe_dev);
+		vpe_dev->state = VPE_STATE_OFF;
+	}
+	mutex_unlock(&vpe_dev->mutex);
+	return 0;
+}
+
+static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops = {
+	.open = vpe_open_node,
+	.close = vpe_close_node,
+};
+
+static int msm_vpe_buffer_ops(struct vpe_device *vpe_dev,
+	uint32_t buff_mgr_ops, struct msm_buf_mngr_info *buff_mgr_info)
+{
+	int rc = -EINVAL;
+
+	rc = v4l2_subdev_call(vpe_dev->buf_mgr_subdev, core, ioctl,
+		buff_mgr_ops, buff_mgr_info);
+	if (rc < 0)
+		pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+	return rc;
+}
+
+static int msm_vpe_notify_frame_done(struct vpe_device *vpe_dev)
+{
+	struct v4l2_event v4l2_evt;
+	struct msm_queue_cmd *frame_qcmd;
+	struct msm_queue_cmd *event_qcmd;
+	struct msm_vpe_frame_info_t *processed_frame;
+	struct msm_device_queue *queue = &vpe_dev->processing_q;
+	struct msm_buf_mngr_info buff_mgr_info;
+	int rc = 0;
+
+	if (queue->len > 0) {
+		frame_qcmd = msm_dequeue(queue, list_frame);
+		processed_frame = frame_qcmd->command;
+		do_gettimeofday(&(processed_frame->out_time));
+		kfree(frame_qcmd);
+		event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
+		if (!event_qcmd) {
+			pr_err("%s: Insufficient memory\n", __func__);
+			return -ENOMEM;
+		}
+		atomic_set(&event_qcmd->on_heap, 1);
+		event_qcmd->command = processed_frame;
+		VPE_DBG("fid %d\n", processed_frame->frame_id);
+		msm_enqueue(&vpe_dev->eventData_q, &event_qcmd->list_eventdata);
+
+		if (!processed_frame->output_buffer_info.processed_divert) {
+			memset(&buff_mgr_info, 0 ,
+				sizeof(buff_mgr_info));
+			buff_mgr_info.session_id =
+				((processed_frame->identity >> 16) & 0xFFFF);
+			buff_mgr_info.stream_id =
+				(processed_frame->identity & 0xFFFF);
+			buff_mgr_info.frame_id = processed_frame->frame_id;
+			buff_mgr_info.timestamp = processed_frame->timestamp;
+			buff_mgr_info.index =
+				processed_frame->output_buffer_info.index;
+			rc = msm_vpe_buffer_ops(vpe_dev,
+						VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+						&buff_mgr_info);
+			if (rc < 0) {
+				pr_err("%s: error doing VIDIOC_MSM_BUF_MNGR_BUF_DONE\n",
+					__func__);
+				rc = -EINVAL;
+			}
+		}
+
+		v4l2_evt.id = processed_frame->inst_id;
+		v4l2_evt.type = V4L2_EVENT_VPE_FRAME_DONE;
+		v4l2_event_queue(vpe_dev->msm_sd.sd.devnode, &v4l2_evt);
+	}
+	return rc;
+}
+
+static void vpe_update_scaler_params(struct vpe_device *vpe_dev,
+			struct msm_vpe_frame_strip_info strip_info)
+{
+	uint32_t out_ROI_width, out_ROI_height;
+	uint32_t src_ROI_width, src_ROI_height;
+
+	/*
+	* phase_step_x, phase_step_y, phase_init_x and phase_init_y
+	* are represented in fixed-point, unsigned 3.29 format
+	*/
+	uint32_t phase_step_x = 0;
+	uint32_t phase_step_y = 0;
+	uint32_t phase_init_x = 0;
+	uint32_t phase_init_y = 0;
+
+	uint32_t src_roi, src_x, src_y, src_xy, temp;
+	uint32_t yscale_filter_sel, xscale_filter_sel;
+	uint32_t scale_unit_sel_x, scale_unit_sel_y;
+	uint64_t numerator, denominator;
+
+	/*
+	 * assumption is both direction need zoom. this can be
+	 * improved.
+	 */
+	temp = msm_camera_io_r(vpe_dev->base + VPE_OP_MODE_OFFSET) | 0x3;
+	msm_camera_io_w(temp, vpe_dev->base + VPE_OP_MODE_OFFSET);
+
+	src_ROI_width  = strip_info.src_w;
+	src_ROI_height = strip_info.src_h;
+	out_ROI_width  = strip_info.dst_w;
+	out_ROI_height = strip_info.dst_h;
+
+	VPE_DBG("src w = %u, h=%u, dst w = %u, h =%u.\n",
+		src_ROI_width, src_ROI_height, out_ROI_width,
+		out_ROI_height);
+	src_roi = (src_ROI_height << 16) + src_ROI_width;
+
+	msm_camera_io_w(src_roi, vpe_dev->base + VPE_SRC_SIZE_OFFSET);
+
+	src_x = strip_info.src_x;
+	src_y = strip_info.src_y;
+
+	VPE_DBG("src_x = %d, src_y=%d.\n", src_x, src_y);
+
+	src_xy = src_y*(1<<16) + src_x;
+	msm_camera_io_w(src_xy, vpe_dev->base +
+			VPE_SRC_XY_OFFSET);
+	VPE_DBG("src_xy = 0x%x, src_roi=0x%x.\n", src_xy, src_roi);
+
+	/* decide whether to use FIR or M/N for scaling */
+	if ((out_ROI_width == 1 && src_ROI_width < 4) ||
+		(src_ROI_width < 4 * out_ROI_width - 3))
+		scale_unit_sel_x = 0;/* use FIR scalar */
+	else
+		scale_unit_sel_x = 1;/* use M/N scalar */
+
+	if ((out_ROI_height == 1 && src_ROI_height < 4) ||
+		(src_ROI_height < 4 * out_ROI_height - 3))
+		scale_unit_sel_y = 0;/* use FIR scalar */
+	else
+		scale_unit_sel_y = 1;/* use M/N scalar */
+
+	/* calculate phase step for the x direction */
+
+	/*
+	 * if destination is only 1 pixel wide, the value of
+	 * phase_step_x is unimportant. Assigning phase_step_x to src
+	 * ROI width as an arbitrary value.
+	 */
+	if (out_ROI_width == 1)
+		phase_step_x = (uint32_t) ((src_ROI_width) <<
+						SCALER_PHASE_BITS);
+
+		/* if using FIR scalar */
+	else if (scale_unit_sel_x == 0) {
+
+		/*
+		 * Calculate the quotient ( src_ROI_width - 1 ) (
+		 * out_ROI_width - 1) with u3.29 precision. Quotient
+		 * is rounded up to the larger 29th decimal point
+		 */
+		numerator = (uint64_t)(src_ROI_width - 1) <<
+			SCALER_PHASE_BITS;
+		/*
+		 * never equals to 0 because of the "(out_ROI_width ==
+		 * 1 )"
+		 */
+		denominator = (uint64_t)(out_ROI_width - 1);
+		/*
+		 * divide and round up to the larger 29th decimal
+		 * point.
+		 */
+		phase_step_x = (uint32_t) vpe_do_div((numerator +
+					denominator - 1), denominator);
+	} else if (scale_unit_sel_x == 1) { /* if M/N scalar */
+		/*
+		 * Calculate the quotient ( src_ROI_width ) / (
+		 * out_ROI_width) with u3.29 precision. Quotient is
+		 * rounded down to the smaller 29th decimal point.
+		 */
+		numerator = (uint64_t)(src_ROI_width) <<
+			SCALER_PHASE_BITS;
+		denominator = (uint64_t)(out_ROI_width);
+		phase_step_x =
+			(uint32_t) vpe_do_div(numerator, denominator);
+	}
+	/* calculate phase step for the y direction */
+
+	/*
+	 * if destination is only 1 pixel wide, the value of
+	 * phase_step_x is unimportant. Assigning phase_step_x to src
+	 * ROI width as an arbitrary value.
+	 */
+	if (out_ROI_height == 1)
+		phase_step_y =
+		(uint32_t) ((src_ROI_height) << SCALER_PHASE_BITS);
+
+	/* if FIR scalar */
+	else if (scale_unit_sel_y == 0) {
+		/*
+		 * Calculate the quotient ( src_ROI_height - 1 ) / (
+		 * out_ROI_height - 1) with u3.29 precision. Quotient
+		 * is rounded up to the larger 29th decimal point.
+		 */
+		numerator = (uint64_t)(src_ROI_height - 1) <<
+			SCALER_PHASE_BITS;
+		/*
+		 * never equals to 0 because of the " ( out_ROI_height
+		 * == 1 )" case
+		 */
+		denominator = (uint64_t)(out_ROI_height - 1);
+		/*
+		 * Quotient is rounded up to the larger 29th decimal
+		 * point.
+		 */
+		phase_step_y =
+		(uint32_t) vpe_do_div(
+			(numerator + denominator - 1), denominator);
+	} else if (scale_unit_sel_y == 1) { /* if M/N scalar */
+		/*
+		 * Calculate the quotient ( src_ROI_height ) (
+		 * out_ROI_height) with u3.29 precision. Quotient is
+		 * rounded down to the smaller 29th decimal point.
+		 */
+		numerator = (uint64_t)(src_ROI_height) <<
+			SCALER_PHASE_BITS;
+		denominator = (uint64_t)(out_ROI_height);
+		phase_step_y = (uint32_t) vpe_do_div(
+			numerator, denominator);
+	}
+
+	/* decide which set of FIR coefficients to use */
+	if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
+		xscale_filter_sel = 0;
+	else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
+		xscale_filter_sel = 1;
+	else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
+		xscale_filter_sel = 2;
+	else
+		xscale_filter_sel = 3;
+
+	if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
+		yscale_filter_sel = 0;
+	else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
+		yscale_filter_sel = 1;
+	else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
+		yscale_filter_sel = 2;
+	else
+		yscale_filter_sel = 3;
+
+	/* calculate phase init for the x direction */
+
+	/* if using FIR scalar */
+	if (scale_unit_sel_x == 0) {
+		if (out_ROI_width == 1)
+			phase_init_x =
+				(uint32_t) ((src_ROI_width - 1) <<
+							SCALER_PHASE_BITS);
+		else
+			phase_init_x = 0;
+	} else if (scale_unit_sel_x == 1) /* M over N scalar  */
+		phase_init_x = 0;
+
+	/*
+	 * calculate phase init for the y direction if using FIR
+	 * scalar
+	 */
+	if (scale_unit_sel_y == 0) {
+		if (out_ROI_height == 1)
+			phase_init_y =
+			(uint32_t) ((src_ROI_height -
+						1) << SCALER_PHASE_BITS);
+		else
+			phase_init_y = 0;
+	} else if (scale_unit_sel_y == 1) /* M over N scalar   */
+		phase_init_y = 0;
+
+	strip_info.phase_step_x = phase_step_x;
+	strip_info.phase_step_y = phase_step_y;
+	strip_info.phase_init_x = phase_init_x;
+	strip_info.phase_init_y = phase_init_y;
+	VPE_DBG("phase step x = %d, step y = %d.\n",
+		 strip_info.phase_step_x, strip_info.phase_step_y);
+	VPE_DBG("phase init x = %d, init y = %d.\n",
+		 strip_info.phase_init_x, strip_info.phase_init_y);
+
+	msm_camera_io_w(strip_info.phase_step_x, vpe_dev->base +
+			VPE_SCALE_PHASEX_STEP_OFFSET);
+	msm_camera_io_w(strip_info.phase_step_y, vpe_dev->base +
+			VPE_SCALE_PHASEY_STEP_OFFSET);
+
+	msm_camera_io_w(strip_info.phase_init_x, vpe_dev->base +
+			VPE_SCALE_PHASEX_INIT_OFFSET);
+	msm_camera_io_w(strip_info.phase_init_y, vpe_dev->base +
+			VPE_SCALE_PHASEY_INIT_OFFSET);
+}
+
+static void vpe_program_buffer_addresses(
+	struct vpe_device *vpe_dev,
+	unsigned long srcP0,
+	unsigned long srcP1,
+	unsigned long outP0,
+	unsigned long outP1)
+{
+	VPE_DBG("%s VPE Configured with:\n"
+		"Src %x, %x Dest %x, %x",
+		__func__, (uint32_t)srcP0, (uint32_t)srcP1,
+		(uint32_t)outP0, (uint32_t)outP1);
+
+	msm_camera_io_w(srcP0, vpe_dev->base + VPE_SRCP0_ADDR_OFFSET);
+	msm_camera_io_w(srcP1, vpe_dev->base + VPE_SRCP1_ADDR_OFFSET);
+	msm_camera_io_w(outP0, vpe_dev->base + VPE_OUTP0_ADDR_OFFSET);
+	msm_camera_io_w(outP1, vpe_dev->base + VPE_OUTP1_ADDR_OFFSET);
+}
+
+static int vpe_start(struct vpe_device *vpe_dev)
+{
+	/*  enable the frame irq, bit 0 = Display list 0 ROI done */
+	msm_camera_io_w_mb(1, vpe_dev->base + VPE_INTR_ENABLE_OFFSET);
+	msm_camera_io_dump(vpe_dev->base, 0x120);
+	msm_camera_io_dump(vpe_dev->base + 0x00400, 0x18);
+	msm_camera_io_dump(vpe_dev->base + 0x10000, 0x250);
+	msm_camera_io_dump(vpe_dev->base + 0x30000, 0x20);
+	msm_camera_io_dump(vpe_dev->base + 0x50000, 0x30);
+	msm_camera_io_dump(vpe_dev->base + 0x50400, 0x10);
+
+	/*
+	 * This triggers the operation. When the VPE is done,
+	 * msm_vpe_irq will fire.
+	 */
+	msm_camera_io_w_mb(1, vpe_dev->base + VPE_DL0_START_OFFSET);
+	return 0;
+}
+
+static void vpe_config_axi_default(struct vpe_device *vpe_dev)
+{
+	msm_camera_io_w(0x25, vpe_dev->base + VPE_AXI_ARB_2_OFFSET);
+}
+
+static int vpe_reset(struct vpe_device *vpe_dev)
+{
+	uint32_t vpe_version;
+	uint32_t rc = 0;
+
+	vpe_version = msm_camera_io_r(
+			vpe_dev->base + VPE_HW_VERSION_OFFSET);
+	VPE_DBG("vpe_version = 0x%x\n", vpe_version);
+	/* disable all interrupts.*/
+	msm_camera_io_w(0, vpe_dev->base + VPE_INTR_ENABLE_OFFSET);
+	/* clear all pending interrupts*/
+	msm_camera_io_w(0x1fffff, vpe_dev->base + VPE_INTR_CLEAR_OFFSET);
+	/* write sw_reset to reset the core. */
+	msm_camera_io_w(0x10, vpe_dev->base + VPE_SW_RESET_OFFSET);
+	/* then poll the reset bit, it should be self-cleared. */
+	while (1) {
+		rc = msm_camera_io_r(vpe_dev->base + VPE_SW_RESET_OFFSET) \
+			& 0x10;
+		if (rc == 0)
+			break;
+		cpu_relax();
+	}
+	/*
+	 * at this point, hardware is reset. Then pogram to default
+	 * values.
+	 */
+	msm_camera_io_w(VPE_AXI_RD_ARB_CONFIG_VALUE,
+			vpe_dev->base + VPE_AXI_RD_ARB_CONFIG_OFFSET);
+
+	msm_camera_io_w(VPE_CGC_ENABLE_VALUE,
+			vpe_dev->base + VPE_CGC_EN_OFFSET);
+	msm_camera_io_w(1, vpe_dev->base + VPE_CMD_MODE_OFFSET);
+	msm_camera_io_w(VPE_DEFAULT_OP_MODE_VALUE,
+			vpe_dev->base + VPE_OP_MODE_OFFSET);
+	msm_camera_io_w(VPE_DEFAULT_SCALE_CONFIG,
+			vpe_dev->base + VPE_SCALE_CONFIG_OFFSET);
+	vpe_config_axi_default(vpe_dev);
+	return rc;
+}
+
+static void vpe_update_scale_coef(struct vpe_device *vpe_dev, uint32_t *p)
+{
+	uint32_t i, offset;
+	offset = *p;
+	for (i = offset; i < (VPE_SCALE_COEFF_NUM + offset); i++) {
+		VPE_DBG("Setting scale table %d\n", i);
+		msm_camera_io_w(*(++p),
+			vpe_dev->base + VPE_SCALE_COEFF_LSBn(i));
+		msm_camera_io_w(*(++p),
+			vpe_dev->base + VPE_SCALE_COEFF_MSBn(i));
+	}
+}
+
+static void vpe_input_plane_config(struct vpe_device *vpe_dev, uint32_t *p)
+{
+	msm_camera_io_w(*p, vpe_dev->base + VPE_SRC_FORMAT_OFFSET);
+	msm_camera_io_w(*(++p),
+		vpe_dev->base + VPE_SRC_UNPACK_PATTERN1_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_SRC_IMAGE_SIZE_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_SRC_YSTRIDE1_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_SRC_SIZE_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_SRC_XY_OFFSET);
+}
+
+static void vpe_output_plane_config(struct vpe_device *vpe_dev, uint32_t *p)
+{
+	msm_camera_io_w(*p, vpe_dev->base + VPE_OUT_FORMAT_OFFSET);
+	msm_camera_io_w(*(++p),
+		vpe_dev->base + VPE_OUT_PACK_PATTERN1_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_OUT_YSTRIDE1_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_OUT_SIZE_OFFSET);
+	msm_camera_io_w(*(++p), vpe_dev->base + VPE_OUT_XY_OFFSET);
+}
+
+static void vpe_operation_config(struct vpe_device *vpe_dev, uint32_t *p)
+{
+	msm_camera_io_w(*p, vpe_dev->base + VPE_OP_MODE_OFFSET);
+}
+
+/**
+ * msm_vpe_transaction_setup() - send setup for one frame to VPE
+ * @vpe_dev:	vpe device
+ * @data:	packed setup commands
+ *
+ * See msm_vpe.h for the expected format of `data'
+ */
+static void msm_vpe_transaction_setup(struct vpe_device *vpe_dev, void *data)
+{
+	int i;
+	void *iter = data;
+
+	vpe_mem_dump("vpe_transaction", data, VPE_TRANSACTION_SETUP_CONFIG_LEN);
+
+	for (i = 0; i < VPE_NUM_SCALER_TABLES; ++i) {
+		vpe_update_scale_coef(vpe_dev, (uint32_t *)iter);
+		iter += VPE_SCALER_CONFIG_LEN;
+	}
+	vpe_input_plane_config(vpe_dev, (uint32_t *)iter);
+	iter += VPE_INPUT_PLANE_CFG_LEN;
+	vpe_output_plane_config(vpe_dev, (uint32_t *)iter);
+	iter += VPE_OUTPUT_PLANE_CFG_LEN;
+	vpe_operation_config(vpe_dev, (uint32_t *)iter);
+}
+
+static int msm_vpe_send_frame_to_hardware(struct vpe_device *vpe_dev,
+	struct msm_queue_cmd *frame_qcmd)
+{
+	struct msm_vpe_frame_info_t *process_frame;
+
+	if (vpe_dev->processing_q.len < MAX_VPE_PROCESSING_FRAME) {
+		process_frame = frame_qcmd->command;
+		msm_enqueue(&vpe_dev->processing_q,
+					&frame_qcmd->list_frame);
+
+		vpe_update_scaler_params(vpe_dev, process_frame->strip_info);
+		vpe_program_buffer_addresses(
+			vpe_dev,
+			process_frame->src_phyaddr,
+			process_frame->src_phyaddr
+			+ process_frame->src_chroma_plane_offset,
+			process_frame->dest_phyaddr,
+			process_frame->dest_phyaddr
+			+ process_frame->dest_chroma_plane_offset);
+		vpe_start(vpe_dev);
+		do_gettimeofday(&(process_frame->in_time));
+	}
+	return 0;
+}
+
+static int msm_vpe_cfg(struct vpe_device *vpe_dev,
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+	int rc = 0;
+	struct msm_queue_cmd *frame_qcmd = NULL;
+	struct msm_vpe_frame_info_t *new_frame =
+		kzalloc(sizeof(struct msm_vpe_frame_info_t), GFP_KERNEL);
+	unsigned long in_phyaddr, out_phyaddr;
+	struct msm_buf_mngr_info buff_mgr_info;
+
+	if (!new_frame) {
+		pr_err("Insufficient memory. return\n");
+		return -ENOMEM;
+	}
+
+	rc = copy_from_user(new_frame, (void __user *)ioctl_ptr->ioctl_ptr,
+			sizeof(struct msm_vpe_frame_info_t));
+	if (rc) {
+		pr_err("%s:%d copy from user\n", __func__, __LINE__);
+		rc = -EINVAL;
+		goto err_free_new_frame;
+	}
+
+	in_phyaddr = msm_vpe_fetch_buffer_info(vpe_dev,
+		&new_frame->input_buffer_info,
+		((new_frame->identity >> 16) & 0xFFFF),
+		(new_frame->identity & 0xFFFF));
+	if (!in_phyaddr) {
+		pr_err("error gettting input physical address\n");
+		rc = -EINVAL;
+		goto err_free_new_frame;
+	}
+
+	memset(&new_frame->output_buffer_info, 0,
+		sizeof(struct msm_vpe_buffer_info_t));
+	memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
+	buff_mgr_info.session_id = ((new_frame->identity >> 16) & 0xFFFF);
+	buff_mgr_info.stream_id = (new_frame->identity & 0xFFFF);
+	rc = msm_vpe_buffer_ops(vpe_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
+				&buff_mgr_info);
+	if (rc < 0) {
+		pr_err("error getting buffer\n");
+		rc = -EINVAL;
+		goto err_free_new_frame;
+	}
+
+	new_frame->output_buffer_info.index = buff_mgr_info.index;
+	out_phyaddr = msm_vpe_fetch_buffer_info(vpe_dev,
+		&new_frame->output_buffer_info,
+		((new_frame->identity >> 16) & 0xFFFF),
+		(new_frame->identity & 0xFFFF));
+	if (!out_phyaddr) {
+		pr_err("error gettting output physical address\n");
+		rc = -EINVAL;
+		goto err_put_buf;
+	}
+
+	new_frame->src_phyaddr = in_phyaddr;
+	new_frame->dest_phyaddr = out_phyaddr;
+
+	frame_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+	if (!frame_qcmd) {
+		pr_err("Insufficient memory. return\n");
+		rc = -ENOMEM;
+		goto err_put_buf;
+	}
+
+	atomic_set(&frame_qcmd->on_heap, 1);
+	frame_qcmd->command = new_frame;
+	rc = msm_vpe_send_frame_to_hardware(vpe_dev, frame_qcmd);
+	if (rc < 0) {
+		pr_err("error cannot send frame to hardware\n");
+		rc = -EINVAL;
+		goto err_free_frame_qcmd;
+	}
+
+	return rc;
+
+err_free_frame_qcmd:
+	kfree(frame_qcmd);
+err_put_buf:
+	msm_vpe_buffer_ops(vpe_dev, VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+		&buff_mgr_info);
+err_free_new_frame:
+	kfree(new_frame);
+	return rc;
+}
+
+static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
+			unsigned int cmd, void *arg)
+{
+	struct vpe_device *vpe_dev = v4l2_get_subdevdata(sd);
+	struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+	int rc = 0;
+
+	mutex_lock(&vpe_dev->mutex);
+	switch (cmd) {
+	case VIDIOC_MSM_VPE_TRANSACTION_SETUP: {
+		struct msm_vpe_transaction_setup_cfg *cfg;
+		VPE_DBG("VIDIOC_MSM_VPE_TRANSACTION_SETUP\n");
+		if (sizeof(*cfg) != ioctl_ptr->len) {
+			pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+				__func__, cmd, ioctl_ptr->len,
+				sizeof(*cfg));
+			rc = -EINVAL;
+			break;
+		}
+
+		cfg = kzalloc(ioctl_ptr->len, GFP_KERNEL);
+		if (!cfg) {
+			pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		rc = copy_from_user(cfg, (void __user *)ioctl_ptr->ioctl_ptr,
+				ioctl_ptr->len);
+		if (rc) {
+			pr_err("%s:%d copy from user\n", __func__, __LINE__);
+			kfree(cfg);
+			break;
+		}
+
+		msm_vpe_transaction_setup(vpe_dev, (void *)cfg);
+		kfree(cfg);
+		break;
+	}
+	case VIDIOC_MSM_VPE_CFG: {
+		VPE_DBG("VIDIOC_MSM_VPE_CFG\n");
+		rc = msm_vpe_cfg(vpe_dev, ioctl_ptr);
+		break;
+	}
+	case VIDIOC_MSM_VPE_ENQUEUE_STREAM_BUFF_INFO: {
+		struct msm_vpe_stream_buff_info_t *u_stream_buff_info;
+		struct msm_vpe_stream_buff_info_t k_stream_buff_info;
+
+		VPE_DBG("VIDIOC_MSM_VPE_ENQUEUE_STREAM_BUFF_INFO\n");
+
+		if (sizeof(struct msm_vpe_stream_buff_info_t) !=
+			ioctl_ptr->len) {
+			pr_err("%s:%d: invalid length\n", __func__, __LINE__);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		u_stream_buff_info = kzalloc(ioctl_ptr->len, GFP_KERNEL);
+		if (!u_stream_buff_info) {
+			pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		rc = (copy_from_user(u_stream_buff_info,
+				(void __user *)ioctl_ptr->ioctl_ptr,
+				ioctl_ptr->len) ? -EFAULT : 0);
+		if (rc) {
+			pr_err("%s:%d copy from user\n", __func__, __LINE__);
+			kfree(u_stream_buff_info);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		k_stream_buff_info.num_buffs = u_stream_buff_info->num_buffs;
+		k_stream_buff_info.identity = u_stream_buff_info->identity;
+		k_stream_buff_info.buffer_info =
+			kzalloc(k_stream_buff_info.num_buffs *
+			sizeof(struct msm_vpe_buffer_info_t), GFP_KERNEL);
+		if (!k_stream_buff_info.buffer_info) {
+			pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+			kfree(u_stream_buff_info);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		rc = (copy_from_user(k_stream_buff_info.buffer_info,
+				(void __user *)u_stream_buff_info->buffer_info,
+				k_stream_buff_info.num_buffs *
+				sizeof(struct msm_vpe_buffer_info_t)) ?
+				-EFAULT : 0);
+		if (rc) {
+			pr_err("%s:%d copy from user\n", __func__, __LINE__);
+			kfree(k_stream_buff_info.buffer_info);
+			kfree(u_stream_buff_info);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		rc = msm_vpe_add_buff_queue_entry(vpe_dev,
+			((k_stream_buff_info.identity >> 16) & 0xFFFF),
+			(k_stream_buff_info.identity & 0xFFFF));
+		if (!rc)
+			rc = msm_vpe_enqueue_buff_info_list(vpe_dev,
+				&k_stream_buff_info);
+
+		kfree(k_stream_buff_info.buffer_info);
+		kfree(u_stream_buff_info);
+		break;
+	}
+	case VIDIOC_MSM_VPE_DEQUEUE_STREAM_BUFF_INFO: {
+		uint32_t identity;
+		struct msm_vpe_buff_queue_info_t *buff_queue_info;
+
+		VPE_DBG("VIDIOC_MSM_VPE_DEQUEUE_STREAM_BUFF_INFO\n");
+
+		rc = (copy_from_user(&identity,
+				(void __user *)ioctl_ptr->ioctl_ptr,
+				ioctl_ptr->len) ? -EFAULT : 0);
+		if (rc) {
+			pr_err("%s:%d copy from user\n", __func__, __LINE__);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		buff_queue_info = msm_vpe_get_buff_queue_entry(vpe_dev,
+			((identity >> 16) & 0xFFFF), (identity & 0xFFFF));
+		if (buff_queue_info == NULL) {
+			pr_err("error finding buffer queue entry for identity:%d\n",
+				identity);
+			mutex_unlock(&vpe_dev->mutex);
+			return -EINVAL;
+		}
+
+		msm_vpe_dequeue_buff_info_list(vpe_dev, buff_queue_info);
+		rc = msm_vpe_free_buff_queue_entry(vpe_dev,
+			buff_queue_info->session_id,
+			buff_queue_info->stream_id);
+		break;
+	}
+	case VIDIOC_MSM_VPE_GET_EVENTPAYLOAD: {
+		struct msm_device_queue *queue = &vpe_dev->eventData_q;
+		struct msm_queue_cmd *event_qcmd;
+		struct msm_vpe_frame_info_t *process_frame;
+		VPE_DBG("VIDIOC_MSM_VPE_GET_EVENTPAYLOAD\n");
+		event_qcmd = msm_dequeue(queue, list_eventdata);
+		process_frame = event_qcmd->command;
+		VPE_DBG("fid %d\n", process_frame->frame_id);
+		if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+				process_frame,
+				sizeof(struct msm_vpe_frame_info_t))) {
+					mutex_unlock(&vpe_dev->mutex);
+					return -EINVAL;
+		}
+
+		kfree(process_frame);
+		kfree(event_qcmd);
+		break;
+	}
+	}
+	mutex_unlock(&vpe_dev->mutex);
+	return rc;
+}
+
+static int msm_vpe_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_subscribe(fh, sub, MAX_VPE_V4l2_EVENTS);
+}
+
+static int msm_vpe_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
+static struct v4l2_subdev_core_ops msm_vpe_subdev_core_ops = {
+	.ioctl = msm_vpe_subdev_ioctl,
+	.subscribe_event = msm_vpe_subscribe_event,
+	.unsubscribe_event = msm_vpe_unsubscribe_event,
+};
+
+static const struct v4l2_subdev_ops msm_vpe_subdev_ops = {
+	.core = &msm_vpe_subdev_core_ops,
+};
+
+static struct v4l2_file_operations msm_vpe_v4l2_subdev_fops;
+
+static long msm_vpe_subdev_do_ioctl(
+	struct file *file, unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+	struct v4l2_fh *vfh = file->private_data;
+
+	switch (cmd) {
+	case VIDIOC_DQEVENT:
+		if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
+			return -ENOIOCTLCMD;
+
+		return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
+
+	case VIDIOC_SUBSCRIBE_EVENT:
+		return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
+
+	case VIDIOC_UNSUBSCRIBE_EVENT:
+		return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+	case VIDIOC_MSM_VPE_GET_INST_INFO: {
+		uint32_t i;
+		struct vpe_device *vpe_dev = v4l2_get_subdevdata(sd);
+		struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+		struct msm_vpe_frame_info_t inst_info;
+		for (i = 0; i < MAX_ACTIVE_VPE_INSTANCE; i++) {
+			if (vpe_dev->vpe_subscribe_list[i].vfh == vfh) {
+				inst_info.inst_id = i;
+				break;
+			}
+		}
+		if (copy_to_user(
+				(void __user *)ioctl_ptr->ioctl_ptr, &inst_info,
+				sizeof(struct msm_vpe_frame_info_t))) {
+			return -EINVAL;
+		}
+	}
+	default:
+		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
+	}
+
+	return 0;
+}
+
+static long msm_vpe_subdev_fops_ioctl(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	return video_usercopy(file, cmd, arg, msm_vpe_subdev_do_ioctl);
+}
+
+static int vpe_register_domain(void)
+{
+	struct msm_iova_partition vpe_iommu_partition = {
+		/* TODO: verify that these are correct? */
+		.start = SZ_128K,
+		.size = SZ_2G - SZ_128K,
+	};
+	struct msm_iova_layout vpe_iommu_layout = {
+		.partitions = &vpe_iommu_partition,
+		.npartitions = 1,
+		.client_name = "camera_vpe",
+		.domain_flags = 0,
+	};
+
+	return msm_register_domain(&vpe_iommu_layout);
+}
+
+static int __devinit vpe_probe(struct platform_device *pdev)
+{
+	struct vpe_device *vpe_dev;
+	int rc = 0;
+
+	vpe_dev = kzalloc(sizeof(struct vpe_device), GFP_KERNEL);
+	if (!vpe_dev) {
+		pr_err("not enough memory\n");
+		return -ENOMEM;
+	}
+
+	vpe_dev->vpe_clk = kzalloc(sizeof(struct clk *) *
+				ARRAY_SIZE(vpe_clk_info), GFP_KERNEL);
+	if (!vpe_dev->vpe_clk) {
+		pr_err("not enough memory\n");
+		rc = -ENOMEM;
+		goto err_free_vpe_dev;
+	}
+
+	v4l2_subdev_init(&vpe_dev->msm_sd.sd, &msm_vpe_subdev_ops);
+	vpe_dev->msm_sd.sd.internal_ops = &msm_vpe_internal_ops;
+	snprintf(vpe_dev->msm_sd.sd.name, ARRAY_SIZE(vpe_dev->msm_sd.sd.name),
+		"vpe");
+	vpe_dev->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	vpe_dev->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+	v4l2_set_subdevdata(&vpe_dev->msm_sd.sd, vpe_dev);
+	platform_set_drvdata(pdev, &vpe_dev->msm_sd.sd);
+	mutex_init(&vpe_dev->mutex);
+	spin_lock_init(&vpe_dev->tasklet_lock);
+
+	vpe_dev->pdev = pdev;
+
+	vpe_dev->mem = platform_get_resource_byname(pdev,
+						IORESOURCE_MEM, "vpe");
+	if (!vpe_dev->mem) {
+		pr_err("no mem resource?\n");
+		rc = -ENODEV;
+		goto err_free_vpe_clk;
+	}
+
+	vpe_dev->irq = platform_get_resource_byname(pdev,
+						IORESOURCE_IRQ, "vpe");
+	if (!vpe_dev->irq) {
+		pr_err("%s: no irq resource?\n", __func__);
+		rc = -ENODEV;
+		goto err_release_mem;
+	}
+
+	vpe_dev->domain_num = vpe_register_domain();
+	if (vpe_dev->domain_num < 0) {
+		pr_err("%s: could not register domain\n", __func__);
+		rc = -ENODEV;
+		goto err_release_mem;
+	}
+
+	vpe_dev->domain =
+		msm_get_iommu_domain(vpe_dev->domain_num);
+	if (!vpe_dev->domain) {
+		pr_err("%s: cannot find domain\n", __func__);
+		rc = -ENODEV;
+		goto err_release_mem;
+	}
+
+	vpe_dev->iommu_ctx_src = msm_iommu_get_ctx("vpe_src");
+	vpe_dev->iommu_ctx_dst = msm_iommu_get_ctx("vpe_dst");
+	if (!vpe_dev->iommu_ctx_src || !vpe_dev->iommu_ctx_dst) {
+		pr_err("%s: cannot get iommu_ctx\n", __func__);
+		rc = -ENODEV;
+		goto err_release_mem;
+	}
+
+	media_entity_init(&vpe_dev->msm_sd.sd.entity, 0, NULL, 0);
+	vpe_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+	vpe_dev->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_VPE;
+	vpe_dev->msm_sd.sd.entity.name = pdev->name;
+	msm_sd_register(&vpe_dev->msm_sd);
+	msm_vpe_v4l2_subdev_fops.owner = v4l2_subdev_fops.owner;
+	msm_vpe_v4l2_subdev_fops.open = v4l2_subdev_fops.open;
+	msm_vpe_v4l2_subdev_fops.unlocked_ioctl = msm_vpe_subdev_fops_ioctl;
+	msm_vpe_v4l2_subdev_fops.release = v4l2_subdev_fops.release;
+	msm_vpe_v4l2_subdev_fops.poll = v4l2_subdev_fops.poll;
+
+	vpe_dev->msm_sd.sd.devnode->fops = &msm_vpe_v4l2_subdev_fops;
+	vpe_dev->msm_sd.sd.entity.revision = vpe_dev->msm_sd.sd.devnode->num;
+	vpe_dev->state = VPE_STATE_BOOT;
+	rc = vpe_init_hardware(vpe_dev);
+	if (rc < 0) {
+		pr_err("%s: Couldn't init vpe hardware\n", __func__);
+		rc = -ENODEV;
+		goto err_unregister_sd;
+	}
+	vpe_reset(vpe_dev);
+	vpe_release_hardware(vpe_dev);
+	vpe_dev->state = VPE_STATE_OFF;
+
+	rc = iommu_attach_device(vpe_dev->domain, vpe_dev->iommu_ctx_src);
+	if (rc < 0) {
+		pr_err("Couldn't attach to vpe_src context bank\n");
+		rc = -ENODEV;
+		goto err_unregister_sd;
+	}
+	rc = iommu_attach_device(vpe_dev->domain, vpe_dev->iommu_ctx_dst);
+	if (rc < 0) {
+		pr_err("Couldn't attach to vpe_dst context bank\n");
+		rc = -ENODEV;
+		goto err_detach_src;
+	}
+
+	vpe_dev->state = VPE_STATE_OFF;
+
+	msm_queue_init(&vpe_dev->eventData_q, "vpe-eventdata");
+	msm_queue_init(&vpe_dev->processing_q, "vpe-frame");
+	INIT_LIST_HEAD(&vpe_dev->tasklet_q);
+	tasklet_init(&vpe_dev->vpe_tasklet, msm_vpe_do_tasklet,
+		(unsigned long)vpe_dev);
+	vpe_dev->vpe_open_cnt = 0;
+
+	return rc;
+
+err_detach_src:
+	iommu_detach_device(vpe_dev->domain, vpe_dev->iommu_ctx_src);
+err_unregister_sd:
+	msm_sd_unregister(&vpe_dev->msm_sd);
+err_release_mem:
+	release_mem_region(vpe_dev->mem->start, resource_size(vpe_dev->mem));
+err_free_vpe_clk:
+	kfree(vpe_dev->vpe_clk);
+err_free_vpe_dev:
+	kfree(vpe_dev);
+	return rc;
+}
+
+static int vpe_device_remove(struct platform_device *dev)
+{
+	struct v4l2_subdev *sd = platform_get_drvdata(dev);
+	struct vpe_device  *vpe_dev;
+	if (!sd) {
+		pr_err("%s: Subdevice is NULL\n", __func__);
+		return 0;
+	}
+
+	vpe_dev = (struct vpe_device *)v4l2_get_subdevdata(sd);
+	if (!vpe_dev) {
+		pr_err("%s: vpe device is NULL\n", __func__);
+		return 0;
+	}
+
+	iommu_detach_device(vpe_dev->domain, vpe_dev->iommu_ctx_dst);
+	iommu_detach_device(vpe_dev->domain, vpe_dev->iommu_ctx_src);
+	msm_sd_unregister(&vpe_dev->msm_sd);
+	release_mem_region(vpe_dev->mem->start, resource_size(vpe_dev->mem));
+	mutex_destroy(&vpe_dev->mutex);
+	kfree(vpe_dev);
+	return 0;
+}
+
+static struct platform_driver vpe_driver = {
+	.probe = vpe_probe,
+	.remove = __devexit_p(vpe_device_remove),
+	.driver = {
+		.name = MSM_VPE_DRV_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_vpe_init_module(void)
+{
+	return platform_driver_register(&vpe_driver);
+}
+
+static void __exit msm_vpe_exit_module(void)
+{
+	platform_driver_unregister(&vpe_driver);
+}
+
+module_init(msm_vpe_init_module);
+module_exit(msm_vpe_exit_module);
+MODULE_DESCRIPTION("MSM VPE driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h
new file mode 100644
index 0000000..c02432e
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/pproc/vpe/msm_vpe.h
@@ -0,0 +1,255 @@
+/* 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 __MSM_VPE_H__
+#define __MSM_VPE_H__
+
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-subdev.h>
+#include "msm_sd.h"
+
+/***********  start of register offset *********************/
+#define VPE_INTR_ENABLE_OFFSET                0x0020
+#define VPE_INTR_STATUS_OFFSET                0x0024
+#define VPE_INTR_CLEAR_OFFSET                 0x0028
+#define VPE_DL0_START_OFFSET                  0x0030
+#define VPE_HW_VERSION_OFFSET                 0x0070
+#define VPE_SW_RESET_OFFSET                   0x0074
+#define VPE_AXI_RD_ARB_CONFIG_OFFSET          0x0078
+#define VPE_SEL_CLK_OR_HCLK_TEST_BUS_OFFSET   0x007C
+#define VPE_CGC_EN_OFFSET                     0x0100
+#define VPE_CMD_STATUS_OFFSET                 0x10008
+#define VPE_PROFILE_EN_OFFSET                 0x10010
+#define VPE_PROFILE_COUNT_OFFSET              0x10014
+#define VPE_CMD_MODE_OFFSET                   0x10060
+#define VPE_SRC_SIZE_OFFSET                   0x10108
+#define VPE_SRCP0_ADDR_OFFSET                 0x1010C
+#define VPE_SRCP1_ADDR_OFFSET                 0x10110
+#define VPE_SRC_YSTRIDE1_OFFSET               0x1011C
+#define VPE_SRC_FORMAT_OFFSET                 0x10124
+#define VPE_SRC_UNPACK_PATTERN1_OFFSET        0x10128
+#define VPE_OP_MODE_OFFSET                    0x10138
+#define VPE_SCALE_PHASEX_INIT_OFFSET          0x1013C
+#define VPE_SCALE_PHASEY_INIT_OFFSET          0x10140
+#define VPE_SCALE_PHASEX_STEP_OFFSET          0x10144
+#define VPE_SCALE_PHASEY_STEP_OFFSET          0x10148
+#define VPE_OUT_FORMAT_OFFSET                 0x10150
+#define VPE_OUT_PACK_PATTERN1_OFFSET          0x10154
+#define VPE_OUT_SIZE_OFFSET                   0x10164
+#define VPE_OUTP0_ADDR_OFFSET                 0x10168
+#define VPE_OUTP1_ADDR_OFFSET                 0x1016C
+#define VPE_OUT_YSTRIDE1_OFFSET               0x10178
+#define VPE_OUT_XY_OFFSET                     0x1019C
+#define VPE_SRC_XY_OFFSET                     0x10200
+#define VPE_SRC_IMAGE_SIZE_OFFSET             0x10208
+#define VPE_SCALE_CONFIG_OFFSET               0x10230
+#define VPE_DEINT_STATUS_OFFSET               0x30000
+#define VPE_DEINT_DECISION_OFFSET             0x30004
+#define VPE_DEINT_COEFF0_OFFSET               0x30010
+#define VPE_SCALE_STATUS_OFFSET               0x50000
+#define VPE_SCALE_SVI_PARAM_OFFSET            0x50010
+#define VPE_SCALE_SHARPEN_CFG_OFFSET          0x50020
+#define VPE_SCALE_COEFF_LSP_0_OFFSET          0x50400
+#define VPE_SCALE_COEFF_MSP_0_OFFSET          0x50404
+
+#define VPE_AXI_ARB_1_OFFSET                  0x00408
+#define VPE_AXI_ARB_2_OFFSET                  0x0040C
+
+#define VPE_SCALE_COEFF_LSBn(n)	(0x50400 + 8 * (n))
+#define VPE_SCALE_COEFF_MSBn(n)	(0x50404 + 8 * (n))
+#define VPE_SCALE_COEFF_NUM			32
+
+/*********** end of register offset ********************/
+
+
+#define VPE_HARDWARE_VERSION          0x00080308
+#define VPE_SW_RESET_VALUE            0x00000010  /* bit 4 for PPP*/
+#define VPE_AXI_RD_ARB_CONFIG_VALUE   0x124924
+#define VPE_CMD_MODE_VALUE            0x1
+#define VPE_DEFAULT_OP_MODE_VALUE     0x40FC0004
+#define VPE_CGC_ENABLE_VALUE          0xffff
+#define VPE_DEFAULT_SCALE_CONFIG      0x3c
+
+#define VPE_NORMAL_MODE_CLOCK_RATE   150000000
+#define VPE_TURBO_MODE_CLOCK_RATE    200000000
+#define VPE_SUBDEV_MAX_EVENTS        30
+
+/**************************************************/
+/*********** End of command id ********************/
+/**************************************************/
+
+#define SCALER_PHASE_BITS 29
+#define HAL_MDP_PHASE_STEP_2P50    0x50000000
+#define HAL_MDP_PHASE_STEP_1P66    0x35555555
+#define HAL_MDP_PHASE_STEP_1P25    0x28000000
+
+
+#define MAX_ACTIVE_VPE_INSTANCE 8
+#define MAX_VPE_PROCESSING_FRAME 2
+#define MAX_VPE_V4l2_EVENTS 30
+
+#define MSM_VPE_TASKLETQ_SIZE		16
+
+/**
+ * The format of the msm_vpe_transaction_setup_cfg is as follows:
+ *
+ * - vpe_update_scale_coef (65*4 uint32_t's)
+ *   - Each table is 65 uint32_t's long
+ *   - 1st uint32_t in each table indicates offset
+ *   - Following 64 uint32_t's are the data
+ *
+ * - vpe_input_plane_config (6 uint32_t's)
+ *   - VPE_SRC_FORMAT_OFFSET
+ *   - VPE_SRC_UNPACK_PATTERN1_OFFSET
+ *   - VPE_SRC_IMAGE_SIZE_OFFSET
+ *   - VPE_SRC_YSTRIDE1_OFFSET
+ *   - VPE_SRC_SIZE_OFFSET
+ *   - VPE_SRC_XY_OFFSET
+ *
+ * - vpe_output_plane_config (5 uint32_t's)
+ *   - VPE_OUT_FORMAT_OFFSET
+ *   - VPE_OUT_PACK_PATTERN1_OFFSET
+ *   - VPE_OUT_YSTRIDE1_OFFSET
+ *   - VPE_OUT_SIZE_OFFSET
+ *   - VPE_OUT_XY_OFFSET
+ *
+ * - vpe_operation_config (1 uint32_t)
+ *   - VPE_OP_MODE_OFFSET
+ *
+ */
+
+#define VPE_SCALER_CONFIG_LEN           260
+#define VPE_INPUT_PLANE_CFG_LEN         24
+#define VPE_OUTPUT_PLANE_CFG_LEN        20
+#define VPE_OPERATION_MODE_CFG_LEN      4
+#define VPE_NUM_SCALER_TABLES		4
+
+#define VPE_TRANSACTION_SETUP_CONFIG_LEN (			\
+		(VPE_SCALER_CONFIG_LEN * VPE_NUM_SCALER_TABLES)	\
+		+ VPE_INPUT_PLANE_CFG_LEN			\
+		+ VPE_OUTPUT_PLANE_CFG_LEN			\
+		+ VPE_OPERATION_MODE_CFG_LEN)
+/* VPE_TRANSACTION_SETUP_CONFIG_LEN = 1088 */
+
+struct msm_vpe_transaction_setup_cfg {
+	uint8_t scaler_cfg[VPE_TRANSACTION_SETUP_CONFIG_LEN];
+};
+
+struct vpe_subscribe_info {
+	struct v4l2_fh *vfh;
+	uint32_t active;
+};
+
+enum vpe_state {
+	VPE_STATE_BOOT,
+	VPE_STATE_IDLE,
+	VPE_STATE_ACTIVE,
+	VPE_STATE_OFF,
+};
+
+struct msm_queue_cmd {
+	struct list_head list_config;
+	struct list_head list_control;
+	struct list_head list_frame;
+	struct list_head list_pict;
+	struct list_head list_vpe_frame;
+	struct list_head list_eventdata;
+	void *command;
+	atomic_t on_heap;
+	struct timespec ts;
+	uint32_t error_code;
+	uint32_t trans_code;
+};
+
+struct msm_device_queue {
+	struct list_head list;
+	spinlock_t lock;
+	wait_queue_head_t wait;
+	int max;
+	int len;
+	const char *name;
+};
+
+struct msm_vpe_tasklet_queue_cmd {
+	struct list_head list;
+	uint32_t irq_status;
+	uint8_t cmd_used;
+};
+
+struct msm_vpe_buffer_map_info_t {
+	unsigned long len;
+	unsigned long phy_addr;
+	struct ion_handle *ion_handle;
+	struct msm_vpe_buffer_info_t buff_info;
+};
+
+struct msm_vpe_buffer_map_list_t {
+	struct msm_vpe_buffer_map_info_t map_info;
+	struct list_head entry;
+};
+
+struct msm_vpe_buff_queue_info_t {
+	uint32_t used;
+	uint16_t session_id;
+	uint16_t stream_id;
+	struct list_head vb2_buff_head;
+	struct list_head native_buff_head;
+};
+
+struct vpe_device {
+	struct platform_device *pdev;
+	struct msm_sd_subdev msm_sd;
+	struct v4l2_subdev subdev;
+	struct resource *mem;
+	struct resource *irq;
+	void __iomem *base;
+	struct clk **vpe_clk;
+	struct regulator *fs_vpe;
+	struct mutex mutex;
+	enum vpe_state state;
+
+	int domain_num;
+	struct iommu_domain *domain;
+	struct device *iommu_ctx_src;
+	struct device *iommu_ctx_dst;
+	struct ion_client *client;
+	struct kref refcount;
+
+	/* Reusing proven tasklet from msm isp */
+	atomic_t irq_cnt;
+	uint8_t taskletq_idx;
+	spinlock_t  tasklet_lock;
+	struct list_head tasklet_q;
+	struct tasklet_struct vpe_tasklet;
+	struct msm_vpe_tasklet_queue_cmd
+	tasklet_queue_cmd[MSM_VPE_TASKLETQ_SIZE];
+
+	struct vpe_subscribe_info vpe_subscribe_list[MAX_ACTIVE_VPE_INSTANCE];
+	uint32_t vpe_open_cnt;
+
+	struct msm_device_queue eventData_q; /* V4L2 Event Payload Queue */
+
+	/*
+	 * Processing Queue: store frame info for frames sent to
+	 * microcontroller
+	 */
+	struct msm_device_queue processing_q;
+
+	struct msm_vpe_buff_queue_info_t *buff_queue;
+	uint32_t num_buffq;
+	struct v4l2_subdev *buf_mgr_subdev;
+};
+
+#endif /* __MSM_VPE_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/sensor/imx135.c b/drivers/media/platform/msm/camera_v2/sensor/imx135.c
index c9476ee..9b02b17 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/imx135.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/imx135.c
@@ -36,6 +36,12 @@
 		.delay = 0,
 	},
 	{
+		.seq_type = SENSOR_VREG,
+		.seq_val = CAM_VAF,
+		.config_val = 0,
+		.delay = 0,
+	},
+	{
 		.seq_type = SENSOR_GPIO,
 		.seq_val = SENSOR_GPIO_RESET,
 		.config_val = GPIO_OUT_LOW,
@@ -48,6 +54,18 @@
 		.delay = 30,
 	},
 	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_LOW,
+		.delay = 1,
+	},
+	{
+		.seq_type = SENSOR_GPIO,
+		.seq_val = SENSOR_GPIO_STANDBY,
+		.config_val = GPIO_OUT_HIGH,
+		.delay = 30,
+	},
+	{
 		.seq_type = SENSOR_CLK,
 		.seq_val = SENSOR_CAM_MCLK,
 		.config_val = 0,
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 511a478..1885379 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -1498,6 +1498,6 @@
 		kfree(curr->cluster);
 		kfree(curr);
 	}
-
+	v4l2_ctrl_handler_free(&inst->ctrl_handler);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index e03edd7..20cb08d 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -2541,6 +2541,6 @@
 		kfree(curr->cluster);
 		kfree(curr);
 	}
-
+	v4l2_ctrl_handler_free(&inst->ctrl_handler);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 0fbfd72..1c43f1e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -565,6 +565,7 @@
 	struct msm_vidc_core *core;
 	struct list_head *ptr, *next;
 	int rc = 0;
+	int i;
 
 	if (!inst)
 		return -EINVAL;
@@ -592,6 +593,9 @@
 	if (rc)
 		dprintk(VIDC_ERR,
 			"Failed to move video instance to uninit state\n");
+	for (i = 0; i < MAX_PORT_NUM; i++)
+		vb2_queue_release(&inst->bufq[i].vb2_bufq);
+
 	pr_info(VIDC_DBG_TAG "Closed video instance: %p\n", VIDC_INFO, inst);
 	kfree(inst);
 	return 0;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index fa28d6a..f139b21 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -540,6 +540,8 @@
 	unsigned long flags;
 	struct qseecom_client_listener_data_irsp send_data_rsp;
 	struct qseecom_registered_listener_list *ptr_svc = NULL;
+	sigset_t new_sigset;
+	sigset_t old_sigset;
 
 	while (resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
@@ -564,17 +566,24 @@
 		}
 		pr_debug("waking up rcv_req_wq and "
 				"waiting for send_resp_wq\n");
-		if (wait_event_freezable(qseecom.send_resp_wq,
-				__qseecom_listener_has_sent_rsp(data))) {
-			pr_warning("Interrupted: exiting send_cmd loop\n");
-			ret = -ERESTARTSYS;
-		}
 
-		if ((data->abort) || (ret == -ERESTARTSYS)) {
+		/* initialize the new signal mask with all signals*/
+		sigfillset(&new_sigset);
+		/* block all signals */
+		sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset);
+
+		do {
+			if (!wait_event_freezable(qseecom.send_resp_wq,
+				__qseecom_listener_has_sent_rsp(data)))
+				break;
+		} while (1);
+
+		/* restore signal mask */
+		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+		if (data->abort) {
 			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
 				data->client.app_id, lstnr, ret);
-			if (data->abort)
-				rc = -ENODEV;
+			rc = -ENODEV;
 			send_data_rsp.status  = QSEOS_RESULT_FAILURE;
 		} else {
 			send_data_rsp.status  = QSEOS_RESULT_SUCCESS;
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index fe151b5..acd42ae3 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -107,4 +107,10 @@
 	help
 	  OpenFirmware SLIMBUS accessors
 
+config OF_CORESIGHT
+	def_bool y
+	depends on CORESIGHT
+	help
+	  OpenFirmware CoreSight accessors
+
 endmenu # OF
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index c3a31c8..61a99f2 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -15,3 +15,4 @@
 obj-$(CONFIG_OF_SPMI)	+= of_spmi.o
 obj-$(CONFIG_OF_MTD)	+= of_mtd.o
 obj-$(CONFIG_OF_SLIMBUS)	+= of_slimbus.o
+obj-$(CONFIG_OF_CORESIGHT) += of_coresight.o
diff --git a/drivers/coresight/of_coresight.c b/drivers/of/of_coresight.c
similarity index 100%
rename from drivers/coresight/of_coresight.c
rename to drivers/of/of_coresight.c
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 5313593..c53bcd2 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -790,6 +790,15 @@
 	return 0;
 }
 
+static int pm8xxx_ccadc_suspend(struct device *dev)
+{
+	struct pm8xxx_ccadc_chip *chip = dev_get_drvdata(dev);
+
+	cancel_delayed_work_sync(&chip->calib_ccadc_work);
+
+	return 0;
+}
+
 #define CCADC_CALIB_TEMP_THRESH 20
 static int pm8xxx_ccadc_resume(struct device *dev)
 {
@@ -823,8 +832,11 @@
 				|| delta_temp > CCADC_CALIB_TEMP_THRESH) {
 			the_chip->last_calib_time = current_time_sec;
 			the_chip->last_calib_temp = batt_temp;
-			cancel_delayed_work(&the_chip->calib_ccadc_work);
 			schedule_delayed_work(&the_chip->calib_ccadc_work, 0);
+		} else {
+			schedule_delayed_work(&the_chip->calib_ccadc_work,
+				msecs_to_jiffies(the_chip->calib_delay_ms -
+					(time_since_last_calib * 1000)));
 		}
 	}
 
@@ -832,6 +844,7 @@
 }
 
 static const struct dev_pm_ops pm8xxx_ccadc_pm_ops = {
+	.suspend	= pm8xxx_ccadc_suspend,
 	.resume		= pm8xxx_ccadc_resume,
 };
 
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index 2c58e49..43eda51 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -1,4 +1,5 @@
 mdss-mdp3-objs = mdp3.o mdp3_dma.o mdp3_ctrl.o
+mdss-mdp3-objs += mdp3_ppp.o mdp3_ppp_hwio.o mdp3_ppp_data.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp3.o
 
 mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index 290e317..5223e66 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -48,11 +48,12 @@
 #include "mdss_fb.h"
 #include "mdp3_hwio.h"
 #include "mdp3_ctrl.h"
+#include "mdp3_ppp.h"
 
 #define MDP_CORE_HW_VERSION	0x03040310
 struct mdp3_hw_resource *mdp3_res;
 
-#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val)		\
+#define MDP_BUS_VECTOR_ENTRY_DMA(ab_val, ib_val)		\
 	{						\
 		.src = MSM_BUS_MASTER_MDP_PORT0,	\
 		.dst = MSM_BUS_SLAVE_EBI_CH0,		\
@@ -60,20 +61,59 @@
 		.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_vectors mdp_bus_dma_vectors[] = {
+	MDP_BUS_VECTOR_ENTRY_DMA(0, 0),
+	MDP_BUS_VECTOR_ENTRY_DMA(SZ_128M, SZ_256M),
+	MDP_BUS_VECTOR_ENTRY_DMA(SZ_256M, SZ_512M),
+};
+static struct msm_bus_paths
+	mdp_bus_dma_usecases[ARRAY_SIZE(mdp_bus_dma_vectors)];
+static struct msm_bus_scale_pdata mdp_bus_dma_scale_table = {
+	.usecase = mdp_bus_dma_usecases,
+	.num_usecases = ARRAY_SIZE(mdp_bus_dma_usecases),
+	.name = "mdp3",
 };
 
-static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)];
+#define MDP_BUS_VECTOR_ENTRY_PPP(ab_val, ib_val)		\
+	{						\
+		.src = MSM_BUS_MASTER_MDPE,	\
+		.dst = MSM_BUS_SLAVE_EBI_CH0,		\
+		.ab = (ab_val),				\
+		.ib = (ib_val),				\
+	}
 
-static struct msm_bus_scale_pdata mdp_bus_scale_table = {
-	.usecase = mdp_bus_usecases,
-	.num_usecases = ARRAY_SIZE(mdp_bus_usecases),
+static struct msm_bus_vectors mdp_bus_ppp_vectors[] = {
+	MDP_BUS_VECTOR_ENTRY_PPP(0, 0),
+	MDP_BUS_VECTOR_ENTRY_PPP(SZ_128M, SZ_256M),
+	MDP_BUS_VECTOR_ENTRY_PPP(SZ_256M, SZ_512M),
+};
+
+static struct msm_bus_paths
+	mdp_bus_ppp_usecases[ARRAY_SIZE(mdp_bus_ppp_vectors)];
+
+static struct msm_bus_scale_pdata mdp_bus_ppp_scale_table = {
+	.usecase = mdp_bus_ppp_usecases,
+	.num_usecases = ARRAY_SIZE(mdp_bus_ppp_usecases),
 	.name = "mdp3",
 };
 
+struct mdp3_bus_handle_map mdp3_bus_handle[MDP3_BUS_HANDLE_MAX] = {
+	[MDP3_BUS_HANDLE_DMA] = {
+		.bus_vector = mdp_bus_dma_vectors,
+		.usecases = mdp_bus_dma_usecases,
+		.scale_pdata = &mdp_bus_dma_scale_table,
+		.current_bus_idx = 0,
+		.handle = 0,
+	},
+	[MDP3_BUS_HANDLE_PPP] = {
+		.bus_vector = mdp_bus_ppp_vectors,
+		.usecases = mdp_bus_ppp_usecases,
+		.scale_pdata = &mdp_bus_ppp_scale_table,
+		.current_bus_idx = 0,
+		.handle = 0,
+	},
+};
+
 struct mdp3_iommu_domain_map mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_MAX] = {
 	[MDP3_IOMMU_DOMAIN] = {
 		.domain_type = MDP3_IOMMU_DOMAIN,
@@ -213,71 +253,106 @@
 
 static int mdp3_bus_scale_register(void)
 {
+	int i;
+
 	if (!mdp3_res->bus_handle) {
-		struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table;
-		int i;
+		pr_err("No bus handle\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < MDP3_BUS_HANDLE_MAX; i++) {
+		struct mdp3_bus_handle_map *bus_handle =
+			&mdp3_res->bus_handle[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];
-		}
+		if (!bus_handle->handle) {
+			int j;
+			struct msm_bus_scale_pdata *bus_pdata =
+				bus_handle->scale_pdata;
 
-		mdp3_res->bus_handle = msm_bus_scale_register_client(bus_pdata);
-		if (!mdp3_res->bus_handle) {
-			pr_err("not able to get bus scale\n");
-			return -ENOMEM;
+			for (j = 0; j < bus_pdata->num_usecases; j++) {
+				bus_handle->usecases[j].num_paths = 1;
+				bus_handle->usecases[j].vectors =
+					&bus_handle->bus_vector[j];
+			}
+
+			bus_handle->handle =
+				msm_bus_scale_register_client(bus_pdata);
+			if (!bus_handle->handle) {
+				pr_err("not able to get bus scale i=%d\n", i);
+				return -ENOMEM;
+			}
+			pr_debug("register bus_hdl=%x\n",
+				bus_handle->handle);
 		}
-		pr_debug("register bus_hdl=%x\n", mdp3_res->bus_handle);
 	}
 	return 0;
 }
 
 static void mdp3_bus_scale_unregister(void)
 {
-	pr_debug("unregister bus_handle=%x\n", mdp3_res->bus_handle);
-
-	if (mdp3_res->bus_handle)
-		msm_bus_scale_unregister_client(mdp3_res->bus_handle);
+	int i;
+	for (i = 0; i < MDP3_BUS_HANDLE_MAX; i++) {
+		pr_debug("unregister index=%d bus_handle=%x\n",
+			i, mdp3_res->bus_handle[i].handle);
+		if (mdp3_res->bus_handle[i].handle) {
+			msm_bus_scale_unregister_client(
+			   mdp3_res->bus_handle[i].handle);
+			mdp3_res->bus_handle[i].handle = 0;
+		}
+	}
 }
 
 int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota)
 {
-	static int current_bus_idx;
+	struct mdp3_bus_handle_map *bus_handle;
+	int cur_bus_idx;
 	int bus_idx;
+	int client_idx;
 	int rc;
 
-	if (mdp3_res->bus_handle < 1) {
-		pr_err("invalid bus handle %d\n", mdp3_res->bus_handle);
+	if (client == MDP3_CLIENT_DMA_P) {
+		client_idx  = MDP3_BUS_HANDLE_DMA;
+	} else if (client == MDP3_CLIENT_PPP) {
+		client_idx  = MDP3_BUS_HANDLE_PPP;
+	} else {
+		pr_err("invalid client %d\n", client);
+		return -EINVAL;
+	}
+
+	bus_handle = &mdp3_res->bus_handle[client_idx];
+	cur_bus_idx = bus_handle->current_bus_idx;
+
+	if (bus_handle->handle < 1) {
+		pr_err("invalid bus handle %d\n", bus_handle->handle);
 		return -EINVAL;
 	}
 
 	if ((ab_quota | ib_quota) == 0) {
 		bus_idx = 0;
 	} else {
-		int num_cases = mdp_bus_scale_table.num_usecases;
+		int num_cases = bus_handle->scale_pdata->num_usecases;
 		struct msm_bus_vectors *vect = NULL;
 
-		bus_idx = (current_bus_idx % (num_cases - 1)) + 1;
+		bus_idx = (cur_bus_idx % (num_cases - 1)) + 1;
 
 		/* aligning to avoid performing updates for small changes */
 		ab_quota = ALIGN(ab_quota, SZ_64M);
 		ib_quota = ALIGN(ib_quota, SZ_64M);
 
-		vect = mdp_bus_scale_table.usecase[current_bus_idx].vectors;
+		vect = bus_handle->scale_pdata->usecase[cur_bus_idx].vectors;
 		if ((ab_quota == vect->ab) && (ib_quota == vect->ib)) {
 			pr_debug("skip bus scaling, no change in vectors\n");
 			return 0;
 		}
 
-		vect = mdp_bus_scale_table.usecase[bus_idx].vectors;
+		vect = bus_handle->scale_pdata->usecase[bus_idx].vectors;
 		vect->ab = ab_quota;
 		vect->ib = ib_quota;
 
 		pr_debug("bus scale idx=%d ab=%llu ib=%llu\n", bus_idx,
 				vect->ab, vect->ib);
 	}
-	current_bus_idx = bus_idx;
-	rc = msm_bus_scale_client_update_request(mdp3_res->bus_handle, bus_idx);
+	bus_handle->current_bus_idx = bus_idx;
+	rc = msm_bus_scale_client_update_request(bus_handle->handle, bus_idx);
 	return rc;
 }
 
@@ -298,7 +373,7 @@
 		mdp3_res->clock_ref_count[clk_idx]--;
 
 	count = mdp3_res->clock_ref_count[clk_idx];
-	if (count == 1) {
+	if (count == 1 && enable) {
 		pr_debug("clk=%d en=%d\n", clk_idx, enable);
 		ret = clk_prepare_enable(clk);
 	} else if (count == 0) {
@@ -655,6 +730,7 @@
 		pr_err("fail to attach DMA-P context 0\n");
 		return rc;
 	}
+	mdp3_res->bus_handle = mdp3_bus_handle;
 	rc = mdp3_bus_scale_register();
 	if (rc) {
 		pr_err("unable to register bus scaling\n");
@@ -800,9 +876,28 @@
 	return ret;
 }
 
+int mdp3_ppp_iommu_attach(void)
+{
+	int rc;
+	rc = mdp3_iommu_attach(MDP3_IOMMU_CTX_PPP_0);
+	rc |= mdp3_iommu_attach(MDP3_IOMMU_CTX_PPP_1);
+	return rc;
+}
+
+int mdp3_ppp_iommu_dettach(void)
+{
+	int rc;
+	rc = mdp3_iommu_dettach(MDP3_IOMMU_CTX_PPP_0);
+	rc = mdp3_iommu_dettach(MDP3_IOMMU_CTX_PPP_1);
+	return rc;
+}
+
 static int mdp3_init(struct msm_fb_data_type *mfd)
 {
-	return mdp3_ctrl_init(mfd);
+	int rc;
+	rc = mdp3_ctrl_init(mfd);
+	rc |= mdp3_ppp_res_init();
+	return rc;
 }
 
 u32 mdp3_fb_stride(u32 fb_index, u32 xres, int bpp)
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index 7e395e1..878fe25 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -35,6 +35,12 @@
 };
 
 enum {
+	MDP3_BUS_HANDLE_DMA,
+	MDP3_BUS_HANDLE_PPP,
+	MDP3_BUS_HANDLE_MAX,
+};
+
+enum {
 	MDP3_IOMMU_DOMAIN,
 	MDP3_IOMMU_DOMAIN_MAX
 };
@@ -48,10 +54,16 @@
 };
 
 enum {
-	MDP3_BW_CLIENT_DMA_P,
-	MDP3_BW_CLIENT_DMA_S,
-	MDP3_BW_CLIENT_DMA_E,
-	MDP3_BW_CLIENT_PPP,
+	MDP3_CLIENT_DMA_P,
+	MDP3_CLIENT_PPP,
+};
+
+struct mdp3_bus_handle_map {
+	struct msm_bus_vectors *bus_vector;
+	struct msm_bus_paths *usecases;
+	struct msm_bus_scale_pdata *scale_pdata;
+	int current_bus_idx;
+	u32 handle;
 };
 
 struct mdp3_iommu_domain_map {
@@ -86,12 +98,14 @@
 
 	struct clk *clocks[MDP3_MAX_CLK];
 	int clock_ref_count[MDP3_MAX_CLK];
+	unsigned long dma_core_clk_request;
+	unsigned long ppp_core_clk_request;
 
 	char __iomem *mdp_base;
 	size_t mdp_reg_size;
 
 	u32 irq;
-	u32 bus_handle;
+	struct mdp3_bus_handle_map *bus_handle;
 
 	struct ion_client *ion_client;
 	struct mdp3_iommu_domain_map *domains;
@@ -130,6 +144,8 @@
 int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota);
 int mdp3_put_img(struct mdp3_img_data *data);
 int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data);
+int mdp3_ppp_iommu_attach(void);
+int mdp3_ppp_iommu_dettach(void);
 
 #define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr)
 #define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr)
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index f5ac5e9..3d990c2 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -22,6 +22,7 @@
 
 #include "mdp3_ctrl.h"
 #include "mdp3.h"
+#include "mdp3_ppp.h"
 
 #define MDP_VSYNC_CLK_RATE	19200000
 #define VSYNC_PERIOD 16
@@ -127,6 +128,53 @@
 	return 0;
 }
 
+static int mdp3_ctrl_blit_req(struct msm_fb_data_type *mfd, void __user *p)
+{
+	const int MAX_LIST_WINDOW = 16;
+	struct mdp_blit_req req_list[MAX_LIST_WINDOW];
+	struct mdp_blit_req_list req_list_header;
+	int rc, count, i, req_list_count;
+
+	if (copy_from_user(&req_list_header, p, sizeof(req_list_header)))
+		return -EFAULT;
+	p += sizeof(req_list_header);
+	count = req_list_header.count;
+	if (count < 0 || count >= MAX_BLIT_REQ)
+		return -EINVAL;
+	while (count > 0) {
+		/*
+		 * Access the requests through a narrow window to decrease copy
+		 * overhead and make larger requests accessible to the
+		 * coherency management code.
+		 * NOTE: The window size is intended to be larger than the
+		 *       typical request size, but not require more than 2
+		 *       kbytes of stack storage.
+		 */
+		req_list_count = count;
+		if (req_list_count > MAX_LIST_WINDOW)
+			req_list_count = MAX_LIST_WINDOW;
+		if (copy_from_user(&req_list, p,
+				sizeof(struct mdp_blit_req)*req_list_count))
+			return -EFAULT;
+		/*
+		 * Do the blit DMA, if required -- returning early only if
+		 * there is a failure.
+		 */
+		for (i = 0; i < req_list_count; i++) {
+			if (!(req_list[i].flags & MDP_NO_BLIT)) {
+				/* Do the actual blit. */
+				rc = mdp3_ppp_start_blit(mfd, &(req_list[i]));
+				if (rc)
+					return rc;
+			}
+		}
+
+		/* Go to next window of requests. */
+		count -= req_list_count;
+		p += sizeof(struct mdp_blit_req)*req_list_count;
+	}
+	return 0;
+}
 
 static ssize_t mdp3_vsync_show_event(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -181,9 +229,9 @@
 		ab = panel_info->xres * panel_info->yres * 4;
 		ab *= panel_info->mipi.frame_rate;
 		ib = (ab * 3) / 2;
-		rc = mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, ab, ib);
+		rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
 	} else {
-		rc = mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, 0, 0);
+		rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
 	}
 	return rc;
 }
@@ -394,6 +442,12 @@
 		goto on_error;
 	}
 
+	rc = mdp3_ppp_init();
+	if (rc) {
+		pr_err("ppp init failed\n");
+		goto on_error;
+	}
+
 	rc = mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
 	if (rc) {
 		pr_err("display interface init failed\n");
@@ -701,6 +755,9 @@
 			rc = -EFAULT;
 		}
 		break;
+	case MSMFB_BLIT:
+		rc = mdp3_ctrl_blit_req(mfd, argp);
+		break;
 	case MSMFB_METADATA_GET:
 		rc = copy_from_user(&metadata, argp, sizeof(metadata));
 		if (rc)
diff --git a/drivers/video/msm/mdss/mdp3_hwio.h b/drivers/video/msm/mdss/mdp3_hwio.h
index 2763f46..1c5bf46 100644
--- a/drivers/video/msm/mdss/mdp3_hwio.h
+++ b/drivers/video/msm/mdss/mdp3_hwio.h
@@ -148,6 +148,70 @@
 #define MDP3_REG_DSI_CMD_MODE_ID_MAP			0xF1000
 #define MDP3_REG_DSI_CMD_MODE_TRIGGER_EN		0xF1004
 
+#define MDP3_PPP_CSC_PFMVn(n)		(0x40400 + (4 * (n)))
+#define MDP3_PPP_CSC_PRMVn(n)		(0x40440 + (4 * (n)))
+#define MDP3_PPP_CSC_PBVn(n)		(0x40500 + (4 * (n)))
+#define MDP3_PPP_CSC_PLVn(n)		(0x40580 + (4 * (n)))
+
+#define MDP3_PPP_CSC_SFMVn(n)		(0x40480 + (4 * (n)))
+#define MDP3_PPP_CSC_SRMVn(n)		(0x404C0 + (4 * (n)))
+#define MDP3_PPP_CSC_SBVn(n)		(0x40540 + (4 * (n)))
+#define MDP3_PPP_CSC_SLVn(n)		(0x405C0 + (4 * (n)))
+
+#define MDP3_PPP_SCALE_PHASEX_INIT	0x1013C
+#define MDP3_PPP_SCALE_PHASEY_INIT	0x10140
+#define MDP3_PPP_SCALE_PHASEX_STEP	0x10144
+#define MDP3_PPP_SCALE_PHASEY_STEP	0x10148
+
+#define MDP3_PPP_OP_MODE			0x10138
+
+#define MDP3_PPP_PRE_LUT			0x40800
+#define MDP3_PPP_POST_LUT			0x40C00
+#define MDP3_PPP_LUTn(n)			((4 * (n)))
+
+#define MDP3_PPP_BG_EDGE_REP		0x101BC
+#define MDP3_PPP_SRC_EDGE_REP		0x101B8
+
+#define MDP3_PPP_STRIDE_MASK		0x3FFF
+#define MDP3_PPP_STRIDE1_OFFSET		16
+
+#define MDP3_PPP_XY_MASK			0x0FFF
+#define MDP3_PPP_XY_OFFSET			16
+
+#define MDP3_PPP_SRC_SIZE			0x10108
+#define MDP3_PPP_SRCP0_ADDR			0x1010C
+#define MDP3_PPP_SRCP1_ADDR			0x10110
+#define MDP3_PPP_SRCP3_ADDR			0x10118
+#define MDP3_PPP_SRC_YSTRIDE1_ADDR	0x1011C
+#define MDP3_PPP_SRC_YSTRIDE2_ADDR	0x10120
+#define MDP3_PPP_SRC_FORMAT			0x10124
+#define MDP3_PPP_SRC_UNPACK_PATTERN1	0x10128
+#define MDP3_PPP_SRC_UNPACK_PATTERN2	0x1012C
+
+#define MDP3_PPP_OUT_FORMAT			0x10150
+#define MDP3_PPP_OUT_PACK_PATTERN1	0x10154
+#define MDP3_PPP_OUT_PACK_PATTERN2	0x10158
+#define MDP3_PPP_OUT_SIZE			0x10164
+#define MDP3_PPP_OUTP0_ADDR			0x10168
+#define MDP3_PPP_OUTP1_ADDR			0x1016C
+#define MDP3_PPP_OUTP3_ADDR			0x10174
+#define MDP3_PPP_OUT_YSTRIDE1_ADDR	0x10178
+#define MDP3_PPP_OUT_YSTRIDE2_ADDR	0x1017C
+#define MDP3_PPP_OUT_XY				0x1019C
+
+#define MDP3_PPP_BGP0_ADDR			0x101C0
+#define MDP3_PPP_BGP1_ADDR			0x101C4
+#define MDP3_PPP_BGP3_ADDR			0x101C8
+#define MDP3_PPP_BG_YSTRIDE1_ADDR	0x101CC
+#define MDP3_PPP_BG_YSTRIDE2_ADDR	0x101D0
+#define MDP3_PPP_BG_FORMAT			0x101D4
+#define MDP3_PPP_BG_UNPACK_PATTERN1	0x101D8
+#define MDP3_PPP_BG_UNPACK_PATTERN2	0x101DC
+
+#define MDP3_PPP_BLEND_PARAM		0x1014C
+
+#define MDP3_PPP_BLEND_BG_ALPHA_SEL	0x70010
+
 /*interrupt mask*/
 
 #define MDP3_INTR_DP0_ROI_DONE_BIT			BIT(0)
@@ -212,5 +276,6 @@
 
 #define MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT		BIT(0)
 #define MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT		BIT(1)
+#define MDP3_PPP_DONE MDP3_INTR_DP0_ROI_DONE
 
 #endif /* MDP3_HWIO_H */
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
new file mode 100644
index 0000000..7164086
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -0,0 +1,760 @@
+/* Copyright (c) 2007, 2013 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * 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.
+ */
+
+#include <linux/file.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include "linux/proc_fs.h"
+
+#include "mdss_fb.h"
+#include "mdp3_ppp.h"
+#include "mdp3_hwio.h"
+#include "mdp3.h"
+
+#define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT)
+
+static const bool valid_fmt[MDP_IMGTYPE_LIMIT] = {
+	[MDP_RGB_565] = true,
+	[MDP_BGR_565] = true,
+	[MDP_RGB_888] = true,
+	[MDP_BGR_888] = true,
+	[MDP_BGRA_8888] = true,
+	[MDP_RGBA_8888] = true,
+	[MDP_ARGB_8888] = true,
+	[MDP_XRGB_8888] = true,
+	[MDP_RGBX_8888] = true,
+	[MDP_Y_CRCB_H2V2] = true,
+	[MDP_Y_CBCR_H2V2] = true,
+	[MDP_Y_CBCR_H2V2_ADRENO] = true,
+	[MDP_YCRYCB_H2V1] = true,
+	[MDP_Y_CBCR_H2V1] = true,
+	[MDP_Y_CRCB_H2V1] = true,
+};
+
+struct ppp_status {
+	int busy;
+	spinlock_t ppp_lock;
+	struct completion ppp_comp;
+	struct mutex config_mutex;
+};
+
+static struct ppp_status *ppp_stat;
+
+
+int ppp_get_bpp(uint32_t format, uint32_t fb_format)
+{
+	int bpp = -EINVAL;
+	if (format == MDP_FB_FORMAT)
+		format = fb_format;
+
+	bpp = ppp_bpp(format);
+	if (bpp <= 0)
+		pr_err("%s incorrect format %d\n", __func__, format);
+	return bpp;
+}
+
+int mdp3_ppp_get_img(struct mdp_img *img, struct mdp_blit_req *req,
+		struct mdp3_img_data *data)
+{
+	struct msmfb_data fb_data;
+	fb_data.flags = img->priv;
+	fb_data.memory_id = img->memory_id;
+	fb_data.offset = 0;
+
+	return mdp3_get_img(&fb_data, data);
+}
+
+/* Check format */
+int mdp3_ppp_verify_fmt(struct mdp_blit_req *req)
+{
+	if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
+	    MDP_IS_IMGTYPE_BAD(req->dst.format)) {
+		pr_err("%s: Color format out of range\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!valid_fmt[req->src.format] ||
+	    !valid_fmt[req->dst.format]) {
+		pr_err("%s: Color format not supported\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Check resolution */
+int mdp3_ppp_verify_res(struct mdp_blit_req *req)
+{
+	if ((req->src.width == 0) || (req->src.height == 0) ||
+	    (req->src_rect.w == 0) || (req->src_rect.h == 0) ||
+	    (req->dst.width == 0) || (req->dst.height == 0) ||
+	    (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) {
+		pr_err("%s: Height/width can't be 0\n", __func__);
+		return -EINVAL;
+	}
+
+	if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+	    ((req->src_rect.y + req->src_rect.h) > req->src.height)) {
+		pr_err("%s: src roi larger than boundary\n", __func__);
+		return -EINVAL;
+	}
+
+	if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
+	    ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) {
+		pr_err("%s: dst roi larger than boundary\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* scaling range check */
+int mdp3_ppp_verify_scale(struct mdp_blit_req *req)
+{
+	u32 src_width, src_height, dst_width, dst_height;
+
+	src_width = req->src_rect.w;
+	src_height = req->src_rect.h;
+
+	if (req->flags & MDP_ROT_90) {
+		dst_width = req->dst_rect.h;
+		dst_height = req->dst_rect.w;
+	} else {
+		dst_width = req->dst_rect.w;
+		dst_height = req->dst_rect.h;
+	}
+
+	switch (req->dst.format) {
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CBCR_H2V2:
+		src_width = (src_width / 2) * 2;
+		src_height = (src_height / 2) * 2;
+		dst_width = (dst_width / 2) * 2;
+		dst_height = (dst_height / 2) * 2;
+		break;
+
+	case MDP_Y_CRCB_H2V1:
+	case MDP_Y_CBCR_H2V1:
+	case MDP_YCRYCB_H2V1:
+		src_width = (src_width / 2) * 2;
+		dst_width = (dst_width / 2) * 2;
+		break;
+
+	default:
+		break;
+	}
+
+	if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width >
+	     MDP_MAX_X_SCALE_FACTOR)
+	    || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width <
+		MDP_MIN_X_SCALE_FACTOR)) {
+		pr_err("%s: x req scale factor beyond capability\n", __func__);
+		return -EINVAL;
+	}
+
+	if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height >
+	     MDP_MAX_Y_SCALE_FACTOR)
+	    || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height <
+		MDP_MIN_Y_SCALE_FACTOR)) {
+		pr_err("%s: y req scale factor beyond capability\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* operation check */
+int mdp3_ppp_verify_op(struct mdp_blit_req *req)
+{
+	if (req->flags & MDP_DEINTERLACE) {
+		pr_err("\n%s(): deinterlace not supported", __func__);
+		return -EINVAL;
+	}
+
+	if (req->flags & MDP_SHARPENING) {
+		pr_err("\n%s(): sharpening not supported", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int mdp3_ppp_verify_req(struct mdp_blit_req *req)
+{
+	int rc;
+
+	if (req == NULL) {
+		pr_err("%s: req == null\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = mdp3_ppp_verify_fmt(req);
+	rc |= mdp3_ppp_verify_res(req);
+	rc |= mdp3_ppp_verify_scale(req);
+	rc |= mdp3_ppp_verify_op(req);
+
+	return rc;
+}
+
+int mdp3_ppp_pipe_wait(void)
+{
+	int ret = 1;
+	int wait;
+	unsigned long flag;
+
+	/*
+	 * wait 5 secs for 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__);
+	}
+
+	return ret;
+}
+
+uint32_t mdp3_calc_tpval(struct ppp_img_desc *img, uint32_t old_tp)
+{
+	uint32_t tpVal;
+	uint8_t plane_tp;
+
+	tpVal = 0;
+	if ((img->color_fmt == MDP_RGB_565)
+	    || (img->color_fmt == MDP_BGR_565)) {
+		/* transparent color conversion into 24 bpp */
+		plane_tp = (uint8_t) ((old_tp & 0xF800) >> 11);
+		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
+		plane_tp = (uint8_t) (old_tp & 0x1F);
+		tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
+
+		plane_tp = (uint8_t) ((old_tp & 0x7E0) >> 5);
+		tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
+	} else {
+		/* 24bit RGB to RBG conversion */
+		tpVal = (old_tp & 0xFF00) >> 8;
+		tpVal |= (old_tp & 0xFF) << 8;
+		tpVal |= (old_tp & 0xFF0000);
+	}
+
+	return tpVal;
+}
+
+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)
+{
+	int rc;
+	struct mdp3_intr_cb ppp_done_cb = {
+		.cb = mdp3_ppp_intr_handler,
+		.data = NULL,
+	};
+
+	rc = mdp3_set_intr_callback(MDP3_PPP_DONE, &ppp_done_cb);
+	return rc;
+}
+
+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);
+	ppp_enable();
+
+	mdp3_ppp_pipe_wait();
+}
+
+int mdp3_ppp_turnon(struct ppp_blit_op *blit_op, int on_off)
+{
+	unsigned long clk_rate = 0, dst_rate = 0, src_rate = 0;
+	int ab = 0;
+	int ib = 0;
+	if (on_off) {
+		dst_rate = blit_op->dst.roi.width * blit_op->dst.roi.height;
+		src_rate = blit_op->src.roi.width * blit_op->src.roi.height;
+		clk_rate = max(dst_rate, src_rate);
+		clk_rate = clk_rate * 36 * 12;
+
+		ab = blit_op->dst.roi.width * blit_op->dst.roi.height *
+			ppp_bpp(blit_op->dst.color_fmt) * 2 +
+			blit_op->src.roi.width * blit_op->src.roi.height *
+			ppp_bpp(blit_op->src.color_fmt);
+		ab = ab * 120;
+		ib = (ab * 3) / 2;
+	}
+	mdp3_clk_enable(on_off);
+	mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib);
+	return 0;
+}
+
+void mdp3_start_ppp(struct ppp_blit_op *blit_op)
+{
+	/* Wait for the pipe to clear */
+	do { } while (mdp3_ppp_pipe_wait() <= 0);
+	mutex_lock(&ppp_stat->config_mutex);
+	config_ppp_op_mode(blit_op);
+	mdp3_ppp_kickoff();
+	mutex_unlock(&ppp_stat->config_mutex);
+}
+
+static void mdp3_ppp_process_req(struct ppp_blit_op *blit_op,
+	struct mdp_blit_req *req, struct mdp3_img_data *src_data,
+	struct mdp3_img_data *dst_data)
+{
+	unsigned long srcp0_start, srcp0_len, dst_start, dst_len;
+	uint32_t dst_width, dst_height;
+
+	srcp0_start = (unsigned long) src_data->addr;
+	srcp0_len = (unsigned long) src_data->len;
+	dst_start = (unsigned long) dst_data->addr;
+	dst_len = (unsigned long) dst_data->len;
+
+	blit_op->dst.prop.width = req->dst.width;
+	blit_op->dst.prop.height = req->dst.height;
+
+	blit_op->dst.color_fmt = req->dst.format;
+	blit_op->dst.p0 = (void *) dst_start;
+	blit_op->dst.p0 += req->dst.offset;
+
+	blit_op->dst.roi.x = req->dst_rect.x;
+	blit_op->dst.roi.y = req->dst_rect.y;
+	blit_op->dst.roi.width = req->dst_rect.w;
+	blit_op->dst.roi.height = req->dst_rect.h;
+
+	blit_op->src.roi.x = req->src_rect.x;
+	blit_op->src.roi.y = req->src_rect.y;
+	blit_op->src.roi.width = req->src_rect.w;
+	blit_op->src.roi.height = req->src_rect.h;
+
+	blit_op->src.prop.width = req->src.width;
+	blit_op->src.color_fmt = req->src.format;
+
+
+	blit_op->src.p0 = (void *) (srcp0_start + req->src.offset);
+	if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_ADRENO)
+		blit_op->src.p1 =
+			(void *) ((uint32_t) blit_op->src.p0 +
+				ALIGN((ALIGN(req->src.width, 32) *
+				ALIGN(req->src.height, 32)), 4096));
+	else
+		blit_op->src.p1 = (void *) ((uint32_t) blit_op->src.p0 +
+			req->src.width * req->src.height);
+
+	if (req->flags & MDP_IS_FG)
+		blit_op->mdp_op |= MDPOP_LAYER_IS_FG;
+
+	/* blending check */
+	if (req->transp_mask != MDP_TRANSP_NOP) {
+		blit_op->mdp_op |= MDPOP_TRANSP;
+		blit_op->blend.trans_color =
+			mdp3_calc_tpval(&blit_op->src, req->transp_mask);
+	} else {
+		blit_op->blend.trans_color = 0;
+	}
+
+	req->alpha &= 0xff;
+	if (req->alpha < MDP_ALPHA_NOP) {
+		blit_op->mdp_op |= MDPOP_ALPHAB;
+		blit_op->blend.const_alpha = req->alpha;
+	} else {
+		blit_op->blend.const_alpha = 0xff;
+	}
+
+	/* rotation check */
+	if (req->flags & MDP_FLIP_LR)
+		blit_op->mdp_op |= MDPOP_LR;
+	if (req->flags & MDP_FLIP_UD)
+		blit_op->mdp_op |= MDPOP_UD;
+	if (req->flags & MDP_ROT_90)
+		blit_op->mdp_op |= MDPOP_ROT90;
+	if (req->flags & MDP_DITHER)
+		blit_op->mdp_op |= MDPOP_DITHER;
+
+	if (req->flags & MDP_BLEND_FG_PREMULT)
+		blit_op->mdp_op |= MDPOP_FG_PM_ALPHA;
+
+	/* scale check */
+	if (req->flags & MDP_ROT_90) {
+		dst_width = req->dst_rect.h;
+		dst_height = req->dst_rect.w;
+	} else {
+		dst_width = req->dst_rect.w;
+		dst_height = req->dst_rect.h;
+	}
+
+	if ((blit_op->src.roi.width != dst_width) ||
+			(blit_op->src.roi.height != dst_height))
+		blit_op->mdp_op |= MDPOP_ASCALE;
+
+	if (req->flags & MDP_BLUR)
+		blit_op->mdp_op |= MDPOP_ASCALE | MDPOP_BLUR;
+}
+
+static void mdp3_ppp_tile_workaround(struct ppp_blit_op *blit_op,
+	struct mdp_blit_req *req)
+{
+	int dst_h, src_w, i;
+	uint32_t mdp_op = blit_op->mdp_op;
+
+	src_w = req->src_rect.w;
+	dst_h = blit_op->dst.roi.height;
+	/* bg tile fetching HW workaround */
+	for (i = 0; i < (req->dst_rect.h / 16); i++) {
+		/* this tile size */
+		blit_op->dst.roi.height = 16;
+		blit_op->src.roi.width =
+			(16 * req->src_rect.w) / req->dst_rect.h;
+
+		/* if it's out of scale range... */
+		if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+			 blit_op->src.roi.width) > MDP_MAX_X_SCALE_FACTOR)
+			blit_op->src.roi.width =
+				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+				MDP_MAX_X_SCALE_FACTOR;
+		else if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+			  blit_op->src.roi.width) < MDP_MIN_X_SCALE_FACTOR)
+			blit_op->src.roi.width =
+				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+				MDP_MIN_X_SCALE_FACTOR;
+
+		mdp3_start_ppp(blit_op);
+
+		/* next tile location */
+		blit_op->dst.roi.y += 16;
+		blit_op->src.roi.x += blit_op->src.roi.width;
+
+		/* this is for a remainder update */
+		dst_h -= 16;
+		src_w -= blit_op->src.roi.width;
+		/* restore mdp_op since MDPOP_ASCALE have been cleared */
+		blit_op->mdp_op = mdp_op;
+	}
+
+	if ((dst_h < 0) || (src_w < 0))
+		pr_err
+			("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
+			 __LINE__);
+
+	/* remainder update */
+	if ((dst_h > 0) && (src_w > 0)) {
+		u32 tmp_v;
+
+		blit_op->dst.roi.height = dst_h;
+		blit_op->src.roi.width = src_w;
+
+		if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+			 blit_op->src.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
+			tmp_v =
+				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+				MDP_MAX_X_SCALE_FACTOR +
+				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) %
+				MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+
+			/* move x location as roi width gets bigger */
+			blit_op->src.roi.x -= tmp_v - blit_op->src.roi.width;
+			blit_op->src.roi.width = tmp_v;
+		} else if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+			 blit_op->src.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
+			tmp_v =
+				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
+				MDP_MIN_X_SCALE_FACTOR +
+				(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) %
+				MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+
+			/*
+			 * we don't move x location for continuity of
+			 * source image
+			 */
+			blit_op->src.roi.width = tmp_v;
+		}
+
+
+		mdp3_start_ppp(blit_op);
+	}
+}
+
+static int mdp3_ppp_blit_addr(struct msm_fb_data_type *mfd,
+	struct mdp_blit_req *req, struct mdp3_img_data *src_data,
+	struct mdp3_img_data *dst_data)
+{
+	struct ppp_blit_op blit_op;
+
+	memset(&blit_op, 0, sizeof(blit_op));
+
+	if (req->dst.format == MDP_FB_FORMAT)
+		req->dst.format =  mfd->fb_imgType;
+	if (req->src.format == MDP_FB_FORMAT)
+		req->src.format = mfd->fb_imgType;
+
+	if (mdp3_ppp_verify_req(req)) {
+		pr_err("%s: invalid image!\n", __func__);
+		return -EINVAL;
+	}
+
+	mdp3_ppp_process_req(&blit_op, req, src_data, dst_data);
+
+	mdp3_ppp_turnon(&blit_op, 1);
+
+	if (((blit_op.mdp_op & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
+	     (req->src.format == MDP_ARGB_8888) ||
+	     (req->src.format == MDP_BGRA_8888) ||
+	     (req->src.format == MDP_RGBA_8888)) &&
+	    (blit_op.mdp_op & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
+		mdp3_ppp_tile_workaround(&blit_op, req);
+	} else {
+		mdp3_start_ppp(&blit_op);
+	}
+
+	/* MDP cmd block disable */
+	mdp3_ppp_turnon(&blit_op, 0);
+
+	return 0;
+}
+
+static int mdp3_ppp_blit(struct msm_fb_data_type *mfd, struct mdp_blit_req *req)
+{
+	struct mdp3_img_data src_data;
+	struct mdp3_img_data dst_data;
+	int rc;
+	mdp3_ppp_iommu_attach();
+
+	mdp3_ppp_get_img(&req->src, req, &src_data);
+	if (src_data.len == 0) {
+		pr_err("mdp_ppp: couldn't retrieve src img from mem\n");
+		return -EINVAL;
+	}
+
+	mdp3_ppp_get_img(&req->dst, req, &dst_data);
+	if (dst_data.len == 0) {
+		mdp3_put_img(&src_data);
+		pr_err("mdp_ppp: couldn't retrieve dest img from mem\n");
+		return -EINVAL;
+	}
+
+	rc = mdp3_ppp_blit_addr(mfd, req, &src_data, &dst_data);
+	mdp3_put_img(&src_data);
+	mdp3_put_img(&dst_data);
+	mdp3_ppp_iommu_dettach();
+	return rc;
+}
+
+static int mdp3_ppp_blit_workaround(struct msm_fb_data_type *mfd,
+		struct mdp_blit_req *req, unsigned int remainder)
+{
+	int ret;
+	struct mdp_blit_req splitreq;
+	int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1;
+	int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1;
+
+	/* make new request as provide by user */
+	splitreq = *req;
+
+	/* break dest roi at width*/
+	d_y_0 = d_y_1 = req->dst_rect.y;
+	d_h_0 = d_h_1 = req->dst_rect.h;
+	d_x_0 = req->dst_rect.x;
+
+	if (remainder == 14 || remainder == 6)
+		d_w_1 = req->dst_rect.w / 2;
+	else
+		d_w_1 = (req->dst_rect.w - 1) / 2 - 1;
+
+	d_w_0 = req->dst_rect.w - d_w_1;
+	d_x_1 = d_x_0 + d_w_0;
+	/* blit first region */
+	if (((splitreq.flags & 0x07) == 0x07) ||
+		((splitreq.flags & 0x07) == 0x05) ||
+		((splitreq.flags & 0x07) == 0x02) ||
+		((splitreq.flags & 0x07) == 0x0)) {
+
+		if (splitreq.flags & MDP_ROT_90) {
+			s_x_0 = s_x_1 = req->src_rect.x;
+			s_w_0 = s_w_1 = req->src_rect.w;
+			s_y_0 = req->src_rect.y;
+			s_h_1 = (req->src_rect.h * d_w_1) /
+				req->dst_rect.w;
+			s_h_0 = req->src_rect.h - s_h_1;
+			s_y_1 = s_y_0 + s_h_0;
+			if (d_w_1 >= 8 * s_h_1) {
+				s_h_1++;
+				s_y_1--;
+			}
+		} else {
+			s_y_0 = s_y_1 = req->src_rect.y;
+			s_h_0 = s_h_1 = req->src_rect.h;
+			s_x_0 = req->src_rect.x;
+			s_w_1 = (req->src_rect.w * d_w_1) /
+				req->dst_rect.w;
+			s_w_0 = req->src_rect.w - s_w_1;
+			s_x_1 = s_x_0 + s_w_0;
+			if (d_w_1 >= 8 * s_w_1) {
+				s_w_1++;
+				s_x_1--;
+			}
+		}
+
+		splitreq.src_rect.h = s_h_0;
+		splitreq.src_rect.y = s_y_0;
+		splitreq.dst_rect.h = d_h_0;
+		splitreq.dst_rect.y = d_y_0;
+		splitreq.src_rect.x = s_x_0;
+		splitreq.src_rect.w = s_w_0;
+		splitreq.dst_rect.x = d_x_0;
+		splitreq.dst_rect.w = d_w_0;
+	} else {
+		if (splitreq.flags & MDP_ROT_90) {
+			s_x_0 = s_x_1 = req->src_rect.x;
+			s_w_0 = s_w_1 = req->src_rect.w;
+			s_y_0 = req->src_rect.y;
+			s_h_1 = (req->src_rect.h * d_w_0) /
+				req->dst_rect.w;
+			s_h_0 = req->src_rect.h - s_h_1;
+			s_y_1 = s_y_0 + s_h_0;
+			if (d_w_0 >= 8 * s_h_1) {
+				s_h_1++;
+				s_y_1--;
+			}
+		} else {
+			s_y_0 = s_y_1 = req->src_rect.y;
+			s_h_0 = s_h_1 = req->src_rect.h;
+			s_x_0 = req->src_rect.x;
+			s_w_1 = (req->src_rect.w * d_w_0) /
+				req->dst_rect.w;
+			s_w_0 = req->src_rect.w - s_w_1;
+			s_x_1 = s_x_0 + s_w_0;
+			if (d_w_0 >= 8 * s_w_1) {
+				s_w_1++;
+				s_x_1--;
+			}
+		}
+		splitreq.src_rect.h = s_h_0;
+		splitreq.src_rect.y = s_y_0;
+		splitreq.dst_rect.h = d_h_1;
+		splitreq.dst_rect.y = d_y_1;
+		splitreq.src_rect.x = s_x_0;
+		splitreq.src_rect.w = s_w_0;
+		splitreq.dst_rect.x = d_x_1;
+		splitreq.dst_rect.w = d_w_1;
+	}
+
+	/* No need to split in height */
+	ret = mdp3_ppp_blit(mfd, &splitreq);
+
+	if (ret)
+		return ret;
+	/* blit second region */
+	if (((splitreq.flags & 0x07) == 0x07) ||
+		((splitreq.flags & 0x07) == 0x05) ||
+		((splitreq.flags & 0x07) == 0x02) ||
+		((splitreq.flags & 0x07) == 0x0)) {
+		splitreq.src_rect.h = s_h_1;
+		splitreq.src_rect.y = s_y_1;
+		splitreq.dst_rect.h = d_h_1;
+		splitreq.dst_rect.y = d_y_1;
+		splitreq.src_rect.x = s_x_1;
+		splitreq.src_rect.w = s_w_1;
+		splitreq.dst_rect.x = d_x_1;
+		splitreq.dst_rect.w = d_w_1;
+	} else {
+		splitreq.src_rect.h = s_h_1;
+		splitreq.src_rect.y = s_y_1;
+		splitreq.dst_rect.h = d_h_0;
+		splitreq.dst_rect.y = d_y_0;
+		splitreq.src_rect.x = s_x_1;
+		splitreq.src_rect.w = s_w_1;
+		splitreq.dst_rect.x = d_x_0;
+		splitreq.dst_rect.w = d_w_0;
+	}
+
+	/* No need to split in height ... just width */
+	return mdp3_ppp_blit(mfd, &splitreq);
+}
+
+int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd,
+		struct mdp_blit_req *req)
+{
+	int ret;
+	unsigned int remainder = 0, is_bpp_4 = 0;
+
+	if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) {
+		pr_err("mdp_ppp: src img of zero size!\n");
+		return -EINVAL;
+	}
+	if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0))
+		return 0;
+
+	if (req->flags & MDP_ROT_90) {
+		if (((req->dst_rect.h == 1) && ((req->src_rect.w != 1) ||
+			(req->dst_rect.w != req->src_rect.h))) ||
+			((req->dst_rect.w == 1) && ((req->src_rect.h != 1) ||
+			(req->dst_rect.h != req->src_rect.w)))) {
+			pr_err("mdp_ppp: error scaling when size is 1!\n");
+			return -EINVAL;
+		}
+	} else {
+		if (((req->dst_rect.w == 1) && ((req->src_rect.w != 1) ||
+			(req->dst_rect.h != req->src_rect.h))) ||
+			((req->dst_rect.h == 1) && ((req->src_rect.h != 1) ||
+			(req->dst_rect.w != req->src_rect.w)))) {
+			pr_err("mdp_ppp: error scaling when size is 1!\n");
+			return -EINVAL;
+		}
+	}
+
+	/* MDP width split workaround */
+	remainder = (req->dst_rect.w) % 16;
+	ret = ppp_get_bpp(req->dst.format, mfd->fb_imgType);
+	if (ret <= 0) {
+		pr_err("mdp_ppp: incorrect bpp!\n");
+		return -EINVAL;
+	}
+	is_bpp_4 = (ret == 4) ? 1 : 0;
+
+	if ((is_bpp_4 && (remainder == 6 || remainder == 14)))
+		ret = mdp3_ppp_blit_workaround(mfd, req, remainder);
+	else
+		ret = mdp3_ppp_blit(mfd, req);
+
+	return ret;
+}
+
+int mdp3_ppp_res_init(void)
+{
+	ppp_stat = kmalloc(sizeof(struct ppp_status), GFP_KERNEL);
+	spin_lock_init(&ppp_stat->ppp_lock);
+	mutex_init(&ppp_stat->config_mutex);
+	ppp_stat->busy = false;
+	mdp3_ppp_callback_setup();
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mdp3_ppp.h b/drivers/video/msm/mdss/mdp3_ppp.h
new file mode 100644
index 0000000..afac419
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ppp.h
@@ -0,0 +1,413 @@
+/* Copyright (c) 2007, 2013 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * 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 MDP3_PPP_H
+#define MDP3_PPP_H
+#include "mdp3.h"
+#include "mdss_fb.h"
+
+#define PPP_WRITEL(val, off) MDP3_REG_WRITE(off, val)
+
+#define MAX_BLIT_REQ 256
+#define PPP_UPSCALE_MAX 64
+#define PPP_BLUR_SCALE_MAX 128
+#define PPP_LUT_MAX 256
+
+/* MDP PPP Operations */
+#define MDPOP_NOP               0
+#define MDPOP_LR                BIT(0)	/* left to right flip */
+#define MDPOP_UD                BIT(1)	/* up and down flip */
+#define MDPOP_ROT90             BIT(2)	/* rotate image to 90 degree */
+#define MDPOP_ROT180            (MDPOP_UD|MDPOP_LR)
+#define MDPOP_ROT270            (MDPOP_ROT90|MDPOP_UD|MDPOP_LR)
+#define MDPOP_ASCALE            BIT(7)
+#define MDPOP_ALPHAB            BIT(8)	/* enable alpha blending */
+#define MDPOP_TRANSP            BIT(9)	/* enable transparency */
+#define MDPOP_DITHER            BIT(10)	/* enable dither */
+#define MDPOP_SHARPENING		BIT(11) /* enable sharpening */
+#define MDPOP_BLUR				BIT(12) /* enable blur */
+#define MDPOP_FG_PM_ALPHA       BIT(13)
+#define MDPOP_LAYER_IS_FG       BIT(14)
+
+#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD)
+
+#define PPP_OP_CONVERT_YCBCR2RGB BIT(2)
+#define PPP_OP_CONVERT_ON		BIT(3)
+#define PPP_OP_SCALE_X_ON		BIT(0)
+#define PPP_OP_SCALE_Y_ON		BIT(1)
+#define PPP_OP_ROT_ON			BIT(8)
+#define PPP_OP_ROT_90			BIT(9)
+#define PPP_OP_FLIP_LR			BIT(10)
+#define PPP_OP_FLIP_UD			BIT(11)
+#define PPP_OP_BLEND_ON			BIT(12)
+#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14)
+#define PPP_OP_DITHER_EN		BIT(16)
+#define PPP_BLEND_CALPHA_TRNASP BIT(24)
+
+#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0
+#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0
+#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15)
+
+#define PPP_BLEND_BG_USE_ALPHA_SEL      (1 << 0)
+#define PPP_BLEND_BG_ALPHA_REVERSE      (1 << 3)
+#define PPP_BLEND_BG_SRCPIXEL_ALPHA     (0 << 1)
+#define PPP_BLEND_BG_DSTPIXEL_ALPHA     (1 << 1)
+#define PPP_BLEND_BG_CONSTANT_ALPHA     (2 << 1)
+#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
+#define PPP_OP_BG_CHROMA_H2V1 BIT(25)
+
+#define CLR_G 0x0
+#define CLR_B 0x1
+#define CLR_R 0x2
+#define CLR_ALPHA 0x3
+
+#define CLR_Y  CLR_G
+#define CLR_CB CLR_B
+#define CLR_CR CLR_R
+
+/* from lsb to msb */
+#define PPP_GET_PACK_PATTERN(a, x, y, z, bit) \
+	(((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z))
+
+/* Frame unpacking */
+#define PPP_C0G_8BITS (BIT(1)|BIT(0))
+#define PPP_C1B_8BITS (BIT(3)|BIT(2))
+#define PPP_C2R_8BITS (BIT(5)|BIT(4))
+#define PPP_C3A_8BITS (BIT(7)|BIT(6))
+
+#define PPP_C0G_6BITS BIT(1)
+#define PPP_C1B_6BITS BIT(3)
+#define PPP_C2R_6BITS BIT(5)
+
+#define PPP_C0G_5BITS BIT(0)
+#define PPP_C1B_5BITS BIT(2)
+#define PPP_C2R_5BITS BIT(4)
+
+#define PPP_SRC_C3_ALPHA_EN BIT(8)
+
+#define PPP_SRC_BPP_INTERLVD_1BYTES 0
+#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9)
+#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10)
+#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9))
+
+#define PPP_SRC_BPP_ROI_ODD_X BIT(11)
+#define PPP_SRC_BPP_ROI_ODD_Y BIT(12)
+#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13)
+#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14)
+#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13))
+
+#define PPP_SRC_UNPACK_TIGHT BIT(17)
+#define PPP_SRC_UNPACK_LOOSE 0
+#define PPP_SRC_UNPACK_ALIGN_LSB 0
+#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18)
+
+#define PPP_SRC_FETCH_PLANES_INTERLVD 0
+#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20)
+
+#define PPP_OP_SRC_CHROMA_H2V1 BIT(18)
+#define PPP_OP_SRC_CHROMA_H1V2 BIT(19)
+#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19))
+#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20)
+
+#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9)
+#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10)
+#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9))
+#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9))
+
+#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6))
+#define PPP_DST_C3ALPHA_EN BIT(8)
+
+#define PPP_DST_PACK_LOOSE 0
+#define PPP_DST_PACK_TIGHT BIT(13)
+#define PPP_DST_PACK_ALIGN_LSB 0
+#define PPP_DST_PACK_ALIGN_MSB BIT(14)
+
+#define PPP_DST_OUT_SEL_AXI 0
+#define PPP_DST_OUT_SEL_MDDI BIT(15)
+
+#define PPP_DST_BPP_2BYTES BIT(16)
+#define PPP_DST_BPP_3BYTES BIT(17)
+#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16))
+
+#define PPP_DST_PLANE_INTERLVD 0
+#define PPP_DST_PLANE_PLANAR BIT(18)
+#define PPP_DST_PLANE_PSEUDOPLN BIT(19)
+
+#define PPP_OP_DST_CHROMA_H2V1 BIT(21)
+#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22))
+#define PPP_OP_COLOR_SPACE_YCBCR BIT(17)
+
+#define MDP_SCALE_Q_FACTOR 512
+#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4)
+#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4)
+
+#define MDP_TOP_LUMA       16
+#define MDP_TOP_CHROMA     0
+#define MDP_BOTTOM_LUMA    19
+#define MDP_BOTTOM_CHROMA  3
+#define MDP_LEFT_LUMA      22
+#define MDP_LEFT_CHROMA    6
+#define MDP_RIGHT_LUMA     25
+#define MDP_RIGHT_CHROMA   9
+
+#define MDP_RGB_565_SRC_REG (PPP_C2R_5BITS | PPP_C0G_6BITS | \
+	PPP_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \
+	PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | \
+	PPP_SRC_UNPACK_ALIGN_LSB | \
+	PPP_SRC_FETCH_PLANES_INTERLVD)
+
+#define MDP_RGB_888_SRC_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \
+	PPP_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | \
+	PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | \
+	PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD)
+
+#define MDP_RGBX_8888_SRC_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \
+	PPP_C1B_8BITS | PPP_C3A_8BITS | \
+	PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES | \
+	PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT | \
+	PPP_SRC_UNPACK_ALIGN_LSB | \
+	PPP_SRC_FETCH_PLANES_INTERLVD)
+
+#define MDP_Y_CBCR_H2V2_SRC_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \
+	PPP_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \
+	PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | \
+	PPP_SRC_UNPACK_ALIGN_LSB | \
+	PPP_SRC_FETCH_PLANES_PSEUDOPLNR)
+
+#define MDP_YCRYCB_H2V1_SRC_REG (PPP_C2R_8BITS | \
+	PPP_C0G_8BITS | PPP_C1B_8BITS | \
+	PPP_C3A_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \
+	PPP_SRC_INTERLVD_4COMPONENTS | \
+	PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB)
+
+#define MDP_Y_CRCB_H2V1_SRC_REG (PPP_C2R_8BITS | \
+	PPP_C0G_8BITS | PPP_C1B_8BITS | \
+	PPP_C3A_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \
+	PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | \
+	PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR)
+
+#define MDP_RGB_565_DST_REG (PPP_C0G_6BITS | \
+	PPP_C1B_5BITS | PPP_C2R_5BITS | \
+	PPP_DST_PACKET_CNT_INTERLVD_3ELEM | \
+	PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \
+	PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | \
+	PPP_DST_PLANE_INTERLVD)
+
+#define MDP_RGB_888_DST_REG (PPP_C0G_8BITS | \
+	PPP_C1B_8BITS | PPP_C2R_8BITS | \
+	PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT | \
+	PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | \
+	PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD)
+
+#define MDP_RGBX_8888_DST_REG (PPP_C0G_8BITS | \
+	PPP_C1B_8BITS | PPP_C2R_8BITS | PPP_C3A_8BITS | \
+	PPP_DST_C3ALPHA_EN | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | \
+	PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \
+	PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_4BYTES | \
+	PPP_DST_PLANE_INTERLVD)
+
+#define MDP_Y_CBCR_H2V2_DST_REG (PPP_C2R_8BITS | \
+	PPP_C0G_8BITS | PPP_C1B_8BITS | PPP_C3A_8BITS | \
+	PPP_DST_PACKET_CNT_INTERLVD_2ELEM | \
+	PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \
+	PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES)
+
+#define MDP_YCRYCB_H2V1_DST_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \
+	PPP_C1B_8BITS | PPP_C3A_8BITS | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | \
+	PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \
+	PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | \
+	PPP_DST_PLANE_INTERLVD)
+
+#define MDP_Y_CRCB_H2V1_DST_REG (PPP_C2R_8BITS | \
+	PPP_C0G_8BITS | PPP_C1B_8BITS | PPP_C3A_8BITS | \
+	PPP_DST_PACKET_CNT_INTERLVD_2ELEM | PPP_DST_PACK_TIGHT | \
+	PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | \
+	PPP_DST_BPP_2BYTES)
+
+/* LUT */
+#define MDP_LUT_C0_EN BIT(5)
+#define MDP_LUT_C1_EN BIT(6)
+#define MDP_LUT_C2_EN BIT(7)
+
+/* Dither */
+#define MDP_OP_DITHER_EN BIT(16)
+
+/* Rotator */
+#define MDP_OP_ROT_ON BIT(8)
+#define MDP_OP_ROT_90 BIT(9)
+#define MDP_OP_FLIP_LR BIT(10)
+#define MDP_OP_FLIP_UD BIT(11)
+
+/* Blend */
+#define MDP_OP_BLEND_EN BIT(12)
+#define MDP_OP_BLEND_EQ_SEL BIT(15)
+#define MDP_OP_BLEND_TRANSP_EN BIT(24)
+#define MDP_BLEND_MASK (MDP_OP_BLEND_EN | MDP_OP_BLEND_EQ_SEL | \
+	MDP_OP_BLEND_TRANSP_EN | BIT(14) | BIT(13))
+
+#define MDP_BLEND_ALPHA_SEL 13
+#define MDP_BLEND_ALPHA_MASK 0x3
+#define MDP_BLEND_CONST_ALPHA 24
+#define MDP_BLEND_TRASP_COL_MASK 0xFFFFFF
+
+/* CSC Matrix */
+#define MDP_CSC_RGB2YUV		0
+#define MDP_CSC_YUV2RGB		1
+
+#define MDP_CSC_SIZE	9
+#define MDP_BV_SIZE		3
+#define MDP_LV_SIZE		4
+
+enum ppp_lut_type {
+	LUT_PRE_TABLE = 0,
+	LUT_POST_TABLE,
+};
+
+enum ppp_csc_matrix {
+	CSC_PRIMARY_MATRIX = 0,
+	CSC_SECONDARY_MATRIX,
+};
+
+/* scale tables */
+enum {
+	PPP_DOWNSCALE_PT2TOPT4,
+	PPP_DOWNSCALE_PT4TOPT6,
+	PPP_DOWNSCALE_PT6TOPT8,
+	PPP_DOWNSCALE_PT8TOPT1,
+	PPP_DOWNSCALE_MAX,
+};
+
+struct ppp_table {
+	uint32_t reg;
+	uint32_t val;
+};
+
+struct ppp_csc_table {
+	int direction;			/* MDP_CCS_RGB2YUV or YUV2RGB */
+	uint16_t fwd_matrix[MDP_CCS_SIZE];	/* 3x3 color coefficients */
+	uint16_t rev_matrix[MDP_CCS_SIZE];	/* 3x3 color coefficients */
+	uint16_t bv[MDP_BV_SIZE];	/* 1x3 bias vector */
+	uint16_t lv[MDP_LV_SIZE];	/* 1x3 limit vector */
+};
+
+struct ppp_blend {
+	int const_alpha;
+	int trans_color; /*color keying*/
+};
+
+struct ppp_img_prop {
+	int32_t x;
+	int32_t y;
+	uint32_t width;
+	uint32_t height;
+};
+
+struct ppp_img_desc {
+	struct ppp_img_prop prop;
+	struct ppp_img_prop roi;
+	int color_fmt;
+	void *p0;  /* plane 0 */
+	void *p1;
+	void *p3;
+	int stride0;
+	int stride1;
+	int stride2;
+};
+
+struct ppp_blit_op {
+	struct ppp_img_desc src;
+	struct ppp_img_desc dst;
+	struct ppp_img_desc bg;
+	struct ppp_blend blend;
+	uint32_t mdp_op; /* Operations */
+};
+
+struct ppp_edge_rep {
+	uint32_t dst_roi_width;
+	uint32_t dst_roi_height;
+	uint32_t is_scale_enabled;
+
+	/*
+	 * positions of the luma pixel(relative to the image ) required for
+	 * scaling the ROI
+	 */
+	int32_t luma_interp_point_left;
+	int32_t luma_interp_point_right;
+	int32_t luma_interp_point_top;
+	int32_t luma_interp_point_bottom;
+
+	/*
+	 * positions of the chroma pixel(relative to the image ) required for
+	 * interpolating a chroma value at all required luma positions
+	 */
+	int32_t chroma_interp_point_left;
+	int32_t chroma_interp_point_right;
+	int32_t chroma_interp_point_top;
+	int32_t chroma_interp_point_bottom;
+
+	/*
+	 * a rectangular region within the chroma plane of the "image".
+	 * Chroma pixels falling inside of this rectangle belongs to the ROI
+	 */
+	int32_t chroma_bound_left;
+	int32_t chroma_bound_right;
+	int32_t chroma_bound_top;
+	int32_t chroma_bound_bottom;
+
+	/*
+	 * number of chroma pixels to replicate on the left, right,
+	 * top and bottom edge of the ROI.
+	 */
+	int32_t chroma_repeat_left;
+	int32_t chroma_repeat_right;
+	int32_t chroma_repeat_top;
+	int32_t chroma_repeat_bottom;
+
+	/*
+	 * number of luma pixels to replicate on the left, right,
+	 * top and bottom edge of the ROI.
+	 */
+	int32_t luma_repeat_left;
+	int32_t luma_repeat_right;
+	int32_t luma_repeat_top;
+	int32_t luma_repeat_bottom;
+};
+
+/* func for ppp register values */
+uint32_t ppp_bpp(uint32_t type);
+uint32_t ppp_src_config(uint32_t type);
+uint32_t ppp_out_config(uint32_t type);
+uint32_t ppp_pack_pattern(uint32_t type);
+uint32_t ppp_dst_op_reg(uint32_t type);
+uint32_t ppp_src_op_reg(uint32_t type);
+bool ppp_per_p_alpha(uint32_t type);
+bool ppp_multi_plane(uint32_t type);
+uint32_t *ppp_default_pre_lut(void);
+uint32_t *ppp_default_post_lut(void);
+struct ppp_csc_table *ppp_csc_rgb2yuv(void);
+struct ppp_csc_table *ppp_csc_table2(void);
+void ppp_load_up_lut(void);
+void ppp_load_gaussian_lut(void);
+void ppp_load_x_scale_table(int idx);
+void ppp_load_y_scale_table(int idx);
+
+int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd,
+	struct mdp_blit_req *req);
+int mdp3_ppp_res_init(void);
+int mdp3_ppp_init(void);
+int config_ppp_op_mode(struct ppp_blit_op *blit_op);
+void ppp_enable(void);
+
+#endif
diff --git a/drivers/video/msm/mdss/mdp3_ppp_data.c b/drivers/video/msm/mdss/mdp3_ppp_data.c
new file mode 100644
index 0000000..d68faad
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ppp_data.c
@@ -0,0 +1,1572 @@
+/* Copyright (c) 2007, 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * 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.
+ */
+
+#include <linux/types.h>
+
+#include "mdss_fb.h"
+#include "mdp3_ppp.h"
+
+/* bg_config_lut not needed since it is same as src */
+const uint32_t src_cfg_lut[MDP_IMGTYPE_LIMIT] = {
+	[MDP_RGB_565] = MDP_RGB_565_SRC_REG,
+	[MDP_BGR_565] = MDP_RGB_565_SRC_REG,
+	[MDP_RGB_888] = MDP_RGB_888_SRC_REG,
+	[MDP_BGR_888] = MDP_RGB_888_SRC_REG,
+	[MDP_BGRA_8888] = MDP_RGBX_8888_SRC_REG,
+	[MDP_RGBA_8888] = MDP_RGBX_8888_SRC_REG,
+	[MDP_ARGB_8888] = MDP_RGBX_8888_SRC_REG,
+	[MDP_XRGB_8888] = MDP_RGBX_8888_SRC_REG,
+	[MDP_RGBX_8888] = MDP_RGBX_8888_SRC_REG,
+	[MDP_Y_CRCB_H2V2] = MDP_Y_CBCR_H2V2_SRC_REG,
+	[MDP_Y_CBCR_H2V2] = MDP_Y_CBCR_H2V2_SRC_REG,
+	[MDP_Y_CBCR_H2V2_ADRENO] = MDP_Y_CBCR_H2V2_SRC_REG,
+	[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_SRC_REG,
+	[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
+	[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
+};
+
+const uint32_t out_cfg_lut[MDP_IMGTYPE_LIMIT] = {
+	[MDP_RGB_565] = MDP_RGB_565_DST_REG,
+	[MDP_BGR_565] = MDP_RGB_565_DST_REG,
+	[MDP_RGB_888] = MDP_RGB_888_DST_REG,
+	[MDP_BGR_888] = MDP_RGB_888_DST_REG,
+	[MDP_BGRA_8888] = MDP_RGBX_8888_DST_REG,
+	[MDP_RGBA_8888] = MDP_RGBX_8888_DST_REG,
+	[MDP_ARGB_8888] = MDP_RGBX_8888_DST_REG,
+	[MDP_XRGB_8888] = MDP_RGBX_8888_DST_REG,
+	[MDP_RGBX_8888] = MDP_RGBX_8888_DST_REG,
+	[MDP_Y_CRCB_H2V2] = MDP_Y_CBCR_H2V2_DST_REG,
+	[MDP_Y_CBCR_H2V2] = MDP_Y_CBCR_H2V2_DST_REG,
+	[MDP_Y_CBCR_H2V2_ADRENO] = MDP_Y_CBCR_H2V2_DST_REG,
+	[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_DST_REG,
+	[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
+	[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
+};
+
+const uint32_t pack_patt_lut[MDP_IMGTYPE_LIMIT] = {
+	[MDP_RGB_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
+	[MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
+	[MDP_RGB_888] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
+	[MDP_BGR_888] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
+	[MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
+		CLR_G, CLR_B, 8),
+	[MDP_RGBA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
+		CLR_G, CLR_B, 8),
+	[MDP_ARGB_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
+		CLR_G, CLR_B, 8),
+	[MDP_XRGB_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
+		CLR_G, CLR_B, 8),
+	[MDP_RGBX_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
+		CLR_G, CLR_B, 8),
+	[MDP_Y_CRCB_H2V2] = PPP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+	[MDP_Y_CBCR_H2V2] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
+	[MDP_Y_CBCR_H2V2_ADRENO] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB,
+		CLR_CR, 8),
+	[MDP_YCRYCB_H2V1] = PPP_GET_PACK_PATTERN(CLR_Y,
+		CLR_CR, CLR_Y, CLR_CB, 8),
+	[MDP_Y_CBCR_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
+	[MDP_Y_CRCB_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+};
+
+const uint32_t dst_op_reg[MDP_IMGTYPE_LIMIT] = {
+	[MDP_Y_CRCB_H2V2] = PPP_OP_DST_CHROMA_420,
+	[MDP_Y_CBCR_H2V2] = PPP_OP_DST_CHROMA_420,
+	[MDP_Y_CBCR_H2V1] = PPP_OP_DST_CHROMA_H2V1,
+	[MDP_Y_CRCB_H2V1] = PPP_OP_DST_CHROMA_H2V1,
+	[MDP_YCRYCB_H2V1] = PPP_OP_DST_CHROMA_H2V1,
+};
+
+const uint32_t src_op_reg[MDP_IMGTYPE_LIMIT] = {
+	[MDP_Y_CRCB_H2V2] = PPP_OP_SRC_CHROMA_420 | PPP_OP_COLOR_SPACE_YCBCR,
+	[MDP_Y_CBCR_H2V2] = PPP_OP_SRC_CHROMA_420 | PPP_OP_COLOR_SPACE_YCBCR,
+	[MDP_Y_CBCR_H2V2_ADRENO] = PPP_OP_SRC_CHROMA_420 |
+			PPP_OP_COLOR_SPACE_YCBCR,
+	[MDP_Y_CBCR_H2V1] = PPP_OP_SRC_CHROMA_H2V1,
+	[MDP_Y_CRCB_H2V1] = PPP_OP_SRC_CHROMA_H2V1,
+	[MDP_YCRYCB_H2V1] = PPP_OP_SRC_CHROMA_H2V1,
+};
+
+const uint32_t bytes_per_pixel[MDP_IMGTYPE_LIMIT] = {
+	[MDP_RGB_565] = 2,
+	[MDP_BGR_565] = 2,
+	[MDP_RGB_888] = 3,
+	[MDP_BGR_888] = 3,
+	[MDP_XRGB_8888] = 4,
+	[MDP_ARGB_8888] = 4,
+	[MDP_RGBA_8888] = 4,
+	[MDP_BGRA_8888] = 4,
+	[MDP_RGBX_8888] = 4,
+	[MDP_Y_CBCR_H2V1] = 1,
+	[MDP_Y_CBCR_H2V2] = 1,
+	[MDP_Y_CBCR_H2V2_ADRENO] = 1,
+	[MDP_Y_CRCB_H2V1] = 1,
+	[MDP_Y_CRCB_H2V2] = 1,
+	[MDP_YCRYCB_H2V1] = 2,
+};
+
+const bool per_pixel_alpha[MDP_IMGTYPE_LIMIT] = {
+	[MDP_BGRA_8888] = true,
+	[MDP_RGBA_8888] = true,
+	[MDP_ARGB_8888] = true,
+};
+
+const bool multi_plane[MDP_IMGTYPE_LIMIT] = {
+	[MDP_Y_CRCB_H2V2] = true,
+	[MDP_Y_CBCR_H2V2] = true,
+	[MDP_Y_CBCR_H2V1] = true,
+	[MDP_Y_CRCB_H2V1] = true,
+};
+
+/* lut default */
+uint32_t default_pre_lut_val[PPP_LUT_MAX] = {
+	0x0,
+	0x151515,
+	0x1d1d1d,
+	0x232323,
+	0x272727,
+	0x2b2b2b,
+	0x2f2f2f,
+	0x333333,
+	0x363636,
+	0x393939,
+	0x3b3b3b,
+	0x3e3e3e,
+	0x404040,
+	0x434343,
+	0x454545,
+	0x474747,
+	0x494949,
+	0x4b4b4b,
+	0x4d4d4d,
+	0x4f4f4f,
+	0x515151,
+	0x535353,
+	0x555555,
+	0x565656,
+	0x585858,
+	0x5a5a5a,
+	0x5b5b5b,
+	0x5d5d5d,
+	0x5e5e5e,
+	0x606060,
+	0x616161,
+	0x636363,
+	0x646464,
+	0x666666,
+	0x676767,
+	0x686868,
+	0x6a6a6a,
+	0x6b6b6b,
+	0x6c6c6c,
+	0x6e6e6e,
+	0x6f6f6f,
+	0x707070,
+	0x717171,
+	0x727272,
+	0x747474,
+	0x757575,
+	0x767676,
+	0x777777,
+	0x787878,
+	0x797979,
+	0x7a7a7a,
+	0x7c7c7c,
+	0x7d7d7d,
+	0x7e7e7e,
+	0x7f7f7f,
+	0x808080,
+	0x818181,
+	0x828282,
+	0x838383,
+	0x848484,
+	0x858585,
+	0x868686,
+	0x878787,
+	0x888888,
+	0x898989,
+	0x8a8a8a,
+	0x8b8b8b,
+	0x8c8c8c,
+	0x8d8d8d,
+	0x8e8e8e,
+	0x8f8f8f,
+	0x8f8f8f,
+	0x909090,
+	0x919191,
+	0x929292,
+	0x939393,
+	0x949494,
+	0x959595,
+	0x969696,
+	0x969696,
+	0x979797,
+	0x989898,
+	0x999999,
+	0x9a9a9a,
+	0x9b9b9b,
+	0x9c9c9c,
+	0x9c9c9c,
+	0x9d9d9d,
+	0x9e9e9e,
+	0x9f9f9f,
+	0xa0a0a0,
+	0xa0a0a0,
+	0xa1a1a1,
+	0xa2a2a2,
+	0xa3a3a3,
+	0xa4a4a4,
+	0xa4a4a4,
+	0xa5a5a5,
+	0xa6a6a6,
+	0xa7a7a7,
+	0xa7a7a7,
+	0xa8a8a8,
+	0xa9a9a9,
+	0xaaaaaa,
+	0xaaaaaa,
+	0xababab,
+	0xacacac,
+	0xadadad,
+	0xadadad,
+	0xaeaeae,
+	0xafafaf,
+	0xafafaf,
+	0xb0b0b0,
+	0xb1b1b1,
+	0xb2b2b2,
+	0xb2b2b2,
+	0xb3b3b3,
+	0xb4b4b4,
+	0xb4b4b4,
+	0xb5b5b5,
+	0xb6b6b6,
+	0xb6b6b6,
+	0xb7b7b7,
+	0xb8b8b8,
+	0xb8b8b8,
+	0xb9b9b9,
+	0xbababa,
+	0xbababa,
+	0xbbbbbb,
+	0xbcbcbc,
+	0xbcbcbc,
+	0xbdbdbd,
+	0xbebebe,
+	0xbebebe,
+	0xbfbfbf,
+	0xc0c0c0,
+	0xc0c0c0,
+	0xc1c1c1,
+	0xc1c1c1,
+	0xc2c2c2,
+	0xc3c3c3,
+	0xc3c3c3,
+	0xc4c4c4,
+	0xc5c5c5,
+	0xc5c5c5,
+	0xc6c6c6,
+	0xc6c6c6,
+	0xc7c7c7,
+	0xc8c8c8,
+	0xc8c8c8,
+	0xc9c9c9,
+	0xc9c9c9,
+	0xcacaca,
+	0xcbcbcb,
+	0xcbcbcb,
+	0xcccccc,
+	0xcccccc,
+	0xcdcdcd,
+	0xcecece,
+	0xcecece,
+	0xcfcfcf,
+	0xcfcfcf,
+	0xd0d0d0,
+	0xd0d0d0,
+	0xd1d1d1,
+	0xd2d2d2,
+	0xd2d2d2,
+	0xd3d3d3,
+	0xd3d3d3,
+	0xd4d4d4,
+	0xd4d4d4,
+	0xd5d5d5,
+	0xd6d6d6,
+	0xd6d6d6,
+	0xd7d7d7,
+	0xd7d7d7,
+	0xd8d8d8,
+	0xd8d8d8,
+	0xd9d9d9,
+	0xd9d9d9,
+	0xdadada,
+	0xdbdbdb,
+	0xdbdbdb,
+	0xdcdcdc,
+	0xdcdcdc,
+	0xdddddd,
+	0xdddddd,
+	0xdedede,
+	0xdedede,
+	0xdfdfdf,
+	0xdfdfdf,
+	0xe0e0e0,
+	0xe0e0e0,
+	0xe1e1e1,
+	0xe1e1e1,
+	0xe2e2e2,
+	0xe3e3e3,
+	0xe3e3e3,
+	0xe4e4e4,
+	0xe4e4e4,
+	0xe5e5e5,
+	0xe5e5e5,
+	0xe6e6e6,
+	0xe6e6e6,
+	0xe7e7e7,
+	0xe7e7e7,
+	0xe8e8e8,
+	0xe8e8e8,
+	0xe9e9e9,
+	0xe9e9e9,
+	0xeaeaea,
+	0xeaeaea,
+	0xebebeb,
+	0xebebeb,
+	0xececec,
+	0xececec,
+	0xededed,
+	0xededed,
+	0xeeeeee,
+	0xeeeeee,
+	0xefefef,
+	0xefefef,
+	0xf0f0f0,
+	0xf0f0f0,
+	0xf1f1f1,
+	0xf1f1f1,
+	0xf2f2f2,
+	0xf2f2f2,
+	0xf2f2f2,
+	0xf3f3f3,
+	0xf3f3f3,
+	0xf4f4f4,
+	0xf4f4f4,
+	0xf5f5f5,
+	0xf5f5f5,
+	0xf6f6f6,
+	0xf6f6f6,
+	0xf7f7f7,
+	0xf7f7f7,
+	0xf8f8f8,
+	0xf8f8f8,
+	0xf9f9f9,
+	0xf9f9f9,
+	0xfafafa,
+	0xfafafa,
+	0xfafafa,
+	0xfbfbfb,
+	0xfbfbfb,
+	0xfcfcfc,
+	0xfcfcfc,
+	0xfdfdfd,
+	0xfdfdfd,
+	0xfefefe,
+	0xfefefe,
+	0xffffff,
+	0xffffff,
+};
+
+uint32_t default_post_lut_val[PPP_LUT_MAX] = {
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x0,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x10101,
+	0x20202,
+	0x20202,
+	0x20202,
+	0x20202,
+	0x20202,
+	0x20202,
+	0x30303,
+	0x30303,
+	0x30303,
+	0x30303,
+	0x30303,
+	0x40404,
+	0x40404,
+	0x40404,
+	0x40404,
+	0x40404,
+	0x50505,
+	0x50505,
+	0x50505,
+	0x50505,
+	0x60606,
+	0x60606,
+	0x60606,
+	0x70707,
+	0x70707,
+	0x70707,
+	0x70707,
+	0x80808,
+	0x80808,
+	0x80808,
+	0x90909,
+	0x90909,
+	0xa0a0a,
+	0xa0a0a,
+	0xa0a0a,
+	0xb0b0b,
+	0xb0b0b,
+	0xb0b0b,
+	0xc0c0c,
+	0xc0c0c,
+	0xd0d0d,
+	0xd0d0d,
+	0xe0e0e,
+	0xe0e0e,
+	0xe0e0e,
+	0xf0f0f,
+	0xf0f0f,
+	0x101010,
+	0x101010,
+	0x111111,
+	0x111111,
+	0x121212,
+	0x121212,
+	0x131313,
+	0x131313,
+	0x141414,
+	0x151515,
+	0x151515,
+	0x161616,
+	0x161616,
+	0x171717,
+	0x171717,
+	0x181818,
+	0x191919,
+	0x191919,
+	0x1a1a1a,
+	0x1b1b1b,
+	0x1b1b1b,
+	0x1c1c1c,
+	0x1c1c1c,
+	0x1d1d1d,
+	0x1e1e1e,
+	0x1f1f1f,
+	0x1f1f1f,
+	0x202020,
+	0x212121,
+	0x212121,
+	0x222222,
+	0x232323,
+	0x242424,
+	0x242424,
+	0x252525,
+	0x262626,
+	0x272727,
+	0x272727,
+	0x282828,
+	0x292929,
+	0x2a2a2a,
+	0x2b2b2b,
+	0x2c2c2c,
+	0x2c2c2c,
+	0x2d2d2d,
+	0x2e2e2e,
+	0x2f2f2f,
+	0x303030,
+	0x313131,
+	0x323232,
+	0x333333,
+	0x333333,
+	0x343434,
+	0x353535,
+	0x363636,
+	0x373737,
+	0x383838,
+	0x393939,
+	0x3a3a3a,
+	0x3b3b3b,
+	0x3c3c3c,
+	0x3d3d3d,
+	0x3e3e3e,
+	0x3f3f3f,
+	0x404040,
+	0x414141,
+	0x424242,
+	0x434343,
+	0x444444,
+	0x464646,
+	0x474747,
+	0x484848,
+	0x494949,
+	0x4a4a4a,
+	0x4b4b4b,
+	0x4c4c4c,
+	0x4d4d4d,
+	0x4f4f4f,
+	0x505050,
+	0x515151,
+	0x525252,
+	0x535353,
+	0x545454,
+	0x565656,
+	0x575757,
+	0x585858,
+	0x595959,
+	0x5b5b5b,
+	0x5c5c5c,
+	0x5d5d5d,
+	0x5e5e5e,
+	0x606060,
+	0x616161,
+	0x626262,
+	0x646464,
+	0x656565,
+	0x666666,
+	0x686868,
+	0x696969,
+	0x6a6a6a,
+	0x6c6c6c,
+	0x6d6d6d,
+	0x6f6f6f,
+	0x707070,
+	0x717171,
+	0x737373,
+	0x747474,
+	0x767676,
+	0x777777,
+	0x797979,
+	0x7a7a7a,
+	0x7c7c7c,
+	0x7d7d7d,
+	0x7f7f7f,
+	0x808080,
+	0x828282,
+	0x838383,
+	0x858585,
+	0x868686,
+	0x888888,
+	0x898989,
+	0x8b8b8b,
+	0x8d8d8d,
+	0x8e8e8e,
+	0x909090,
+	0x919191,
+	0x939393,
+	0x959595,
+	0x969696,
+	0x989898,
+	0x9a9a9a,
+	0x9b9b9b,
+	0x9d9d9d,
+	0x9f9f9f,
+	0xa1a1a1,
+	0xa2a2a2,
+	0xa4a4a4,
+	0xa6a6a6,
+	0xa7a7a7,
+	0xa9a9a9,
+	0xababab,
+	0xadadad,
+	0xafafaf,
+	0xb0b0b0,
+	0xb2b2b2,
+	0xb4b4b4,
+	0xb6b6b6,
+	0xb8b8b8,
+	0xbababa,
+	0xbbbbbb,
+	0xbdbdbd,
+	0xbfbfbf,
+	0xc1c1c1,
+	0xc3c3c3,
+	0xc5c5c5,
+	0xc7c7c7,
+	0xc9c9c9,
+	0xcbcbcb,
+	0xcdcdcd,
+	0xcfcfcf,
+	0xd1d1d1,
+	0xd3d3d3,
+	0xd5d5d5,
+	0xd7d7d7,
+	0xd9d9d9,
+	0xdbdbdb,
+	0xdddddd,
+	0xdfdfdf,
+	0xe1e1e1,
+	0xe3e3e3,
+	0xe5e5e5,
+	0xe7e7e7,
+	0xe9e9e9,
+	0xebebeb,
+	0xeeeeee,
+	0xf0f0f0,
+	0xf2f2f2,
+	0xf4f4f4,
+	0xf6f6f6,
+	0xf8f8f8,
+	0xfbfbfb,
+	0xfdfdfd,
+	0xffffff,
+};
+
+struct ppp_csc_table rgb2yuv = {
+	.fwd_matrix = {
+		0x83,
+		0x102,
+		0x32,
+		0xffb5,
+		0xff6c,
+		0xe1,
+		0xe1,
+		0xff45,
+		0xffdc,
+	},
+	.rev_matrix = {
+		0x254,
+		0x0,
+		0x331,
+		0x254,
+		0xff38,
+		0xfe61,
+		0x254,
+		0x409,
+		0x0,
+	},
+	.bv = {
+		0x10,
+		0x80,
+		0x80,
+	},
+	.lv = {
+		0x10,
+		0xeb,
+		0x10,
+		0xf0,
+	},
+};
+
+struct ppp_csc_table default_table2 = {
+	.fwd_matrix = {
+		0x5d,
+		0x13a,
+		0x20,
+		0xffcd,
+		0xff54,
+		0xe1,
+		0xe1,
+		0xff35,
+	},
+	.rev_matrix = {
+		0x254,
+		0x0,
+		0x396,
+		0x254,
+		0xff94,
+		0xfef0,
+		0x254,
+		0x43a,
+		0x0,
+	},
+	.bv = {
+		0x10,
+		0x80,
+		0x80,
+	},
+	.lv = {
+		0x10,
+		0xeb,
+		0x10,
+		0xf0,
+	},
+};
+
+const struct ppp_table upscale_table[PPP_UPSCALE_MAX] = {
+	{ 0x5fffc, 0x0 },
+	{ 0x50200, 0x7fc00000 },
+	{ 0x5fffc, 0xff80000d },
+	{ 0x50204, 0x7ec003f9 },
+	{ 0x5fffc, 0xfec0001c },
+	{ 0x50208, 0x7d4003f3 },
+	{ 0x5fffc, 0xfe40002b },
+	{ 0x5020c, 0x7b8003ed },
+	{ 0x5fffc, 0xfd80003c },
+	{ 0x50210, 0x794003e8 },
+	{ 0x5fffc, 0xfcc0004d },
+	{ 0x50214, 0x76c003e4 },
+	{ 0x5fffc, 0xfc40005f },
+	{ 0x50218, 0x73c003e0 },
+	{ 0x5fffc, 0xfb800071 },
+	{ 0x5021c, 0x708003de },
+	{ 0x5fffc, 0xfac00085 },
+	{ 0x50220, 0x6d0003db },
+	{ 0x5fffc, 0xfa000098 },
+	{ 0x50224, 0x698003d9 },
+	{ 0x5fffc, 0xf98000ac },
+	{ 0x50228, 0x654003d8 },
+	{ 0x5fffc, 0xf8c000c1 },
+	{ 0x5022c, 0x610003d7 },
+	{ 0x5fffc, 0xf84000d5 },
+	{ 0x50230, 0x5c8003d7 },
+	{ 0x5fffc, 0xf7c000e9 },
+	{ 0x50234, 0x580003d7 },
+	{ 0x5fffc, 0xf74000fd },
+	{ 0x50238, 0x534003d8 },
+	{ 0x5fffc, 0xf6c00112 },
+	{ 0x5023c, 0x4e8003d8 },
+	{ 0x5fffc, 0xf6800126 },
+	{ 0x50240, 0x494003da },
+	{ 0x5fffc, 0xf600013a },
+	{ 0x50244, 0x448003db },
+	{ 0x5fffc, 0xf600014d },
+	{ 0x50248, 0x3f4003dd },
+	{ 0x5fffc, 0xf5c00160 },
+	{ 0x5024c, 0x3a4003df },
+	{ 0x5fffc, 0xf5c00172 },
+	{ 0x50250, 0x354003e1 },
+	{ 0x5fffc, 0xf5c00184 },
+	{ 0x50254, 0x304003e3 },
+	{ 0x5fffc, 0xf6000195 },
+	{ 0x50258, 0x2b0003e6 },
+	{ 0x5fffc, 0xf64001a6 },
+	{ 0x5025c, 0x260003e8 },
+	{ 0x5fffc, 0xf6c001b4 },
+	{ 0x50260, 0x214003eb },
+	{ 0x5fffc, 0xf78001c2 },
+	{ 0x50264, 0x1c4003ee },
+	{ 0x5fffc, 0xf80001cf },
+	{ 0x50268, 0x17c003f1 },
+	{ 0x5fffc, 0xf90001db },
+	{ 0x5026c, 0x134003f3 },
+	{ 0x5fffc, 0xfa0001e5 },
+	{ 0x50270, 0xf0003f6 },
+	{ 0x5fffc, 0xfb4001ee },
+	{ 0x50274, 0xac003f9 },
+	{ 0x5fffc, 0xfcc001f5 },
+	{ 0x50278, 0x70003fb },
+	{ 0x5fffc, 0xfe4001fb },
+	{ 0x5027c, 0x34003fe },
+};
+
+const struct ppp_table mdp_gaussian_blur_table[PPP_BLUR_SCALE_MAX] = {
+	/* max variance */
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50280, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50284, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50288, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5028c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50290, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50294, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50298, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5029c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502a8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502ac, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502b8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502bc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502c8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502cc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502d8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502dc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502e8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502ec, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f0, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f4, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502f8, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x502fc, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50300, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50304, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50308, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5030c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50310, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50314, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50318, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5031c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50320, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50324, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50328, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5032c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50330, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50334, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50338, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5033c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50340, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50344, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50348, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5034c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50350, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50354, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50358, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5035c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50360, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50364, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50368, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5036c, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50370, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50374, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x50378, 0x20000080 },
+	{ 0x5fffc, 0x20000080 },
+	{ 0x5037c, 0x20000080 },
+};
+
+const struct ppp_table downscale_x_table_pt2topt4[] = {
+	{ 0x5fffc, 0x740008c },
+	{ 0x50280, 0x33800088 },
+	{ 0x5fffc, 0x800008e },
+	{ 0x50284, 0x33400084 },
+	{ 0x5fffc, 0x8400092 },
+	{ 0x50288, 0x33000080 },
+	{ 0x5fffc, 0x9000094 },
+	{ 0x5028c, 0x3300007b },
+	{ 0x5fffc, 0x9c00098 },
+	{ 0x50290, 0x32400077 },
+	{ 0x5fffc, 0xa40009b },
+	{ 0x50294, 0x32000073 },
+	{ 0x5fffc, 0xb00009d },
+	{ 0x50298, 0x31c0006f },
+	{ 0x5fffc, 0xbc000a0 },
+	{ 0x5029c, 0x3140006b },
+	{ 0x5fffc, 0xc8000a2 },
+	{ 0x502a0, 0x31000067 },
+	{ 0x5fffc, 0xd8000a5 },
+	{ 0x502a4, 0x30800062 },
+	{ 0x5fffc, 0xe4000a8 },
+	{ 0x502a8, 0x2fc0005f },
+	{ 0x5fffc, 0xec000aa },
+	{ 0x502ac, 0x2fc0005b },
+	{ 0x5fffc, 0xf8000ad },
+	{ 0x502b0, 0x2f400057 },
+	{ 0x5fffc, 0x108000b0 },
+	{ 0x502b4, 0x2e400054 },
+	{ 0x5fffc, 0x114000b2 },
+	{ 0x502b8, 0x2e000050 },
+	{ 0x5fffc, 0x124000b4 },
+	{ 0x502bc, 0x2d80004c },
+	{ 0x5fffc, 0x130000b6 },
+	{ 0x502c0, 0x2d000049 },
+	{ 0x5fffc, 0x140000b8 },
+	{ 0x502c4, 0x2c800045 },
+	{ 0x5fffc, 0x150000b9 },
+	{ 0x502c8, 0x2c000042 },
+	{ 0x5fffc, 0x15c000bd },
+	{ 0x502cc, 0x2b40003e },
+	{ 0x5fffc, 0x16c000bf },
+	{ 0x502d0, 0x2a80003b },
+	{ 0x5fffc, 0x17c000bf },
+	{ 0x502d4, 0x2a000039 },
+	{ 0x5fffc, 0x188000c2 },
+	{ 0x502d8, 0x29400036 },
+	{ 0x5fffc, 0x19c000c4 },
+	{ 0x502dc, 0x28800032 },
+	{ 0x5fffc, 0x1ac000c5 },
+	{ 0x502e0, 0x2800002f },
+	{ 0x5fffc, 0x1bc000c7 },
+	{ 0x502e4, 0x2740002c },
+	{ 0x5fffc, 0x1cc000c8 },
+	{ 0x502e8, 0x26c00029 },
+	{ 0x5fffc, 0x1dc000c9 },
+	{ 0x502ec, 0x26000027 },
+	{ 0x5fffc, 0x1ec000cc },
+	{ 0x502f0, 0x25000024 },
+	{ 0x5fffc, 0x200000cc },
+	{ 0x502f4, 0x24800021 },
+	{ 0x5fffc, 0x210000cd },
+	{ 0x502f8, 0x23800020 },
+	{ 0x5fffc, 0x220000ce },
+	{ 0x502fc, 0x2300001d },
+};
+
+static const struct ppp_table downscale_x_table_pt4topt6[] = {
+	{ 0x5fffc, 0x740008c },
+	{ 0x50280, 0x33800088 },
+	{ 0x5fffc, 0x800008e },
+	{ 0x50284, 0x33400084 },
+	{ 0x5fffc, 0x8400092 },
+	{ 0x50288, 0x33000080 },
+	{ 0x5fffc, 0x9000094 },
+	{ 0x5028c, 0x3300007b },
+	{ 0x5fffc, 0x9c00098 },
+	{ 0x50290, 0x32400077 },
+	{ 0x5fffc, 0xa40009b },
+	{ 0x50294, 0x32000073 },
+	{ 0x5fffc, 0xb00009d },
+	{ 0x50298, 0x31c0006f },
+	{ 0x5fffc, 0xbc000a0 },
+	{ 0x5029c, 0x3140006b },
+	{ 0x5fffc, 0xc8000a2 },
+	{ 0x502a0, 0x31000067 },
+	{ 0x5fffc, 0xd8000a5 },
+	{ 0x502a4, 0x30800062 },
+	{ 0x5fffc, 0xe4000a8 },
+	{ 0x502a8, 0x2fc0005f },
+	{ 0x5fffc, 0xec000aa },
+	{ 0x502ac, 0x2fc0005b },
+	{ 0x5fffc, 0xf8000ad },
+	{ 0x502b0, 0x2f400057 },
+	{ 0x5fffc, 0x108000b0 },
+	{ 0x502b4, 0x2e400054 },
+	{ 0x5fffc, 0x114000b2 },
+	{ 0x502b8, 0x2e000050 },
+	{ 0x5fffc, 0x124000b4 },
+	{ 0x502bc, 0x2d80004c },
+	{ 0x5fffc, 0x130000b6 },
+	{ 0x502c0, 0x2d000049 },
+	{ 0x5fffc, 0x140000b8 },
+	{ 0x502c4, 0x2c800045 },
+	{ 0x5fffc, 0x150000b9 },
+	{ 0x502c8, 0x2c000042 },
+	{ 0x5fffc, 0x15c000bd },
+	{ 0x502cc, 0x2b40003e },
+	{ 0x5fffc, 0x16c000bf },
+	{ 0x502d0, 0x2a80003b },
+	{ 0x5fffc, 0x17c000bf },
+	{ 0x502d4, 0x2a000039 },
+	{ 0x5fffc, 0x188000c2 },
+	{ 0x502d8, 0x29400036 },
+	{ 0x5fffc, 0x19c000c4 },
+	{ 0x502dc, 0x28800032 },
+	{ 0x5fffc, 0x1ac000c5 },
+	{ 0x502e0, 0x2800002f },
+	{ 0x5fffc, 0x1bc000c7 },
+	{ 0x502e4, 0x2740002c },
+	{ 0x5fffc, 0x1cc000c8 },
+	{ 0x502e8, 0x26c00029 },
+	{ 0x5fffc, 0x1dc000c9 },
+	{ 0x502ec, 0x26000027 },
+	{ 0x5fffc, 0x1ec000cc },
+	{ 0x502f0, 0x25000024 },
+	{ 0x5fffc, 0x200000cc },
+	{ 0x502f4, 0x24800021 },
+	{ 0x5fffc, 0x210000cd },
+	{ 0x502f8, 0x23800020 },
+	{ 0x5fffc, 0x220000ce },
+	{ 0x502fc, 0x2300001d },
+};
+
+static const struct ppp_table downscale_x_table_pt6topt8[] = {
+	{ 0x5fffc, 0xfe000070 },
+	{ 0x50280, 0x4bc00068 },
+	{ 0x5fffc, 0xfe000078 },
+	{ 0x50284, 0x4bc00060 },
+	{ 0x5fffc, 0xfe000080 },
+	{ 0x50288, 0x4b800059 },
+	{ 0x5fffc, 0xfe000089 },
+	{ 0x5028c, 0x4b000052 },
+	{ 0x5fffc, 0xfe400091 },
+	{ 0x50290, 0x4a80004b },
+	{ 0x5fffc, 0xfe40009a },
+	{ 0x50294, 0x4a000044 },
+	{ 0x5fffc, 0xfe8000a3 },
+	{ 0x50298, 0x4940003d },
+	{ 0x5fffc, 0xfec000ac },
+	{ 0x5029c, 0x48400037 },
+	{ 0x5fffc, 0xff0000b4 },
+	{ 0x502a0, 0x47800031 },
+	{ 0x5fffc, 0xff8000bd },
+	{ 0x502a4, 0x4640002b },
+	{ 0x5fffc, 0xc5 },
+	{ 0x502a8, 0x45000026 },
+	{ 0x5fffc, 0x8000ce },
+	{ 0x502ac, 0x43800021 },
+	{ 0x5fffc, 0x10000d6 },
+	{ 0x502b0, 0x4240001c },
+	{ 0x5fffc, 0x18000df },
+	{ 0x502b4, 0x40800018 },
+	{ 0x5fffc, 0x24000e6 },
+	{ 0x502b8, 0x3f000014 },
+	{ 0x5fffc, 0x30000ee },
+	{ 0x502bc, 0x3d400010 },
+	{ 0x5fffc, 0x40000f5 },
+	{ 0x502c0, 0x3b80000c },
+	{ 0x5fffc, 0x50000fc },
+	{ 0x502c4, 0x39800009 },
+	{ 0x5fffc, 0x6000102 },
+	{ 0x502c8, 0x37c00006 },
+	{ 0x5fffc, 0x7000109 },
+	{ 0x502cc, 0x35800004 },
+	{ 0x5fffc, 0x840010e },
+	{ 0x502d0, 0x33800002 },
+	{ 0x5fffc, 0x9800114 },
+	{ 0x502d4, 0x31400000 },
+	{ 0x5fffc, 0xac00119 },
+	{ 0x502d8, 0x2f4003fe },
+	{ 0x5fffc, 0xc40011e },
+	{ 0x502dc, 0x2d0003fc },
+	{ 0x5fffc, 0xdc00121 },
+	{ 0x502e0, 0x2b0003fb },
+	{ 0x5fffc, 0xf400125 },
+	{ 0x502e4, 0x28c003fa },
+	{ 0x5fffc, 0x11000128 },
+	{ 0x502e8, 0x268003f9 },
+	{ 0x5fffc, 0x12c0012a },
+	{ 0x502ec, 0x244003f9 },
+	{ 0x5fffc, 0x1480012c },
+	{ 0x502f0, 0x224003f8 },
+	{ 0x5fffc, 0x1640012e },
+	{ 0x502f4, 0x200003f8 },
+	{ 0x5fffc, 0x1800012f },
+	{ 0x502f8, 0x1e0003f8 },
+	{ 0x5fffc, 0x1a00012f },
+	{ 0x502fc, 0x1c0003f8 },
+};
+
+static const struct ppp_table downscale_x_table_pt8topt1[] = {
+	{ 0x5fffc, 0x0 },
+	{ 0x50280, 0x7fc00000 },
+	{ 0x5fffc, 0xff80000d },
+	{ 0x50284, 0x7ec003f9 },
+	{ 0x5fffc, 0xfec0001c },
+	{ 0x50288, 0x7d4003f3 },
+	{ 0x5fffc, 0xfe40002b },
+	{ 0x5028c, 0x7b8003ed },
+	{ 0x5fffc, 0xfd80003c },
+	{ 0x50290, 0x794003e8 },
+	{ 0x5fffc, 0xfcc0004d },
+	{ 0x50294, 0x76c003e4 },
+	{ 0x5fffc, 0xfc40005f },
+	{ 0x50298, 0x73c003e0 },
+	{ 0x5fffc, 0xfb800071 },
+	{ 0x5029c, 0x708003de },
+	{ 0x5fffc, 0xfac00085 },
+	{ 0x502a0, 0x6d0003db },
+	{ 0x5fffc, 0xfa000098 },
+	{ 0x502a4, 0x698003d9 },
+	{ 0x5fffc, 0xf98000ac },
+	{ 0x502a8, 0x654003d8 },
+	{ 0x5fffc, 0xf8c000c1 },
+	{ 0x502ac, 0x610003d7 },
+	{ 0x5fffc, 0xf84000d5 },
+	{ 0x502b0, 0x5c8003d7 },
+	{ 0x5fffc, 0xf7c000e9 },
+	{ 0x502b4, 0x580003d7 },
+	{ 0x5fffc, 0xf74000fd },
+	{ 0x502b8, 0x534003d8 },
+	{ 0x5fffc, 0xf6c00112 },
+	{ 0x502bc, 0x4e8003d8 },
+	{ 0x5fffc, 0xf6800126 },
+	{ 0x502c0, 0x494003da },
+	{ 0x5fffc, 0xf600013a },
+	{ 0x502c4, 0x448003db },
+	{ 0x5fffc, 0xf600014d },
+	{ 0x502c8, 0x3f4003dd },
+	{ 0x5fffc, 0xf5c00160 },
+	{ 0x502cc, 0x3a4003df },
+	{ 0x5fffc, 0xf5c00172 },
+	{ 0x502d0, 0x354003e1 },
+	{ 0x5fffc, 0xf5c00184 },
+	{ 0x502d4, 0x304003e3 },
+	{ 0x5fffc, 0xf6000195 },
+	{ 0x502d8, 0x2b0003e6 },
+	{ 0x5fffc, 0xf64001a6 },
+	{ 0x502dc, 0x260003e8 },
+	{ 0x5fffc, 0xf6c001b4 },
+	{ 0x502e0, 0x214003eb },
+	{ 0x5fffc, 0xf78001c2 },
+	{ 0x502e4, 0x1c4003ee },
+	{ 0x5fffc, 0xf80001cf },
+	{ 0x502e8, 0x17c003f1 },
+	{ 0x5fffc, 0xf90001db },
+	{ 0x502ec, 0x134003f3 },
+	{ 0x5fffc, 0xfa0001e5 },
+	{ 0x502f0, 0xf0003f6 },
+	{ 0x5fffc, 0xfb4001ee },
+	{ 0x502f4, 0xac003f9 },
+	{ 0x5fffc, 0xfcc001f5 },
+	{ 0x502f8, 0x70003fb },
+	{ 0x5fffc, 0xfe4001fb },
+	{ 0x502fc, 0x34003fe },
+};
+
+static const struct ppp_table *downscale_x_table[PPP_DOWNSCALE_MAX] = {
+	[PPP_DOWNSCALE_PT2TOPT4] = downscale_x_table_pt2topt4,
+	[PPP_DOWNSCALE_PT4TOPT6] = downscale_x_table_pt4topt6,
+	[PPP_DOWNSCALE_PT6TOPT8] = downscale_x_table_pt6topt8,
+	[PPP_DOWNSCALE_PT8TOPT1] = downscale_x_table_pt8topt1,
+};
+
+static const struct ppp_table downscale_y_table_pt2topt4[] = {
+	{ 0x5fffc, 0x740008c },
+	{ 0x50300, 0x33800088 },
+	{ 0x5fffc, 0x800008e },
+	{ 0x50304, 0x33400084 },
+	{ 0x5fffc, 0x8400092 },
+	{ 0x50308, 0x33000080 },
+	{ 0x5fffc, 0x9000094 },
+	{ 0x5030c, 0x3300007b },
+	{ 0x5fffc, 0x9c00098 },
+	{ 0x50310, 0x32400077 },
+	{ 0x5fffc, 0xa40009b },
+	{ 0x50314, 0x32000073 },
+	{ 0x5fffc, 0xb00009d },
+	{ 0x50318, 0x31c0006f },
+	{ 0x5fffc, 0xbc000a0 },
+	{ 0x5031c, 0x3140006b },
+	{ 0x5fffc, 0xc8000a2 },
+	{ 0x50320, 0x31000067 },
+	{ 0x5fffc, 0xd8000a5 },
+	{ 0x50324, 0x30800062 },
+	{ 0x5fffc, 0xe4000a8 },
+	{ 0x50328, 0x2fc0005f },
+	{ 0x5fffc, 0xec000aa },
+	{ 0x5032c, 0x2fc0005b },
+	{ 0x5fffc, 0xf8000ad },
+	{ 0x50330, 0x2f400057 },
+	{ 0x5fffc, 0x108000b0 },
+	{ 0x50334, 0x2e400054 },
+	{ 0x5fffc, 0x114000b2 },
+	{ 0x50338, 0x2e000050 },
+	{ 0x5fffc, 0x124000b4 },
+	{ 0x5033c, 0x2d80004c },
+	{ 0x5fffc, 0x130000b6 },
+	{ 0x50340, 0x2d000049 },
+	{ 0x5fffc, 0x140000b8 },
+	{ 0x50344, 0x2c800045 },
+	{ 0x5fffc, 0x150000b9 },
+	{ 0x50348, 0x2c000042 },
+	{ 0x5fffc, 0x15c000bd },
+	{ 0x5034c, 0x2b40003e },
+	{ 0x5fffc, 0x16c000bf },
+	{ 0x50350, 0x2a80003b },
+	{ 0x5fffc, 0x17c000bf },
+	{ 0x50354, 0x2a000039 },
+	{ 0x5fffc, 0x188000c2 },
+	{ 0x50358, 0x29400036 },
+	{ 0x5fffc, 0x19c000c4 },
+	{ 0x5035c, 0x28800032 },
+	{ 0x5fffc, 0x1ac000c5 },
+	{ 0x50360, 0x2800002f },
+	{ 0x5fffc, 0x1bc000c7 },
+	{ 0x50364, 0x2740002c },
+	{ 0x5fffc, 0x1cc000c8 },
+	{ 0x50368, 0x26c00029 },
+	{ 0x5fffc, 0x1dc000c9 },
+	{ 0x5036c, 0x26000027 },
+	{ 0x5fffc, 0x1ec000cc },
+	{ 0x50370, 0x25000024 },
+	{ 0x5fffc, 0x200000cc },
+	{ 0x50374, 0x24800021 },
+	{ 0x5fffc, 0x210000cd },
+	{ 0x50378, 0x23800020 },
+	{ 0x5fffc, 0x220000ce },
+	{ 0x5037c, 0x2300001d },
+};
+
+static const struct ppp_table downscale_y_table_pt4topt6[] = {
+	{ 0x5fffc, 0x740008c },
+	{ 0x50300, 0x33800088 },
+	{ 0x5fffc, 0x800008e },
+	{ 0x50304, 0x33400084 },
+	{ 0x5fffc, 0x8400092 },
+	{ 0x50308, 0x33000080 },
+	{ 0x5fffc, 0x9000094 },
+	{ 0x5030c, 0x3300007b },
+	{ 0x5fffc, 0x9c00098 },
+	{ 0x50310, 0x32400077 },
+	{ 0x5fffc, 0xa40009b },
+	{ 0x50314, 0x32000073 },
+	{ 0x5fffc, 0xb00009d },
+	{ 0x50318, 0x31c0006f },
+	{ 0x5fffc, 0xbc000a0 },
+	{ 0x5031c, 0x3140006b },
+	{ 0x5fffc, 0xc8000a2 },
+	{ 0x50320, 0x31000067 },
+	{ 0x5fffc, 0xd8000a5 },
+	{ 0x50324, 0x30800062 },
+	{ 0x5fffc, 0xe4000a8 },
+	{ 0x50328, 0x2fc0005f },
+	{ 0x5fffc, 0xec000aa },
+	{ 0x5032c, 0x2fc0005b },
+	{ 0x5fffc, 0xf8000ad },
+	{ 0x50330, 0x2f400057 },
+	{ 0x5fffc, 0x108000b0 },
+	{ 0x50334, 0x2e400054 },
+	{ 0x5fffc, 0x114000b2 },
+	{ 0x50338, 0x2e000050 },
+	{ 0x5fffc, 0x124000b4 },
+	{ 0x5033c, 0x2d80004c },
+	{ 0x5fffc, 0x130000b6 },
+	{ 0x50340, 0x2d000049 },
+	{ 0x5fffc, 0x140000b8 },
+	{ 0x50344, 0x2c800045 },
+	{ 0x5fffc, 0x150000b9 },
+	{ 0x50348, 0x2c000042 },
+	{ 0x5fffc, 0x15c000bd },
+	{ 0x5034c, 0x2b40003e },
+	{ 0x5fffc, 0x16c000bf },
+	{ 0x50350, 0x2a80003b },
+	{ 0x5fffc, 0x17c000bf },
+	{ 0x50354, 0x2a000039 },
+	{ 0x5fffc, 0x188000c2 },
+	{ 0x50358, 0x29400036 },
+	{ 0x5fffc, 0x19c000c4 },
+	{ 0x5035c, 0x28800032 },
+	{ 0x5fffc, 0x1ac000c5 },
+	{ 0x50360, 0x2800002f },
+	{ 0x5fffc, 0x1bc000c7 },
+	{ 0x50364, 0x2740002c },
+	{ 0x5fffc, 0x1cc000c8 },
+	{ 0x50368, 0x26c00029 },
+	{ 0x5fffc, 0x1dc000c9 },
+	{ 0x5036c, 0x26000027 },
+	{ 0x5fffc, 0x1ec000cc },
+	{ 0x50370, 0x25000024 },
+	{ 0x5fffc, 0x200000cc },
+	{ 0x50374, 0x24800021 },
+	{ 0x5fffc, 0x210000cd },
+	{ 0x50378, 0x23800020 },
+	{ 0x5fffc, 0x220000ce },
+	{ 0x5037c, 0x2300001d },
+};
+
+static const struct ppp_table downscale_y_table_pt6topt8[] = {
+	{ 0x5fffc, 0xfe000070 },
+	{ 0x50300, 0x4bc00068 },
+	{ 0x5fffc, 0xfe000078 },
+	{ 0x50304, 0x4bc00060 },
+	{ 0x5fffc, 0xfe000080 },
+	{ 0x50308, 0x4b800059 },
+	{ 0x5fffc, 0xfe000089 },
+	{ 0x5030c, 0x4b000052 },
+	{ 0x5fffc, 0xfe400091 },
+	{ 0x50310, 0x4a80004b },
+	{ 0x5fffc, 0xfe40009a },
+	{ 0x50314, 0x4a000044 },
+	{ 0x5fffc, 0xfe8000a3 },
+	{ 0x50318, 0x4940003d },
+	{ 0x5fffc, 0xfec000ac },
+	{ 0x5031c, 0x48400037 },
+	{ 0x5fffc, 0xff0000b4 },
+	{ 0x50320, 0x47800031 },
+	{ 0x5fffc, 0xff8000bd },
+	{ 0x50324, 0x4640002b },
+	{ 0x5fffc, 0xc5 },
+	{ 0x50328, 0x45000026 },
+	{ 0x5fffc, 0x8000ce },
+	{ 0x5032c, 0x43800021 },
+	{ 0x5fffc, 0x10000d6 },
+	{ 0x50330, 0x4240001c },
+	{ 0x5fffc, 0x18000df },
+	{ 0x50334, 0x40800018 },
+	{ 0x5fffc, 0x24000e6 },
+	{ 0x50338, 0x3f000014 },
+	{ 0x5fffc, 0x30000ee },
+	{ 0x5033c, 0x3d400010 },
+	{ 0x5fffc, 0x40000f5 },
+	{ 0x50340, 0x3b80000c },
+	{ 0x5fffc, 0x50000fc },
+	{ 0x50344, 0x39800009 },
+	{ 0x5fffc, 0x6000102 },
+	{ 0x50348, 0x37c00006 },
+	{ 0x5fffc, 0x7000109 },
+	{ 0x5034c, 0x35800004 },
+	{ 0x5fffc, 0x840010e },
+	{ 0x50350, 0x33800002 },
+	{ 0x5fffc, 0x9800114 },
+	{ 0x50354, 0x31400000 },
+	{ 0x5fffc, 0xac00119 },
+	{ 0x50358, 0x2f4003fe },
+	{ 0x5fffc, 0xc40011e },
+	{ 0x5035c, 0x2d0003fc },
+	{ 0x5fffc, 0xdc00121 },
+	{ 0x50360, 0x2b0003fb },
+	{ 0x5fffc, 0xf400125 },
+	{ 0x50364, 0x28c003fa },
+	{ 0x5fffc, 0x11000128 },
+	{ 0x50368, 0x268003f9 },
+	{ 0x5fffc, 0x12c0012a },
+	{ 0x5036c, 0x244003f9 },
+	{ 0x5fffc, 0x1480012c },
+	{ 0x50370, 0x224003f8 },
+	{ 0x5fffc, 0x1640012e },
+	{ 0x50374, 0x200003f8 },
+	{ 0x5fffc, 0x1800012f },
+	{ 0x50378, 0x1e0003f8 },
+	{ 0x5fffc, 0x1a00012f },
+	{ 0x5037c, 0x1c0003f8 },
+};
+
+static const struct ppp_table downscale_y_table_pt8topt1[] = {
+	{ 0x5fffc, 0x0 },
+	{ 0x50300, 0x7fc00000 },
+	{ 0x5fffc, 0xff80000d },
+	{ 0x50304, 0x7ec003f9 },
+	{ 0x5fffc, 0xfec0001c },
+	{ 0x50308, 0x7d4003f3 },
+	{ 0x5fffc, 0xfe40002b },
+	{ 0x5030c, 0x7b8003ed },
+	{ 0x5fffc, 0xfd80003c },
+	{ 0x50310, 0x794003e8 },
+	{ 0x5fffc, 0xfcc0004d },
+	{ 0x50314, 0x76c003e4 },
+	{ 0x5fffc, 0xfc40005f },
+	{ 0x50318, 0x73c003e0 },
+	{ 0x5fffc, 0xfb800071 },
+	{ 0x5031c, 0x708003de },
+	{ 0x5fffc, 0xfac00085 },
+	{ 0x50320, 0x6d0003db },
+	{ 0x5fffc, 0xfa000098 },
+	{ 0x50324, 0x698003d9 },
+	{ 0x5fffc, 0xf98000ac },
+	{ 0x50328, 0x654003d8 },
+	{ 0x5fffc, 0xf8c000c1 },
+	{ 0x5032c, 0x610003d7 },
+	{ 0x5fffc, 0xf84000d5 },
+	{ 0x50330, 0x5c8003d7 },
+	{ 0x5fffc, 0xf7c000e9 },
+	{ 0x50334, 0x580003d7 },
+	{ 0x5fffc, 0xf74000fd },
+	{ 0x50338, 0x534003d8 },
+	{ 0x5fffc, 0xf6c00112 },
+	{ 0x5033c, 0x4e8003d8 },
+	{ 0x5fffc, 0xf6800126 },
+	{ 0x50340, 0x494003da },
+	{ 0x5fffc, 0xf600013a },
+	{ 0x50344, 0x448003db },
+	{ 0x5fffc, 0xf600014d },
+	{ 0x50348, 0x3f4003dd },
+	{ 0x5fffc, 0xf5c00160 },
+	{ 0x5034c, 0x3a4003df },
+	{ 0x5fffc, 0xf5c00172 },
+	{ 0x50350, 0x354003e1 },
+	{ 0x5fffc, 0xf5c00184 },
+	{ 0x50354, 0x304003e3 },
+	{ 0x5fffc, 0xf6000195 },
+	{ 0x50358, 0x2b0003e6 },
+	{ 0x5fffc, 0xf64001a6 },
+	{ 0x5035c, 0x260003e8 },
+	{ 0x5fffc, 0xf6c001b4 },
+	{ 0x50360, 0x214003eb },
+	{ 0x5fffc, 0xf78001c2 },
+	{ 0x50364, 0x1c4003ee },
+	{ 0x5fffc, 0xf80001cf },
+	{ 0x50368, 0x17c003f1 },
+	{ 0x5fffc, 0xf90001db },
+	{ 0x5036c, 0x134003f3 },
+	{ 0x5fffc, 0xfa0001e5 },
+	{ 0x50370, 0xf0003f6 },
+	{ 0x5fffc, 0xfb4001ee },
+	{ 0x50374, 0xac003f9 },
+	{ 0x5fffc, 0xfcc001f5 },
+	{ 0x50378, 0x70003fb },
+	{ 0x5fffc, 0xfe4001fb },
+	{ 0x5037c, 0x34003fe },
+};
+
+static const struct ppp_table *downscale_y_table[PPP_DOWNSCALE_MAX] = {
+	[PPP_DOWNSCALE_PT2TOPT4] = downscale_y_table_pt2topt4,
+	[PPP_DOWNSCALE_PT4TOPT6] = downscale_y_table_pt4topt6,
+	[PPP_DOWNSCALE_PT6TOPT8] = downscale_y_table_pt6topt8,
+	[PPP_DOWNSCALE_PT8TOPT1] = downscale_y_table_pt8topt1,
+};
+
+void ppp_load_table(const struct ppp_table *table, int len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		PPP_WRITEL(table[i].val, table[i].reg);
+}
+
+void ppp_load_up_lut(void)
+{
+	ppp_load_table(upscale_table,
+		PPP_UPSCALE_MAX);
+}
+
+void ppp_load_gaussian_lut(void)
+{
+	ppp_load_table(mdp_gaussian_blur_table,
+		PPP_BLUR_SCALE_MAX);
+}
+
+void ppp_load_x_scale_table(int idx)
+{
+	ppp_load_table(downscale_x_table[idx], 64);
+}
+
+void ppp_load_y_scale_table(int idx)
+{
+	ppp_load_table(downscale_y_table[idx], 64);
+}
+
+uint32_t ppp_bpp(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return bytes_per_pixel[type];
+}
+
+uint32_t ppp_src_config(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return src_cfg_lut[type];
+}
+
+uint32_t ppp_out_config(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return out_cfg_lut[type];
+}
+
+uint32_t ppp_pack_pattern(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return pack_patt_lut[type];
+}
+
+uint32_t ppp_dst_op_reg(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return dst_op_reg[type];
+}
+
+uint32_t ppp_src_op_reg(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return src_op_reg[type];
+}
+
+bool ppp_per_p_alpha(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return per_pixel_alpha[type];
+}
+
+bool ppp_multi_plane(uint32_t type)
+{
+	if (type > MDP_IMGTYPE_LIMIT)
+		return 0;
+	return multi_plane[type];
+}
+
+uint32_t *ppp_default_pre_lut(void)
+{
+	return default_pre_lut_val;
+}
+
+uint32_t *ppp_default_post_lut(void)
+{
+	return default_post_lut_val;
+}
+
+struct ppp_csc_table *ppp_csc_rgb2yuv(void)
+{
+	return &rgb2yuv;
+}
+
+struct ppp_csc_table *ppp_csc_table2(void)
+{
+	return &default_table2;
+}
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
new file mode 100644
index 0000000..309effc
--- /dev/null
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -0,0 +1,1184 @@
+/* Copyright (c) 2007, 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2007 Google Incorporated
+ *
+ * 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.
+ */
+
+#include <linux/file.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include "linux/proc_fs.h"
+
+#include "mdss_fb.h"
+#include "mdp3_ppp.h"
+#include "mdp3_hwio.h"
+
+/* SHIM Q Factor */
+#define PHI_Q_FACTOR          29
+#define PQF_PLUS_5            (PHI_Q_FACTOR + 5)	/* due to 32 phases */
+#define PQF_PLUS_4            (PHI_Q_FACTOR + 4)
+#define PQF_PLUS_2            (PHI_Q_FACTOR + 2)	/* to get 4.0 */
+#define PQF_MINUS_2           (PHI_Q_FACTOR - 2)	/* to get 0.25 */
+#define PQF_PLUS_5_PLUS_2     (PQF_PLUS_5 + 2)
+#define PQF_PLUS_5_MINUS_2    (PQF_PLUS_5 - 2)
+
+static long long mdp_do_div(long long num, long long den)
+{
+	do_div(num, den);
+	return num;
+}
+
+static int mdp_calc_scale_params(uint32_t org, uint32_t dim_in,
+	uint32_t dim_out, bool is_W, int32_t *phase_init_ptr,
+	uint32_t *phase_step_ptr)
+{
+	bool rpa_on = false;
+	int init_phase = 0;
+	uint64_t numer = 0;
+	uint64_t denom = 0;
+	int64_t point5 = 1;
+	int64_t one = 1;
+	int64_t k1, k2, k3, k4;	/* linear equation coefficients */
+	uint64_t int_mask;
+	uint64_t fract_mask;
+	uint64_t Os;
+	int64_t Osprime;
+	int64_t Od;
+	int64_t Odprime;
+	int64_t Oreq;
+	uint32_t mult;
+
+	/*
+	 * The phase accumulator should really be rational for all cases in a
+	 * general purpose polyphase scaler for a tiled architecture with
+	 * non-zero * origin capability because there is no way to represent
+	 * certain scale factors in fixed point regardless of precision.
+	 * The error incurred in attempting to use fixed point is most
+	 * eggregious for SF where 1/SF is an integral multiple of 1/3.
+	 *
+	 * Set the RPA flag for this dimension.
+	 *
+	 * In order for 1/SF (dim_in/dim_out) to be an integral multiple of
+	 * 1/3, dim_out must be an integral multiple of 3.
+	 */
+	if (!(dim_out % 3)) {
+		mult = dim_out / 3;
+		rpa_on = (!(dim_in % mult));
+	}
+
+	numer = dim_out;
+	denom = dim_in;
+
+	/*
+	 * convert to U30.34 before division
+	 *
+	 * The K vectors carry 4 extra bits of precision
+	 * and are rounded.
+	 *
+	 * We initially go 5 bits over then round by adding
+	 * 1 and right shifting by 1
+	 * so final result is U31.33
+	 */
+	numer <<= PQF_PLUS_5;
+
+	/* now calculate the scale factor (aka k3) */
+	k3 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+	/* check scale factor for legal range [0.25 - 4.0] */
+	if (((k3 >> 4) < (1LL << PQF_MINUS_2)) ||
+	    ((k3 >> 4) > (1LL << PQF_PLUS_2))) {
+		return -EINVAL;
+	}
+
+	/* calculate inverse scale factor (aka k1) for phase init */
+	numer = dim_in;
+	denom = dim_out;
+	numer <<= PQF_PLUS_5;
+	k1 = ((mdp_do_div(numer, denom) + 1) >> 1);
+
+	/*
+	 * calculate initial phase and ROI overfetch
+	 */
+	/* convert point5 & one to S39.24 (will always be positive) */
+	point5 <<= (PQF_PLUS_4 - 1);
+	one <<= PQF_PLUS_4;
+	k2 = ((k1 - one) >> 1);
+	init_phase = (int)(k2 >> 4);
+	k4 = ((k3 - one) >> 1);
+	if (k3 != one) {
+		/* calculate the masks */
+		fract_mask = one - 1;
+		int_mask = ~fract_mask;
+
+		if (!rpa_on) {
+			/*
+			 * FIXED POINT IMPLEMENTATION
+			 */
+			if (org) {
+				/*
+				 * The complicated case; ROI origin != 0
+				 * init_phase needs to be adjusted
+				 * OF is also position dependent
+				 */
+
+				/* map (org - .5) into destination space */
+				Os = ((uint64_t) org << 1) - 1;
+				Od = ((k3 * Os) >> 1) + k4;
+
+				/* take the ceiling */
+				Odprime = (Od & int_mask);
+				if (Odprime != Od)
+					Odprime += one;
+
+				/* now map that back to source space */
+				Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2;
+
+				/* then floor & decrement to calc the required
+				   starting coordinate */
+				Oreq = (Osprime & int_mask) - one;
+
+				/* calculate initial phase */
+				init_phase = (int)((Osprime - Oreq) >> 4);
+			}
+		} else {
+			/*
+			 * RPA IMPLEMENTATION
+			 *
+			 * init_phase needs to be calculated in all RPA_on cases
+			 * because it's a numerator, not a fixed point value.
+			 */
+
+			/* map (org - .5) into destination space */
+			Os = ((uint64_t) org << PQF_PLUS_4) - point5;
+			Od = mdp_do_div((dim_out * (Os + point5)),
+					dim_in);
+			Od -= point5;
+
+			/* take the ceiling */
+			Odprime = (Od & int_mask);
+			if (Odprime != Od)
+				Odprime += one;
+
+			/* now map that back to source space */
+			Osprime =
+			    mdp_do_div((dim_in * (Odprime + point5)),
+				       dim_out);
+			Osprime -= point5;
+
+			/* then floor & decrement to calculate the required
+			   starting coordinate */
+			Oreq = (Osprime & int_mask) - one;
+
+			/* calculate initial phase */
+			init_phase = (int)((Osprime - Oreq) >> 4);
+		}
+	}
+
+	/* return the scale parameters */
+	*phase_init_ptr = init_phase;
+	*phase_step_ptr = (uint32_t) (k1 >> 4);
+
+	return 0;
+}
+
+static int scale_idx(int factor)
+{
+	int idx;
+
+	if (factor > 80)
+		idx = PPP_DOWNSCALE_PT8TOPT1;
+	else if (factor > 60)
+		idx = PPP_DOWNSCALE_PT6TOPT8;
+	else if (factor > 40)
+		idx = PPP_DOWNSCALE_PT4TOPT6;
+	else
+		idx = PPP_DOWNSCALE_PT2TOPT4;
+
+	return idx;
+}
+
+inline int32_t comp_conv_rgb2yuv(int32_t comp, int32_t y_high,
+		int32_t y_low, int32_t c_high, int32_t c_low)
+{
+	if (comp < 0)
+		comp = 0;
+	if (comp > 255)
+		comp = 255;
+
+	/* clamp */
+	if (comp < y_low)
+		comp = y_low;
+	if (comp > y_high)
+		comp = y_high;
+	return comp;
+}
+
+static uint32_t conv_rgb2yuv(uint32_t input_pixel,
+		uint16_t *matrix_vector,
+		uint16_t *bv,
+		uint16_t *clamp_vector)
+{
+	uint8_t input_C2, input_C0, input_C1;
+	uint32_t output;
+	int32_t comp_C2, comp_C1, comp_C0, temp;
+	int32_t temp1, temp2, temp3;
+	int32_t matrix[9];
+	int32_t bias_vector[3];
+	int32_t Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+	int32_t i;
+
+	input_C2 = (input_pixel >> 16) & 0xFF;
+	input_C1 = (input_pixel >> 8) & 0xFF;
+	input_C0 = (input_pixel >> 0) & 0xFF;
+
+	comp_C0 = input_C0;
+	comp_C1 = input_C1;
+	comp_C2 = input_C2;
+
+	for (i = 0; i < MDP_CSC_SIZE; i++)
+		matrix[i] =
+		    ((int32_t) (((int32_t) matrix_vector[i]) << 20)) >> 20;
+
+	bias_vector[0] = (int32_t) (bv[0] & 0xFF);
+	bias_vector[1] = (int32_t) (bv[1] & 0xFF);
+	bias_vector[2] = (int32_t) (bv[2] & 0xFF);
+
+	Y_low_limit = (int32_t) clamp_vector[0];
+	Y_high_limit = (int32_t) clamp_vector[1];
+	C_low_limit = (int32_t) clamp_vector[2];
+	C_high_limit = (int32_t) clamp_vector[3];
+
+	/*
+	 * Color Conversion
+	 * reorder input colors
+	 */
+	temp = comp_C2;
+	comp_C2 = comp_C1;
+	comp_C1 = comp_C0;
+	comp_C0 = temp;
+
+	/* matrix multiplication */
+	temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2];
+	temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5];
+	temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8];
+
+	comp_C0 = temp1 + 0x100;
+	comp_C1 = temp2 + 0x100;
+	comp_C2 = temp3 + 0x100;
+
+	/* take interger part */
+	comp_C0 >>= 9;
+	comp_C1 >>= 9;
+	comp_C2 >>= 9;
+
+	/* post bias (+) */
+	comp_C0 += bias_vector[0];
+	comp_C1 += bias_vector[1];
+	comp_C2 += bias_vector[2];
+
+	/* limit pixel to 8-bit */
+	comp_C0 = comp_conv_rgb2yuv(comp_C0, Y_high_limit,
+			Y_low_limit, C_high_limit, C_low_limit);
+	comp_C1 = comp_conv_rgb2yuv(comp_C1, Y_high_limit,
+			Y_low_limit, C_high_limit, C_low_limit);
+	comp_C2 = comp_conv_rgb2yuv(comp_C2, Y_high_limit,
+			Y_low_limit, C_high_limit, C_low_limit);
+
+	output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+	return output;
+}
+
+inline void y_h_even_num(struct ppp_img_desc *img)
+{
+	img->roi.y = (img->roi.y / 2) * 2;
+	img->roi.height = (img->roi.height / 2) * 2;
+}
+
+inline void x_w_even_num(struct ppp_img_desc *img)
+{
+	img->roi.x = (img->roi.x / 2) * 2;
+	img->roi.width = (img->roi.width / 2) * 2;
+}
+
+bool check_if_rgb(int color)
+{
+	bool rgb = false;
+	switch (color) {
+	case MDP_RGB_565:
+	case MDP_BGR_565:
+	case MDP_RGB_888:
+	case MDP_BGR_888:
+	case MDP_BGRA_8888:
+	case MDP_RGBA_8888:
+	case MDP_ARGB_8888:
+	case MDP_XRGB_8888:
+	case MDP_RGBX_8888:
+		rgb = true;
+	default:
+		break;
+	}
+	return rgb;
+}
+
+static uint8_t *mdp_adjust_rot_addr(struct ppp_blit_op *iBuf,
+	uint8_t *addr, uint32_t bpp, uint32_t uv)
+{
+	uint32_t dest_ystride = iBuf->dst.prop.width * bpp;
+	uint32_t h_slice = 1;
+	if (0)
+		return 0;
+
+	if (uv && ((iBuf->dst.color_fmt == MDP_Y_CBCR_H2V2) ||
+		(iBuf->dst.color_fmt == MDP_Y_CRCB_H2V2)))
+		h_slice = 2;
+
+	if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^
+		((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) {
+		addr +=
+		    (iBuf->dst.roi.width -
+			    MIN(16, iBuf->dst.roi.width)) * bpp;
+	}
+	if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) {
+		if (1) {
+			addr +=
+				((iBuf->dst.roi.height -
+				MIN(16, iBuf->dst.roi.height))/h_slice) *
+				dest_ystride;
+		} else {
+			addr +=
+			(iBuf->dst.roi.width -
+				MIN(16, iBuf->dst.roi.width)) * bpp;
+		}
+	}
+
+	return addr;
+}
+
+void mdp_adjust_start_addr(struct ppp_blit_op *blit_op,
+	struct ppp_img_desc *img, int v_slice,
+	int h_slice, int layer)
+{
+	uint32_t bpp = ppp_bpp(img->color_fmt);
+	int x = img->roi.x;
+	int y = img->roi.y;
+	uint32_t width = img->prop.width;
+
+	if (img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO && layer == 0)
+		img->p0 += (x + y * ALIGN(width, 32)) * bpp;
+	else
+		img->p0 += (x + y * width) * bpp;
+	if (layer != 0)
+		img->p0 = mdp_adjust_rot_addr(blit_op, img->p0, bpp, 0);
+
+	if (img->p1) {
+		/*
+		 * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
+		 * we need to shift x direction same as y dir for offsite
+		 */
+		if (img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO
+							&& layer == 0)
+			img->p1 += ((x / h_slice) * h_slice + ((y == 0) ? 0 :
+			(((y + 1) / v_slice - 1) * (ALIGN(width/2, 32) * 2))))
+									* bpp;
+		else
+			img->p1 += ((x / h_slice) * h_slice +
+			((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+		if (layer != 0)
+			img->p1 = mdp_adjust_rot_addr(blit_op, img->p1, bpp, 1);
+	}
+}
+
+int load_ppp_lut(int tableType, uint32_t *lut)
+{
+	int i;
+	uint32_t base_addr;
+
+	base_addr = tableType ? MDP3_PPP_POST_LUT : MDP3_PPP_PRE_LUT;
+	for (i = 0; i < PPP_LUT_MAX; i++)
+		PPP_WRITEL(lut[i], base_addr + MDP3_PPP_LUTn(i));
+
+	return 0;
+}
+
+/* Configure Primary CSC Matrix */
+int load_primary_matrix(struct ppp_csc_table *csc)
+{
+	int i;
+
+	for (i = 0; i < MDP_CSC_SIZE; i++)
+		PPP_WRITEL(csc->fwd_matrix[i], MDP3_PPP_CSC_PFMVn(i));
+
+	for (i = 0; i < MDP_CSC_SIZE; i++)
+		PPP_WRITEL(csc->rev_matrix[i], MDP3_PPP_CSC_PRMVn(i));
+
+	for (i = 0; i < MDP_BV_SIZE; i++)
+		PPP_WRITEL(csc->bv[i], MDP3_PPP_CSC_PBVn(i));
+
+	for (i = 0; i < MDP_LV_SIZE; i++)
+		PPP_WRITEL(csc->lv[i], MDP3_PPP_CSC_PLVn(i));
+
+	return 0;
+}
+
+/* Load Secondary CSC Matrix */
+int load_secondary_matrix(struct ppp_csc_table *csc)
+{
+	int i;
+
+	for (i = 0; i < MDP_CSC_SIZE; i++)
+		PPP_WRITEL(csc->fwd_matrix[i], MDP3_PPP_CSC_SFMVn(i));
+
+	for (i = 0; i < MDP_CSC_SIZE; i++)
+		PPP_WRITEL(csc->rev_matrix[i], MDP3_PPP_CSC_SRMVn(i));
+
+	for (i = 0; i < MDP_BV_SIZE; i++)
+		PPP_WRITEL(csc->bv[i], MDP3_PPP_CSC_SBVn(i));
+
+	for (i = 0; i < MDP_LV_SIZE; i++)
+		PPP_WRITEL(csc->lv[i], MDP3_PPP_CSC_SLVn(i));
+	return 0;
+}
+
+int load_csc_matrix(int matrix_type, struct ppp_csc_table *csc)
+{
+	if (matrix_type == CSC_PRIMARY_MATRIX)
+		return load_primary_matrix(csc);
+
+	return load_secondary_matrix(csc);
+}
+
+int config_ppp_src(struct ppp_img_desc *src)
+{
+	uint32_t val;
+
+	val = ((src->roi.height & MDP3_PPP_XY_MASK) << MDP3_PPP_XY_OFFSET) |
+		   (src->roi.width & MDP3_PPP_XY_MASK);
+	PPP_WRITEL(val, MDP3_PPP_SRC_SIZE);
+
+	PPP_WRITEL(src->p0, MDP3_PPP_SRCP0_ADDR);
+	PPP_WRITEL(src->p1, MDP3_PPP_SRCP1_ADDR);
+	PPP_WRITEL(src->p3, MDP3_PPP_SRCP3_ADDR);
+
+	val = (src->stride0 & MDP3_PPP_STRIDE_MASK) |
+			((src->stride1 & MDP3_PPP_STRIDE_MASK) <<
+			MDP3_PPP_STRIDE1_OFFSET);
+	PPP_WRITEL(val, MDP3_PPP_SRC_YSTRIDE1_ADDR);
+	val = ((src->stride2 & MDP3_PPP_STRIDE_MASK) <<
+			MDP3_PPP_STRIDE1_OFFSET);
+	PPP_WRITEL(val, MDP3_PPP_SRC_YSTRIDE2_ADDR);
+
+	val = ppp_src_config(src->color_fmt);
+	val |= (src->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+	val |= (src->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+	PPP_WRITEL(val, MDP3_PPP_SRC_FORMAT);
+	PPP_WRITEL(ppp_pack_pattern(src->color_fmt),
+		MDP3_PPP_SRC_UNPACK_PATTERN1);
+	return 0;
+}
+
+int config_ppp_out(struct ppp_img_desc *dst)
+{
+	uint32_t val;
+	bool pseudoplanr_output = false;
+
+	switch (dst->color_fmt) {
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+		pseudoplanr_output = true;
+		break;
+	default:
+		break;
+	}
+	val = ppp_out_config(dst->color_fmt);
+	if (pseudoplanr_output)
+		val |= PPP_DST_PLANE_PSEUDOPLN;
+	PPP_WRITEL(val, MDP3_PPP_OUT_FORMAT);
+	PPP_WRITEL(ppp_pack_pattern(dst->color_fmt),
+		MDP3_PPP_OUT_PACK_PATTERN1);
+
+	val = ((dst->roi.height & MDP3_PPP_XY_MASK) << MDP3_PPP_XY_OFFSET) |
+		   (dst->roi.width & MDP3_PPP_XY_MASK);
+	PPP_WRITEL(val, MDP3_PPP_OUT_SIZE);
+
+	PPP_WRITEL(dst->p0, MDP3_PPP_OUTP0_ADDR);
+	PPP_WRITEL(dst->p1, MDP3_PPP_OUTP1_ADDR);
+	PPP_WRITEL(dst->p3, MDP3_PPP_OUTP3_ADDR);
+
+	val = (dst->stride0 & MDP3_PPP_STRIDE_MASK) |
+			((dst->stride1 & MDP3_PPP_STRIDE_MASK) <<
+			MDP3_PPP_STRIDE1_OFFSET);
+	PPP_WRITEL(val, MDP3_PPP_OUT_YSTRIDE1_ADDR);
+	val = ((dst->stride2 & MDP3_PPP_STRIDE_MASK) <<
+			MDP3_PPP_STRIDE1_OFFSET);
+	PPP_WRITEL(val, MDP3_PPP_OUT_YSTRIDE2_ADDR);
+	return 0;
+}
+
+int config_ppp_background(struct ppp_img_desc *bg)
+{
+	uint32_t val;
+
+	PPP_WRITEL(bg->p0, MDP3_PPP_BGP0_ADDR);
+	PPP_WRITEL(bg->p1, MDP3_PPP_BGP1_ADDR);
+	PPP_WRITEL(bg->p3, MDP3_PPP_BGP3_ADDR);
+
+	val = (bg->stride0 & MDP3_PPP_STRIDE_MASK) |
+			((bg->stride1 & MDP3_PPP_STRIDE_MASK) <<
+			MDP3_PPP_STRIDE1_OFFSET);
+	PPP_WRITEL(val, MDP3_PPP_BG_YSTRIDE1_ADDR);
+	val = ((bg->stride2 & MDP3_PPP_STRIDE_MASK) <<
+			MDP3_PPP_STRIDE1_OFFSET);
+	PPP_WRITEL(val, MDP3_PPP_BG_YSTRIDE2_ADDR);
+
+	PPP_WRITEL(ppp_src_config(bg->color_fmt),
+		MDP3_PPP_BG_FORMAT);
+	PPP_WRITEL(ppp_pack_pattern(bg->color_fmt),
+		MDP3_PPP_BG_UNPACK_PATTERN1);
+	return 0;
+}
+
+void ppp_edge_rep_luma_pixel(struct ppp_blit_op *blit_op,
+	struct ppp_edge_rep *er)
+{
+	if (blit_op->mdp_op & MDPOP_ASCALE) {
+
+		er->is_scale_enabled = 1;
+
+		if (blit_op->mdp_op & MDPOP_ROT90) {
+			er->dst_roi_width = blit_op->dst.roi.height;
+			er->dst_roi_height = blit_op->dst.roi.width;
+		} else {
+			er->dst_roi_width = blit_op->dst.roi.width;
+			er->dst_roi_height = blit_op->dst.roi.height;
+		}
+
+		/*
+		 * Find out the luma pixels needed for scaling in the
+		 * x direction (LEFT and RIGHT).  Locations of pixels are
+		 * relative to the ROI. Upper-left corner of ROI corresponds
+		 * to coordinates (0,0). Also set the number of luma pixel
+		 * to repeat.
+		 */
+		if (blit_op->src.roi.width > 3 * er->dst_roi_width) {
+			/* scale factor < 1/3 */
+			er->luma_interp_point_right =
+				(blit_op->src.roi.width - 1);
+		} else if (blit_op->src.roi.width == 3 * er->dst_roi_width) {
+			/* scale factor == 1/3 */
+			er->luma_interp_point_right =
+				(blit_op->src.roi.width - 1) + 1;
+			er->luma_repeat_right = 1;
+		} else if ((blit_op->src.roi.width > er->dst_roi_width) &&
+			   (blit_op->src.roi.width < 3 * er->dst_roi_width)) {
+			/* 1/3 < scale factor < 1 */
+			er->luma_interp_point_left = -1;
+			er->luma_interp_point_right =
+				(blit_op->src.roi.width - 1) + 1;
+			er->luma_repeat_left = 1;
+			er->luma_repeat_right = 1;
+		} else if (blit_op->src.roi.width == er->dst_roi_width) {
+			/* scale factor == 1 */
+			er->luma_interp_point_left = -1;
+			er->luma_interp_point_right =
+				(blit_op->src.roi.width - 1) + 2;
+			er->luma_repeat_left = 1;
+			er->luma_repeat_right = 2;
+		} else {
+			  /* scale factor > 1 */
+			er->luma_interp_point_left = -2;
+			er->luma_interp_point_right =
+				(blit_op->src.roi.width - 1) + 2;
+			er->luma_repeat_left = 2;
+			er->luma_repeat_right = 2;
+		}
+
+		/*
+		 * Find out the number of pixels needed for scaling in the
+		 * y direction (TOP and BOTTOM).  Locations of pixels are
+		 * relative to the ROI. Upper-left corner of ROI corresponds
+		 * to coordinates (0,0). Also set the number of luma pixel
+		 * to repeat.
+		 */
+		if (blit_op->src.roi.height > 3 * er->dst_roi_height) {
+			er->luma_interp_point_bottom =
+				(blit_op->src.roi.height - 1);
+		} else if (blit_op->src.roi.height == 3 * er->dst_roi_height) {
+			er->luma_interp_point_bottom =
+				(blit_op->src.roi.height - 1) + 1;
+			er->luma_repeat_bottom = 1;
+		} else if ((blit_op->src.roi.height > er->dst_roi_height) &&
+			   (blit_op->src.roi.height < 3 * er->dst_roi_height)) {
+			er->luma_interp_point_top = -1;
+			er->luma_interp_point_bottom =
+				(blit_op->src.roi.height - 1) + 1;
+			er->luma_repeat_top = 1;
+			er->luma_repeat_bottom = 1;
+		} else if (blit_op->src.roi.height == er->dst_roi_height) {
+			er->luma_interp_point_top = -1;
+			er->luma_interp_point_bottom =
+				(blit_op->src.roi.height - 1) + 2;
+			er->luma_repeat_top = 1;
+			er->luma_repeat_bottom = 2;
+		} else {
+			er->luma_interp_point_top = -2;
+			er->luma_interp_point_bottom =
+				(blit_op->src.roi.height - 1) + 2;
+			er->luma_repeat_top = 2;
+			er->luma_repeat_bottom = 2;
+		}
+	} else {
+		/*
+		 * Since no scaling needed, Tile Fetch does not require any
+		 * more luma pixel than what the ROI contains.
+		 */
+		er->luma_interp_point_right =
+			(int32_t) (blit_op->src.roi.width - 1);
+		er->luma_interp_point_bottom =
+			(int32_t) (blit_op->src.roi.height - 1);
+	}
+	/* After adding the ROI offsets, we have locations of
+	 * luma_interp_points relative to the image.
+	 */
+	er->luma_interp_point_left += (int32_t) (blit_op->src.roi.x);
+	er->luma_interp_point_right += (int32_t) (blit_op->src.roi.x);
+	er->luma_interp_point_top += (int32_t) (blit_op->src.roi.y);
+	er->luma_interp_point_bottom += (int32_t) (blit_op->src.roi.y);
+}
+
+void ppp_edge_rep_chroma_pixel(struct ppp_blit_op *blit_op,
+	struct ppp_edge_rep *er)
+{
+	bool chroma_edge_enable = true;
+	uint32_t is_yuv_offsite_vertical = 0;
+
+	/* find out which chroma pixels are needed for chroma upsampling. */
+	switch (blit_op->src.color_fmt) {
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+	case MDP_YCRYCB_H2V1:
+		er->chroma_interp_point_left = er->luma_interp_point_left >> 1;
+		er->chroma_interp_point_right =
+			(er->luma_interp_point_right + 1) >> 1;
+		er->chroma_interp_point_top = er->luma_interp_point_top;
+		er->chroma_interp_point_bottom = er->luma_interp_point_bottom;
+		break;
+
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_ADRENO:
+	case MDP_Y_CRCB_H2V2:
+		er->chroma_interp_point_left = er->luma_interp_point_left >> 1;
+		er->chroma_interp_point_right =
+			(er->luma_interp_point_right + 1) >> 1;
+		er->chroma_interp_point_top =
+			(er->luma_interp_point_top - 1) >> 1;
+		er->chroma_interp_point_bottom =
+		    (er->luma_interp_point_bottom + 1) >> 1;
+		is_yuv_offsite_vertical = 1;
+		break;
+
+	default:
+		chroma_edge_enable = false;
+		er->chroma_interp_point_left = er->luma_interp_point_left;
+		er->chroma_interp_point_right = er->luma_interp_point_right;
+		er->chroma_interp_point_top = er->luma_interp_point_top;
+		er->chroma_interp_point_bottom = er->luma_interp_point_bottom;
+
+		break;
+	}
+
+	if (chroma_edge_enable) {
+		/* Defines which chroma pixels belongs to the roi */
+		switch (blit_op->src.color_fmt) {
+		case MDP_Y_CBCR_H2V1:
+		case MDP_Y_CRCB_H2V1:
+		case MDP_YCRYCB_H2V1:
+			er->chroma_bound_left = blit_op->src.roi.x / 2;
+			/* there are half as many chroma pixel as luma pixels */
+			er->chroma_bound_right =
+			    (blit_op->src.roi.width +
+				blit_op->src.roi.x - 1) / 2;
+			er->chroma_bound_top = blit_op->src.roi.y;
+			er->chroma_bound_bottom =
+			    (blit_op->src.roi.height + blit_op->src.roi.y - 1);
+			break;
+		case MDP_Y_CBCR_H2V2:
+		case MDP_Y_CBCR_H2V2_ADRENO:
+		case MDP_Y_CRCB_H2V2:
+			/*
+			 * cosite in horizontal dir, and offsite in vertical dir
+			 * width of chroma ROI is 1/2 of size of luma ROI
+			 * height of chroma ROI is 1/2 of size of luma ROI
+			 */
+			er->chroma_bound_left = blit_op->src.roi.x / 2;
+			er->chroma_bound_right =
+			    (blit_op->src.roi.width +
+				blit_op->src.roi.x - 1) / 2;
+			er->chroma_bound_top = blit_op->src.roi.y / 2;
+			er->chroma_bound_bottom =
+			    (blit_op->src.roi.height +
+				blit_op->src.roi.y - 1) / 2;
+			break;
+
+		default:
+			/*
+			 * If no valid chroma sub-sampling format specified,
+			 * assume 4:4:4 ( i.e. fully sampled).
+			 */
+			er->chroma_bound_left = blit_op->src.roi.x;
+			er->chroma_bound_right = blit_op->src.roi.width +
+				blit_op->src.roi.x - 1;
+			er->chroma_bound_top = blit_op->src.roi.y;
+			er->chroma_bound_bottom =
+			    (blit_op->src.roi.height + blit_op->src.roi.y - 1);
+			break;
+		}
+
+		/*
+		 * Knowing which chroma pixels are needed, and which chroma
+		 * pixels belong to the ROI (i.e. available for fetching ),
+		 * calculate how many chroma pixels Tile Fetch needs to
+		 * duplicate.  If any required chroma pixels falls outside
+		 * of the ROI, Tile Fetch must obtain them by replicating
+		 * pixels.
+		 */
+		if (er->chroma_bound_left > er->chroma_interp_point_left)
+			er->chroma_repeat_left =
+			    er->chroma_bound_left -
+				er->chroma_interp_point_left;
+		else
+			er->chroma_repeat_left = 0;
+
+		if (er->chroma_interp_point_right > er->chroma_bound_right)
+			er->chroma_repeat_right =
+			    er->chroma_interp_point_right -
+				er->chroma_bound_right;
+		else
+			er->chroma_repeat_right = 0;
+
+		if (er->chroma_bound_top > er->chroma_interp_point_top)
+			er->chroma_repeat_top =
+			    er->chroma_bound_top -
+				er->chroma_interp_point_top;
+		else
+			er->chroma_repeat_top = 0;
+
+		if (er->chroma_interp_point_bottom > er->chroma_bound_bottom)
+			er->chroma_repeat_bottom =
+			    er->chroma_interp_point_bottom -
+				er->chroma_bound_bottom;
+		else
+			er->chroma_repeat_bottom = 0;
+
+		if (er->is_scale_enabled && (blit_op->src.roi.height == 1)
+		    && is_yuv_offsite_vertical) {
+			er->chroma_repeat_bottom = 3;
+			er->chroma_repeat_top = 0;
+		}
+	}
+}
+
+int config_ppp_edge_rep(struct ppp_blit_op *blit_op)
+{
+	uint32_t reg = 0;
+	struct ppp_edge_rep er;
+
+	memset(&er, 0, sizeof(er));
+
+	ppp_edge_rep_luma_pixel(blit_op, &er);
+
+	/*
+	 * After adding the ROI offsets, we have locations of
+	 * chroma_interp_points relative to the image.
+	 */
+	er.chroma_interp_point_left = er.luma_interp_point_left;
+	er.chroma_interp_point_right = er.luma_interp_point_right;
+	er.chroma_interp_point_top = er.luma_interp_point_top;
+	er.chroma_interp_point_bottom = er.luma_interp_point_bottom;
+
+	ppp_edge_rep_chroma_pixel(blit_op, &er);
+	/* ensure repeats are >=0 and no larger than 3 pixels */
+	if ((er.chroma_repeat_left < 0) || (er.chroma_repeat_right < 0) ||
+	    (er.chroma_repeat_top < 0) || (er.chroma_repeat_bottom < 0))
+		return -EINVAL;
+	if ((er.chroma_repeat_left > 3) || (er.chroma_repeat_right > 3) ||
+	    (er.chroma_repeat_top > 3) || (er.chroma_repeat_bottom > 3))
+		return -EINVAL;
+	if ((er.luma_repeat_left < 0) || (er.luma_repeat_right < 0) ||
+	    (er.luma_repeat_top < 0) || (er.luma_repeat_bottom < 0))
+		return -EINVAL;
+	if ((er.luma_repeat_left > 3) || (er.luma_repeat_right > 3) ||
+	    (er.luma_repeat_top > 3) || (er.luma_repeat_bottom > 3))
+		return -EINVAL;
+
+	reg |= (er.chroma_repeat_left & 3) << MDP_LEFT_CHROMA;
+	reg |= (er.chroma_repeat_right & 3) << MDP_RIGHT_CHROMA;
+	reg |= (er.chroma_repeat_top & 3) << MDP_TOP_CHROMA;
+	reg |= (er.chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA;
+	reg |= (er.luma_repeat_left & 3) << MDP_LEFT_LUMA;
+	reg |= (er.luma_repeat_right & 3) << MDP_RIGHT_LUMA;
+	reg |= (er.luma_repeat_top & 3) << MDP_TOP_LUMA;
+	reg |= (er.luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA;
+	PPP_WRITEL(reg, MDP3_PPP_SRC_EDGE_REP);
+	return 0;
+}
+
+int config_ppp_bg_edge_rep(struct ppp_blit_op *blit_op)
+{
+	uint32_t reg = 0;
+
+	switch (blit_op->dst.color_fmt) {
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		if (blit_op->dst.roi.y == 0)
+			reg |= BIT(MDP_TOP_CHROMA);
+
+		if ((blit_op->dst.roi.y + blit_op->dst.roi.height) ==
+		    blit_op->dst.prop.height) {
+			reg |= BIT(MDP_BOTTOM_CHROMA);
+		}
+
+		if (((blit_op->dst.roi.x + blit_op->dst.roi.width) ==
+				blit_op->dst.prop.width) &&
+				((blit_op->dst.roi.width % 2) == 0))
+			reg |= BIT(MDP_RIGHT_CHROMA);
+		break;
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+	case MDP_YCRYCB_H2V1:
+		if (((blit_op->dst.roi.x + blit_op->dst.roi.width) ==
+				blit_op->dst.prop.width) &&
+				((blit_op->dst.roi.width % 2) == 0))
+			reg |= BIT(MDP_RIGHT_CHROMA);
+		break;
+	default:
+		break;
+	}
+	PPP_WRITEL(reg, MDP3_PPP_BG_EDGE_REP);
+	return 0;
+}
+
+int config_ppp_lut(uint32_t *pppop_reg_ptr, int lut_c0_en,
+	int lut_c1_en, int lut_c2_en)
+{
+	if (lut_c0_en)
+		*pppop_reg_ptr |= MDP_LUT_C0_EN;
+	if (lut_c1_en)
+		*pppop_reg_ptr |= MDP_LUT_C1_EN;
+	if (lut_c2_en)
+		*pppop_reg_ptr |= MDP_LUT_C2_EN;
+	return 0;
+}
+
+int config_ppp_scale(struct ppp_blit_op *blit_op, uint32_t *pppop_reg_ptr)
+{
+	struct ppp_img_desc *src = &blit_op->src;
+	struct ppp_img_desc *dst = &blit_op->dst;
+	uint32_t dstW, dstH;
+	uint32_t x_fac, y_fac;
+	uint32_t mdp_blur = 0;
+	uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
+	int x_idx, y_idx;
+
+	if (blit_op->mdp_op & MDPOP_ASCALE) {
+		if (blit_op->mdp_op & MDPOP_ROT90) {
+			dstW = dst->roi.height;
+			dstH = dst->roi.width;
+		} else {
+			dstW = dst->roi.width;
+			dstH = dst->roi.height;
+		}
+		*pppop_reg_ptr |=
+			(PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
+
+		mdp_blur = blit_op->mdp_op & MDPOP_BLUR;
+
+		if ((dstW != src->roi.width) ||
+		    (dstH != src->roi.height) || mdp_blur) {
+
+				mdp_calc_scale_params(blit_op->src.roi.x,
+					blit_op->src.roi.width,
+					dstW, 1, &phase_init_x,
+					&phase_step_x);
+				mdp_calc_scale_params(blit_op->src.roi.y,
+					blit_op->src.roi.height,
+					dstH, 0, &phase_init_y,
+					&phase_step_y);
+
+			PPP_WRITEL(phase_init_x, MDP3_PPP_SCALE_PHASEX_INIT);
+			PPP_WRITEL(phase_init_y, MDP3_PPP_SCALE_PHASEY_INIT);
+			PPP_WRITEL(phase_step_x, MDP3_PPP_SCALE_PHASEX_STEP);
+			PPP_WRITEL(phase_step_y, MDP3_PPP_SCALE_PHASEY_STEP);
+
+
+			if (dstW > src->roi.width || dstW > src->roi.height)
+				ppp_load_up_lut();
+
+			if (mdp_blur)
+				ppp_load_gaussian_lut();
+
+			if (dstW <= src->roi.width) {
+				x_fac = (dstW * 100) / src->roi.width;
+				x_idx = scale_idx(x_fac);
+				ppp_load_x_scale_table(x_idx);
+			}
+			if (dstH <= src->roi.height) {
+				y_fac = (dstH * 100) / src->roi.height;
+				y_idx = scale_idx(y_fac);
+				ppp_load_y_scale_table(y_idx);
+			}
+
+		} else {
+			blit_op->mdp_op &= ~(MDPOP_ASCALE);
+		}
+	}
+	config_ppp_edge_rep(blit_op);
+	config_ppp_bg_edge_rep(blit_op);
+	return 0;
+}
+
+int config_ppp_csc(int src_color, int dst_color, uint32_t *pppop_reg_ptr)
+{
+	bool inputRGB, outputRGB;
+
+	inputRGB = check_if_rgb(src_color);
+	outputRGB = check_if_rgb(dst_color);
+
+	if ((!inputRGB) && (outputRGB))
+		*pppop_reg_ptr |= PPP_OP_CONVERT_YCBCR2RGB |
+			PPP_OP_CONVERT_ON;
+	if ((inputRGB) && (!outputRGB))
+		*pppop_reg_ptr |= PPP_OP_CONVERT_ON;
+
+	return 0;
+}
+
+int config_ppp_blend(struct ppp_blit_op *blit_op,
+			uint32_t *pppop_reg_ptr)
+{
+	struct ppp_csc_table *csc;
+	uint32_t alpha, trans_color;
+	uint32_t val = 0;
+	int c_fmt = blit_op->src.color_fmt;
+	int bg_alpha;
+
+	csc = ppp_csc_rgb2yuv();
+	alpha = blit_op->blend.const_alpha;
+	trans_color = blit_op->blend.trans_color;
+	if (blit_op->mdp_op & MDPOP_FG_PM_ALPHA) {
+		if (ppp_per_p_alpha(c_fmt)) {
+			*pppop_reg_ptr |= PPP_OP_ROT_ON |
+					  PPP_OP_BLEND_ON |
+					  PPP_OP_BLEND_CONSTANT_ALPHA;
+		} else {
+			if ((blit_op->mdp_op & MDPOP_ALPHAB)
+				&& (blit_op->blend.const_alpha == 0xff)) {
+				blit_op->mdp_op &= ~(MDPOP_ALPHAB);
+			}
+
+			if ((blit_op->mdp_op & MDPOP_ALPHAB)
+			   || (blit_op->mdp_op & MDPOP_TRANSP)) {
+
+				*pppop_reg_ptr |= PPP_OP_ROT_ON |
+					PPP_OP_BLEND_ON |
+					PPP_OP_BLEND_CONSTANT_ALPHA |
+					PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+			}
+		}
+
+		bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+			PPP_BLEND_BG_ALPHA_REVERSE;
+
+		if ((ppp_per_p_alpha(c_fmt)) && !(blit_op->mdp_op &
+						MDPOP_LAYER_IS_FG)) {
+			bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+		} else {
+			bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+			bg_alpha |= blit_op->blend.const_alpha << 24;
+		}
+		PPP_WRITEL(bg_alpha, MDP3_PPP_BLEND_BG_ALPHA_SEL);
+
+		if (blit_op->mdp_op & MDPOP_TRANSP)
+			*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+	} else if (ppp_per_p_alpha(c_fmt)) {
+		if (blit_op->mdp_op & MDPOP_LAYER_IS_FG)
+			*pppop_reg_ptr |= PPP_OP_ROT_ON |
+				  PPP_OP_BLEND_ON |
+				  PPP_OP_BLEND_CONSTANT_ALPHA;
+		else
+			*pppop_reg_ptr |= PPP_OP_ROT_ON |
+				  PPP_OP_BLEND_ON |
+				  PPP_OP_BLEND_SRCPIXEL_ALPHA;
+		PPP_WRITEL(0, MDP3_PPP_BLEND_BG_ALPHA_SEL);
+	} else {
+		if ((blit_op->mdp_op & MDPOP_ALPHAB)
+				&& (blit_op->blend.const_alpha == 0xff)) {
+			blit_op->mdp_op &=
+				~(MDPOP_ALPHAB);
+		}
+
+		if ((blit_op->mdp_op & MDPOP_ALPHAB)
+		   || (blit_op->mdp_op & MDPOP_TRANSP)) {
+			*pppop_reg_ptr |= PPP_OP_ROT_ON |
+				PPP_OP_BLEND_ON |
+				PPP_OP_BLEND_CONSTANT_ALPHA |
+				PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+		}
+
+		if (blit_op->mdp_op & MDPOP_TRANSP)
+			*pppop_reg_ptr |=
+				PPP_BLEND_CALPHA_TRNASP;
+		PPP_WRITEL(0, MDP3_PPP_BLEND_BG_ALPHA_SEL);
+	}
+
+	if (*pppop_reg_ptr & PPP_OP_BLEND_ON) {
+		blit_op->bg = blit_op->dst;
+		config_ppp_background(&blit_op->bg);
+
+		if (blit_op->dst.color_fmt == MDP_YCRYCB_H2V1) {
+			*pppop_reg_ptr |= PPP_OP_BG_CHROMA_H2V1;
+			if (blit_op->mdp_op & MDPOP_TRANSP) {
+				trans_color = conv_rgb2yuv(trans_color,
+					&csc->fwd_matrix[0],
+					&csc->bv[0],
+					&csc->lv[0]);
+			}
+		}
+	}
+	val = (alpha << MDP_BLEND_CONST_ALPHA);
+	val |= (trans_color & MDP_BLEND_TRASP_COL_MASK);
+	PPP_WRITEL(val, MDP3_PPP_BLEND_PARAM);
+	return 0;
+}
+
+int config_ppp_rotation(uint32_t mdp_op, uint32_t *pppop_reg_ptr)
+{
+	*pppop_reg_ptr |= PPP_OP_ROT_ON;
+
+	if (mdp_op & MDPOP_ROT90)
+		*pppop_reg_ptr |= PPP_OP_ROT_90;
+	if (mdp_op & MDPOP_LR)
+		*pppop_reg_ptr |= PPP_OP_FLIP_LR;
+	if (mdp_op & MDPOP_UD)
+		*pppop_reg_ptr |= PPP_OP_FLIP_UD;
+
+	return 0;
+}
+
+int config_ppp_op_mode(struct ppp_blit_op *blit_op)
+{
+	uint32_t ppp_operation_reg = 0;
+	int sv_slice, sh_slice;
+	int dv_slice, dh_slice;
+
+	sv_slice = sh_slice = dv_slice = dh_slice = 1;
+
+	ppp_operation_reg |= ppp_dst_op_reg(blit_op->dst.color_fmt);
+	switch (blit_op->dst.color_fmt) {
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CRCB_H2V2:
+		y_h_even_num(&blit_op->dst);
+		y_h_even_num(&blit_op->src);
+		dv_slice = 2;
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+	case MDP_YCRYCB_H2V1:
+		x_w_even_num(&blit_op->dst);
+		x_w_even_num(&blit_op->src);
+		dh_slice = 2;
+		break;
+	default:
+		break;
+	}
+
+	ppp_operation_reg |= ppp_src_op_reg(blit_op->src.color_fmt);
+	switch (blit_op->src.color_fmt) {
+	case MDP_Y_CBCR_H2V2:
+	case MDP_Y_CBCR_H2V2_ADRENO:
+	case MDP_Y_CRCB_H2V2:
+		sh_slice = sv_slice = 2;
+		break;
+	case MDP_YCRYCB_H2V1:
+		x_w_even_num(&blit_op->dst);
+		x_w_even_num(&blit_op->src);
+	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H2V1:
+		sh_slice = 2;
+		break;
+	default:
+		break;
+	}
+
+	config_ppp_csc(blit_op->src.color_fmt,
+		blit_op->dst.color_fmt, &ppp_operation_reg);
+
+	if (blit_op->mdp_op & MDPOP_DITHER)
+		ppp_operation_reg |= PPP_OP_DITHER_EN;
+
+	if (blit_op->mdp_op & MDPOP_ROTATION)
+		config_ppp_rotation(blit_op->mdp_op, &ppp_operation_reg);
+
+	if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_ADRENO) {
+		blit_op->src.stride0 = ALIGN(blit_op->src.prop.width, 32) *
+			ppp_bpp(blit_op->src.color_fmt);
+		blit_op->src.stride1 = 2 * ALIGN(blit_op->src.prop.width/2, 32);
+	} else {
+		blit_op->src.stride0 = blit_op->src.prop.width *
+			ppp_bpp(blit_op->src.color_fmt);
+		blit_op->src.stride1 = blit_op->src.stride0;
+	}
+
+	blit_op->dst.stride0 = blit_op->dst.prop.width *
+		ppp_bpp(blit_op->dst.color_fmt);
+
+	if (ppp_multi_plane(blit_op->dst.color_fmt)) {
+		blit_op->dst.p1 = blit_op->dst.p0;
+		blit_op->dst.p1 += blit_op->dst.prop.width *
+			blit_op->dst.prop.height *
+			ppp_bpp(blit_op->dst.color_fmt);
+	} else {
+		blit_op->dst.p1 = NULL;
+	}
+
+	/* Jumping from Y-Plane to Chroma Plane */
+	/* first pixel addr calculation */
+	mdp_adjust_start_addr(blit_op, &blit_op->src, sv_slice, sh_slice, 0);
+	mdp_adjust_start_addr(blit_op, &blit_op->dst, dv_slice, dh_slice, 2);
+
+	config_ppp_scale(blit_op, &ppp_operation_reg);
+
+	config_ppp_blend(blit_op, &ppp_operation_reg);
+
+	config_ppp_src(&blit_op->src);
+	config_ppp_out(&blit_op->dst);
+	PPP_WRITEL(ppp_operation_reg, MDP3_PPP_OP_MODE);
+	mb();
+	return 0;
+}
+
+void ppp_enable(void)
+{
+	PPP_WRITEL(0x1000, 0x30);
+	mb();
+}
+
+int mdp3_ppp_init(void)
+{
+	load_ppp_lut(LUT_PRE_TABLE, ppp_default_pre_lut());
+	load_ppp_lut(LUT_POST_TABLE, ppp_default_post_lut());
+	load_csc_matrix(CSC_PRIMARY_MATRIX, ppp_csc_rgb2yuv());
+	load_csc_matrix(CSC_SECONDARY_MATRIX, ppp_csc_table2());
+	return 0;
+}
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index e57e381..c663170 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -408,12 +408,14 @@
 	pr_debug("%s+: ctrl=%p ndx=%d\n", __func__,
 				ctrl_pdata, ctrl_pdata->ndx);
 
-	mdss_dsi_clk_disable(pdata);
-	mdss_dsi_unprepare_clocks(ctrl_pdata);
+	if (pdata->panel_info.type == MIPI_CMD_PANEL)
+		mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 
 	/* disable DSI controller */
 	mdss_dsi_controller_cfg(0, pdata);
 
+	mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+
 	/* disable DSI phy */
 	mdss_dsi_phy_enable(ctrl_pdata->ctrl_base, 0);
 	ret = mdss_dsi_panel_power_on(pdata, 0);
@@ -503,8 +505,7 @@
 	mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
 	mdss_dsi_phy_init(pdata);
 
-	mdss_dsi_prepare_clocks(ctrl_pdata);
-	mdss_dsi_clk_enable(pdata);
+	mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 
 	clk_rate = pdata->panel_info.clk_rate;
 	clk_rate = min(clk_rate, pdata->panel_info.clk_max);
@@ -582,6 +583,9 @@
 		wmb();
 	}
 
+	if (pdata->panel_info.type == MIPI_CMD_PANEL)
+		mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+
 	pr_debug("%s-:\n", __func__);
 	return 0;
 }
@@ -665,35 +669,38 @@
 	switch (event) {
 	case MDSS_EVENT_UNBLANK:
 		rc = mdss_dsi_on(pdata);
-		if (ctrl_pdata->on_cmds->ctrl_state == DSI_LP_MODE) {
+		if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE)
 			rc = mdss_dsi_unblank(pdata);
-		}
 		break;
 	case MDSS_EVENT_PANEL_ON:
-		if (ctrl_pdata->on_cmds->ctrl_state == DSI_HS_MODE)
+		if (ctrl_pdata->on_cmds.link_state == DSI_HS_MODE)
 			rc = mdss_dsi_unblank(pdata);
 		break;
 	case MDSS_EVENT_BLANK:
-		if (ctrl_pdata->off_cmds->ctrl_state == DSI_HS_MODE) {
+		if (ctrl_pdata->off_cmds.link_state == DSI_HS_MODE)
 			rc = mdss_dsi_blank(pdata);
-		}
 		break;
 	case MDSS_EVENT_PANEL_OFF:
-		if (ctrl_pdata->off_cmds->ctrl_state == DSI_LP_MODE) {
+		if (ctrl_pdata->off_cmds.link_state == DSI_LP_MODE)
 			rc = mdss_dsi_blank(pdata);
-		}
 		rc = mdss_dsi_off(pdata);
 		break;
 	case MDSS_EVENT_CONT_SPLASH_FINISH:
-		if (ctrl_pdata->on_cmds->ctrl_state == DSI_LP_MODE) {
+		if (ctrl_pdata->on_cmds.link_state == DSI_LP_MODE) {
 			rc = mdss_dsi_cont_splash_on(pdata);
 		} else {
 			pr_debug("%s:event=%d, Dsi On not called: ctrl_state: %d\n",
 				 __func__, event,
-				 ctrl_pdata->on_cmds->ctrl_state);
+				 ctrl_pdata->on_cmds.link_state);
 			rc = -EINVAL;
 		}
 		break;
+	case MDSS_EVENT_PANEL_CLK_CTRL:
+		mdss_dsi_clk_req(ctrl_pdata, (int)arg);
+		break;
+	case MDSS_EVENT_DSI_CMDLIST_KOFF:
+		mdss_dsi_cmdlist_commit(ctrl_pdata, 1);
+		break;
 	default:
 		pr_debug("%s: unhandled event=%d\n", __func__, event);
 		break;
@@ -1065,17 +1072,16 @@
 
 	ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
 
-	ctrl_pdata->on_cmds = panel_data->dsi_panel_on_cmds;
-	ctrl_pdata->off_cmds = panel_data->dsi_panel_off_cmds;
+	ctrl_pdata->on_cmds = panel_data->on_cmds;
+	ctrl_pdata->off_cmds = panel_data->off_cmds;
 
 	memcpy(&((ctrl_pdata->panel_data).panel_info),
 				&(panel_data->panel_info),
 				       sizeof(struct mdss_panel_info));
 
-	mdss_dsi_irq_handler_config(ctrl_pdata);
 	ctrl_pdata->panel_data.set_backlight = panel_data->bl_fnc;
 	ctrl_pdata->bklt_ctrl = panel_data->panel_info.bklt_ctrl;
-	ctrl_pdata->pwm_gpio = panel_data->panel_info.pwm_gpio;
+	ctrl_pdata->pwm_pmic_gpio = panel_data->panel_info.pwm_pmic_gpio;
 	ctrl_pdata->pwm_period = panel_data->panel_info.pwm_period;
 	ctrl_pdata->pwm_lpg_chan = panel_data->panel_info.pwm_lpg_chan;
 	ctrl_pdata->bklt_max = panel_data->panel_info.bl_max;
@@ -1083,6 +1089,7 @@
 	if (ctrl_pdata->bklt_ctrl == BL_PWM)
 		mdss_dsi_panel_pwm_cfg(ctrl_pdata);
 
+	mdss_dsi_ctrl_init(ctrl_pdata);
 	/*
 	 * register in mdp driver
 	 */
@@ -1112,10 +1119,8 @@
 	pr_debug("%s: pclk=%d, bclk=%d\n", __func__,
 			ctrl_pdata->pclk_rate, ctrl_pdata->byte_clk_rate);
 
-	if (ctrl_pdata->panel_data.panel_info.cont_splash_enabled) {
-		mdss_dsi_prepare_clocks(ctrl_pdata);
-		mdss_dsi_clk_enable(&(ctrl_pdata->panel_data));
-	}
+	if (ctrl_pdata->panel_data.panel_info.cont_splash_enabled)
+		mdss_dsi_clk_ctrl(ctrl_pdata, 1);
 
 	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
 	if (rc) {
@@ -1170,8 +1175,6 @@
 {
 	int ret;
 
-	mdss_dsi_init();
-
 	ret = mdss_dsi_register_driver();
 	if (ret) {
 		pr_err("mdss_dsi_register_driver() failed!\n");
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 9a32dc5..602ed9e 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -133,6 +133,10 @@
 #define DSI_CMD_TRIGGER_SW_SEOF		0x05	/* cmd dma only */
 #define DSI_CMD_TRIGGER_SW_TE		0x06
 
+#define DSI_VIDEO_TERM  BIT(16)
+#define DSI_MDP_TERM    BIT(8)
+#define DSI_CMD_TERM    BIT(0)
+
 extern struct device dsi_dev;
 extern int mdss_dsi_clk_on;
 extern u32 dsi_irq;
@@ -188,7 +192,6 @@
 #define DSI_HDR_DATA1(data)	((data) & 0x0ff)
 #define DSI_HDR_WC(wc)		((wc) & 0x0ffff)
 
-#define DSI_BUF_SIZE	1024
 #define MDSS_DSI_MRPS	0x04  /* Maximum Return Packet Size */
 
 #define MDSS_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align  */
@@ -240,35 +243,67 @@
 #define DTYPE_DCS_READ1_RESP    0x21    /* 1 parameter, short */
 #define DTYPE_DCS_READ2_RESP    0x22    /* 2 parameter, short */
 
+
+struct dsi_ctrl_hdr {
+	char dtype;	/* data type */
+	char last;	/* last in chain */
+	char vc;	/* virtual chan */
+	char ack;	/* ask ACK from peripheral */
+	char wait;	/* ms */
+	short dlen;	/* 16 bits */
+} __packed;
+
 struct dsi_cmd_desc {
-	int dtype;
-	int last;
-	int vc;
-	int ack;	/* ask ACK from peripheral */
-	int wait;
-	int dlen;
+	struct dsi_ctrl_hdr dchdr;
 	char *payload;
 };
 
+struct dsi_panel_cmds {
+	char *buf;
+	int blen;
+	struct dsi_cmd_desc *cmds;
+	int cmd_cnt;
+	int link_state;
+};
+
+#define CMD_REQ_MAX     4
+
+typedef void (*fxn)(u32 data);
+
+#define CMD_REQ_RX      0x0001
+#define CMD_REQ_COMMIT  0x0002
+#define CMD_CLK_CTRL    0x0004
+#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+
+struct dcs_cmd_req {
+	struct dsi_cmd_desc *cmds;
+	int cmds_cnt;
+	u32 flags;
+	int rlen;       /* rx length */
+	fxn cb;
+};
+
+struct dcs_cmd_list {
+	int put;
+	int get;
+	int tot;
+	struct dcs_cmd_req list[CMD_REQ_MAX];
+};
+
 struct dsi_kickoff_action {
 	struct list_head act_entry;
 	void (*action) (void *);
 	void *data;
 };
 
-struct dsi_panel_cmds_list {
-	struct dsi_cmd_desc *buf;
-	u32 size;
-	char ctrl_state;
-};
-
 struct mdss_panel_common_pdata {
 	struct mdss_panel_info panel_info;
 	int (*on) (struct mdss_panel_data *pdata);
 	int (*off) (struct mdss_panel_data *pdata);
 	void (*bl_fnc) (struct mdss_panel_data *pdata, u32 bl_level);
-	struct dsi_panel_cmds_list *dsi_panel_on_cmds;
-	struct dsi_panel_cmds_list *dsi_panel_off_cmds;
+
+	struct dsi_panel_cmds on_cmds;
+	struct dsi_panel_cmds off_cmds;
 };
 
 struct dsi_drv_cm_data {
@@ -278,14 +313,20 @@
 	int broadcast_enable;
 };
 
+enum {
+	DSI_CTRL_0,
+	DSI_CTRL_1,
+	DSI_CTRL_MAX,
+};
+
 struct mdss_dsi_ctrl_pdata {
-	int ndx;
+	int ndx;	/* panel_num */
 	int (*on) (struct mdss_panel_data *pdata);
 	int (*off) (struct mdss_panel_data *pdata);
 	struct mdss_panel_data panel_data;
-	struct mdss_hw *mdss_hw;
 	unsigned char *ctrl_base;
 	int reg_size;
+	u32 clk_cnt;
 	struct clk *byte_clk;
 	struct clk *esc_clk;
 	struct clk *pixel_clk;
@@ -297,16 +338,32 @@
 	int disp_te_gpio;
 	int bklt_ctrl;	/* backlight ctrl */
 	int pwm_period;
-	int pwm_gpio;
+	int pwm_pmic_gpio;
 	int pwm_lpg_chan;
 	int bklt_max;
 	struct pwm_device *pwm_bl;
-	struct dsi_panel_cmds_list *on_cmds;
-	struct dsi_panel_cmds_list *off_cmds;
 	struct dsi_drv_cm_data shared_pdata;
 	u32 pclk_rate;
 	u32 byte_clk_rate;
 	struct dss_module_power power_data;
+	u32 dsi_irq_mask;
+	struct mdss_hw *dsi_hw;
+
+	struct dsi_panel_cmds on_cmds;
+	struct dsi_panel_cmds off_cmds;
+
+	struct dcs_cmd_list cmdlist;
+	struct completion dma_comp;
+	struct completion mdp_comp;
+	struct completion video_comp;
+	spinlock_t irq_lock;
+	spinlock_t mdp_lock;
+	int mdp_busy;
+	struct mutex mutex;
+	struct mutex cmd_mutex;
+
+	struct dsi_buf tx_buf;
+	struct dsi_buf rx_buf;
 };
 
 int dsi_panel_device_register(struct platform_device *pdev,
@@ -317,29 +374,26 @@
 void mdss_dsi_init(void);
 int mdss_dsi_buf_alloc(struct dsi_buf *, int size);
 int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm);
-int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
-		struct dsi_buf *dp, struct dsi_cmd_desc *cmds, int cnt);
+int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+		struct dsi_cmd_desc *cmds, int cnt);
 
-int mdss_dsi_cmd_dma_tx(struct dsi_buf *dp,
-				struct mdss_panel_data *pdata);
-int mdss_dsi_cmd_reg_tx(u32 data,
-				unsigned char *ctrl_base);
-int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_buf *rp,
-			struct dsi_cmd_desc *cmds, int len);
-int mdss_dsi_cmd_dma_rx(struct dsi_buf *tp, int rlen,
-				struct mdss_panel_data *pdata);
+int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_cmd_desc *cmds, int rlen, u32 rx_flags);
+
 void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
 				struct mdss_panel_data *pdata);
 void mdss_dsi_op_mode_config(int mode,
 				struct mdss_panel_data *pdata);
 void mdss_dsi_cmd_mode_ctrl(int enable);
 void mdp4_dsi_cmd_trigger(void);
-void mdss_dsi_cmd_mdp_start(struct mdss_panel_data *pdata);
+void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl);
 void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
 void mdss_dsi_ack_err_status(unsigned char *dsi_base);
-void mdss_dsi_clk_enable(struct mdss_panel_data *pdata);
-void mdss_dsi_clk_disable(struct mdss_panel_data *pdata);
+void mdss_dsi_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
+void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl,
+				int enable);
 void mdss_dsi_controller_cfg(int enable,
 				struct mdss_panel_data *pdata);
 void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
@@ -362,4 +416,13 @@
 void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata);
 void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl);
 
+void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
+int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *cmdreq);
+struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl);
+void mdss_dsi_cmdlist_kickoff(int intf);
+
 #endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 3c0dfc2..6b210af 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -25,12 +25,11 @@
 #include "mdss.h"
 #include "mdss_dsi.h"
 
-static struct completion dsi_dma_comp;
-static spinlock_t dsi_irq_lock;
-static spinlock_t dsi_mdp_lock;
-static int dsi_mdp_busy;
 static struct mdss_dsi_ctrl_pdata *left_ctrl_pdata;
 
+static struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
+
+
 struct mdss_hw mdss_dsi0_hw = {
 	.hw_ndx = MDSS_HW_DSI0,
 	.ptr = NULL,
@@ -43,58 +42,128 @@
 	.irq_handler = mdss_dsi_isr,
 };
 
-void mdss_dsi_init(void)
+void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
 {
-	init_completion(&dsi_dma_comp);
-	spin_lock_init(&dsi_irq_lock);
-	spin_lock_init(&dsi_mdp_lock);
-}
-
-void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl)
-{
-	int ret;
-
 	if (ctrl->panel_data.panel_info.pdest == DISPLAY_1) {
 		mdss_dsi0_hw.ptr = (void *)(ctrl);
-		ctrl->mdss_hw = &mdss_dsi0_hw;
+		ctrl->dsi_hw = &mdss_dsi0_hw;
+		ctrl->ndx = DSI_CTRL_0;
 	} else {
 		mdss_dsi1_hw.ptr = (void *)(ctrl);
-		ctrl->mdss_hw = &mdss_dsi1_hw;
+		ctrl->dsi_hw = &mdss_dsi1_hw;
+		ctrl->ndx = DSI_CTRL_1;
 	}
 
-	ret = mdss_register_irq(ctrl->mdss_hw);
-	if (ret)
+	ctrl_list[ctrl->ndx] = ctrl;	/* keep it */
+
+	if (mdss_register_irq(ctrl->dsi_hw))
 		pr_err("%s: mdss_register_irq failed.\n", __func__);
+
+	pr_debug("%s: ndx=%d base=%p\n", __func__, ctrl->ndx, ctrl->ctrl_base);
+
+	init_completion(&ctrl->dma_comp);
+	init_completion(&ctrl->mdp_comp);
+	init_completion(&ctrl->video_comp);
+	spin_lock_init(&ctrl->irq_lock);
+	spin_lock_init(&ctrl->mdp_lock);
+	mutex_init(&ctrl->mutex);
+	mutex_init(&ctrl->cmd_mutex);
+	mdss_dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
+	mdss_dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
 }
 
-void mdss_dsi_irq_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable, int isr)
+/*
+ * acquire ctrl->mutex first
+ */
+void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
 {
-	unsigned long flags;
-
-	if (ctrl == NULL) {
-		pr_err("%s: Invalid ctrl\n", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&dsi_irq_lock, flags);
+	mutex_lock(&ctrl->mutex);
 	if (enable) {
-		if (ctrl->irq_cnt == 0)
-			mdss_enable_irq(ctrl->mdss_hw);
-		ctrl->irq_cnt++;
+		if (ctrl->clk_cnt == 0) {
+			mdss_dsi_prepare_clocks(ctrl);
+			mdss_dsi_clk_enable(ctrl);
+		}
+		ctrl->clk_cnt++;
 	} else {
-		if (ctrl->irq_cnt) {
-			ctrl->irq_cnt--;
-			if (ctrl->irq_cnt == 0) {
-				if (isr)
-					mdss_disable_irq_nosync(ctrl->mdss_hw);
-				else
-					mdss_disable_irq(ctrl->mdss_hw);
+		if (ctrl->clk_cnt) {
+			ctrl->clk_cnt--;
+			if (ctrl->clk_cnt == 0) {
+				mdss_dsi_clk_disable(ctrl);
+				mdss_dsi_unprepare_clocks(ctrl);
 			}
 		}
 	}
-	pr_debug("%s: ctrl=%d enable=%d cnt=%d\n", __func__,
-					ctrl->ndx, enable, ctrl->irq_cnt);
-	spin_unlock_irqrestore(&dsi_irq_lock, flags);
+	pr_debug("%s: ctrl ndx=%d enabled=%d clk_cnt=%d\n",
+			__func__, ctrl->ndx, enable, ctrl->clk_cnt);
+	mutex_unlock(&ctrl->mutex);
+}
+
+void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+{
+	if (enable == 0) {
+		/* need wait before disable */
+		mutex_lock(&ctrl->cmd_mutex);
+		mdss_dsi_cmd_mdp_busy(ctrl);
+		mutex_unlock(&ctrl->cmd_mutex);
+	}
+
+	mdss_dsi_clk_ctrl(ctrl, enable);
+}
+
+void mdss_dsi_enable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctrl->irq_lock, flags);
+	if (ctrl->dsi_irq_mask & term) {
+		spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+		return;
+	}
+	if (ctrl->dsi_irq_mask == 0) {
+		mdss_enable_irq(ctrl->dsi_hw);
+		pr_debug("%s: IRQ Enable, ndx=%d mask=%x term=%x\n", __func__,
+			ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term);
+	}
+	ctrl->dsi_irq_mask |= term;
+	spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+}
+
+void mdss_dsi_disable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctrl->irq_lock, flags);
+	if (!(ctrl->dsi_irq_mask & term)) {
+		spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+		return;
+	}
+	ctrl->dsi_irq_mask &= ~term;
+	if (ctrl->dsi_irq_mask == 0) {
+		mdss_disable_irq(ctrl->dsi_hw);
+		pr_debug("%s: IRQ Disable, ndx=%d mask=%x term=%x\n", __func__,
+			ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term);
+	}
+	spin_unlock_irqrestore(&ctrl->irq_lock, flags);
+}
+
+/*
+ * mdss_dsi_disale_irq_nosync() should be called
+ * from interrupt context
+ */
+void mdss_dsi_disable_irq_nosync(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
+{
+	spin_lock(&ctrl->irq_lock);
+	if (!(ctrl->dsi_irq_mask & term)) {
+		spin_unlock(&ctrl->irq_lock);
+		return;
+	}
+	ctrl->dsi_irq_mask &= ~term;
+	if (ctrl->dsi_irq_mask == 0) {
+		mdss_disable_irq_nosync(ctrl->dsi_hw);
+		pr_debug("%s: IRQ Disable, ndx=%d mask=%x term=%x\n", __func__,
+			ctrl->ndx, (int)ctrl->dsi_irq_mask, (int)term);
+	}
+	spin_unlock(&ctrl->irq_lock);
 }
 
 /*
@@ -165,18 +234,20 @@
  */
 static int mdss_dsi_generic_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	char *bp;
 	u32 *hp;
 	int i, len;
 
+	dchdr = &cm->dchdr;
 	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 
 	/* fill up payload */
 	if (cm->payload) {
-		len = cm->dlen;
+		len = dchdr->dlen;
 		len += 3;
 		len &= ~0x03;	/* multipled by 4 */
-		for (i = 0; i < cm->dlen; i++)
+		for (i = 0; i < dchdr->dlen; i++)
 			*bp++ = cm->payload[i];
 
 		/* append 0xff to the end */
@@ -189,11 +260,11 @@
 	/* fill up header */
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_LONG_PKT;
 	*hp |= DSI_HDR_DTYPE(DTYPE_GEN_LWRITE);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -206,10 +277,12 @@
  */
 static int mdss_dsi_generic_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 	int len;
 
-	if (cm->dlen && cm->payload == 0) {
+	dchdr = &cm->dchdr;
+	if (dchdr->dlen && cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return 0;
 	}
@@ -217,12 +290,12 @@
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
-	if (cm->last)
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 
-	len = (cm->dlen > 2) ? 2 : cm->dlen;
+	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
 
 	if (len == 1) {
 		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_WRITE1);
@@ -248,10 +321,12 @@
  */
 static int mdss_dsi_generic_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 	int len;
 
-	if (cm->dlen && cm->payload == 0) {
+	dchdr = &cm->dchdr;
+	if (dchdr->dlen && cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return 0;
 	}
@@ -259,12 +334,12 @@
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_BTA;
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
-	len = (cm->dlen > 2) ? 2 : cm->dlen;
+	len = (dchdr->dlen > 2) ? 2 : dchdr->dlen;
 
 	if (len == 1) {
 		*hp |= DSI_HDR_DTYPE(DTYPE_GEN_READ1);
@@ -289,10 +364,12 @@
  */
 static int mdss_dsi_dcs_lwrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	char *bp;
 	u32 *hp;
 	int i, len;
 
+	dchdr = &cm->dchdr;
 	bp = mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 
 	/*
@@ -300,10 +377,10 @@
 	 * dcs command byte (first byte) followed by payload
 	 */
 	if (cm->payload) {
-		len = cm->dlen;
+		len = dchdr->dlen;
 		len += 3;
 		len &= ~0x03;	/* multipled by 4 */
-		for (i = 0; i < cm->dlen; i++)
+		for (i = 0; i < dchdr->dlen; i++)
 			*bp++ = cm->payload[i];
 
 		/* append 0xff to the end */
@@ -316,11 +393,11 @@
 	/* fill up header */
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp = DSI_HDR_WC(dchdr->dlen);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_LONG_PKT;
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_LWRITE);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -333,9 +410,11 @@
  */
 static int mdss_dsi_dcs_swrite(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 	int len;
 
+	dchdr = &cm->dchdr;
 	if (cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return -EINVAL;
@@ -344,13 +423,13 @@
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
-	if (cm->ack)		/* ask ACK trigger msg from peripeheral */
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->ack)		/* ask ACK trigger msg from peripeheral */
 		*hp |= DSI_HDR_BTA;
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
-	len = (cm->dlen > 1) ? 1 : cm->dlen;
+	len = (dchdr->dlen > 1) ? 1 : dchdr->dlen;
 
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE);
 	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
@@ -365,9 +444,11 @@
  */
 static int mdss_dsi_dcs_swrite1(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
-	if (cm->dlen < 2 || cm->payload == 0) {
+	dchdr = &cm->dchdr;
+	if (dchdr->dlen < 2 || cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return -EINVAL;
 	}
@@ -375,10 +456,10 @@
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
-	if (cm->ack)		/* ask ACK trigger msg from peripeheral */
+	*hp |= DSI_HDR_VC(dchdr->vc);
+	if (dchdr->ack)		/* ask ACK trigger msg from peripeheral */
 		*hp |= DSI_HDR_BTA;
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_WRITE1);
@@ -395,8 +476,10 @@
 
 static int mdss_dsi_dcs_read(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	if (cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return -EINVAL;
@@ -405,10 +488,10 @@
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_BTA;
 	*hp |= DSI_HDR_DTYPE(DTYPE_DCS_READ);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	*hp |= DSI_HDR_DATA1(cm->payload[0]);	/* dcs command byte */
@@ -421,14 +504,16 @@
 
 static int mdss_dsi_cm_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_CM_ON);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -438,14 +523,16 @@
 
 static int mdss_dsi_cm_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_CM_OFF);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -455,14 +542,16 @@
 
 static int mdss_dsi_peripheral_on(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_ON);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -472,14 +561,16 @@
 
 static int mdss_dsi_peripheral_off(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_PERIPHERAL_OFF);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -489,8 +580,10 @@
 
 static int mdss_dsi_set_max_pktsize(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	if (cm->payload == 0) {
 		pr_err("%s: NO payload error\n", __func__);
 		return 0;
@@ -499,9 +592,9 @@
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_MAX_PKTSIZE);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	*hp |= DSI_HDR_DATA1(cm->payload[0]);
@@ -514,16 +607,18 @@
 
 static int mdss_dsi_null_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
+	*hp = DSI_HDR_WC(dchdr->dlen);
 	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_NULL_PKT);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -533,16 +628,18 @@
 
 static int mdss_dsi_blank_pkt(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	u32 *hp;
 
+	dchdr = &cm->dchdr;
 	mdss_dsi_buf_reserve_hdr(dp, DSI_HOST_HDR_SIZE);
 	hp = dp->hdr;
 	*hp = 0;
-	*hp = DSI_HDR_WC(cm->dlen);
+	*hp = DSI_HDR_WC(dchdr->dlen);
 	*hp |= DSI_HDR_LONG_PKT;
-	*hp |= DSI_HDR_VC(cm->vc);
+	*hp |= DSI_HDR_VC(dchdr->vc);
 	*hp |= DSI_HDR_DTYPE(DTYPE_BLANK_PKT);
-	if (cm->last)
+	if (dchdr->last)
 		*hp |= DSI_HDR_LAST;
 
 	mdss_dsi_buf_push(dp, DSI_HOST_HDR_SIZE);
@@ -555,9 +652,12 @@
  */
 int mdss_dsi_cmd_dma_add(struct dsi_buf *dp, struct dsi_cmd_desc *cm)
 {
+	struct dsi_ctrl_hdr *dchdr;
 	int len = 0;
 
-	switch (cm->dtype) {
+	dchdr = &cm->dchdr;
+
+	switch (dchdr->dtype) {
 	case DTYPE_GEN_WRITE:
 	case DTYPE_GEN_WRITE1:
 	case DTYPE_GEN_WRITE2:
@@ -606,7 +706,7 @@
 		break;
 	default:
 		pr_debug("%s: dtype=%x NOT supported\n",
-					__func__, cm->dtype);
+					__func__, dchdr->dtype);
 		break;
 
 	}
@@ -820,7 +920,7 @@
 	wmb();
 }
 
-void mipi_set_tx_power_mode(int mode, struct mdss_panel_data *pdata)
+void mdss_set_tx_power_mode(int mode, struct mdss_panel_data *pdata)
 {
 	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	u32 data;
@@ -1034,94 +1134,84 @@
 	return 4;
 }
 
+
+static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+					struct dsi_buf *tp);
+
+static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_buf *rp, int rlen);
 /*
  * mdss_dsi_cmds_tx:
- * ov_mutex need to be acquired before call this function.
+ * thread context only
  */
-int mdss_dsi_cmds_tx(struct mdss_panel_data *pdata,
-		struct dsi_buf *tp, struct dsi_cmd_desc *cmds, int cnt)
+int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+		struct dsi_cmd_desc *cmds, int cnt)
 {
+	struct dsi_buf *tp;
 	struct dsi_cmd_desc *cm;
-	u32 dsi_ctrl, ctrl;
+	struct dsi_ctrl_hdr *dchdr;
+	u32 dsi_ctrl, data;
 	int i, video_mode;
-	unsigned long flag;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return -EINVAL;
-	}
-
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-
-	if (ctrl_pdata->shared_pdata.broadcast_enable)
-		if (pdata->panel_info.pdest == DISPLAY_1) {
+	if (ctrl->shared_pdata.broadcast_enable) {
+		if (ctrl->ndx == DSI_CTRL_0) {
 			pr_debug("%s: Broadcast mode. 1st ctrl\n",
 				 __func__);
 			return 0;
 		}
+	}
+
+	if (ctrl->shared_pdata.broadcast_enable) {
+		if ((ctrl->ndx == DSI_CTRL_1)
+		  && (left_ctrl_pdata != NULL)) {
+			dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
+								+ 0x0004);
+			video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+			if (video_mode) {
+				data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
+						data);
+			}
+		}
+	}
 
 	/* turn on cmd mode
 	* for video mode, do not send cmds more than
 	* one pixel line, since it only transmit it
 	* during BLLP.
 	*/
-
-	if (ctrl_pdata->shared_pdata.broadcast_enable)
-		if ((pdata->panel_info.pdest == DISPLAY_2)
-		  && (left_ctrl_pdata != NULL)) {
-			dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
-								+ 0x0004);
-			video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
-			if (video_mode) {
-				ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
-				MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
-						ctrl);
-			}
-		}
-
-	dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
+	dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
 	video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
 	if (video_mode) {
-		ctrl = dsi_ctrl | 0x04; /* CMD_MODE_EN */
-		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, ctrl);
+		data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+		MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
 	}
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0);
-
-	dsi_mdp_busy = true;
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
+	tp = &ctrl->tx_buf;
 	cm = cmds;
-	mdss_dsi_buf_init(tp);
 	for (i = 0; i < cnt; i++) {
+		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
 		mdss_dsi_buf_init(tp);
 		mdss_dsi_cmd_dma_add(tp, cm);
-		mdss_dsi_cmd_dma_tx(tp, pdata);
-		if (cm->wait)
-			msleep(cm->wait);
+		mdss_dsi_cmd_dma_tx(ctrl, tp);
+		dchdr = &cm->dchdr;
+		if (dchdr->wait)
+			usleep(dchdr->wait * 1000);
 		cm++;
 	}
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = false;
-	mdss_dsi_irq_ctrl(ctrl_pdata, 0, 0);
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	if (video_mode)
-		MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
+		MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
 					dsi_ctrl); /* restore */
 	return cnt;
 }
 
-/* MDSS_DSI_MRPS, Maximum Return Packet Size */
+/* MIPI_DSI_MRPS, Maximum Return Packet Size */
 static char max_pktsize[2] = {0x00, 0x00}; /* LSB tx first, 10 bytes */
 
-static struct dsi_cmd_desc pkt_size_cmd[] = {
-	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0,
-		sizeof(max_pktsize), max_pktsize}
+static struct dsi_cmd_desc pkt_size_cmd = {
+	{DTYPE_MAX_PKTSIZE, 1, 0, 0, 0, sizeof(max_pktsize)},
+	max_pktsize,
 };
 
 /*
@@ -1129,31 +1219,24 @@
  * plus DCS header, ECC and CRC for DCS long read response
  * mdss_dsi_controller only have 4x32 bits register ( 16 bytes) to
  * hold data per transaction.
- * MDSS_DSI_LEN equal to 8
+ * MIPI_DSI_LEN equal to 8
  * len should be either 4 or 8
- * any return data more than MDSS_DSI_LEN need to be break down
+ * any return data more than MIPI_DSI_LEN need to be break down
  * to multiple transactions.
  *
  * ov_mutex need to be acquired before call this function.
  */
-int mdss_dsi_cmds_rx(struct mdss_panel_data *pdata,
-			struct dsi_buf *tp, struct dsi_buf *rp,
-			struct dsi_cmd_desc *cmds, int rlen)
+
+int mdss_dsi_cmds_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_cmd_desc *cmds, int rlen, u32 rx_flags)
 {
 	int cnt, len, diff, pkt_size;
-	unsigned long flag;
+	struct dsi_buf *tp, *rp;
+	int no_max_pkt_size;
 	char cmd;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return -EINVAL;
-	}
-
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
-
-	if (pdata->panel_info.mipi.no_max_pkt_size)
+	no_max_pkt_size = rx_flags & CMD_REQ_NO_MAX_PKT_SIZE;
+	if (no_max_pkt_size)
 		rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
 
 	len = rlen;
@@ -1178,33 +1261,33 @@
 		cnt = len + 6; /* 4 bytes header + 2 bytes crc */
 	}
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0);
-	dsi_mdp_busy = true;
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+	tp = &ctrl->tx_buf;
+	rp = &ctrl->rx_buf;
 
-	if (!pdata->panel_info.mipi.no_max_pkt_size) {
+	if (!no_max_pkt_size) {
 		/* packet size need to be set at every read */
 		pkt_size = len;
 		max_pktsize[0] = pkt_size;
+		mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
 		mdss_dsi_buf_init(tp);
-		mdss_dsi_cmd_dma_add(tp, pkt_size_cmd);
-		mdss_dsi_cmd_dma_tx(tp, pdata);
+		mdss_dsi_cmd_dma_add(tp, &pkt_size_cmd);
+		mdss_dsi_cmd_dma_tx(ctrl, tp);
 		pr_debug("%s: Max packet size sent\n", __func__);
 	}
 
+	mdss_dsi_enable_irq(ctrl, DSI_CMD_TERM);
 	mdss_dsi_buf_init(tp);
 	mdss_dsi_cmd_dma_add(tp, cmds);
 
 	/* transmit read comamnd to client */
-	mdss_dsi_cmd_dma_tx(tp, pdata);
+	mdss_dsi_cmd_dma_tx(ctrl, tp);
 	/*
 	 * once cmd_dma_done interrupt received,
 	 * return data from client is ready and stored
 	 * at RDBK_DATA register already
 	 */
 	mdss_dsi_buf_init(rp);
-	if (pdata->panel_info.mipi.no_max_pkt_size) {
+	if (no_max_pkt_size) {
 		/*
 		 * expect rlen = n * 4
 		 * short alignement for start addr
@@ -1212,14 +1295,9 @@
 		rp->data += 2;
 	}
 
-	mdss_dsi_cmd_dma_rx(rp, cnt, pdata);
+	mdss_dsi_cmd_dma_rx(ctrl, rp, cnt);
 
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = false;
-	mdss_dsi_irq_ctrl(ctrl_pdata, 0, 0);
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
-	if (pdata->panel_info.mipi.no_max_pkt_size) {
+	if (no_max_pkt_size) {
 		/*
 		 * remove extra 2 bytes from previous
 		 * rx transaction at shift register
@@ -1257,22 +1335,16 @@
 	return rp->len;
 }
 
-int mdss_dsi_cmd_dma_tx(struct dsi_buf *tp,
-			struct mdss_panel_data *pdata)
+#define DMA_TX_TIMEOUT 200
+
+static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+					struct dsi_buf *tp)
 {
 	int len;
 	int domain = MDSS_IOMMU_DOMAIN_UNSECURE;
 	char *bp;
 	unsigned long size, addr;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return -EINVAL;
-	}
-
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
 	bp = tp->data;
 
 	len = ALIGN(tp->len, 4);
@@ -1296,29 +1368,32 @@
 		addr = tp->dmap;
 	}
 
-	INIT_COMPLETION(dsi_dma_comp);
+	INIT_COMPLETION(ctrl->dma_comp);
 
-	if (ctrl_pdata->shared_pdata.broadcast_enable)
-		if ((pdata->panel_info.pdest == DISPLAY_2)
+	if (ctrl->shared_pdata.broadcast_enable)
+		if ((ctrl->ndx == DSI_CTRL_1)
 		  && (left_ctrl_pdata != NULL)) {
 			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x048, addr);
 			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x04c, len);
 		}
 
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x048, addr);
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04c, len);
+	MIPI_OUTP((ctrl->ctrl_base) + 0x048, addr);
+	MIPI_OUTP((ctrl->ctrl_base) + 0x04c, len);
 	wmb();
 
-	if (ctrl_pdata->shared_pdata.broadcast_enable)
-		if ((pdata->panel_info.pdest == DISPLAY_2)
+	if (ctrl->shared_pdata.broadcast_enable)
+		if ((ctrl->ndx == DSI_CTRL_1)
 		  && (left_ctrl_pdata != NULL)) {
 			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01);
 		}
 
-	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x090, 0x01);	/* trigger */
+	MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01);	/* trigger */
 	wmb();
 
-	wait_for_completion(&dsi_dma_comp);
+	if (!wait_for_completion_timeout(&ctrl->dma_comp,
+				msecs_to_jiffies(DMA_TX_TIMEOUT))) {
+		pr_err("%s: dma timeout error\n", __func__);
+	}
 
 	if (is_mdss_iommu_attached())
 		msm_iommu_unmap_contig_buffer(addr,
@@ -1329,20 +1404,13 @@
 	return tp->len;
 }
 
-int mdss_dsi_cmd_dma_rx(struct dsi_buf *rp, int rlen,
-			struct mdss_panel_data *pdata)
+static int mdss_dsi_cmd_dma_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_buf *rp, int rlen)
+
 {
 	u32 *lp, data;
 	int i, off, cnt;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 
-	if (pdata == NULL) {
-		pr_err("%s: Invalid input data\n", __func__);
-		return -EINVAL;
-	}
-
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
 	lp = (u32 *)rp->data;
 	cnt = rlen;
 	cnt += 3;
@@ -1354,106 +1422,289 @@
 	off = 0x06c;	/* DSI_RDBK_DATA0 */
 	off += ((cnt - 1) * 4);
 
-
 	for (i = 0; i < cnt; i++) {
-		data = (u32)MIPI_INP((ctrl_pdata->ctrl_base) + off);
+		data = (u32)MIPI_INP((ctrl->ctrl_base) + off);
 		*lp++ = ntohl(data);	/* to network byte order */
 		pr_debug("%s: data = 0x%x and ntohl(data) = 0x%x\n",
 					 __func__, data, ntohl(data));
 		off -= 4;
 		rp->len += sizeof(*lp);
 	}
-
 	return rlen;
 }
 
-void mdss_dsi_ack_err_status(unsigned char *dsi_base)
+#define VSYNC_PERIOD 17
+
+void mdss_dsi_wait4video_done(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&ctrl->mdp_lock, flag);
+	INIT_COMPLETION(ctrl->video_comp);
+	mdss_dsi_enable_irq(ctrl, DSI_VIDEO_TERM);
+	spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
+
+	wait_for_completion_timeout(&ctrl->video_comp,
+			msecs_to_jiffies(VSYNC_PERIOD * 4));
+}
+
+static void mdss_dsi_wait4video_eng_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	mdss_dsi_wait4video_done(ctrl);
+	/* delay 4 ms to skip BLLP */
+	usleep(4000);
+}
+
+void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	unsigned long flag;
+
+	spin_lock_irqsave(&ctrl->mdp_lock, flag);
+	mdss_dsi_enable_irq(ctrl, DSI_MDP_TERM);
+	ctrl->mdp_busy = true;
+	INIT_COMPLETION(ctrl->mdp_comp);
+	spin_unlock_irqrestore(&ctrl->mdp_lock, flag);
+}
+
+void mdss_dsi_cmd_mdp_busy(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	unsigned long flags;
+	int need_wait = 0;
+
+	pr_debug("%s: start pid=%d\n",
+				__func__, current->pid);
+	spin_lock_irqsave(&ctrl->mdp_lock, flags);
+	if (ctrl->mdp_busy == true)
+		need_wait++;
+	spin_unlock_irqrestore(&ctrl->mdp_lock, flags);
+
+	if (need_wait) {
+		/* wait until DMA finishes the current job */
+		pr_debug("%s: pending pid=%d\n",
+				__func__, current->pid);
+		wait_for_completion(&ctrl->mdp_comp);
+	}
+	pr_debug("%s: done pid=%d\n",
+				__func__, current->pid);
+}
+
+void mdss_dsi_cmdlist_tx(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *req)
+{
+	int ret;
+
+	ret = mdss_dsi_cmds_tx(ctrl, req->cmds, req->cmds_cnt);
+
+	if (req->cb)
+		req->cb(ret);
+
+}
+
+void mdss_dsi_cmdlist_rx(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *req)
+{
+	int len;
+	u32 data, *dp;
+	struct dsi_buf *rp;
+
+	len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen, req->flags);
+	rp = &ctrl->rx_buf;
+	dp = (u32 *)rp->data;
+	data = *dp;
+
+	if (req->cb)
+		req->cb(data);
+}
+
+void mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
+{
+	struct dcs_cmd_req *req;
+	u32 data;
+
+	mutex_lock(&ctrl->cmd_mutex);
+	req = mdss_dsi_cmdlist_get(ctrl);
+
+	/* make sure dsi_cmd_mdp is idle */
+	mdss_dsi_cmd_mdp_busy(ctrl);
+
+	if (req == NULL)
+		goto need_lock;
+
+	pr_debug("%s:  from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
+	mdss_dsi_clk_ctrl(ctrl, 1);
+
+	data = MIPI_INP((ctrl->ctrl_base) + 0x0004);
+	if (data & 0x02) {
+		/* video mode, make sure video engine is busy
+		 * so dcs command will be sent at start of BLLP
+		 */
+		mdss_dsi_wait4video_eng_busy(ctrl);
+	} else {
+		/* command mode */
+		if (!from_mdp) { /* cmdlist_put */
+			/* make sure dsi_cmd_mdp is idle */
+			mdss_dsi_cmd_mdp_busy(ctrl);
+		}
+	}
+
+	if (req->flags & CMD_REQ_RX)
+		mdss_dsi_cmdlist_rx(ctrl, req);
+	else
+		mdss_dsi_cmdlist_tx(ctrl, req);
+
+	mdss_dsi_clk_ctrl(ctrl, 0);
+
+need_lock:
+
+	if (from_mdp) /* from pipe_commit */
+		mdss_dsi_cmd_mdp_start(ctrl);
+
+	mutex_unlock(&ctrl->cmd_mutex);
+}
+
+/*
+ * mdss_dsi_cmd_get: ctrl->cmd_mutex acquired by caller
+ */
+struct dcs_cmd_req *mdss_dsi_cmdlist_get(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct dcs_cmd_list *clist;
+	struct dcs_cmd_req *req = NULL;
+
+	clist = &ctrl->cmdlist;
+	if (clist->get != clist->put) {
+		req = &clist->list[clist->get];
+		clist->get++;
+		clist->get %= CMD_REQ_MAX;
+		clist->tot--;
+		pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+		clist->tot, clist->put, clist->get);
+	}
+	return req;
+}
+
+int mdss_dsi_cmdlist_put(struct mdss_dsi_ctrl_pdata *ctrl,
+				struct dcs_cmd_req *cmdreq)
+{
+	struct dcs_cmd_req *req;
+	struct dcs_cmd_list *clist;
+	int ret = 0;
+
+	mutex_lock(&ctrl->cmd_mutex);
+	clist = &ctrl->cmdlist;
+	req = &clist->list[clist->put];
+	*req = *cmdreq;
+	clist->put++;
+	clist->put %= CMD_REQ_MAX;
+	clist->tot++;
+	if (clist->put == clist->get) {
+		/* drop the oldest one */
+		pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
+			clist->tot, clist->put, clist->get);
+		clist->get++;
+		clist->get %= CMD_REQ_MAX;
+		clist->tot--;
+	}
+	mutex_unlock(&ctrl->cmd_mutex);
+
+	ret++;
+	pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+		clist->tot, clist->put, clist->get);
+
+	if (req->flags & CMD_REQ_COMMIT)
+		mdss_dsi_cmdlist_commit(ctrl, 0);
+
+	return ret;
+}
+
+void mdss_dsi_ack_err_status(unsigned char *base)
 {
 	u32 status;
 
-	status = MIPI_INP(dsi_base + 0x0068);/* DSI_ACK_ERR_STATUS */
+	status = MIPI_INP(base + 0x0068);/* DSI_ACK_ERR_STATUS */
 
 	if (status) {
-		MIPI_OUTP(dsi_base + 0x0068, status);
+		MIPI_OUTP(base + 0x0068, status);
 		pr_debug("%s: status=%x\n", __func__, status);
 	}
 }
 
-void mdss_dsi_timeout_status(unsigned char *dsi_base)
+void mdss_dsi_timeout_status(unsigned char *base)
 {
 	u32 status;
 
-	status = MIPI_INP(dsi_base + 0x00c0);/* DSI_TIMEOUT_STATUS */
+	status = MIPI_INP(base + 0x00c0);/* DSI_TIMEOUT_STATUS */
 	if (status & 0x0111) {
-		MIPI_OUTP(dsi_base + 0x00c0, status);
+		MIPI_OUTP(base + 0x00c0, status);
 		pr_debug("%s: status=%x\n", __func__, status);
 	}
 }
 
-void mdss_dsi_dln0_phy_err(unsigned char *dsi_base)
+void mdss_dsi_dln0_phy_err(unsigned char *base)
 {
 	u32 status;
 
-	status = MIPI_INP(dsi_base + 0x00b4);/* DSI_DLN0_PHY_ERR */
+	status = MIPI_INP(base + 0x00b4);/* DSI_DLN0_PHY_ERR */
 
 	if (status & 0x011111) {
-		MIPI_OUTP(dsi_base + 0x00b4, status);
+		MIPI_OUTP(base + 0x00b4, status);
 		pr_debug("%s: status=%x\n", __func__, status);
 	}
 }
 
-void mdss_dsi_fifo_status(unsigned char *dsi_base)
+void mdss_dsi_fifo_status(unsigned char *base)
 {
 	u32 status;
 
-	status = MIPI_INP(dsi_base + 0x000c);/* DSI_FIFO_STATUS */
+	status = MIPI_INP(base + 0x000c);/* DSI_FIFO_STATUS */
 
 	if (status & 0x44444489) {
-		MIPI_OUTP(dsi_base + 0x000c, status);
+		MIPI_OUTP(base + 0x000c, status);
 		pr_debug("%s: status=%x\n", __func__, status);
 	}
 }
 
-void mdss_dsi_status(unsigned char *dsi_base)
+void mdss_dsi_status(unsigned char *base)
 {
 	u32 status;
 
-	status = MIPI_INP(dsi_base + 0x0008);/* DSI_STATUS */
+	status = MIPI_INP(base + 0x0008);/* DSI_STATUS */
 
 	if (status & 0x80000000) {
-		MIPI_OUTP(dsi_base + 0x0008, status);
+		MIPI_OUTP(base + 0x0008, status);
 		pr_debug("%s: status=%x\n", __func__, status);
 	}
 }
 
-void mdss_dsi_error(unsigned char *dsi_base)
+void mdss_dsi_error(struct mdss_dsi_ctrl_pdata *ctrl)
 {
+	unsigned char *base;
+
+	base = ctrl->ctrl_base;
+
 	/* DSI_ERR_INT_MASK0 */
-	mdss_dsi_ack_err_status(dsi_base);	/* mask0, 0x01f */
-	mdss_dsi_timeout_status(dsi_base);	/* mask0, 0x0e0 */
-	mdss_dsi_fifo_status(dsi_base);		/* mask0, 0x133d00 */
-	mdss_dsi_status(dsi_base);		/* mask0, 0xc0100 */
-	mdss_dsi_dln0_phy_err(dsi_base);	/* mask0, 0x3e00000 */
+	mdss_dsi_ack_err_status(base);	/* mask0, 0x01f */
+	mdss_dsi_timeout_status(base);	/* mask0, 0x0e0 */
+	mdss_dsi_fifo_status(base);		/* mask0, 0x133d00 */
+	mdss_dsi_status(base);		/* mask0, 0xc0100 */
+	mdss_dsi_dln0_phy_err(base);	/* mask0, 0x3e00000 */
 }
 
 
 irqreturn_t mdss_dsi_isr(int irq, void *ptr)
 {
 	u32 isr;
-	unsigned char *dsi_base;
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata =
+	struct mdss_dsi_ctrl_pdata *ctrl =
 			(struct mdss_dsi_ctrl_pdata *)ptr;
 
-	dsi_base = ctrl_pdata->ctrl_base;
-	if (!dsi_base)
+	if (!ctrl->ctrl_base)
 		pr_err("%s:%d DSI base adr no Initialized",
 				       __func__, __LINE__);
 
-	isr = MIPI_INP(dsi_base + 0x0110);/* DSI_INTR_CTRL */
-	MIPI_OUTP(dsi_base + 0x0110, isr);
+	isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
+	MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);
 
-	if (ctrl_pdata->shared_pdata.broadcast_enable)
-		if ((ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_2)
+	if (ctrl->shared_pdata.broadcast_enable)
+		if ((ctrl->panel_data.panel_info.pdest == DISPLAY_2)
 		    && (left_ctrl_pdata != NULL)) {
 			u32 isr0;
 			isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base
@@ -1461,24 +1712,38 @@
 			MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0);
 		}
 
-	pr_debug("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
+	pr_debug("%s: isr=%x", __func__, isr);
 
-	if (isr & DSI_INTR_ERROR)
-		mdss_dsi_error(dsi_base);
-
-	if (isr & DSI_INTR_VIDEO_DONE) {
-		/*
-		* do something  here
-		*/
+	if (isr & DSI_INTR_ERROR) {
+		pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
+		spin_lock(&ctrl->mdp_lock);
+		ctrl->mdp_busy = false;
+		mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
+		complete(&ctrl->mdp_comp);
+		mdss_dsi_error(ctrl);
+		spin_unlock(&ctrl->mdp_lock);
 	}
 
-	if (isr & DSI_INTR_CMD_DMA_DONE)
-		complete(&dsi_dma_comp);
+	if (isr & DSI_INTR_VIDEO_DONE) {
+		spin_lock(&ctrl->mdp_lock);
+		mdss_dsi_disable_irq_nosync(ctrl, DSI_VIDEO_TERM);
+		complete(&ctrl->video_comp);
+		spin_unlock(&ctrl->mdp_lock);
+	}
+
+	if (isr & DSI_INTR_CMD_DMA_DONE) {
+		spin_lock(&ctrl->mdp_lock);
+		mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM);
+		complete(&ctrl->dma_comp);
+		spin_unlock(&ctrl->mdp_lock);
+	}
 
 	if (isr & DSI_INTR_CMD_MDP_DONE) {
-		spin_lock(&dsi_mdp_lock);
-		dsi_mdp_busy = false;
-		spin_unlock(&dsi_mdp_lock);
+		spin_lock(&ctrl->mdp_lock);
+		ctrl->mdp_busy = false;
+		mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
+		complete(&ctrl->mdp_comp);
+		spin_unlock(&ctrl->mdp_lock);
 	}
 
 	return IRQ_HANDLED;
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index c56cd41..6b0f68e 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -26,9 +26,6 @@
 
 #define DT_CMD_HDR 6
 
-static struct dsi_buf dsi_panel_tx_buf;
-static struct dsi_buf dsi_panel_rx_buf;
-
 DEFINE_LED_TRIGGER(bl_led_trigger);
 
 static struct mdss_dsi_phy_ctrl phy_params;
@@ -37,16 +34,18 @@
 {
 	int ret;
 
-	if (!gpio_is_valid(ctrl->pwm_gpio)) {
-		pr_err("%s: pwm_gpio=%d Invalid\n", __func__,
-				ctrl->pwm_gpio);
+	if (!gpio_is_valid(ctrl->pwm_pmic_gpio)) {
+		pr_err("%s: pwm_pmic_gpio=%d Invalid\n", __func__,
+				ctrl->pwm_pmic_gpio);
+		ctrl->pwm_pmic_gpio = -1;
 		return;
 	}
 
-	ret = gpio_request(ctrl->pwm_gpio, "disp_pwm");
+	ret = gpio_request(ctrl->pwm_pmic_gpio, "disp_pwm");
 	if (ret) {
-		pr_err("%s: pwm_gpio=%d request failed\n", __func__,
-				ctrl->pwm_gpio);
+		pr_err("%s: pwm_pmic_gpio=%d request failed\n", __func__,
+				ctrl->pwm_pmic_gpio);
+		ctrl->pwm_pmic_gpio = -1;
 		return;
 	}
 
@@ -54,8 +53,8 @@
 	if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
 		pr_err("%s: lpg_chan=%d pwm request failed", __func__,
 				ctrl->pwm_lpg_chan);
-		gpio_free(ctrl->pwm_gpio);
-		ctrl->pwm_gpio = -1;
+		gpio_free(ctrl->pwm_pmic_gpio);
+		ctrl->pwm_pmic_gpio = -1;
 	}
 }
 
@@ -74,7 +73,7 @@
 
 	pr_debug("%s: bklt_ctrl=%d pwm_period=%d pwm_gpio=%d pwm_lpg_chan=%d\n",
 			__func__, ctrl->bklt_ctrl, ctrl->pwm_period,
-				ctrl->pwm_gpio, ctrl->pwm_lpg_chan);
+				ctrl->pwm_pmic_gpio, ctrl->pwm_lpg_chan);
 
 	pr_debug("%s: ndx=%d level=%d duty=%d\n", __func__,
 					ctrl->ndx, level, duty);
@@ -90,6 +89,71 @@
 		pr_err("%s: pwm_enable() failed err=%d\n", __func__, ret);
 }
 
+static char dcs_cmd[2] = {0x54, 0x00}; /* DTYPE_DCS_READ */
+static struct dsi_cmd_desc dcs_read_cmd = {
+	{DTYPE_DCS_READ, 1, 0, 1, 5, sizeof(dcs_cmd)},
+	dcs_cmd
+};
+
+u32 mdss_dsi_dcs_read(struct mdss_dsi_ctrl_pdata *ctrl,
+			char cmd0, char cmd1)
+{
+	struct dcs_cmd_req cmdreq;
+
+	dcs_cmd[0] = cmd0;
+	dcs_cmd[1] = cmd1;
+	memset(&cmdreq, 0, sizeof(cmdreq));
+	cmdreq.cmds = &dcs_read_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_RX | CMD_REQ_COMMIT;
+	cmdreq.rlen = 1;
+	cmdreq.cb = NULL; /* call back */
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+	/*
+	 * blocked here, until call back called
+	 */
+
+	return 0;
+}
+
+static void mdss_dsi_panel_cmds_send(struct mdss_dsi_ctrl_pdata *ctrl,
+			struct dsi_panel_cmds *pcmds)
+{
+	struct dcs_cmd_req cmdreq;
+
+	memset(&cmdreq, 0, sizeof(cmdreq));
+	cmdreq.cmds = pcmds->cmds;
+	cmdreq.cmds_cnt = pcmds->cmd_cnt;
+	cmdreq.flags = CMD_REQ_COMMIT;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
+
+static char led_pwm1[2] = {0x51, 0x0};	/* DTYPE_DCS_WRITE1 */
+static struct dsi_cmd_desc backlight_cmd = {
+	{DTYPE_DCS_WRITE1, 1, 0, 0, 1, sizeof(led_pwm1)},
+	led_pwm1
+};
+
+static void mdss_dsi_panel_bklt_dcs(struct mdss_dsi_ctrl_pdata *ctrl, int level)
+{
+	struct dcs_cmd_req cmdreq;
+
+	pr_debug("%s: level=%d\n", __func__, level);
+
+	led_pwm1[1] = (unsigned char)level;
+
+	memset(&cmdreq, 0, sizeof(cmdreq));
+	cmdreq.cmds = &backlight_cmd;
+	cmdreq.cmds_cnt = 1;
+	cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL;
+	cmdreq.rlen = 0;
+	cmdreq.cb = NULL;
+
+	mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+}
 
 void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
 {
@@ -152,6 +216,9 @@
 	case BL_PWM:
 		mdss_dsi_panel_bklt_pwm(ctrl_pdata, bl_level);
 		break;
+	case BL_DCS_CMD:
+		mdss_dsi_panel_bklt_dcs(ctrl_pdata, bl_level);
+		break;
 	default:
 		pr_err("%s: Unknown bl_ctrl configuration\n",
 			__func__);
@@ -159,14 +226,6 @@
 	}
 }
 
-static char set_tear_on[2] = {0x35, 0x00};
-static struct dsi_cmd_desc dsi_tear_on_cmd = {
-	DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on), set_tear_on};
-
-static char set_tear_off[2] = {0x34, 0x00};
-static struct dsi_cmd_desc dsi_tear_off_cmd = {
-	DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off), set_tear_off};
-
 static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
 {
 	struct mipi_panel_info *mipi;
@@ -183,14 +242,10 @@
 
 	pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx);
 
-	if (ctrl->on_cmds->size)
-		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
-				 ctrl->on_cmds->buf,
-				 ctrl->on_cmds->size);
+	if (ctrl->on_cmds.cmd_cnt)
+		mdss_dsi_panel_cmds_send(ctrl, &ctrl->on_cmds);
 
-	mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
-			&dsi_tear_on_cmd, 1);
-
+	pr_debug("%s:-\n", __func__);
 	return 0;
 }
 
@@ -211,17 +266,95 @@
 
 	mipi  = &pdata->panel_info.mipi;
 
-	mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
-			&dsi_tear_off_cmd, 1);
+	if (ctrl->off_cmds.cmd_cnt)
+		mdss_dsi_panel_cmds_send(ctrl, &ctrl->off_cmds);
 
-	if (ctrl->off_cmds->size)
-		mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
-				 ctrl->off_cmds->buf,
-				 ctrl->off_cmds->size);
+	pr_debug("%s:-\n", __func__);
+	return 0;
+}
+
+
+static int mdss_dsi_parse_dcs_cmds(struct device_node *np,
+		struct dsi_panel_cmds *pcmds, char *cmd_key, char *link_key)
+{
+	const char *data;
+	int blen = 0, len;
+	char *buf, *bp;
+	struct dsi_ctrl_hdr *dchdr;
+	int i, cnt;
+
+	data = of_get_property(np, cmd_key, &blen);
+	if (!data) {
+		pr_err("%s: failed, key=%s\n", __func__, cmd_key);
+		return -ENOMEM;
+	}
+
+	buf = kzalloc(sizeof(char) * blen, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	memcpy(buf, data, blen);
+
+	/* scan dcs commands */
+	bp = buf;
+	len = blen;
+	cnt = 0;
+	while (len > sizeof(*dchdr)) {
+		dchdr = (struct dsi_ctrl_hdr *)bp;
+		dchdr->dlen = ntohs(dchdr->dlen);
+		if (dchdr->dlen > len) {
+			pr_err("%s: dtsi cmd=%x error, len=%d",
+				__func__, dchdr->dtype, dchdr->dlen);
+			return -ENOMEM;
+		}
+		bp += sizeof(*dchdr);
+		len -= sizeof(*dchdr);
+		bp += dchdr->dlen;
+		len -= dchdr->dlen;
+		cnt++;
+	}
+
+	if (len != 0) {
+		pr_err("%s: dcs_cmd=%x len=%d error!",
+				__func__, buf[0], blen);
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	pcmds->cmds = kzalloc(cnt * sizeof(struct dsi_cmd_desc),
+						GFP_KERNEL);
+	if (!pcmds->cmds)
+		return -ENOMEM;
+
+	pcmds->cmd_cnt = cnt;
+	pcmds->buf = buf;
+	pcmds->blen = blen;
+
+	bp = buf;
+	len = blen;
+	for (i = 0; i < cnt; i++) {
+		dchdr = (struct dsi_ctrl_hdr *)bp;
+		len -= sizeof(*dchdr);
+		bp += sizeof(*dchdr);
+		pcmds->cmds[i].dchdr = *dchdr;
+		pcmds->cmds[i].payload = bp;
+		bp += dchdr->dlen;
+		len -= dchdr->dlen;
+	}
+
+	pcmds->link_state = DSI_LP_MODE; /* default */
+
+	data = of_get_property(np, link_key, NULL);
+	if (!strncmp(data, "DSI_HS_MODE", 11))
+		pcmds->link_state = DSI_HS_MODE;
+
+	pr_debug("%s: dcs_cmd=%x len=%d, cmd_cnt=%d link_state=%d\n", __func__,
+		pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt, pcmds->link_state);
 
 	return 0;
 }
 
+
 static int mdss_panel_parse_dt(struct platform_device *pdev,
 			       struct mdss_panel_common_pdata *panel_data)
 {
@@ -229,12 +362,8 @@
 	u32 res[6], tmp;
 	u32 fbc_res[7];
 	int rc, i, len;
-	int cmd_plen, data_offset;
 	const char *data;
 	static const char *bl_ctrl_type, *pdest;
-	static const char *on_cmds_state, *off_cmds_state;
-	char *on_cmds = NULL, *off_cmds = NULL;
-	int num_of_on_cmds = 0, num_of_off_cmds = 0;
 	bool fbc_enabled = false;
 
 	rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
@@ -301,15 +430,15 @@
 	} else if (!strncmp(bl_ctrl_type, "bl_ctrl_pwm", 11)) {
 		panel_data->panel_info.bklt_ctrl = BL_PWM;
 
-		rc = of_property_read_u32(np, "qcom,dsi-pwm-period", &tmp);
+		rc = of_property_read_u32(np, "qcom,pwm-period", &tmp);
 		if (rc) {
-			pr_err("%s:%d, Error, dsi pwm_period\n",
+			pr_err("%s:%d, Error, panel pwm_period\n",
 						__func__, __LINE__);
 			return -EINVAL;
 		}
 		panel_data->panel_info.pwm_period = tmp;
 
-		rc = of_property_read_u32(np, "qcom,dsi-lpg-channel", &tmp);
+		rc = of_property_read_u32(np, "qcom,pwm-lpg-channel", &tmp);
 		if (rc) {
 			pr_err("%s:%d, Error, dsi lpg channel\n",
 						__func__, __LINE__);
@@ -317,8 +446,10 @@
 		}
 		panel_data->panel_info.pwm_lpg_chan = tmp;
 
-		tmp = of_get_named_gpio(np, "qcom,dsi-pwm-gpio", 0);
-		panel_data->panel_info.pwm_gpio =  tmp;
+		tmp = of_get_named_gpio(np, "qcom,pwm-pmic-gpio", 0);
+		panel_data->panel_info.pwm_pmic_gpio =  tmp;
+	} else if (!strncmp(bl_ctrl_type, "bl_ctrl_dcs", 11)) {
+		panel_data->panel_info.bklt_ctrl = BL_DCS_CMD;
 	} else {
 		pr_debug("%s: Unknown backlight control\n", __func__);
 		panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
@@ -529,171 +660,15 @@
 			panel_data->panel_info.bpp;
 	}
 
-	data = of_get_property(np, "qcom,panel-on-cmds", &len);
-	if (!data) {
-		pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
-		goto error;
-	}
+	mdss_dsi_parse_dcs_cmds(np, &panel_data->on_cmds,
+		"qcom,panel-on-cmds", "qcom,on-cmds-dsi-state");
 
-	on_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
-	if (!on_cmds)
-		return -ENOMEM;
-
-	memcpy(on_cmds, data, len);
-
-	data_offset = 0;
-	cmd_plen = 0;
-	while ((len - data_offset) >= DT_CMD_HDR) {
-		data_offset += (DT_CMD_HDR - 1);
-		cmd_plen = on_cmds[data_offset++];
-		data_offset += cmd_plen;
-		num_of_on_cmds++;
-	}
-	if (!num_of_on_cmds) {
-		pr_err("%s:%d, No ON cmds specified", __func__, __LINE__);
-		goto error;
-	}
-
-	panel_data->dsi_panel_on_cmds =
-		kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
-	if (!panel_data->dsi_panel_on_cmds)
-		return -ENOMEM;
-
-	(panel_data->dsi_panel_on_cmds)->buf =
-		kzalloc((num_of_on_cmds * sizeof(struct dsi_cmd_desc)),
-						GFP_KERNEL);
-	if (!(panel_data->dsi_panel_on_cmds)->buf)
-		return -ENOMEM;
-
-	data_offset = 0;
-	for (i = 0; i < num_of_on_cmds; i++) {
-		panel_data->dsi_panel_on_cmds->buf[i].dtype =
-						on_cmds[data_offset++];
-		panel_data->dsi_panel_on_cmds->buf[i].last =
-						on_cmds[data_offset++];
-		panel_data->dsi_panel_on_cmds->buf[i].vc =
-						on_cmds[data_offset++];
-		panel_data->dsi_panel_on_cmds->buf[i].ack =
-						on_cmds[data_offset++];
-		panel_data->dsi_panel_on_cmds->buf[i].wait =
-						on_cmds[data_offset++];
-		panel_data->dsi_panel_on_cmds->buf[i].dlen =
-						on_cmds[data_offset++];
-		panel_data->dsi_panel_on_cmds->buf[i].payload =
-						&on_cmds[data_offset];
-		data_offset += (panel_data->dsi_panel_on_cmds->buf[i].dlen);
-	}
-
-	if (data_offset != len) {
-		pr_err("%s:%d, Incorrect ON command entries",
-						__func__, __LINE__);
-		goto error;
-	}
-
-	(panel_data->dsi_panel_on_cmds)->size = num_of_on_cmds;
-
-	on_cmds_state = of_get_property(pdev->dev.of_node,
-				"qcom,on-cmds-dsi-state", NULL);
-	if (!strncmp(on_cmds_state, "DSI_LP_MODE", 11)) {
-		(panel_data->dsi_panel_on_cmds)->ctrl_state =
-						DSI_LP_MODE;
-	} else if (!strncmp(on_cmds_state, "DSI_HS_MODE", 11)) {
-		(panel_data->dsi_panel_on_cmds)->ctrl_state =
-						DSI_HS_MODE;
-	} else {
-		pr_debug("%s: ON cmds state not specified. Set Default\n",
-							__func__);
-		(panel_data->dsi_panel_on_cmds)->ctrl_state =
-						DSI_LP_MODE;
-	}
-
-	data = of_get_property(np, "qcom,panel-off-cmds", &len);
-	if (!data) {
-		pr_err("%s:%d, Unable to read OFF cmds", __func__, __LINE__);
-		goto error;
-	}
-
-	off_cmds = kzalloc(sizeof(char) * len, GFP_KERNEL);
-	if (!off_cmds)
-		return -ENOMEM;
-
-	memcpy(off_cmds, data, len);
-
-	data_offset = 0;
-	cmd_plen = 0;
-	while ((len - data_offset) >= DT_CMD_HDR) {
-		data_offset += (DT_CMD_HDR - 1);
-		cmd_plen = off_cmds[data_offset++];
-		data_offset += cmd_plen;
-		num_of_off_cmds++;
-	}
-	if (!num_of_off_cmds) {
-		pr_err("%s:%d, No OFF cmds specified", __func__, __LINE__);
-		goto error;
-	}
-
-	panel_data->dsi_panel_off_cmds =
-		kzalloc(sizeof(struct dsi_panel_cmds_list), GFP_KERNEL);
-	if (!panel_data->dsi_panel_off_cmds)
-		return -ENOMEM;
-
-	(panel_data->dsi_panel_off_cmds)->buf = kzalloc(num_of_off_cmds
-				* sizeof(struct dsi_cmd_desc),
-					GFP_KERNEL);
-	if (!(panel_data->dsi_panel_off_cmds)->buf)
-		return -ENOMEM;
-
-	data_offset = 0;
-	for (i = 0; i < num_of_off_cmds; i++) {
-		panel_data->dsi_panel_off_cmds->buf[i].dtype =
-						off_cmds[data_offset++];
-		panel_data->dsi_panel_off_cmds->buf[i].last =
-						off_cmds[data_offset++];
-		panel_data->dsi_panel_off_cmds->buf[i].vc =
-						off_cmds[data_offset++];
-		panel_data->dsi_panel_off_cmds->buf[i].ack =
-						off_cmds[data_offset++];
-		panel_data->dsi_panel_off_cmds->buf[i].wait =
-						off_cmds[data_offset++];
-		panel_data->dsi_panel_off_cmds->buf[i].dlen =
-						off_cmds[data_offset++];
-		panel_data->dsi_panel_off_cmds->buf[i].payload =
-						&off_cmds[data_offset];
-		data_offset += (panel_data->dsi_panel_off_cmds->buf[i].dlen);
-	}
-
-	if (data_offset != len) {
-		pr_err("%s:%d, Incorrect OFF command entries",
-						__func__, __LINE__);
-		goto error;
-	}
-
-	(panel_data->dsi_panel_off_cmds)->size = num_of_off_cmds;
-
-	off_cmds_state = of_get_property(pdev->dev.of_node,
-				"qcom,off-cmds-dsi-state", NULL);
-	if (!strncmp(off_cmds_state, "DSI_LP_MODE", 11)) {
-		(panel_data->dsi_panel_off_cmds)->ctrl_state =
-						DSI_LP_MODE;
-	} else if (!strncmp(off_cmds_state, "DSI_HS_MODE", 11)) {
-		(panel_data->dsi_panel_off_cmds)->ctrl_state =
-						DSI_HS_MODE;
-	} else {
-		pr_debug("%s: ON cmds state not specified. Set Default\n",
-							__func__);
-		(panel_data->dsi_panel_off_cmds)->ctrl_state =
-						DSI_LP_MODE;
-	}
+	mdss_dsi_parse_dcs_cmds(np, &panel_data->off_cmds,
+		"qcom,panel-off-cmds", "qcom,off-cmds-dsi-state");
 
 	return 0;
-error:
-	kfree((panel_data->dsi_panel_on_cmds)->buf);
-	kfree((panel_data->dsi_panel_off_cmds)->buf);
-	kfree(panel_data->dsi_panel_on_cmds);
-	kfree(panel_data->dsi_panel_off_cmds);
-	kfree(on_cmds);
-	kfree(off_cmds);
 
+error:
 	return -EINVAL;
 }
 
@@ -744,9 +719,6 @@
 
 static int __init mdss_dsi_panel_init(void)
 {
-	mdss_dsi_buf_alloc(&dsi_panel_tx_buf, ALIGN(DSI_BUF_SIZE, SZ_4K));
-	mdss_dsi_buf_alloc(&dsi_panel_rx_buf, ALIGN(DSI_BUF_SIZE, SZ_4K));
-
 	return platform_driver_register(&this_driver);
 }
 module_init(mdss_dsi_panel_init);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 12552bc..ab91320 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -130,9 +130,9 @@
 	{0x18,	0x18,	0x28,	0x28,	0x28,	0x28,	0x28,	0x28,	0x28,
 	 0x28,	0x28,	0x28,	0x28,	0x18,	0x28,	0x18,	0x28,	0x28,
 	 0x28,	0x28}, /*01*/
-	{0x00,	0x04,	0x04,	0x04,	0x04,	0x04,	0x04,	0x04,	0x04,
-	 0x04,	0x04,	0x04,	0x04,	0x88,	0x00,	0x04,	0x04,	0x04,
-	 0x04,	0x04}, /*02*/
+	{0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
+	 0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
+	 0x00,	0x00}, /*02*/
 	{0x02,	0x06,	0x11,	0x15,	0x04,	0x13,	0x10,	0x05,	0x1F,
 	 0x14,	0x20,	0x22,	0x21,	0x01,	0x03,	0x11,	0x00,	0x00,
 	 0x00,	0x00}, /*03*/
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index eb2bd21..afbbe55 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -14,11 +14,12 @@
 #include <linux/kernel.h>
 #include "mdss_panel.h"
 #include "mdss_mdp.h"
+#include "mdss_dsi.h"
 
 #define VSYNC_EXPIRE_TICK 4
 
 #define START_THRESHOLD 4
-#define CONTINUE_TRESHOLD 4
+#define CONTINUE_THRESHOLD 4
 
 #define MAX_SESSIONS 2
 
@@ -26,11 +27,12 @@
 #define KOFF_TIMEOUT msecs_to_jiffies(84)
 
 struct mdss_mdp_cmd_ctx {
+	struct mdss_mdp_ctl *ctl;
 	u32 pp_num;
 	u8 ref_cnt;
+	struct completion vsync_comp;
 	struct completion pp_comp;
 	struct completion stop_comp;
-	atomic_t vsync_ref;
 	mdp_vsync_handler_t send_vsync;
 	int panel_on;
 	int koff_cnt;
@@ -46,6 +48,7 @@
 	u8 tear_check;
 	u16 height;	/* panel height */
 	u16 vporch;	/* vertical porches */
+	u16 start_threshold;
 	u32 vclk_line;	/* vsync clock per line */
 };
 
@@ -83,7 +86,7 @@
 						ctx->height);
 
 	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_THRESH,
-			   (CONTINUE_TRESHOLD << 16) | (START_THRESHOLD));
+		   (CONTINUE_THRESHOLD << 16) | (ctx->start_threshold));
 
 	mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_TEAR_CHECK_EN, enable);
 	return 0;
@@ -118,13 +121,16 @@
 				    pinfo->lcdc.v_front_porch +
 				    pinfo->lcdc.v_pulse_width;
 
+		ctx->start_threshold = START_THRESHOLD;
+
 		total_lines = ctx->height + ctx->vporch;
 		total_lines *= pinfo->mipi.frame_rate;
 		ctx->vclk_line = mdp_vsync_clk_speed_hz / total_lines;
 
-		pr_debug("%s: fr=%d tline=%d vcnt=%d vrate=%d\n",
+		pr_debug("%s: fr=%d tline=%d vcnt=%d thold=%d vrate=%d\n",
 			__func__, pinfo->mipi.frame_rate, total_lines,
-				ctx->vclk_line, mdp_vsync_clk_speed_hz);
+				ctx->vclk_line, ctx->start_threshold,
+				mdp_vsync_clk_speed_hz);
 	} else {
 		enable = 0;
 	}
@@ -151,6 +157,8 @@
 		return;
 	}
 
+	complete_all(&ctx->vsync_comp);
+
 	pr_debug("%s: num=%d ctx=%d expire=%d koff=%d\n", __func__, ctl->num,
 			ctx->pp_num, ctx->expire, ctx->koff_cnt);
 
@@ -226,6 +234,9 @@
 		mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
 						ctx->pp_num);
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+		/* disable dsi clock */
+		mdss_mdp_ctl_intf_event(ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL,
+							(void *)0);
 		complete(&ctx->stop_comp);
 		pr_debug("%s: SET_CLK_OFF, pid=%d\n", __func__, current->pid);
 	} else {
@@ -249,11 +260,12 @@
 
 	enable = (handler->vsync_handler != NULL);
 
+	mutex_lock(&ctx->clk_mtx);
+
 	pr_debug("%s: ctx=%p ctx=%d enabled=%d %d clk_enabled=%d clk_ctrl=%d\n",
 			__func__, ctx, ctx->pp_num, ctx->vsync_enabled, enable,
 					ctx->clk_enabled, ctx->clk_control);
 
-	mutex_lock(&ctx->clk_mtx);
 	if (ctx->vsync_enabled == enable) {
 		mutex_unlock(&ctx->clk_mtx);
 		return 0;
@@ -266,6 +278,8 @@
 		ctx->send_vsync = handler->vsync_handler;
 		spin_unlock_irqrestore(&ctx->clk_lock, flags);
 		if (ctx->clk_enabled == 0) {
+			mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL,
+							(void *)1);
 			mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 			mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
 							ctx->pp_num);
@@ -294,10 +308,11 @@
 		return;
 	}
 
+	mutex_lock(&ctx->clk_mtx);
+
 	pr_debug("%s: ctx=%p num=%d clk_enabled=%d\n", __func__,
 				ctx, ctx->pp_num, ctx->clk_enabled);
 
-	mutex_lock(&ctx->clk_mtx);
 	spin_lock_irqsave(&ctx->clk_lock, flags);
 	ctx->koff_cnt++;
 	ctx->clk_control = 0;
@@ -309,6 +324,8 @@
 	spin_unlock_irqrestore(&ctx->clk_lock, flags);
 
 	if (set_clk_on) {
+		mdss_mdp_ctl_intf_event(ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL,
+							(void *)1);
 		mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
 		ctx->vsync_enabled = 1;
 		mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num);
@@ -331,16 +348,18 @@
 
 	pr_debug("%s: intf_num=%d ctx=%p\n", __func__, ctl->intf_num, ctx);
 
-	rc = wait_for_completion_interruptible_timeout(&ctx->pp_comp,
+	rc = wait_for_completion_interruptible_timeout(&ctx->vsync_comp,
 			KOFF_TIMEOUT);
 	WARN(rc <= 0, "cmd kickoff timed out (%d) ctl=%d\n", rc, ctl->num);
 
-	return rc;
+	return 0;
 }
 
 int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
 {
 	struct mdss_mdp_cmd_ctx *ctx;
+	unsigned long flags;
+	int need_wait = 0;
 	int rc;
 
 	ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
@@ -349,10 +368,21 @@
 		return -ENODEV;
 	}
 
-	pr_debug("%s: kickoff intf_num=%d ctx=%p\n", __func__,
-					ctl->intf_num, ctx);
+	spin_lock_irqsave(&ctx->clk_lock, flags);
+	if (ctx->koff_cnt > 0)
+		need_wait = 1;
+	spin_unlock_irqrestore(&ctx->clk_lock, flags);
 
-	mdss_mdp_cmd_chk_clock(ctx);
+	pr_debug("%s: need_wait=%d  intf_num=%d ctx=%p\n",
+			__func__, need_wait, ctl->intf_num, ctx);
+
+	if (need_wait) {
+		rc = wait_for_completion_interruptible_timeout(
+				&ctx->pp_comp, KOFF_TIMEOUT);
+
+		WARN(rc <= 0, "cmd kickoff timed out (%d) ctl=%d\n",
+						rc, ctl->num);
+	}
 
 	if (ctx->panel_on == 0) {
 		rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);
@@ -364,10 +394,19 @@
 		WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc);
 	}
 
+	mdss_mdp_cmd_chk_clock(ctx);
+
+	/*
+	 * tx dcs command if had any
+	 */
+	mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_DSI_CMDLIST_KOFF, NULL);
+
+	INIT_COMPLETION(ctx->vsync_comp);
 	INIT_COMPLETION(ctx->pp_comp);
 	mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
 
 	mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
+	mb();
 
 	return 0;
 }
@@ -454,10 +493,11 @@
 		return -ENODEV;
 	}
 
+	ctx->ctl = ctl;
 	ctx->pp_num = mixer->num;
+	init_completion(&ctx->vsync_comp);
 	init_completion(&ctx->pp_comp);
 	init_completion(&ctx->stop_comp);
-	atomic_set(&ctx->vsync_ref, 0);
 	spin_lock_init(&ctx->clk_lock);
 	mutex_init(&ctx->clk_mtx);
 	INIT_WORK(&ctx->clk_work, clk_ctrl_work);
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 9e8cfa7..f138420 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -81,6 +81,10 @@
  * @MDSS_EVENT_FB_REGISTERED:	Called after fb dev driver has been registered,
  *				panel driver gets ptr to struct fb_info which
  *				holds fb dev information.
+ * @MDSS_EVENT_PANEL_CLK_CTRL:	panel clock control
+				 - 0 clock disable
+				 - 1 clock enable
+ * @MDSS_EVENT_DSI_CMDLIST_KOFF: kickoff sending dcs command from command list
  */
 enum mdss_intf_events {
 	MDSS_EVENT_RESET = 1,
@@ -94,6 +98,8 @@
 	MDSS_EVENT_CHECK_PARAMS,
 	MDSS_EVENT_CONT_SPLASH_FINISH,
 	MDSS_EVENT_FB_REGISTERED,
+	MDSS_EVENT_PANEL_CLK_CTRL,
+	MDSS_EVENT_DSI_CMDLIST_KOFF,
 };
 
 struct lcd_panel_info {
@@ -222,7 +228,7 @@
 	u32 out_format;
 	u32 vic; /* video identification code */
 	int bklt_ctrl;	/* backlight ctrl */
-	int pwm_gpio;
+	int pwm_pmic_gpio;
 	int pwm_lpg_chan;
 	int pwm_period;
 
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index 5564ceb..12bc5e0 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -170,13 +170,10 @@
 	clk_unprepare(ctrl_pdata->byte_clk);
 }
 
-void mdss_dsi_clk_enable(struct mdss_panel_data *pdata)
+void mdss_dsi_clk_enable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
 	u32 esc_clk_rate = 19200000;
 
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
 	if (!ctrl_pdata) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
@@ -206,12 +203,8 @@
 	ctrl_pdata->mdss_dsi_clk_on = 1;
 }
 
-void mdss_dsi_clk_disable(struct mdss_panel_data *pdata)
+void mdss_dsi_clk_disable(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
 {
-	struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
-
-	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
-				panel_data);
 	if (!ctrl_pdata) {
 		pr_err("%s: Invalid input data\n", __func__);
 		return;
diff --git a/include/linux/dvb/dmx.h b/include/linux/dvb/dmx.h
index aa1eba5..ce9e5b9 100644
--- a/include/linux/dvb/dmx.h
+++ b/include/linux/dvb/dmx.h
@@ -195,7 +195,7 @@
 	/* write pointer offset in bytes */
 	unsigned int write_offset;
 
-	/* non-zero if data error occured */
+	/* non-zero if data error occurred */
 	int error;
 };
 
@@ -237,7 +237,10 @@
 	 * (dmx_sct_filter_params) and no sections were
 	 * received for the given time.
 	 */
-	DMX_EVENT_SECTION_TIMEOUT = 0x00000400
+	DMX_EVENT_SECTION_TIMEOUT = 0x00000400,
+
+	/* Scrambling bits change between clear and scrambled */
+	DMX_EVENT_SCRAMBLING_STATUS_CHANGE = 0x00000800
 };
 
 enum dmx_oob_cmd {
@@ -256,7 +259,7 @@
 /* Discontinuity indicator was set */
 #define DMX_FILTER_DISCONTINUITY_INDICATOR	0x02
 
-/* PES legnth in PES header is not correct */
+/* PES length in PES header is not correct */
 #define DMX_FILTER_PES_LENGTH_ERROR		0x04
 
 
@@ -412,7 +415,7 @@
 	/*
 	 * The PID the index entry belongs to.
 	 * In case of recording filter, multiple PIDs may exist in the same
-	 * filter through DMX_ADD_PID ioctl and each can be indexed seperatly.
+	 * filter through DMX_ADD_PID ioctl and each can be indexed separately.
 	 */
 	__u16 pid;
 
@@ -423,7 +426,7 @@
 	__u64 match_tsp_num;
 
 	/*
-	 * The TS packet number in the recorded data preceeding
+	 * The TS packet number in the recorded data preceding
 	 * match_tsp_num and has PUSI set.
 	 */
 	__u64 last_pusi_tsp_num;
@@ -432,6 +435,23 @@
 	__u64 stc;
 };
 
+/* Scrambling information associated with DMX_EVENT_SCRAMBLING_STATUS_CHANGE */
+struct dmx_scrambling_status_event_info {
+	/*
+	 * The PID which its scrambling bit status changed.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have
+	 * different scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* old value of scrambling bits */
+	__u8 old_value;
+
+	/* new value of scrambling bits */
+	__u8 new_value;
+};
+
 /*
  * Filter's event returned through DMX_GET_EVENT.
  * poll with POLLPRI would block until events are available.
@@ -447,6 +467,7 @@
 		struct dmx_es_data_event_info es_data;
 		struct dmx_marker_event_info marker;
 		struct dmx_index_event_info index;
+		struct dmx_scrambling_status_event_info scrambling_status;
 	} params;
 };
 
@@ -754,6 +775,19 @@
 	__u32 identifier;
 };
 
+struct dmx_scrambling_bits {
+	/*
+	 * The PID to return its scrambling bit value.
+	 * In case of recording filter, multiple PIDs may exist in the same
+	 * filter through DMX_ADD_PID ioctl, each may have different
+	 * scrambling bits status.
+	 */
+	__u16 pid;
+
+	/* Current value of scrambling bits: 0, 1, 2 or 3 */
+	__u8 value;
+};
+
 #define DMX_START                _IO('o', 41)
 #define DMX_STOP                 _IO('o', 42)
 #define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
@@ -784,5 +818,6 @@
 #define DMX_SET_INDEXING_PARAMS _IOW('o', 69, struct dmx_indexing_params)
 #define DMX_SET_TS_INSERTION _IOW('o', 70, struct dmx_set_ts_insertion)
 #define DMX_ABORT_TS_INSERTION _IOW('o', 71, struct dmx_abort_ts_insertion)
+#define DMX_GET_SCRAMBLING_BITS _IOWR('o', 72, struct dmx_scrambling_bits)
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index f551e75..6d7d178 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -3069,4 +3069,32 @@
 	NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U =	1<<3,
 };
 
+/**
+ * enum nl80211_connect_failed_reason - connection request failed reasons
+ * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be
+ *  handled by the AP is reached.
+ * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL.
+ */
+enum nl80211_connect_failed_reason {
+	NL80211_CONN_FAIL_MAX_CLIENTS,
+	NL80211_CONN_FAIL_BLOCKED_CLIENT,
+};
+
+/**
+ * enum nl80211_acl_policy - access control policy
+ *
+ * Access control policy is applied on a MAC list set by
+ * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to
+ * be used with %NL80211_ATTR_ACL_POLICY.
+ *
+ * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are
+ *   listed in ACL, i.e. allow all the stations which are not listed
+ *  in ACL to authenticate.
+ * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed
+ *    in ACL, i.e. deny all the stations which are not listed in ACL.
+ */
+enum nl80211_acl_policy {
+	NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED,
+	NL80211_ACL_POLICY_DENY_UNLESS_LISTED,
+};
 #endif /* __LINUX_NL80211_H */
diff --git a/include/linux/of_coresight.h b/include/linux/of_coresight.h
index 0943dda..eb20e80 100644
--- a/include/linux/of_coresight.h
+++ b/include/linux/of_coresight.h
@@ -13,7 +13,7 @@
 #ifndef __LINUX_OF_CORESIGHT_H
 #define __LINUX_OF_CORESIGHT_H
 
-#ifdef CONFIG_OF
+#ifdef CONFIG_OF_CORESIGHT
 extern struct coresight_platform_data *of_get_coresight_platform_data(
 				struct device *dev, struct device_node *node);
 extern struct coresight_cti_data *of_get_coresight_cti_data(
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 67889bf..952bcb1 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2726,6 +2726,8 @@
 
 #endif /* CONFIG_SMP */
 
+extern struct atomic_notifier_head migration_notifier_head;
+
 extern long sched_setaffinity(pid_t pid, const struct cpumask *new_mask);
 extern long sched_getaffinity(pid_t pid, struct cpumask *mask);
 
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index c185096..aead2d2 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -18,6 +18,11 @@
 	MSM_CPP_REALTIME_FRAME,
 };
 
+enum msm_vpe_frame_type {
+	MSM_VPE_OFFLINE_FRAME,
+	MSM_VPE_REALTIME_FRAME,
+};
+
 struct msm_cpp_frame_strip_info {
 	int scale_v_en;
 	int scale_h_en;
@@ -117,6 +122,57 @@
 	uint32_t cpp_hw_caps;
 };
 
+struct msm_vpe_frame_strip_info {
+	uint32_t src_w;
+	uint32_t src_h;
+	uint32_t dst_w;
+	uint32_t dst_h;
+	uint32_t src_x;
+	uint32_t src_y;
+	uint32_t phase_step_x;
+	uint32_t phase_step_y;
+	uint32_t phase_init_x;
+	uint32_t phase_init_y;
+};
+
+struct msm_vpe_buffer_info_t {
+	int fd;
+	uint32_t index;
+	uint32_t offset;
+	uint8_t native_buff;
+	uint8_t processed_divert;
+};
+
+struct msm_vpe_stream_buff_info_t {
+	uint32_t identity;
+	uint32_t num_buffs;
+	struct msm_vpe_buffer_info_t *buffer_info;
+};
+
+struct msm_vpe_frame_info_t {
+	int32_t frame_id;
+	struct timeval timestamp;
+	uint32_t inst_id;
+	uint32_t identity;
+	uint32_t client_id;
+	enum msm_vpe_frame_type frame_type;
+	struct msm_vpe_frame_strip_info strip_info;
+	int src_fd;
+	int dst_fd;
+	struct ion_handle *src_ion_handle;
+	struct ion_handle *dest_ion_handle;
+	unsigned long src_phyaddr;
+	unsigned long dest_phyaddr;
+	unsigned long src_chroma_plane_offset;
+	unsigned long dest_chroma_plane_offset;
+	struct timeval in_time, out_time;
+	void *cookie;
+
+	struct msm_vpe_buffer_info_t input_buffer_info;
+	struct msm_vpe_buffer_info_t output_buffer_info;
+};
+
+
 #define VIDIOC_MSM_CPP_CFG \
 	_IOWR('V', BASE_VIDIOC_PRIVATE, struct msm_camera_v4l2_ioctl_t)
 
@@ -141,7 +197,27 @@
 #define VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_camera_v4l2_ioctl_t)
 
+
+#define VIDIOC_MSM_VPE_CFG \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_VPE_TRANSACTION_SETUP \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_VPE_GET_EVENTPAYLOAD \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 10, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_VPE_GET_INST_INFO \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 11, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_VPE_ENQUEUE_STREAM_BUFF_INFO \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 12, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_VPE_DEQUEUE_STREAM_BUFF_INFO \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 13, struct msm_camera_v4l2_ioctl_t)
+
 #define V4L2_EVENT_CPP_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 0)
+#define V4L2_EVENT_VPE_FRAME_DONE  (V4L2_EVENT_PRIVATE_START + 1)
 
 struct msm_camera_v4l2_ioctl_t {
 	uint32_t id;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index dc29eb9..fb2b57a 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -416,6 +416,26 @@
 	size_t probe_resp_len;
 };
 
+struct mac_address {
+	u8 addr[ETH_ALEN];
+};
+
+/**
+ * struct cfg80211_acl_data - Access control list data
+ *
+ * @acl_policy: ACL policy to be applied on the station's
+ *	entry specified by mac_addr
+ * @n_acl_entries: Number of MAC address entries passed
+ * @mac_addrs: List of MAC addresses of stations to be used for ACL
+ */
+struct cfg80211_acl_data {
+	enum nl80211_acl_policy acl_policy;
+	int n_acl_entries;
+
+	/* Keep it last */
+	struct mac_address mac_addrs[];
+};
+
 /**
  * struct cfg80211_ap_settings - AP configuration
  *
@@ -432,6 +452,8 @@
  * @privacy: the BSS uses privacy
  * @auth_type: Authentication type (algorithm)
  * @inactivity_timeout: time in seconds to determine station's inactivity.
+ * @acl: ACL configuration used by the drivers which has support for
+ *	MAC address based access control
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_beacon_data beacon;
@@ -444,6 +466,7 @@
 	bool privacy;
 	enum nl80211_auth_type auth_type;
 	int inactivity_timeout;
+	const struct cfg80211_acl_data *acl;
 };
 
 /**
@@ -1559,6 +1582,13 @@
  *	later passes to cfg80211_probe_status().
  *
  * @set_noack_map: Set the NoAck Map for the TIDs.
+ * @set_mac_acl: Sets MAC address control list in AP and P2P GO mode.
+ *	Parameters include ACL policy, an array of MAC address of stations
+ *	and the number of MAC addresses. If there is already a list in driver
+ *	this new list replaces the existing one. Driver has to clear its ACL
+ *	when number of MAC addresses entries is passed as 0. Drivers which
+ *	advertise the support for MAC based ACL have to implement this callback.
+ *
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1757,6 +1787,9 @@
 	struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
 	int	(*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
 				 struct cfg80211_update_ft_ies_params *ftie);
+
+	int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev,
+			   const struct cfg80211_acl_data *params);
 };
 
 /*
@@ -1924,10 +1957,6 @@
 	bool beacon_int_infra_match;
 };
 
-struct mac_address {
-	u8 addr[ETH_ALEN];
-};
-
 struct ieee80211_txrx_stypes {
 	u16 tx, rx;
 };
@@ -2068,6 +2097,9 @@
  * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
  * @ht_capa_mod_mask:  Specify what ht_cap values can be over-ridden.
  *	If null, then none can be over-ridden.
+ *
+ * @max_acl_mac_addrs: Maximum number of MAC addresses that the device
+ *	supports for ACL.
  */
 struct wiphy {
 	/* assign these fields before you register the wiphy */
@@ -2089,6 +2121,8 @@
 	/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
 	u16 interface_modes;
 
+	u16 max_acl_mac_addrs;
+
 	u32 flags, features;
 
 	u32 ap_sme_capa;
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 862e172..1a07d2e 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -87,6 +87,8 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/sched.h>
 
+ATOMIC_NOTIFIER_HEAD(migration_notifier_head);
+
 void start_bandwidth_timer(struct hrtimer *period_timer, ktime_t period)
 {
 	unsigned long delta;
@@ -1589,15 +1591,17 @@
 try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags)
 {
 	unsigned long flags;
-	int cpu, success = 0;
+	int cpu, src_cpu, success = 0;
 
 	smp_wmb();
 	raw_spin_lock_irqsave(&p->pi_lock, flags);
+	src_cpu = task_cpu(p);
+	cpu = src_cpu;
+
 	if (!(p->state & state))
 		goto out;
 
 	success = 1; /* we're going to change ->state */
-	cpu = task_cpu(p);
 
 	if (p->on_rq && ttwu_remote(p, wake_flags))
 		goto stat;
@@ -1634,7 +1638,7 @@
 		p->sched_class->task_waking(p);
 
 	cpu = select_task_rq(p, SD_BALANCE_WAKE, wake_flags);
-	if (task_cpu(p) != cpu) {
+	if (src_cpu != cpu) {
 		wake_flags |= WF_MIGRATED;
 		set_task_cpu(p, cpu);
 	}
@@ -1646,6 +1650,9 @@
 out:
 	raw_spin_unlock_irqrestore(&p->pi_lock, flags);
 
+	if (src_cpu != cpu && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   cpu, (void *)src_cpu);
 	return success;
 }
 
@@ -5068,6 +5075,7 @@
 static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
 {
 	struct rq *rq_dest, *rq_src;
+	bool moved = false;
 	int ret = 0;
 
 	if (unlikely(!cpu_active(dest_cpu)))
@@ -5094,12 +5102,16 @@
 		set_task_cpu(p, dest_cpu);
 		enqueue_task(rq_dest, p, 0);
 		check_preempt_curr(rq_dest, p, 0);
+		moved = true;
 	}
 done:
 	ret = 1;
 fail:
 	double_rq_unlock(rq_src, rq_dest);
 	raw_spin_unlock(&p->pi_lock);
+	if (moved && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   dest_cpu, (void *)src_cpu);
 	return ret;
 }
 
@@ -7731,6 +7743,24 @@
 	sched_move_task(task);
 }
 
+static u64 cpu_notify_on_migrate_read_u64(struct cgroup *cgrp,
+					  struct cftype *cft)
+{
+	struct task_group *tg = cgroup_tg(cgrp);
+
+	return tg->notify_on_migrate;
+}
+
+static int cpu_notify_on_migrate_write_u64(struct cgroup *cgrp,
+					   struct cftype *cft, u64 notify)
+{
+	struct task_group *tg = cgroup_tg(cgrp);
+
+	tg->notify_on_migrate = (notify > 0);
+
+	return 0;
+}
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 static int cpu_shares_write_u64(struct cgroup *cgrp, struct cftype *cftype,
 				u64 shareval)
@@ -8002,6 +8032,11 @@
 #endif /* CONFIG_RT_GROUP_SCHED */
 
 static struct cftype cpu_files[] = {
+	{
+		.name = "notify_on_migrate",
+		.read_u64 = cpu_notify_on_migrate_read_u64,
+		.write_u64 = cpu_notify_on_migrate_write_u64,
+	},
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	{
 		.name = "shares",
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 7e31770..103730d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -2126,11 +2126,11 @@
 static void hrtick_start_fair(struct rq *rq, struct task_struct *p)
 {
 	struct sched_entity *se = &p->se;
-	struct cfs_rq *cfs_rq = &rq->cfs;
+	struct cfs_rq *cfs_rq = cfs_rq_of(se);
 
 	WARN_ON(task_rq(p) != rq);
 
-	if (cfs_rq->h_nr_running > 1) {
+	if (rq->cfs.h_nr_running > 1) {
 		u64 slice = sched_slice(cfs_rq, se);
 		u64 ran = se->sum_exec_runtime - se->prev_sum_exec_runtime;
 		s64 delta = slice - ran;
@@ -3101,6 +3101,8 @@
 	unsigned int		loop_max;
 };
 
+static DEFINE_PER_CPU(bool, dbs_boost_needed);
+
 /*
  * move_task - move a task from one runqueue to another runqueue.
  * Both runqueues must be locked.
@@ -3111,6 +3113,8 @@
 	set_task_cpu(p, env->dst_cpu);
 	activate_task(env->dst_rq, p, 0);
 	check_preempt_curr(env->dst_rq, p, 0);
+	if (task_notify_on_migrate(p))
+		per_cpu(dbs_boost_needed, env->dst_cpu) = true;
 }
 
 /*
@@ -4541,9 +4545,15 @@
 			 */
 			sd->nr_balance_failed = sd->cache_nice_tries+1;
 		}
-	} else
+	} else {
 		sd->nr_balance_failed = 0;
-
+		if (per_cpu(dbs_boost_needed, this_cpu)) {
+			per_cpu(dbs_boost_needed, this_cpu) = false;
+			atomic_notifier_call_chain(&migration_notifier_head,
+						   this_cpu,
+						   (void *)cpu_of(busiest));
+		}
+	}
 	if (likely(!active_balance)) {
 		/* We were unbalanced, so reset the balancing interval */
 		sd->balance_interval = sd->min_interval;
@@ -4698,6 +4708,12 @@
 out_unlock:
 	busiest_rq->active_balance = 0;
 	raw_spin_unlock_irq(&busiest_rq->lock);
+	if (per_cpu(dbs_boost_needed, target_cpu)) {
+		per_cpu(dbs_boost_needed, target_cpu) = false;
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   target_cpu,
+					   (void *)cpu_of(busiest_rq));
+	}
 	return 0;
 }
 
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 8f32475..f8317df 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1604,6 +1604,7 @@
 	struct task_struct *next_task;
 	struct rq *lowest_rq;
 	int ret = 0;
+	bool moved = false;
 
 	if (!rq->rt.overloaded)
 		return 0;
@@ -1673,6 +1674,7 @@
 
 	deactivate_task(rq, next_task, 0);
 	set_task_cpu(next_task, lowest_rq->cpu);
+	moved = true;
 	activate_task(lowest_rq, next_task, 0);
 	ret = 1;
 
@@ -1683,6 +1685,11 @@
 out:
 	put_task_struct(next_task);
 
+	if (moved && task_notify_on_migrate(next_task))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   cpu_of(lowest_rq),
+					   (void *)cpu_of(rq));
+
 	return ret;
 }
 
@@ -1696,8 +1703,10 @@
 static int pull_rt_task(struct rq *this_rq)
 {
 	int this_cpu = this_rq->cpu, ret = 0, cpu;
-	struct task_struct *p;
+	struct task_struct *p = NULL;
 	struct rq *src_rq;
+	bool moved = false;
+	int src_cpu = 0;
 
 	if (likely(!rt_overloaded(this_rq)))
 		return 0;
@@ -1758,6 +1767,10 @@
 			deactivate_task(src_rq, p, 0);
 			set_task_cpu(p, this_cpu);
 			activate_task(this_rq, p, 0);
+
+			moved = true;
+			src_cpu = cpu_of(src_rq);
+
 			/*
 			 * We continue with the search, just in
 			 * case there's an even higher prio task
@@ -1769,6 +1782,11 @@
 		double_unlock_balance(this_rq, src_rq);
 	}
 
+	if (moved && task_notify_on_migrate(p))
+		atomic_notifier_call_chain(&migration_notifier_head,
+					   this_cpu,
+					   (void *)src_cpu);
+
 	return ret;
 }
 
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 451bd4f..5370bcb 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -104,6 +104,8 @@
 struct task_group {
 	struct cgroup_subsys_state css;
 
+	bool notify_on_migrate;
+
 #ifdef CONFIG_FAIR_GROUP_SCHED
 	/* schedulable entities of this group on each cpu */
 	struct sched_entity **se;
@@ -554,6 +556,11 @@
 	return autogroup_task_group(p, tg);
 }
 
+static inline bool task_notify_on_migrate(struct task_struct *p)
+{
+	return task_group(p)->notify_on_migrate;
+}
+
 /* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
 static inline void set_task_rq(struct task_struct *p, unsigned int cpu)
 {
@@ -579,7 +586,10 @@
 {
 	return NULL;
 }
-
+static inline bool task_notify_on_migrate(struct task_struct *p)
+{
+	return false;
+}
 #endif /* CONFIG_CGROUP_SCHED */
 
 static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ccdfed8..674c1fa 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -505,6 +505,11 @@
 			   ETH_ALEN)))
 		return -EINVAL;
 
+	if (WARN_ON(wiphy->max_acl_mac_addrs &&
+		    (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) ||
+		     !rdev->ops->set_mac_acl)))
+		return -EINVAL;
+
 	if (wiphy->addresses)
 		memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN);
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e1fa62e..6ed6d3e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -210,6 +210,8 @@
 	[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
 	[NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
+	[NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
+	[NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
 	[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
 	[NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
@@ -1066,6 +1068,11 @@
 			sizeof(*dev->wiphy.ht_capa_mod_mask),
 			dev->wiphy.ht_capa_mod_mask);
 
+	if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME &&
+	    dev->wiphy.max_acl_mac_addrs)
+		NLA_PUT_U32(msg, NL80211_ATTR_MAC_ACL_MAX,
+			    dev->wiphy.max_acl_mac_addrs);
+
 	return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -2105,6 +2112,97 @@
 	return err;
 }
 
+/* This function returns an error or the number of nested attributes */
+static int validate_acl_mac_addrs(struct nlattr *nl_attr)
+{
+	struct nlattr *attr;
+	int n_entries = 0, tmp;
+
+	nla_for_each_nested(attr, nl_attr, tmp) {
+		if (nla_len(attr) != ETH_ALEN)
+			return -EINVAL;
+
+		n_entries++;
+	}
+
+	return n_entries;
+}
+
+/*
+ * This function parses ACL information and allocates memory for ACL data.
+ * On successful return, the calling function is responsible to free the
+ * ACL buffer returned by this function.
+ */
+static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy,
+						struct genl_info *info)
+{
+	enum nl80211_acl_policy acl_policy;
+	struct nlattr *attr;
+	struct cfg80211_acl_data *acl;
+	int i = 0, n_entries, tmp;
+
+	if (!wiphy->max_acl_mac_addrs)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	if (!info->attrs[NL80211_ATTR_ACL_POLICY])
+		return ERR_PTR(-EINVAL);
+
+	acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]);
+	if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
+	    acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
+		return ERR_PTR(-EINVAL);
+
+	if (!info->attrs[NL80211_ATTR_MAC_ADDRS])
+		return ERR_PTR(-EINVAL);
+
+	n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]);
+	if (n_entries < 0)
+		return ERR_PTR(n_entries);
+
+	if (n_entries > wiphy->max_acl_mac_addrs)
+		return ERR_PTR(-ENOTSUPP);
+
+	acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries),
+		      GFP_KERNEL);
+	if (!acl)
+		return ERR_PTR(-ENOMEM);
+
+	nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) {
+		memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN);
+		i++;
+	}
+
+	acl->n_acl_entries = n_entries;
+	acl->acl_policy = acl_policy;
+
+	return acl;
+}
+
+static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct cfg80211_acl_data *acl;
+	int err;
+
+	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+		return -EOPNOTSUPP;
+
+	if (!dev->ieee80211_ptr->beacon_interval)
+		return -EINVAL;
+
+	acl = parse_acl_data(&rdev->wiphy, info);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+
+	err = rdev->ops->set_mac_acl(&rdev->wiphy, dev, acl);
+
+	kfree(acl);
+
+	return err;
+}
+
 static int nl80211_parse_beacon(struct genl_info *info,
 				struct cfg80211_beacon_data *bcn)
 {
@@ -2251,9 +2349,18 @@
 			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
 	}
 
+	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
+		params.acl = parse_acl_data(&rdev->wiphy, info);
+		if (IS_ERR(params.acl))
+			return PTR_ERR(params.acl);
+	}
+
 	err = rdev->ops->start_ap(&rdev->wiphy, dev, &params);
 	if (!err)
 		wdev->beacon_interval = params.beacon_interval;
+
+	kfree(params.acl);
+
 	return err;
 }
 
@@ -7063,6 +7170,14 @@
 				  NL80211_FLAG_NEED_RTNL,
 	},
 	{
+		.cmd = NL80211_CMD_SET_MAC_ACL,
+		.doit = nl80211_set_mac_acl,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
 		.cmd = NL80211_CMD_UPDATE_FT_IES,
 		.doit = nl80211_update_ft_ies,
 		.policy = nl80211_policy,
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index a37b4eb..cc22fd4 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -134,6 +134,14 @@
 	WCD9XXX_HPHR_DAC_OFF_ACK
 };
 
+enum wcd9xxx_current_v_idx {
+	WCD9XXX_CURRENT_V_INS_H,
+	WCD9XXX_CURRENT_V_INS_HU,
+	WCD9XXX_CURRENT_V_B1_H,
+	WCD9XXX_CURRENT_V_B1_HU,
+	WCD9XXX_CURRENT_V_BR_H,
+};
+
 static bool wcd9xxx_mbhc_polling(struct wcd9xxx_mbhc *mbhc)
 {
 	return mbhc->polling_active;
@@ -266,6 +274,7 @@
 	int cfilt_k_val;
 	bool override;
 	struct snd_soc_codec *codec;
+	struct mbhc_internal_cal_data *d = &mbhc->mbhc_data;
 
 	codec = mbhc->codec;
 
@@ -278,7 +287,7 @@
 		if (!override)
 			wcd9xxx_turn_onoff_override(codec, true);
 		/* Adjust threshold if Mic Bias voltage changes */
-		if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+		if (d->micb_mv != VDDIO_MICBIAS_MV) {
 			cfilt_k_val = wcd9xxx_resmgr_get_k_val(mbhc->resmgr,
 							      VDDIO_MICBIAS_MV);
 			usleep_range(10000, 10000);
@@ -286,11 +295,28 @@
 					mbhc->mbhc_bias_regs.cfilt_val,
 					0xFC, (cfilt_k_val << 2));
 			usleep_range(10000, 10000);
+			/* Threshods for insertion/removal */
 			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL,
-				      mbhc->mbhc_data.adj_v_ins_hu & 0xFF);
+				      d->v_ins_hu[MBHC_V_IDX_VDDIO] & 0xFF);
 			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL,
-				      (mbhc->mbhc_data.adj_v_ins_hu >> 8) &
+				      (d->v_ins_hu[MBHC_V_IDX_VDDIO] >> 8) &
 				      0xFF);
+			/* Threshods for button press */
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B3_CTL,
+				      d->v_b1_hu[MBHC_V_IDX_VDDIO] & 0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B4_CTL,
+				      (d->v_b1_hu[MBHC_V_IDX_VDDIO] >> 8) &
+				      0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B5_CTL,
+				      d->v_b1_h[MBHC_V_IDX_VDDIO] & 0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B6_CTL,
+				      (d->v_b1_h[MBHC_V_IDX_VDDIO] >> 8) &
+				      0xFF);
+			/* Threshods for button release */
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B9_CTL,
+				      d->v_brh[MBHC_V_IDX_VDDIO] & 0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B10_CTL,
+				      (d->v_brh[MBHC_V_IDX_VDDIO] >> 8) & 0xFF);
 			pr_debug("%s: Programmed MBHC thresholds to VDDIO\n",
 				 __func__);
 		}
@@ -312,18 +338,36 @@
 		    restartpolling)
 			wcd9xxx_pause_hs_polling(mbhc);
 		/* Reprogram thresholds */
-		if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+		if (d->micb_mv != VDDIO_MICBIAS_MV) {
 			cfilt_k_val =
 			    wcd9xxx_resmgr_get_k_val(mbhc->resmgr,
-						     mbhc->mbhc_data.micb_mv);
+						     d->micb_mv);
 			snd_soc_update_bits(codec,
 					mbhc->mbhc_bias_regs.cfilt_val,
 					0xFC, (cfilt_k_val << 2));
 			usleep_range(10000, 10000);
+			/* Revert threshods for insertion/removal */
 			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL,
-					mbhc->mbhc_data.v_ins_hu & 0xFF);
+					d->v_ins_hu[MBHC_V_IDX_CFILT] & 0xFF);
 			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL,
-					(mbhc->mbhc_data.v_ins_hu >> 8) & 0xFF);
+					(d->v_ins_hu[MBHC_V_IDX_CFILT] >> 8) &
+					0xFF);
+			/* Revert threshods for button press */
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B3_CTL,
+				      d->v_b1_hu[MBHC_V_IDX_CFILT] & 0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B4_CTL,
+				      (d->v_b1_hu[MBHC_V_IDX_CFILT] >> 8) &
+				      0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B5_CTL,
+				      d->v_b1_h[MBHC_V_IDX_CFILT] & 0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B6_CTL,
+				      (d->v_b1_h[MBHC_V_IDX_CFILT] >> 8) &
+				      0xFF);
+			/* Revert threshods for button release */
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B9_CTL,
+				      d->v_brh[MBHC_V_IDX_CFILT] & 0xFF);
+			snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B10_CTL,
+				      (d->v_brh[MBHC_V_IDX_CFILT] >> 8) & 0xFF);
 			pr_debug("%s: Programmed MBHC thresholds to MICBIAS\n",
 					__func__);
 		}
@@ -347,17 +391,37 @@
 	return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
 }
 
-static s16 wcd9xxx_get_current_v_ins(struct wcd9xxx_mbhc *mbhc, bool hu)
+static s16 wcd9xxx_get_current_v(struct wcd9xxx_mbhc *mbhc,
+				 const enum wcd9xxx_current_v_idx idx)
 {
-	s16 v_ins;
+	enum mbhc_v_index vidx;
+	s16 ret = -EINVAL;
+
 	if ((mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
 	    mbhc->mbhc_micbias_switched)
-		v_ins = hu ? (s16)mbhc->mbhc_data.adj_v_ins_hu :
-			(s16)mbhc->mbhc_data.adj_v_ins_h;
+		vidx = MBHC_V_IDX_VDDIO;
 	else
-		v_ins = hu ? (s16)mbhc->mbhc_data.v_ins_hu :
-			(s16)mbhc->mbhc_data.v_ins_h;
-	return v_ins;
+		vidx = MBHC_V_IDX_CFILT;
+
+	switch (idx) {
+	case WCD9XXX_CURRENT_V_INS_H:
+		ret = (s16)mbhc->mbhc_data.v_ins_h[vidx];
+		break;
+	case WCD9XXX_CURRENT_V_INS_HU:
+		ret = (s16)mbhc->mbhc_data.v_ins_hu[vidx];
+		break;
+	case WCD9XXX_CURRENT_V_B1_H:
+		ret = (s16)mbhc->mbhc_data.v_b1_h[vidx];
+		break;
+	case WCD9XXX_CURRENT_V_B1_HU:
+		ret = (s16)mbhc->mbhc_data.v_b1_hu[vidx];
+		break;
+	case WCD9XXX_CURRENT_V_BR_H:
+		ret = (s16)mbhc->mbhc_data.v_brh[vidx];
+		break;
+	}
+
+	return ret;
 }
 
 void *wcd9xxx_mbhc_cal_btn_det_mp(
@@ -389,27 +453,25 @@
 static void wcd9xxx_calibrate_hs_polling(struct wcd9xxx_mbhc *mbhc)
 {
 	struct snd_soc_codec *codec = mbhc->codec;
-	const s16 v_ins_hu = wcd9xxx_get_current_v_ins(mbhc, true);
+	const s16 v_ins_hu = wcd9xxx_get_current_v(mbhc,
+						   WCD9XXX_CURRENT_V_INS_HU);
+	const s16 v_b1_hu = wcd9xxx_get_current_v(mbhc,
+						  WCD9XXX_CURRENT_V_B1_HU);
+	const s16 v_b1_h = wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_B1_H);
+	const s16 v_brh = wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_BR_H);
 
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, v_ins_hu & 0xFF);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL,
 		      (v_ins_hu >> 8) & 0xFF);
-
-	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B3_CTL,
-		      mbhc->mbhc_data.v_b1_hu & 0xFF);
+	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B3_CTL, v_b1_hu & 0xFF);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B4_CTL,
-		      (mbhc->mbhc_data.v_b1_hu >> 8) & 0xFF);
-
-	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B5_CTL,
-		      mbhc->mbhc_data.v_b1_h & 0xFF);
+		      (v_b1_hu >> 8) & 0xFF);
+	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B5_CTL, v_b1_h & 0xFF);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B6_CTL,
-		      (mbhc->mbhc_data.v_b1_h >> 8) & 0xFF);
-
-	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B9_CTL,
-		      mbhc->mbhc_data.v_brh & 0xFF);
+		      (v_b1_h >> 8) & 0xFF);
+	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B9_CTL, v_brh & 0xFF);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B10_CTL,
-		      (mbhc->mbhc_data.v_brh >> 8) & 0xFF);
-
+		      (v_brh >> 8) & 0xFF);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B11_CTL,
 		      mbhc->mbhc_data.v_brl & 0xFF);
 	snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B12_CTL,
@@ -813,6 +875,19 @@
 	WCD9XXX_BCL_LOCK(mbhc->resmgr);
 }
 
+static s16 scale_v_micb_vddio(struct wcd9xxx_mbhc *mbhc, int v, bool tovddio)
+{
+	int r;
+	int vddio_k, mb_k;
+	vddio_k = wcd9xxx_resmgr_get_k_val(mbhc->resmgr, VDDIO_MICBIAS_MV);
+	mb_k = wcd9xxx_resmgr_get_k_val(mbhc->resmgr, mbhc->mbhc_data.micb_mv);
+	if (tovddio)
+		r = v * vddio_k / mb_k;
+	else
+		r = v * mb_k / vddio_k;
+	return r;
+}
+
 static s16 wcd9xxx_get_current_v_hs_max(struct wcd9xxx_mbhc *mbhc)
 {
 	s16 v_hs_max;
@@ -821,7 +896,7 @@
 	plug_type = WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
 	if ((mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
 	    mbhc->mbhc_micbias_switched)
-		v_hs_max = mbhc->mbhc_data.adj_v_hs_max;
+		v_hs_max = scale_v_micb_vddio(mbhc, plug_type->v_hs_max, true);
 	else
 		v_hs_max = plug_type->v_hs_max;
 	return v_hs_max;
@@ -1032,19 +1107,6 @@
 	mbhc->mbhc_state = MBHC_STATE_NONE;
 }
 
-static s16 scale_v_micb_vddio(struct wcd9xxx_mbhc *mbhc, int v, bool tovddio)
-{
-	int r;
-	int vddio_k, mb_k;
-	vddio_k = wcd9xxx_resmgr_get_k_val(mbhc->resmgr, VDDIO_MICBIAS_MV);
-	mb_k = wcd9xxx_resmgr_get_k_val(mbhc->resmgr, mbhc->mbhc_data.micb_mv);
-	if (tovddio)
-		r = v * vddio_k / mb_k;
-	else
-		r = v * mb_k / vddio_k;
-	return r;
-}
-
 /* called under codec_resource_lock acquisition */
 static void wcd9xxx_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on)
 {
@@ -1680,7 +1742,8 @@
 		bias_value = wcd9xxx_codec_sta_dce(mbhc, 1,  true);
 		pr_debug("%s: DCE %d,%d, %d us left\n", __func__, bias_value,
 			 wcd9xxx_codec_sta_dce_v(mbhc, 1, bias_value), min_us);
-		if (bias_value < wcd9xxx_get_current_v_ins(mbhc, false)) {
+		if (bias_value <
+		    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_INS_H)) {
 			pr_debug("%s: checking false removal\n", __func__);
 			msleep(500);
 			removed = !wcd9xxx_hs_remove_settle(mbhc);
@@ -1942,7 +2005,8 @@
 static void wcd9xxx_mbhc_calc_thres(struct wcd9xxx_mbhc *mbhc)
 {
 	struct snd_soc_codec *codec;
-	s16 btn_mv = 0, btn_delta_mv;
+	s16 adj_v_hs_max;
+	s16 btn_mv = 0, btn_mv_sta[MBHC_V_IDX_NUM], btn_mv_dce[MBHC_V_IDX_NUM];
 	struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
 	struct wcd9xxx_mbhc_plug_type_cfg *plug_type;
 	u16 *btn_high;
@@ -1953,23 +2017,21 @@
 	btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
 	plug_type = WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
 
-	mbhc->mbhc_data.v_ins_hu =
+	mbhc->mbhc_data.v_ins_hu[MBHC_V_IDX_CFILT] =
 	    wcd9xxx_codec_v_sta_dce(mbhc, STA, plug_type->v_hs_max);
-	mbhc->mbhc_data.v_ins_h =
+	mbhc->mbhc_data.v_ins_h[MBHC_V_IDX_CFILT] =
 	    wcd9xxx_codec_v_sta_dce(mbhc, DCE, plug_type->v_hs_max);
 
 	mbhc->mbhc_data.v_inval_ins_low = FAKE_INS_LOW;
 	mbhc->mbhc_data.v_inval_ins_high = FAKE_INS_HIGH;
 
 	if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
-		mbhc->mbhc_data.adj_v_hs_max =
-		    scale_v_micb_vddio(mbhc, plug_type->v_hs_max, true);
-		mbhc->mbhc_data.adj_v_ins_hu =
-		    wcd9xxx_codec_v_sta_dce(mbhc, STA,
-					    mbhc->mbhc_data.adj_v_hs_max);
-		mbhc->mbhc_data.adj_v_ins_h =
-		    wcd9xxx_codec_v_sta_dce(mbhc, DCE,
-					    mbhc->mbhc_data.adj_v_hs_max);
+		adj_v_hs_max = scale_v_micb_vddio(mbhc, plug_type->v_hs_max,
+						  true);
+		mbhc->mbhc_data.v_ins_hu[MBHC_V_IDX_VDDIO] =
+		    wcd9xxx_codec_v_sta_dce(mbhc, STA, adj_v_hs_max);
+		mbhc->mbhc_data.v_ins_h[MBHC_V_IDX_VDDIO] =
+		    wcd9xxx_codec_v_sta_dce(mbhc, DCE, adj_v_hs_max);
 		mbhc->mbhc_data.v_inval_ins_low =
 		    scale_v_micb_vddio(mbhc, mbhc->mbhc_data.v_inval_ins_low,
 				       false);
@@ -1983,17 +2045,27 @@
 	for (i = 0; i < btn_det->num_btn; i++)
 		btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
 
-	mbhc->mbhc_data.v_b1_h = wcd9xxx_codec_v_sta_dce(mbhc, DCE, btn_mv);
-	btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
-	mbhc->mbhc_data.v_b1_hu =
-	    wcd9xxx_codec_v_sta_dce(mbhc, STA, btn_delta_mv);
+	btn_mv_sta[MBHC_V_IDX_CFILT] = btn_mv + btn_det->v_btn_press_delta_sta;
+	btn_mv_dce[MBHC_V_IDX_CFILT] = btn_mv + btn_det->v_btn_press_delta_cic;
+	btn_mv_sta[MBHC_V_IDX_VDDIO] =
+	    scale_v_micb_vddio(mbhc, btn_mv_sta[MBHC_V_IDX_CFILT], true);
+	btn_mv_dce[MBHC_V_IDX_VDDIO] =
+	    scale_v_micb_vddio(mbhc, btn_mv_dce[MBHC_V_IDX_CFILT], true);
 
-	btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
+	mbhc->mbhc_data.v_b1_hu[MBHC_V_IDX_CFILT] =
+	    wcd9xxx_codec_v_sta_dce(mbhc, STA, btn_mv_sta[MBHC_V_IDX_CFILT]);
+	mbhc->mbhc_data.v_b1_h[MBHC_V_IDX_CFILT] =
+	    wcd9xxx_codec_v_sta_dce(mbhc, DCE, btn_mv_dce[MBHC_V_IDX_CFILT]);
+	mbhc->mbhc_data.v_b1_hu[MBHC_V_IDX_VDDIO] =
+	    wcd9xxx_codec_v_sta_dce(mbhc, STA, btn_mv_sta[MBHC_V_IDX_VDDIO]);
+	mbhc->mbhc_data.v_b1_h[MBHC_V_IDX_VDDIO] =
+	    wcd9xxx_codec_v_sta_dce(mbhc, DCE, btn_mv_dce[MBHC_V_IDX_VDDIO]);
 
-	mbhc->mbhc_data.v_b1_huc =
-	    wcd9xxx_codec_v_sta_dce(mbhc, DCE, btn_delta_mv);
+	mbhc->mbhc_data.v_brh[MBHC_V_IDX_CFILT] =
+	    mbhc->mbhc_data.v_b1_h[MBHC_V_IDX_CFILT];
+	mbhc->mbhc_data.v_brh[MBHC_V_IDX_VDDIO] =
+	    mbhc->mbhc_data.v_b1_h[MBHC_V_IDX_VDDIO];
 
-	mbhc->mbhc_data.v_brh = mbhc->mbhc_data.v_b1_h;
 	mbhc->mbhc_data.v_brl = BUTTON_MIN;
 
 	mbhc->mbhc_data.v_no_mic =
@@ -2278,12 +2350,17 @@
 static int wcd9xxx_is_fake_press(struct wcd9xxx_mbhc *mbhc)
 {
 	int i;
+	s16 mb_v;
 	int r = 0;
 	const int dces = NUM_DCE_PLUG_DETECT;
-	s16 mb_v, v_ins_hu, v_ins_h;
-
-	v_ins_hu = wcd9xxx_get_current_v_ins(mbhc, true);
-	v_ins_h = wcd9xxx_get_current_v_ins(mbhc, false);
+	const s16 v_ins_hu =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_INS_HU);
+	const s16 v_ins_h =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_INS_H);
+	const s16 v_b1_hu =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_B1_HU);
+	const s16 v_b1_h =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_B1_H);
 
 	for (i = 0; i < dces; i++) {
 		usleep_range(10000, 10000);
@@ -2291,8 +2368,7 @@
 			mb_v = wcd9xxx_codec_sta_dce(mbhc, 0, true);
 			pr_debug("%s: STA[0]: %d,%d\n", __func__, mb_v,
 				 wcd9xxx_codec_sta_dce_v(mbhc, 0, mb_v));
-			if (mb_v < (s16)mbhc->mbhc_data.v_b1_hu ||
-			    mb_v > v_ins_hu) {
+			if (mb_v < v_b1_hu || mb_v > v_ins_hu) {
 				r = 1;
 				break;
 			}
@@ -2300,8 +2376,7 @@
 			mb_v = wcd9xxx_codec_sta_dce(mbhc, 1, true);
 			pr_debug("%s: DCE[%d]: %d,%d\n", __func__, i, mb_v,
 				 wcd9xxx_codec_sta_dce_v(mbhc, 1, mb_v));
-			if (mb_v < (s16)mbhc->mbhc_data.v_b1_h ||
-			    mb_v > v_ins_h) {
+			if (mb_v < v_b1_h || mb_v > v_ins_h) {
 				r = 1;
 				break;
 			}
@@ -2995,8 +3070,16 @@
 	int n = 0;
 	struct wcd9xxx_mbhc *mbhc = file->private_data;
 	const struct mbhc_internal_cal_data *p = &mbhc->mbhc_data;
-	const s16 v_ins_hu_cur = wcd9xxx_get_current_v_ins(mbhc, true);
-	const s16 v_ins_h_cur = wcd9xxx_get_current_v_ins(mbhc, false);
+	const s16 v_ins_hu =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_INS_HU);
+	const s16 v_ins_h =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_INS_H);
+	const s16 v_b1_hu =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_B1_HU);
+	const s16 v_b1_h =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_B1_H);
+	const s16 v_br_h =
+	    wcd9xxx_get_current_v(mbhc, WCD9XXX_CURRENT_V_BR_H);
 
 	n = scnprintf(buffer, size - n, "dce_z = %x(%dmv)\n",  p->dce_z,
 		      wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_z));
@@ -3006,35 +3089,19 @@
 		       p->sta_z, wcd9xxx_codec_sta_dce_v(mbhc, 0, p->sta_z));
 	n += scnprintf(buffer + n, size - n, "sta_mb = %x(%dmv)\n",
 		       p->sta_mb, wcd9xxx_codec_sta_dce_v(mbhc, 0, p->sta_mb));
-	n += scnprintf(buffer + n, size - n, "t_dce = %x\n",  p->t_dce);
-	n += scnprintf(buffer + n, size - n, "t_sta = %x\n",  p->t_sta);
-	n += scnprintf(buffer + n, size - n, "micb_mv = %dmv\n",
-		       p->micb_mv);
-	n += scnprintf(buffer + n, size - n, "v_ins_hu = %x(%dmv)%s\n",
-		       p->v_ins_hu,
-		       wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_ins_hu),
-		       p->v_ins_hu == v_ins_hu_cur ? "*" : "");
-	n += scnprintf(buffer + n, size - n, "v_ins_h = %x(%dmv)%s\n",
-		       p->v_ins_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_ins_h),
-		       p->v_ins_h == v_ins_h_cur ? "*" : "");
-	n += scnprintf(buffer + n, size - n, "adj_v_ins_hu = %x(%dmv)%s\n",
-		       p->adj_v_ins_hu,
-		       wcd9xxx_codec_sta_dce_v(mbhc, 0, p->adj_v_ins_hu),
-		       p->adj_v_ins_hu == v_ins_hu_cur ? "*" : "");
-	n += scnprintf(buffer + n, size - n, "adj_v_ins_h = %x(%dmv)%s\n",
-		       p->adj_v_ins_h,
-		       wcd9xxx_codec_sta_dce_v(mbhc, 1, p->adj_v_ins_h),
-		       p->adj_v_ins_h == v_ins_h_cur ? "*" : "");
+	n += scnprintf(buffer + n, size - n, "t_dce = %d\n",  p->t_dce);
+	n += scnprintf(buffer + n, size - n, "t_sta = %d\n",  p->t_sta);
+	n += scnprintf(buffer + n, size - n, "micb_mv = %dmv\n", p->micb_mv);
+	n += scnprintf(buffer + n, size - n, "v_ins_hu = %x(%dmv)\n",
+		       v_ins_hu, wcd9xxx_codec_sta_dce_v(mbhc, 0, v_ins_hu));
+	n += scnprintf(buffer + n, size - n, "v_ins_h = %x(%dmv)\n",
+		       v_ins_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, v_ins_h));
 	n += scnprintf(buffer + n, size - n, "v_b1_hu = %x(%dmv)\n",
-		       p->v_b1_hu,
-		       wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_b1_hu));
+		       v_b1_hu, wcd9xxx_codec_sta_dce_v(mbhc, 0, v_b1_hu));
 	n += scnprintf(buffer + n, size - n, "v_b1_h = %x(%dmv)\n",
-		       p->v_b1_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_b1_h));
-	n += scnprintf(buffer + n, size - n, "v_b1_huc = %x(%dmv)\n",
-		       p->v_b1_huc,
-		       wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_b1_huc));
+		       v_b1_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, v_b1_h));
 	n += scnprintf(buffer + n, size - n, "v_brh = %x(%dmv)\n",
-		       p->v_brh, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_brh));
+		       v_br_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, v_br_h));
 	n += scnprintf(buffer + n, size - n, "v_brl = %x(%dmv)\n",  p->v_brl,
 		       wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_brl));
 	n += scnprintf(buffer + n, size - n, "v_no_mic = %x(%dmv)\n",
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 300e34e..4f8f3cf 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -28,6 +28,12 @@
 	u8 cfilt_sel;
 };
 
+enum mbhc_v_index {
+	MBHC_V_IDX_CFILT,
+	MBHC_V_IDX_VDDIO,
+	MBHC_V_IDX_NUM,
+};
+
 /* Data used by MBHC */
 struct mbhc_internal_cal_data {
 	u16 dce_z;
@@ -38,17 +44,13 @@
 	u32 t_dce;
 	u32 t_sta;
 	u32 micb_mv;
-	u16 v_ins_hu;
-	u16 v_ins_h;
-	u16 v_b1_hu;
-	u16 v_b1_h;
-	u16 v_b1_huc;
-	u16 v_brh;
+	u16 v_ins_hu[MBHC_V_IDX_NUM];
+	u16 v_ins_h[MBHC_V_IDX_NUM];
+	u16 v_b1_hu[MBHC_V_IDX_NUM];
+	u16 v_b1_h[MBHC_V_IDX_NUM];
+	u16 v_brh[MBHC_V_IDX_NUM];
 	u16 v_brl;
 	u16 v_no_mic;
-	s16 adj_v_hs_max;
-	u16 adj_v_ins_hu;
-	u16 adj_v_ins_h;
 	s16 v_inval_ins_low;
 	s16 v_inval_ins_high;
 };
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index c2fd2d7..ac26d0c 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -3363,6 +3363,7 @@
 	u32 lbuf_addr_lsw;
 	u32 liomode;
 	u32 io_compressed;
+	int dir = 0;
 
 	if (!ac || ac->apr == NULL) {
 		pr_err("%s: APR handle NULL\n", __func__);
@@ -3380,15 +3381,21 @@
 	read.seq_id = param->uid;
 	liomode = (NT_MODE | ASYNC_IO_MODE);
 	io_compressed = (ASYNC_IO_MODE | COMPRESSED_IO);
-	if (ac->io_mode == liomode)
+	if (ac->io_mode == liomode) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 32);
-	else if (ac->io_mode == io_compressed)
+		/*legacy wma driver case*/
+		dir = IN;
+	} else if (ac->io_mode == io_compressed) {
 		lbuf_addr_lsw = (read.buf_addr_lsw - 64);
-	else
+		dir = OUT;
+	} else {
 		lbuf_addr_lsw = read.buf_addr_lsw;
+		dir = OUT;
+	}
 
-	list_for_each_safe(ptr, next, &ac->port[OUT].mem_map_handle) {
-		buf_node = list_entry(ptr, struct asm_buffer_node, list);
+	list_for_each_safe(ptr, next, &ac->port[dir].mem_map_handle) {
+		buf_node = list_entry(ptr, struct asm_buffer_node,
+			list);
 			if (buf_node->buf_addr_lsw == lbuf_addr_lsw) {
 				read.mem_map_handle = buf_node->mmap_hdl;
 				break;